price policy
This commit is contained in:
@@ -1,185 +0,0 @@
|
||||
/// Price Policy Local DataSource
|
||||
///
|
||||
/// Handles all local data operations for price policy documents.
|
||||
/// Currently provides mock data for development and testing.
|
||||
/// Will be extended to use Hive cache when backend API is available.
|
||||
library;
|
||||
|
||||
import 'package:worker/features/price_policy/data/models/price_document_model.dart';
|
||||
|
||||
/// Price Policy Local Data Source
|
||||
///
|
||||
/// Provides mock data for price policy documents.
|
||||
/// In production, this will cache data from the remote API.
|
||||
class PricePolicyLocalDataSource {
|
||||
/// Get all price policy documents
|
||||
///
|
||||
/// Returns a list of all documents from mock data.
|
||||
/// In production, this will fetch from Hive cache.
|
||||
Future<List<PriceDocumentModel>> getAllDocuments() async {
|
||||
// Simulate network delay
|
||||
await Future<void>.delayed(const Duration(milliseconds: 300));
|
||||
|
||||
return _mockDocuments;
|
||||
}
|
||||
|
||||
/// Get documents by category
|
||||
///
|
||||
/// Returns filtered list of documents matching the [category].
|
||||
Future<List<PriceDocumentModel>> getDocumentsByCategory(
|
||||
String category,
|
||||
) async {
|
||||
// Simulate network delay
|
||||
await Future<void>.delayed(const Duration(milliseconds: 200));
|
||||
|
||||
return _mockDocuments
|
||||
.where((doc) => doc.category.toLowerCase() == category.toLowerCase())
|
||||
.toList();
|
||||
}
|
||||
|
||||
/// Get a specific document by ID
|
||||
///
|
||||
/// Returns the document if found, null otherwise.
|
||||
Future<PriceDocumentModel?> getDocumentById(String documentId) async {
|
||||
// Simulate network delay
|
||||
await Future<void>.delayed(const Duration(milliseconds: 100));
|
||||
|
||||
try {
|
||||
return _mockDocuments.firstWhere((doc) => doc.id == documentId);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if cache is valid
|
||||
///
|
||||
/// Returns true if cached data is still valid.
|
||||
/// Currently always returns false since we're using mock data.
|
||||
Future<bool> isCacheValid() async {
|
||||
// TODO: Implement cache validation when using Hive
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Cache documents locally
|
||||
///
|
||||
/// Saves documents to Hive for offline access.
|
||||
/// Currently not implemented (using mock data).
|
||||
Future<void> cacheDocuments(List<PriceDocumentModel> documents) async {
|
||||
// TODO: Implement Hive caching when backend API is ready
|
||||
}
|
||||
|
||||
/// Clear cached documents
|
||||
///
|
||||
/// Removes all cached documents from Hive.
|
||||
/// Currently not implemented (using mock data).
|
||||
Future<void> clearCache() async {
|
||||
// TODO: Implement cache clearing when using Hive
|
||||
}
|
||||
|
||||
/// Mock documents matching HTML design
|
||||
///
|
||||
/// This data will be replaced with real API data in production.
|
||||
static final List<PriceDocumentModel> _mockDocuments = [
|
||||
// Policy documents (Chính sách giá)
|
||||
const PriceDocumentModel(
|
||||
id: 'policy-eurotile-10-2025',
|
||||
title: 'Chính sách giá Eurotile T10/2025',
|
||||
description:
|
||||
'Chính sách giá mới nhất cho sản phẩm gạch Eurotile, áp dụng từ tháng 10/2025',
|
||||
publishedDate: '2025-10-01T00:00:00.000Z',
|
||||
documentType: 'pdf',
|
||||
category: 'policy',
|
||||
downloadUrl: '/documents/policy-eurotile-10-2025.pdf',
|
||||
fileSize: '2.5 MB',
|
||||
),
|
||||
const PriceDocumentModel(
|
||||
id: 'policy-vasta-10-2025',
|
||||
title: 'Chính sách giá Vasta Stone T10/2025',
|
||||
description:
|
||||
'Chính sách giá đá tự nhiên Vasta Stone, hiệu lực từ tháng 10/2025',
|
||||
publishedDate: '2025-10-01T00:00:00.000Z',
|
||||
documentType: 'pdf',
|
||||
category: 'policy',
|
||||
downloadUrl: '/documents/policy-vasta-10-2025.pdf',
|
||||
fileSize: '1.8 MB',
|
||||
),
|
||||
const PriceDocumentModel(
|
||||
id: 'policy-dealer-2025',
|
||||
title: 'Chính sách chiết khấu đại lý 2025',
|
||||
description:
|
||||
'Chương trình chiết khấu và ưu đãi dành cho đại lý, thầu thợ',
|
||||
publishedDate: '2025-09-15T00:00:00.000Z',
|
||||
documentType: 'pdf',
|
||||
category: 'policy',
|
||||
downloadUrl: '/documents/policy-dealer-2025.pdf',
|
||||
fileSize: '3.2 MB',
|
||||
),
|
||||
const PriceDocumentModel(
|
||||
id: 'policy-payment-2025',
|
||||
title: 'Điều kiện thanh toán & giao hàng',
|
||||
description:
|
||||
'Điều khoản thanh toán, chính sách giao hàng và bảo hành sản phẩm',
|
||||
publishedDate: '2025-08-01T00:00:00.000Z',
|
||||
documentType: 'pdf',
|
||||
category: 'policy',
|
||||
downloadUrl: '/documents/policy-payment-2025.pdf',
|
||||
fileSize: '1.5 MB',
|
||||
),
|
||||
|
||||
// Price list documents (Bảng giá)
|
||||
const PriceDocumentModel(
|
||||
id: 'pricelist-granite-2025',
|
||||
title: 'Bảng giá Gạch Granite Eurotile 2025',
|
||||
description:
|
||||
'Bảng giá chi tiết toàn bộ sản phẩm gạch granite, kích thước 60x60, 80x80, 120x120',
|
||||
publishedDate: '2025-10-01T00:00:00.000Z',
|
||||
documentType: 'excel',
|
||||
category: 'priceList',
|
||||
downloadUrl: '/documents/pricelist-granite-2025.xlsx',
|
||||
fileSize: '850 KB',
|
||||
),
|
||||
const PriceDocumentModel(
|
||||
id: 'pricelist-ceramic-2025',
|
||||
title: 'Bảng giá Gạch Ceramic Eurotile 2025',
|
||||
description: 'Bảng giá gạch ceramic vân gỗ, vân đá, vân xi măng các loại',
|
||||
publishedDate: '2025-10-01T00:00:00.000Z',
|
||||
documentType: 'excel',
|
||||
category: 'priceList',
|
||||
downloadUrl: '/documents/pricelist-ceramic-2025.xlsx',
|
||||
fileSize: '720 KB',
|
||||
),
|
||||
const PriceDocumentModel(
|
||||
id: 'pricelist-stone-2025',
|
||||
title: 'Bảng giá Đá tự nhiên Vasta Stone 2025',
|
||||
description:
|
||||
'Bảng giá đá marble, granite tự nhiên nhập khẩu, kích thước tấm lớn',
|
||||
publishedDate: '2025-10-01T00:00:00.000Z',
|
||||
documentType: 'excel',
|
||||
category: 'priceList',
|
||||
downloadUrl: '/documents/pricelist-stone-2025.xlsx',
|
||||
fileSize: '950 KB',
|
||||
),
|
||||
const PriceDocumentModel(
|
||||
id: 'pricelist-accessories-2025',
|
||||
title: 'Bảng giá Phụ kiện & Vật liệu 2025',
|
||||
description:
|
||||
'Giá keo dán, chà ron, nẹp nhựa, nẹp inox và các phụ kiện thi công',
|
||||
publishedDate: '2025-09-15T00:00:00.000Z',
|
||||
documentType: 'excel',
|
||||
category: 'priceList',
|
||||
downloadUrl: '/documents/pricelist-accessories-2025.xlsx',
|
||||
fileSize: '640 KB',
|
||||
),
|
||||
const PriceDocumentModel(
|
||||
id: 'pricelist-outdoor-2025',
|
||||
title: 'Bảng giá Gạch Outdoor & Chống trơn 2025',
|
||||
description:
|
||||
'Bảng giá sản phẩm outdoor, gạch chống trơn dành cho ngoại thất',
|
||||
publishedDate: '2025-09-01T00:00:00.000Z',
|
||||
documentType: 'excel',
|
||||
category: 'priceList',
|
||||
downloadUrl: '/documents/pricelist-outdoor-2025.xlsx',
|
||||
fileSize: '780 KB',
|
||||
),
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/// Remote Data Source: Price Policy
|
||||
///
|
||||
/// Handles API communication for price policy documents.
|
||||
library;
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:worker/core/network/dio_client.dart';
|
||||
import 'package:worker/features/price_policy/data/models/price_document_model.dart';
|
||||
|
||||
/// Price Policy Remote Data Source Interface
|
||||
abstract class PricePolicyRemoteDataSource {
|
||||
/// Get documents by pricing type
|
||||
Future<List<PriceDocumentModel>> getDocumentsByType(String pricingType);
|
||||
|
||||
/// Get all documents (both pricing rule and price list)
|
||||
Future<List<PriceDocumentModel>> getAllDocuments();
|
||||
}
|
||||
|
||||
/// Price Policy Remote Data Source Implementation
|
||||
class PricePolicyRemoteDataSourceImpl implements PricePolicyRemoteDataSource {
|
||||
|
||||
const PricePolicyRemoteDataSourceImpl(this._dioClient);
|
||||
final DioClient _dioClient;
|
||||
|
||||
@override
|
||||
Future<List<PriceDocumentModel>> getDocumentsByType(String pricingType) async {
|
||||
try {
|
||||
final response = await _dioClient.post<Map<String, dynamic>>(
|
||||
'/api/method/building_material.building_material.api.pricing.get_pricing_info',
|
||||
data: {
|
||||
'pricing_type': pricingType,
|
||||
'limit_page_length': 0,
|
||||
'limit_start': 0,
|
||||
},
|
||||
);
|
||||
|
||||
if (response.data == null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
final apiResponse = PricingApiResponse.fromJson(response.data!);
|
||||
return apiResponse.message;
|
||||
} on DioException catch (e) {
|
||||
throw Exception('Failed to fetch pricing documents: ${e.message}');
|
||||
} catch (e) {
|
||||
throw Exception('Failed to parse pricing documents: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<PriceDocumentModel>> getAllDocuments() async {
|
||||
try {
|
||||
// Fetch both pricing rule and price list in parallel
|
||||
final results = await Future.wait([
|
||||
getDocumentsByType('PRICING_RULE'),
|
||||
getDocumentsByType('PRICE_LIST'),
|
||||
]);
|
||||
|
||||
// Combine results
|
||||
return [...results[0], ...results[1]];
|
||||
} catch (e) {
|
||||
throw Exception('Failed to fetch all documents: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,158 +1,115 @@
|
||||
/// Data Model: Price Document Model
|
||||
/// Data Model: Price Document
|
||||
///
|
||||
/// Data layer model for price policy documents.
|
||||
/// Handles JSON serialization and conversion to/from domain entity.
|
||||
/// Data model for price policy documents from API.
|
||||
library;
|
||||
|
||||
import 'package:worker/features/price_policy/domain/entities/price_document.dart';
|
||||
|
||||
/// Price Document Model
|
||||
///
|
||||
/// Used in the data layer for:
|
||||
/// - JSON serialization/deserialization from API
|
||||
/// - Conversion to domain entity
|
||||
/// - Local storage (if needed)
|
||||
/// Price document data model
|
||||
class PriceDocumentModel {
|
||||
/// Unique document ID
|
||||
final String id;
|
||||
|
||||
/// Document title
|
||||
final String title;
|
||||
|
||||
/// Document description
|
||||
final String description;
|
||||
|
||||
/// Date the document was published (ISO 8601 string)
|
||||
final String publishedDate;
|
||||
|
||||
/// Type of document (pdf or excel)
|
||||
final String documentType;
|
||||
|
||||
/// Category (policy or priceList)
|
||||
final String category;
|
||||
|
||||
/// URL to download the document
|
||||
final String downloadUrl;
|
||||
final String fileUrl;
|
||||
|
||||
/// Optional file size display string
|
||||
final String? fileSize;
|
||||
/// Last updated timestamp
|
||||
final String updatedAt;
|
||||
|
||||
/// Constructor
|
||||
const PriceDocumentModel({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.description,
|
||||
required this.publishedDate,
|
||||
required this.documentType,
|
||||
required this.category,
|
||||
required this.downloadUrl,
|
||||
this.fileSize,
|
||||
required this.fileUrl,
|
||||
required this.updatedAt,
|
||||
});
|
||||
|
||||
/// Create model from JSON
|
||||
/// Create from JSON
|
||||
factory PriceDocumentModel.fromJson(Map<String, dynamic> json) {
|
||||
return PriceDocumentModel(
|
||||
id: json['id'] as String,
|
||||
title: json['title'] as String,
|
||||
description: json['description'] as String,
|
||||
publishedDate: json['published_date'] as String,
|
||||
documentType: json['document_type'] as String,
|
||||
category: json['category'] as String,
|
||||
downloadUrl: json['download_url'] as String,
|
||||
fileSize: json['file_size'] as String?,
|
||||
title: json['title'] as String? ?? '',
|
||||
fileUrl: json['file_url'] as String? ?? '',
|
||||
updatedAt: json['updated_at'] as String? ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
/// Convert model to JSON
|
||||
/// Convert to JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'title': title,
|
||||
'description': description,
|
||||
'published_date': publishedDate,
|
||||
'document_type': documentType,
|
||||
'category': category,
|
||||
'download_url': downloadUrl,
|
||||
'file_size': fileSize,
|
||||
'file_url': fileUrl,
|
||||
'updated_at': updatedAt,
|
||||
};
|
||||
}
|
||||
|
||||
/// Convert model to domain entity
|
||||
PriceDocument toEntity() {
|
||||
/// Convert to domain entity
|
||||
PriceDocument toEntity(DocumentCategory category) {
|
||||
return PriceDocument(
|
||||
id: id,
|
||||
title: title,
|
||||
description: description,
|
||||
publishedDate: DateTime.parse(publishedDate),
|
||||
documentType: _parseDocumentType(documentType),
|
||||
category: _parseCategory(category),
|
||||
downloadUrl: downloadUrl,
|
||||
fileSize: fileSize,
|
||||
fileUrl: fileUrl,
|
||||
updatedAt: _parseDateTime(updatedAt),
|
||||
category: category,
|
||||
);
|
||||
}
|
||||
|
||||
/// Create model from domain entity
|
||||
/// Parse datetime string from API format
|
||||
/// Format: "2025-11-26 11:36:43"
|
||||
DateTime _parseDateTime(String dateTimeStr) {
|
||||
try {
|
||||
// Replace space with 'T' for ISO 8601 format
|
||||
final isoFormat = dateTimeStr.trim().replaceFirst(' ', 'T');
|
||||
return DateTime.parse(isoFormat);
|
||||
} catch (e) {
|
||||
// If parsing fails, return current datetime
|
||||
return DateTime.now();
|
||||
}
|
||||
}
|
||||
|
||||
/// Create from domain entity
|
||||
factory PriceDocumentModel.fromEntity(PriceDocument entity) {
|
||||
return PriceDocumentModel(
|
||||
id: entity.id,
|
||||
title: entity.title,
|
||||
description: entity.description,
|
||||
publishedDate: entity.publishedDate.toIso8601String(),
|
||||
documentType: _documentTypeToString(entity.documentType),
|
||||
category: _categoryToString(entity.category),
|
||||
downloadUrl: entity.downloadUrl,
|
||||
fileSize: entity.fileSize,
|
||||
fileUrl: entity.fileUrl,
|
||||
updatedAt: _formatDateTime(entity.updatedAt),
|
||||
);
|
||||
}
|
||||
|
||||
/// Parse document type from string
|
||||
static DocumentType _parseDocumentType(String type) {
|
||||
switch (type.toLowerCase()) {
|
||||
case 'pdf':
|
||||
return DocumentType.pdf;
|
||||
case 'excel':
|
||||
return DocumentType.excel;
|
||||
default:
|
||||
return DocumentType.pdf;
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse category from string
|
||||
static DocumentCategory _parseCategory(String category) {
|
||||
switch (category.toLowerCase()) {
|
||||
case 'policy':
|
||||
return DocumentCategory.policy;
|
||||
case 'pricelist':
|
||||
case 'price_list':
|
||||
return DocumentCategory.priceList;
|
||||
default:
|
||||
return DocumentCategory.policy;
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert document type to string
|
||||
static String _documentTypeToString(DocumentType type) {
|
||||
switch (type) {
|
||||
case DocumentType.pdf:
|
||||
return 'pdf';
|
||||
case DocumentType.excel:
|
||||
return 'excel';
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert category to string
|
||||
static String _categoryToString(DocumentCategory category) {
|
||||
switch (category) {
|
||||
case DocumentCategory.policy:
|
||||
return 'policy';
|
||||
case DocumentCategory.priceList:
|
||||
return 'priceList';
|
||||
}
|
||||
/// Format datetime to API format
|
||||
static String _formatDateTime(DateTime dateTime) {
|
||||
return '${dateTime.year}-'
|
||||
'${dateTime.month.toString().padLeft(2, '0')}-'
|
||||
'${dateTime.day.toString().padLeft(2, '0')} '
|
||||
'${dateTime.hour.toString().padLeft(2, '0')}:'
|
||||
'${dateTime.minute.toString().padLeft(2, '0')}:'
|
||||
'${dateTime.second.toString().padLeft(2, '0')}';
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PriceDocumentModel(id: $id, title: $title, category: $category, '
|
||||
'documentType: $documentType, publishedDate: $publishedDate)';
|
||||
return 'PriceDocumentModel(title: $title, fileUrl: $fileUrl, updatedAt: $updatedAt)';
|
||||
}
|
||||
}
|
||||
|
||||
/// API Response wrapper
|
||||
class PricingApiResponse {
|
||||
/// List of price documents
|
||||
final List<PriceDocumentModel> message;
|
||||
|
||||
const PricingApiResponse({required this.message});
|
||||
|
||||
/// Create from JSON
|
||||
factory PricingApiResponse.fromJson(Map<String, dynamic> json) {
|
||||
final messageList = json['message'] as List<dynamic>? ?? [];
|
||||
return PricingApiResponse(
|
||||
message: messageList
|
||||
.map((item) => PriceDocumentModel.fromJson(item as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
|
||||
/// Convert to JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'message': message.map((doc) => doc.toJson()).toList(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +1,44 @@
|
||||
/// Repository Implementation: Price Policy Repository
|
||||
///
|
||||
/// Concrete implementation of the PricePolicyRepository interface.
|
||||
/// Coordinates between local and remote data sources to provide price policy data.
|
||||
///
|
||||
/// Currently uses mock data from local datasource.
|
||||
/// Will implement offline-first strategy when backend API is available.
|
||||
/// Fetches price policy documents from remote API.
|
||||
library;
|
||||
|
||||
import 'package:worker/features/price_policy/data/datasources/price_policy_local_datasource.dart';
|
||||
import 'package:worker/features/price_policy/data/datasources/price_policy_remote_datasource.dart';
|
||||
import 'package:worker/features/price_policy/domain/entities/price_document.dart';
|
||||
import 'package:worker/features/price_policy/domain/repositories/price_policy_repository.dart';
|
||||
|
||||
/// Price Policy Repository Implementation
|
||||
///
|
||||
/// Responsibilities:
|
||||
/// - Coordinate between local cache and remote API (when available)
|
||||
/// - Convert data models to domain entities
|
||||
/// - Handle errors gracefully
|
||||
/// - Manage cache invalidation
|
||||
class PricePolicyRepositoryImpl implements PricePolicyRepository {
|
||||
/// Local data source
|
||||
final PricePolicyLocalDataSource localDataSource;
|
||||
|
||||
/// Remote data source (API) - TODO: Add when API is ready
|
||||
// final PricePolicyRemoteDataSource remoteDataSource;
|
||||
/// Remote data source
|
||||
final PricePolicyRemoteDataSource remoteDataSource;
|
||||
|
||||
/// Constructor
|
||||
PricePolicyRepositoryImpl({
|
||||
required this.localDataSource,
|
||||
// required this.remoteDataSource, // TODO: Add when API ready
|
||||
const PricePolicyRepositoryImpl({
|
||||
required this.remoteDataSource,
|
||||
});
|
||||
|
||||
@override
|
||||
Future<List<PriceDocument>> getAllDocuments() async {
|
||||
try {
|
||||
// TODO: Implement offline-first strategy
|
||||
// 1. Check if cache is valid
|
||||
// 2. Return cached data if valid
|
||||
// 3. If cache invalid, fetch from remote
|
||||
// Fetch documents separately to maintain category info
|
||||
final pricingRuleModels =
|
||||
await remoteDataSource.getDocumentsByType('PRICING_RULE');
|
||||
final priceListModels =
|
||||
await remoteDataSource.getDocumentsByType('PRICE_LIST');
|
||||
|
||||
// For now, get from local datasource (mock data)
|
||||
final models = await localDataSource.getAllDocuments();
|
||||
final entities = <PriceDocument>[
|
||||
...pricingRuleModels.map((model) => model.toEntity(DocumentCategory.policy)),
|
||||
...priceListModels.map((model) => model.toEntity(DocumentCategory.priceList)),
|
||||
];
|
||||
|
||||
// Convert models to entities
|
||||
final entities = models.map((model) => model.toEntity()).toList();
|
||||
|
||||
// Sort by published date (newest first)
|
||||
entities.sort((a, b) => b.publishedDate.compareTo(a.publishedDate));
|
||||
// Sort by update date (newest first)
|
||||
entities.sort((a, b) => b.updatedAt.compareTo(a.updatedAt));
|
||||
|
||||
return entities;
|
||||
} catch (e) {
|
||||
// Log error and return empty list
|
||||
// In production, this should throw proper domain failures
|
||||
print('[PricePolicyRepository] Error getting documents: $e');
|
||||
return [];
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,37 +47,35 @@ class PricePolicyRepositoryImpl implements PricePolicyRepository {
|
||||
DocumentCategory category,
|
||||
) async {
|
||||
try {
|
||||
// Convert category to string for datasource
|
||||
final categoryString = _categoryToString(category);
|
||||
// Convert category to API parameter
|
||||
final pricingType = category.apiValue;
|
||||
|
||||
// Get documents from local datasource
|
||||
final models = await localDataSource.getDocumentsByCategory(
|
||||
categoryString,
|
||||
);
|
||||
// Fetch documents by type from API
|
||||
final models = await remoteDataSource.getDocumentsByType(pricingType);
|
||||
|
||||
// Convert models to entities
|
||||
final entities = models.map((model) => model.toEntity()).toList();
|
||||
// Convert models to entities with the correct category
|
||||
final entities = models.map((model) => model.toEntity(category)).toList();
|
||||
|
||||
// Sort by published date (newest first)
|
||||
entities.sort((a, b) => b.publishedDate.compareTo(a.publishedDate));
|
||||
// Sort by update date (newest first)
|
||||
entities.sort((a, b) => b.updatedAt.compareTo(a.updatedAt));
|
||||
|
||||
return entities;
|
||||
} catch (e) {
|
||||
print('[PricePolicyRepository] Error getting documents by category: $e');
|
||||
return [];
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<PriceDocument?> getDocumentById(String documentId) async {
|
||||
try {
|
||||
// Get document from local datasource
|
||||
final model = await localDataSource.getDocumentById(documentId);
|
||||
|
||||
// Convert model to entity
|
||||
return model?.toEntity();
|
||||
// Since API doesn't have a get-by-id endpoint,
|
||||
// we fetch all and find the matching one
|
||||
final allDocuments = await getAllDocuments();
|
||||
return allDocuments.firstWhere(
|
||||
(doc) => doc.title == documentId,
|
||||
orElse: () => throw Exception('Document not found'),
|
||||
);
|
||||
} catch (e) {
|
||||
print('[PricePolicyRepository] Error getting document by id: $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -100,35 +83,10 @@ class PricePolicyRepositoryImpl implements PricePolicyRepository {
|
||||
@override
|
||||
Future<List<PriceDocument>> refreshDocuments() async {
|
||||
try {
|
||||
// TODO: Implement remote fetch when API is available
|
||||
// 1. Fetch from remote API
|
||||
// 2. Cache the results locally
|
||||
// 3. Return fresh data
|
||||
|
||||
// For now, just clear and refetch from local
|
||||
await localDataSource.clearCache();
|
||||
final models = await localDataSource.getAllDocuments();
|
||||
|
||||
// Convert models to entities
|
||||
final entities = models.map((model) => model.toEntity()).toList();
|
||||
|
||||
// Sort by published date (newest first)
|
||||
entities.sort((a, b) => b.publishedDate.compareTo(a.publishedDate));
|
||||
|
||||
return entities;
|
||||
// Refresh is same as getAllDocuments since we're fetching from API
|
||||
return await getAllDocuments();
|
||||
} catch (e) {
|
||||
print('[PricePolicyRepository] Error refreshing documents: $e');
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper method to convert category enum to string
|
||||
String _categoryToString(DocumentCategory category) {
|
||||
switch (category) {
|
||||
case DocumentCategory.policy:
|
||||
return 'policy';
|
||||
case DocumentCategory.priceList:
|
||||
return 'priceList';
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user