183 lines
5.0 KiB
Dart
183 lines
5.0 KiB
Dart
import 'package:hive_ce/hive.dart';
|
|
import 'package:retail/core/database/hive_database.dart';
|
|
import 'package:retail/features/products/data/models/product_model.dart';
|
|
import 'package:retail/features/products/data/datasources/product_local_datasource.dart';
|
|
import 'package:retail/features/products/domain/entities/product.dart';
|
|
|
|
/// Hive implementation of ProductLocalDataSource
|
|
class ProductLocalDataSourceHive implements ProductLocalDataSource {
|
|
final HiveDatabase _database;
|
|
|
|
ProductLocalDataSourceHive(this._database);
|
|
|
|
Box<ProductModel> get _box => _database.productsBox;
|
|
|
|
/// Convert ProductModel to Product entity
|
|
Product _toEntity(ProductModel model) {
|
|
return Product(
|
|
id: model.id,
|
|
name: model.name,
|
|
description: model.description,
|
|
price: model.price,
|
|
imageUrl: model.imageUrl,
|
|
categoryId: model.categoryId,
|
|
stockQuantity: model.stockQuantity,
|
|
isAvailable: model.isAvailable,
|
|
createdAt: model.createdAt,
|
|
updatedAt: model.updatedAt,
|
|
);
|
|
}
|
|
|
|
/// Convert Product entity to ProductModel
|
|
ProductModel _toModel(Product entity) {
|
|
return ProductModel(
|
|
id: entity.id,
|
|
name: entity.name,
|
|
description: entity.description,
|
|
price: entity.price,
|
|
imageUrl: entity.imageUrl,
|
|
categoryId: entity.categoryId,
|
|
stockQuantity: entity.stockQuantity,
|
|
isAvailable: entity.isAvailable,
|
|
createdAt: entity.createdAt,
|
|
updatedAt: entity.updatedAt,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<List<Product>> getAllProducts() async {
|
|
try {
|
|
return _box.values.map(_toEntity).toList();
|
|
} catch (e) {
|
|
throw Exception('Failed to get products: $e');
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<Product?> getProductById(String id) async {
|
|
try {
|
|
final model = _box.get(id);
|
|
return model != null ? _toEntity(model) : null;
|
|
} catch (e) {
|
|
throw Exception('Failed to get product by ID: $e');
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<List<Product>> getProductsByCategory(String categoryId) async {
|
|
try {
|
|
return _box.values
|
|
.where((product) => product.categoryId == categoryId)
|
|
.map(_toEntity)
|
|
.toList();
|
|
} catch (e) {
|
|
throw Exception('Failed to get products by category: $e');
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<void> saveProducts(List<Product> products) async {
|
|
try {
|
|
final models = products.map(_toModel).toList();
|
|
final Map<String, ProductModel> productsMap = {
|
|
for (var model in models) model.id: model
|
|
};
|
|
await _box.putAll(productsMap);
|
|
} catch (e) {
|
|
throw Exception('Failed to save products: $e');
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<void> deleteAllProducts() async {
|
|
try {
|
|
await _box.clear();
|
|
} catch (e) {
|
|
throw Exception('Failed to delete all products: $e');
|
|
}
|
|
}
|
|
|
|
/// Additional Hive-specific methods
|
|
|
|
/// Save a single product
|
|
Future<void> saveProduct(Product product) async {
|
|
try {
|
|
final model = _toModel(product);
|
|
await _box.put(model.id, model);
|
|
} catch (e) {
|
|
throw Exception('Failed to save product: $e');
|
|
}
|
|
}
|
|
|
|
/// Update an existing product
|
|
Future<void> updateProduct(Product product) async {
|
|
try {
|
|
if (!_box.containsKey(product.id)) {
|
|
throw Exception('Product not found: ${product.id}');
|
|
}
|
|
final model = _toModel(product);
|
|
await _box.put(model.id, model);
|
|
} catch (e) {
|
|
throw Exception('Failed to update product: $e');
|
|
}
|
|
}
|
|
|
|
/// Delete a specific product
|
|
Future<void> deleteProduct(String id) async {
|
|
try {
|
|
await _box.delete(id);
|
|
} catch (e) {
|
|
throw Exception('Failed to delete product: $e');
|
|
}
|
|
}
|
|
|
|
/// Check if product exists
|
|
Future<bool> productExists(String id) async {
|
|
try {
|
|
return _box.containsKey(id);
|
|
} catch (e) {
|
|
throw Exception('Failed to check product existence: $e');
|
|
}
|
|
}
|
|
|
|
/// Get available products only
|
|
Future<List<Product>> getAvailableProducts() async {
|
|
try {
|
|
return _box.values
|
|
.where((product) => product.isAvailable && product.stockQuantity > 0)
|
|
.map(_toEntity)
|
|
.toList();
|
|
} catch (e) {
|
|
throw Exception('Failed to get available products: $e');
|
|
}
|
|
}
|
|
|
|
/// Get products with low stock
|
|
Future<List<Product>> getLowStockProducts(int threshold) async {
|
|
try {
|
|
return _box.values
|
|
.where((product) =>
|
|
product.stockQuantity <= threshold && product.stockQuantity > 0)
|
|
.map(_toEntity)
|
|
.toList();
|
|
} catch (e) {
|
|
throw Exception('Failed to get low stock products: $e');
|
|
}
|
|
}
|
|
|
|
/// Search products by name or description
|
|
Future<List<Product>> searchProducts(String query) async {
|
|
try {
|
|
final lowercaseQuery = query.toLowerCase();
|
|
return _box.values
|
|
.where((product) =>
|
|
product.name.toLowerCase().contains(lowercaseQuery) ||
|
|
product.description.toLowerCase().contains(lowercaseQuery))
|
|
.map(_toEntity)
|
|
.toList();
|
|
} catch (e) {
|
|
throw Exception('Failed to search products: $e');
|
|
}
|
|
}
|
|
}
|