Files
worker/lib/features/quotes/domain/entities/quote_item.dart
2025-10-24 11:31:48 +07:00

134 lines
3.4 KiB
Dart

/// Domain Entity: Quote Item
///
/// Represents a single line item in a quotation.
library;
/// Quote Item Entity
///
/// Contains item-level information in a quote:
/// - Product reference
/// - Quantity and pricing
/// - Price negotiation
/// - Discounts
class QuoteItem {
/// Unique quote item identifier
final String quoteItemId;
/// Quote ID this item belongs to
final String quoteId;
/// Product ID
final String productId;
/// Quantity quoted
final double quantity;
/// Original/list price per unit
final double originalPrice;
/// Negotiated price per unit
final double negotiatedPrice;
/// Discount percentage
final double discountPercent;
/// Subtotal (quantity * negotiatedPrice)
final double subtotal;
/// Item notes
final String? notes;
const QuoteItem({
required this.quoteItemId,
required this.quoteId,
required this.productId,
required this.quantity,
required this.originalPrice,
required this.negotiatedPrice,
required this.discountPercent,
required this.subtotal,
this.notes,
});
/// Calculate subtotal at original price
double get subtotalAtOriginalPrice => quantity * originalPrice;
/// Calculate discount amount per unit
double get discountPerUnit => originalPrice - negotiatedPrice;
/// Calculate total discount amount
double get totalDiscountAmount =>
(quantity * originalPrice) - (quantity * negotiatedPrice);
/// Calculate effective discount percentage
double get effectiveDiscountPercentage {
if (originalPrice == 0) return 0;
return ((originalPrice - negotiatedPrice) / originalPrice) * 100;
}
/// Check if item has discount
bool get hasDiscount => negotiatedPrice < originalPrice;
/// Check if price was negotiated
bool get isNegotiated => negotiatedPrice != originalPrice;
/// Copy with method for immutability
QuoteItem copyWith({
String? quoteItemId,
String? quoteId,
String? productId,
double? quantity,
double? originalPrice,
double? negotiatedPrice,
double? discountPercent,
double? subtotal,
String? notes,
}) {
return QuoteItem(
quoteItemId: quoteItemId ?? this.quoteItemId,
quoteId: quoteId ?? this.quoteId,
productId: productId ?? this.productId,
quantity: quantity ?? this.quantity,
originalPrice: originalPrice ?? this.originalPrice,
negotiatedPrice: negotiatedPrice ?? this.negotiatedPrice,
discountPercent: discountPercent ?? this.discountPercent,
subtotal: subtotal ?? this.subtotal,
notes: notes ?? this.notes,
);
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is QuoteItem &&
other.quoteItemId == quoteItemId &&
other.quoteId == quoteId &&
other.productId == productId &&
other.quantity == quantity &&
other.originalPrice == originalPrice &&
other.negotiatedPrice == negotiatedPrice &&
other.subtotal == subtotal;
}
@override
int get hashCode {
return Object.hash(
quoteItemId,
quoteId,
productId,
quantity,
originalPrice,
negotiatedPrice,
subtotal,
);
}
@override
String toString() {
return 'QuoteItem(quoteItemId: $quoteItemId, productId: $productId, '
'quantity: $quantity, originalPrice: $originalPrice, '
'negotiatedPrice: $negotiatedPrice, subtotal: $subtotal)';
}
}