second commit
This commit is contained in:
134
lib/domain/entities/product.dart
Normal file
134
lib/domain/entities/product.dart
Normal file
@@ -0,0 +1,134 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import '../../core/constants/app_constants.dart';
|
||||
|
||||
/// Merchandise categories shown as filter chips on the POS dashboard.
|
||||
enum ProductCategory {
|
||||
dairy('Dairy', '🥛'),
|
||||
grocery('Grocery', '🛒'),
|
||||
fruits('Fruits', '🍎'),
|
||||
vegetables('Vegetables', '🥦'),
|
||||
beverages('Beverages', '🥤'),
|
||||
snacks('Snacks', '🍪'),
|
||||
personalCare('Personal Care', '🧴'),
|
||||
household('Household', '🏠');
|
||||
|
||||
const ProductCategory(this.label, this.emoji);
|
||||
|
||||
final String label;
|
||||
final String emoji;
|
||||
}
|
||||
|
||||
/// Unit of measure — drives whether fractional quantities are permitted.
|
||||
enum UnitOfMeasure {
|
||||
piece('pc'),
|
||||
kilogram('kg'),
|
||||
gram('g'),
|
||||
litre('L'),
|
||||
millilitre('ml'),
|
||||
pack('pack');
|
||||
|
||||
const UnitOfMeasure(this.symbol);
|
||||
|
||||
final String symbol;
|
||||
|
||||
bool get allowsFractional =>
|
||||
this == UnitOfMeasure.kilogram || this == UnitOfMeasure.litre;
|
||||
}
|
||||
|
||||
/// A sellable item in the catalogue.
|
||||
class Product extends Equatable {
|
||||
const Product({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.barcode,
|
||||
required this.sku,
|
||||
required this.category,
|
||||
required this.price,
|
||||
required this.stock,
|
||||
this.mrp,
|
||||
this.emoji = '📦',
|
||||
this.imageUrl,
|
||||
this.unit = UnitOfMeasure.piece,
|
||||
this.gstRate = AppConstants.defaultGstRate,
|
||||
this.brand,
|
||||
this.isActive = true,
|
||||
});
|
||||
|
||||
final String id;
|
||||
final String name;
|
||||
final String barcode;
|
||||
final String sku;
|
||||
final ProductCategory category;
|
||||
|
||||
/// Selling price per [unit], inclusive of GST (Indian retail convention).
|
||||
final double price;
|
||||
|
||||
/// Printed maximum retail price, used to display savings.
|
||||
final double? mrp;
|
||||
|
||||
final double stock;
|
||||
final String emoji;
|
||||
final String? imageUrl;
|
||||
final UnitOfMeasure unit;
|
||||
final double gstRate;
|
||||
final String? brand;
|
||||
final bool isActive;
|
||||
|
||||
bool get isOutOfStock => stock <= 0;
|
||||
bool get isLowStock =>
|
||||
stock > 0 && stock <= AppConstants.lowStockThreshold;
|
||||
|
||||
bool get hasDiscount => mrp != null && mrp! > price;
|
||||
|
||||
double get savings => hasDiscount ? (mrp! - price) : 0;
|
||||
|
||||
double get discountPercent =>
|
||||
hasDiscount ? ((mrp! - price) / mrp!) * 100 : 0;
|
||||
|
||||
/// Price stripped of embedded GST — the taxable value.
|
||||
double get netPrice => price / (1 + gstRate);
|
||||
|
||||
/// GST rupees embedded inside [price].
|
||||
double get taxPerUnit => price - netPrice;
|
||||
|
||||
/// Fuzzy match used by the search bar across name, barcode, SKU and brand.
|
||||
bool matches(String query) {
|
||||
final q = query.trim().toLowerCase();
|
||||
if (q.isEmpty) return true;
|
||||
return name.toLowerCase().contains(q) ||
|
||||
barcode.toLowerCase().contains(q) ||
|
||||
sku.toLowerCase().contains(q) ||
|
||||
(brand?.toLowerCase().contains(q) ?? false) ||
|
||||
category.label.toLowerCase().contains(q);
|
||||
}
|
||||
|
||||
Product copyWith({
|
||||
String? name,
|
||||
double? price,
|
||||
double? mrp,
|
||||
double? stock,
|
||||
ProductCategory? category,
|
||||
bool? isActive,
|
||||
}) {
|
||||
return Product(
|
||||
id: id,
|
||||
name: name ?? this.name,
|
||||
barcode: barcode,
|
||||
sku: sku,
|
||||
category: category ?? this.category,
|
||||
price: price ?? this.price,
|
||||
mrp: mrp ?? this.mrp,
|
||||
stock: stock ?? this.stock,
|
||||
emoji: emoji,
|
||||
imageUrl: imageUrl,
|
||||
unit: unit,
|
||||
gstRate: gstRate,
|
||||
brand: brand,
|
||||
isActive: isActive ?? this.isActive,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id, name, barcode, sku, price, stock, isActive];
|
||||
}
|
||||
Reference in New Issue
Block a user