update database
This commit is contained in:
86
lib/features/orders/data/models/invoice_model.dart
Normal file
86
lib/features/orders/data/models/invoice_model.dart
Normal file
@@ -0,0 +1,86 @@
|
||||
import 'package:hive_ce/hive.dart';
|
||||
import 'package:worker/core/constants/storage_constants.dart';
|
||||
import 'package:worker/core/database/models/enums.dart';
|
||||
|
||||
part 'invoice_model.g.dart';
|
||||
|
||||
@HiveType(typeId: HiveTypeIds.invoiceModel)
|
||||
class InvoiceModel extends HiveObject {
|
||||
InvoiceModel({required this.invoiceId, required this.invoiceNumber, required this.userId, this.orderId, required this.invoiceType, required this.issueDate, required this.dueDate, required this.currency, required this.subtotalAmount, required this.taxAmount, required this.discountAmount, required this.shippingAmount, required this.totalAmount, required this.amountPaid, required this.amountRemaining, required this.status, this.paymentTerms, this.notes, this.erpnextInvoice, required this.createdAt, this.updatedAt, this.lastReminderSent});
|
||||
|
||||
@HiveField(0) final String invoiceId;
|
||||
@HiveField(1) final String invoiceNumber;
|
||||
@HiveField(2) final String userId;
|
||||
@HiveField(3) final String? orderId;
|
||||
@HiveField(4) final InvoiceType invoiceType;
|
||||
@HiveField(5) final DateTime issueDate;
|
||||
@HiveField(6) final DateTime dueDate;
|
||||
@HiveField(7) final String currency;
|
||||
@HiveField(8) final double subtotalAmount;
|
||||
@HiveField(9) final double taxAmount;
|
||||
@HiveField(10) final double discountAmount;
|
||||
@HiveField(11) final double shippingAmount;
|
||||
@HiveField(12) final double totalAmount;
|
||||
@HiveField(13) final double amountPaid;
|
||||
@HiveField(14) final double amountRemaining;
|
||||
@HiveField(15) final InvoiceStatus status;
|
||||
@HiveField(16) final String? paymentTerms;
|
||||
@HiveField(17) final String? notes;
|
||||
@HiveField(18) final String? erpnextInvoice;
|
||||
@HiveField(19) final DateTime createdAt;
|
||||
@HiveField(20) final DateTime? updatedAt;
|
||||
@HiveField(21) final DateTime? lastReminderSent;
|
||||
|
||||
factory InvoiceModel.fromJson(Map<String, dynamic> json) => InvoiceModel(
|
||||
invoiceId: json['invoice_id'] as String,
|
||||
invoiceNumber: json['invoice_number'] as String,
|
||||
userId: json['user_id'] as String,
|
||||
orderId: json['order_id'] as String?,
|
||||
invoiceType: InvoiceType.values.firstWhere((e) => e.name == json['invoice_type']),
|
||||
issueDate: DateTime.parse(json['issue_date']?.toString() ?? ''),
|
||||
dueDate: DateTime.parse(json['due_date']?.toString() ?? ''),
|
||||
currency: json['currency'] as String? ?? 'VND',
|
||||
subtotalAmount: (json['subtotal_amount'] as num).toDouble(),
|
||||
taxAmount: (json['tax_amount'] as num).toDouble(),
|
||||
discountAmount: (json['discount_amount'] as num).toDouble(),
|
||||
shippingAmount: (json['shipping_amount'] as num).toDouble(),
|
||||
totalAmount: (json['total_amount'] as num).toDouble(),
|
||||
amountPaid: (json['amount_paid'] as num).toDouble(),
|
||||
amountRemaining: (json['amount_remaining'] as num).toDouble(),
|
||||
status: InvoiceStatus.values.firstWhere((e) => e.name == json['status']),
|
||||
paymentTerms: json['payment_terms'] as String?,
|
||||
notes: json['notes'] as String?,
|
||||
erpnextInvoice: json['erpnext_invoice'] as String?,
|
||||
createdAt: DateTime.parse(json['created_at']?.toString() ?? ''),
|
||||
updatedAt: json['updated_at'] != null ? DateTime.parse(json['updated_at']?.toString() ?? '') : null,
|
||||
lastReminderSent: json['last_reminder_sent'] != null ? DateTime.parse(json['last_reminder_sent']?.toString() ?? '') : null,
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'invoice_id': invoiceId,
|
||||
'invoice_number': invoiceNumber,
|
||||
'user_id': userId,
|
||||
'order_id': orderId,
|
||||
'invoice_type': invoiceType.name,
|
||||
'issue_date': issueDate.toIso8601String(),
|
||||
'due_date': dueDate.toIso8601String(),
|
||||
'currency': currency,
|
||||
'subtotal_amount': subtotalAmount,
|
||||
'tax_amount': taxAmount,
|
||||
'discount_amount': discountAmount,
|
||||
'shipping_amount': shippingAmount,
|
||||
'total_amount': totalAmount,
|
||||
'amount_paid': amountPaid,
|
||||
'amount_remaining': amountRemaining,
|
||||
'status': status.name,
|
||||
'payment_terms': paymentTerms,
|
||||
'notes': notes,
|
||||
'erpnext_invoice': erpnextInvoice,
|
||||
'created_at': createdAt.toIso8601String(),
|
||||
'updated_at': updatedAt?.toIso8601String(),
|
||||
'last_reminder_sent': lastReminderSent?.toIso8601String(),
|
||||
};
|
||||
|
||||
bool get isOverdue => DateTime.now().isAfter(dueDate) && status != InvoiceStatus.paid;
|
||||
bool get isPaid => status == InvoiceStatus.paid;
|
||||
}
|
||||
104
lib/features/orders/data/models/invoice_model.g.dart
Normal file
104
lib/features/orders/data/models/invoice_model.g.dart
Normal file
@@ -0,0 +1,104 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'invoice_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class InvoiceModelAdapter extends TypeAdapter<InvoiceModel> {
|
||||
@override
|
||||
final typeId = 8;
|
||||
|
||||
@override
|
||||
InvoiceModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return InvoiceModel(
|
||||
invoiceId: fields[0] as String,
|
||||
invoiceNumber: fields[1] as String,
|
||||
userId: fields[2] as String,
|
||||
orderId: fields[3] as String?,
|
||||
invoiceType: fields[4] as InvoiceType,
|
||||
issueDate: fields[5] as DateTime,
|
||||
dueDate: fields[6] as DateTime,
|
||||
currency: fields[7] as String,
|
||||
subtotalAmount: (fields[8] as num).toDouble(),
|
||||
taxAmount: (fields[9] as num).toDouble(),
|
||||
discountAmount: (fields[10] as num).toDouble(),
|
||||
shippingAmount: (fields[11] as num).toDouble(),
|
||||
totalAmount: (fields[12] as num).toDouble(),
|
||||
amountPaid: (fields[13] as num).toDouble(),
|
||||
amountRemaining: (fields[14] as num).toDouble(),
|
||||
status: fields[15] as InvoiceStatus,
|
||||
paymentTerms: fields[16] as String?,
|
||||
notes: fields[17] as String?,
|
||||
erpnextInvoice: fields[18] as String?,
|
||||
createdAt: fields[19] as DateTime,
|
||||
updatedAt: fields[20] as DateTime?,
|
||||
lastReminderSent: fields[21] as DateTime?,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, InvoiceModel obj) {
|
||||
writer
|
||||
..writeByte(22)
|
||||
..writeByte(0)
|
||||
..write(obj.invoiceId)
|
||||
..writeByte(1)
|
||||
..write(obj.invoiceNumber)
|
||||
..writeByte(2)
|
||||
..write(obj.userId)
|
||||
..writeByte(3)
|
||||
..write(obj.orderId)
|
||||
..writeByte(4)
|
||||
..write(obj.invoiceType)
|
||||
..writeByte(5)
|
||||
..write(obj.issueDate)
|
||||
..writeByte(6)
|
||||
..write(obj.dueDate)
|
||||
..writeByte(7)
|
||||
..write(obj.currency)
|
||||
..writeByte(8)
|
||||
..write(obj.subtotalAmount)
|
||||
..writeByte(9)
|
||||
..write(obj.taxAmount)
|
||||
..writeByte(10)
|
||||
..write(obj.discountAmount)
|
||||
..writeByte(11)
|
||||
..write(obj.shippingAmount)
|
||||
..writeByte(12)
|
||||
..write(obj.totalAmount)
|
||||
..writeByte(13)
|
||||
..write(obj.amountPaid)
|
||||
..writeByte(14)
|
||||
..write(obj.amountRemaining)
|
||||
..writeByte(15)
|
||||
..write(obj.status)
|
||||
..writeByte(16)
|
||||
..write(obj.paymentTerms)
|
||||
..writeByte(17)
|
||||
..write(obj.notes)
|
||||
..writeByte(18)
|
||||
..write(obj.erpnextInvoice)
|
||||
..writeByte(19)
|
||||
..write(obj.createdAt)
|
||||
..writeByte(20)
|
||||
..write(obj.updatedAt)
|
||||
..writeByte(21)
|
||||
..write(obj.lastReminderSent);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is InvoiceModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
40
lib/features/orders/data/models/order_item_model.dart
Normal file
40
lib/features/orders/data/models/order_item_model.dart
Normal file
@@ -0,0 +1,40 @@
|
||||
import 'package:hive_ce/hive.dart';
|
||||
import 'package:worker/core/constants/storage_constants.dart';
|
||||
|
||||
part 'order_item_model.g.dart';
|
||||
|
||||
@HiveType(typeId: HiveTypeIds.orderItemModel)
|
||||
class OrderItemModel extends HiveObject {
|
||||
OrderItemModel({required this.orderItemId, required this.orderId, required this.productId, required this.quantity, required this.unitPrice, required this.discountPercent, required this.subtotal, this.notes});
|
||||
|
||||
@HiveField(0) final String orderItemId;
|
||||
@HiveField(1) final String orderId;
|
||||
@HiveField(2) final String productId;
|
||||
@HiveField(3) final double quantity;
|
||||
@HiveField(4) final double unitPrice;
|
||||
@HiveField(5) final double discountPercent;
|
||||
@HiveField(6) final double subtotal;
|
||||
@HiveField(7) final String? notes;
|
||||
|
||||
factory OrderItemModel.fromJson(Map<String, dynamic> json) => OrderItemModel(
|
||||
orderItemId: json['order_item_id'] as String,
|
||||
orderId: json['order_id'] as String,
|
||||
productId: json['product_id'] as String,
|
||||
quantity: (json['quantity'] as num).toDouble(),
|
||||
unitPrice: (json['unit_price'] as num).toDouble(),
|
||||
discountPercent: (json['discount_percent'] as num).toDouble(),
|
||||
subtotal: (json['subtotal'] as num).toDouble(),
|
||||
notes: json['notes'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'order_item_id': orderItemId,
|
||||
'order_id': orderId,
|
||||
'product_id': productId,
|
||||
'quantity': quantity,
|
||||
'unit_price': unitPrice,
|
||||
'discount_percent': discountPercent,
|
||||
'subtotal': subtotal,
|
||||
'notes': notes,
|
||||
};
|
||||
}
|
||||
62
lib/features/orders/data/models/order_item_model.g.dart
Normal file
62
lib/features/orders/data/models/order_item_model.g.dart
Normal file
@@ -0,0 +1,62 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'order_item_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class OrderItemModelAdapter extends TypeAdapter<OrderItemModel> {
|
||||
@override
|
||||
final typeId = 7;
|
||||
|
||||
@override
|
||||
OrderItemModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return OrderItemModel(
|
||||
orderItemId: fields[0] as String,
|
||||
orderId: fields[1] as String,
|
||||
productId: fields[2] as String,
|
||||
quantity: (fields[3] as num).toDouble(),
|
||||
unitPrice: (fields[4] as num).toDouble(),
|
||||
discountPercent: (fields[5] as num).toDouble(),
|
||||
subtotal: (fields[6] as num).toDouble(),
|
||||
notes: fields[7] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, OrderItemModel obj) {
|
||||
writer
|
||||
..writeByte(8)
|
||||
..writeByte(0)
|
||||
..write(obj.orderItemId)
|
||||
..writeByte(1)
|
||||
..write(obj.orderId)
|
||||
..writeByte(2)
|
||||
..write(obj.productId)
|
||||
..writeByte(3)
|
||||
..write(obj.quantity)
|
||||
..writeByte(4)
|
||||
..write(obj.unitPrice)
|
||||
..writeByte(5)
|
||||
..write(obj.discountPercent)
|
||||
..writeByte(6)
|
||||
..write(obj.subtotal)
|
||||
..writeByte(7)
|
||||
..write(obj.notes);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is OrderItemModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
147
lib/features/orders/data/models/order_model.dart
Normal file
147
lib/features/orders/data/models/order_model.dart
Normal file
@@ -0,0 +1,147 @@
|
||||
import 'dart:convert';
|
||||
import 'package:hive_ce/hive.dart';
|
||||
import 'package:worker/core/constants/storage_constants.dart';
|
||||
import 'package:worker/core/database/models/enums.dart';
|
||||
|
||||
part 'order_model.g.dart';
|
||||
|
||||
/// Order Model - Type ID: 6
|
||||
@HiveType(typeId: HiveTypeIds.orderModel)
|
||||
class OrderModel extends HiveObject {
|
||||
OrderModel({
|
||||
required this.orderId,
|
||||
required this.orderNumber,
|
||||
required this.userId,
|
||||
required this.status,
|
||||
required this.totalAmount,
|
||||
required this.discountAmount,
|
||||
required this.taxAmount,
|
||||
required this.shippingFee,
|
||||
required this.finalAmount,
|
||||
this.shippingAddress,
|
||||
this.billingAddress,
|
||||
this.expectedDeliveryDate,
|
||||
this.actualDeliveryDate,
|
||||
this.notes,
|
||||
this.cancellationReason,
|
||||
this.erpnextSalesOrder,
|
||||
required this.createdAt,
|
||||
this.updatedAt,
|
||||
});
|
||||
|
||||
@HiveField(0)
|
||||
final String orderId;
|
||||
|
||||
@HiveField(1)
|
||||
final String orderNumber;
|
||||
|
||||
@HiveField(2)
|
||||
final String userId;
|
||||
|
||||
@HiveField(3)
|
||||
final OrderStatus status;
|
||||
|
||||
@HiveField(4)
|
||||
final double totalAmount;
|
||||
|
||||
@HiveField(5)
|
||||
final double discountAmount;
|
||||
|
||||
@HiveField(6)
|
||||
final double taxAmount;
|
||||
|
||||
@HiveField(7)
|
||||
final double shippingFee;
|
||||
|
||||
@HiveField(8)
|
||||
final double finalAmount;
|
||||
|
||||
@HiveField(9)
|
||||
final String? shippingAddress;
|
||||
|
||||
@HiveField(10)
|
||||
final String? billingAddress;
|
||||
|
||||
@HiveField(11)
|
||||
final DateTime? expectedDeliveryDate;
|
||||
|
||||
@HiveField(12)
|
||||
final DateTime? actualDeliveryDate;
|
||||
|
||||
@HiveField(13)
|
||||
final String? notes;
|
||||
|
||||
@HiveField(14)
|
||||
final String? cancellationReason;
|
||||
|
||||
@HiveField(15)
|
||||
final String? erpnextSalesOrder;
|
||||
|
||||
@HiveField(16)
|
||||
final DateTime createdAt;
|
||||
|
||||
@HiveField(17)
|
||||
final DateTime? updatedAt;
|
||||
|
||||
factory OrderModel.fromJson(Map<String, dynamic> json) {
|
||||
return OrderModel(
|
||||
orderId: json['order_id'] as String,
|
||||
orderNumber: json['order_number'] as String,
|
||||
userId: json['user_id'] as String,
|
||||
status: OrderStatus.values.firstWhere((e) => e.name == json['status']),
|
||||
totalAmount: (json['total_amount'] as num).toDouble(),
|
||||
discountAmount: (json['discount_amount'] as num).toDouble(),
|
||||
taxAmount: (json['tax_amount'] as num).toDouble(),
|
||||
shippingFee: (json['shipping_fee'] as num).toDouble(),
|
||||
finalAmount: (json['final_amount'] as num).toDouble(),
|
||||
shippingAddress: json['shipping_address'] != null ? jsonEncode(json['shipping_address']) : null,
|
||||
billingAddress: json['billing_address'] != null ? jsonEncode(json['billing_address']) : null,
|
||||
expectedDeliveryDate: json['expected_delivery_date'] != null ? DateTime.parse(json['expected_delivery_date']?.toString() ?? '') : null,
|
||||
actualDeliveryDate: json['actual_delivery_date'] != null ? DateTime.parse(json['actual_delivery_date']?.toString() ?? '') : null,
|
||||
notes: json['notes'] as String?,
|
||||
cancellationReason: json['cancellation_reason'] as String?,
|
||||
erpnextSalesOrder: json['erpnext_sales_order'] as String?,
|
||||
createdAt: DateTime.parse(json['created_at']?.toString() ?? ''),
|
||||
updatedAt: json['updated_at'] != null ? DateTime.parse(json['updated_at']?.toString() ?? '') : null,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'order_id': orderId,
|
||||
'order_number': orderNumber,
|
||||
'user_id': userId,
|
||||
'status': status.name,
|
||||
'total_amount': totalAmount,
|
||||
'discount_amount': discountAmount,
|
||||
'tax_amount': taxAmount,
|
||||
'shipping_fee': shippingFee,
|
||||
'final_amount': finalAmount,
|
||||
'shipping_address': shippingAddress != null ? jsonDecode(shippingAddress!) : null,
|
||||
'billing_address': billingAddress != null ? jsonDecode(billingAddress!) : null,
|
||||
'expected_delivery_date': expectedDeliveryDate?.toIso8601String(),
|
||||
'actual_delivery_date': actualDeliveryDate?.toIso8601String(),
|
||||
'notes': notes,
|
||||
'cancellation_reason': cancellationReason,
|
||||
'erpnext_sales_order': erpnextSalesOrder,
|
||||
'created_at': createdAt.toIso8601String(),
|
||||
'updated_at': updatedAt?.toIso8601String(),
|
||||
};
|
||||
|
||||
Map<String, dynamic>? get shippingAddressMap {
|
||||
if (shippingAddress == null) return null;
|
||||
try {
|
||||
return jsonDecode(shippingAddress!) as Map<String, dynamic>;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic>? get billingAddressMap {
|
||||
if (billingAddress == null) return null;
|
||||
try {
|
||||
return jsonDecode(billingAddress!) as Map<String, dynamic>;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
92
lib/features/orders/data/models/order_model.g.dart
Normal file
92
lib/features/orders/data/models/order_model.g.dart
Normal file
@@ -0,0 +1,92 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'order_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class OrderModelAdapter extends TypeAdapter<OrderModel> {
|
||||
@override
|
||||
final typeId = 6;
|
||||
|
||||
@override
|
||||
OrderModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return OrderModel(
|
||||
orderId: fields[0] as String,
|
||||
orderNumber: fields[1] as String,
|
||||
userId: fields[2] as String,
|
||||
status: fields[3] as OrderStatus,
|
||||
totalAmount: (fields[4] as num).toDouble(),
|
||||
discountAmount: (fields[5] as num).toDouble(),
|
||||
taxAmount: (fields[6] as num).toDouble(),
|
||||
shippingFee: (fields[7] as num).toDouble(),
|
||||
finalAmount: (fields[8] as num).toDouble(),
|
||||
shippingAddress: fields[9] as String?,
|
||||
billingAddress: fields[10] as String?,
|
||||
expectedDeliveryDate: fields[11] as DateTime?,
|
||||
actualDeliveryDate: fields[12] as DateTime?,
|
||||
notes: fields[13] as String?,
|
||||
cancellationReason: fields[14] as String?,
|
||||
erpnextSalesOrder: fields[15] as String?,
|
||||
createdAt: fields[16] as DateTime,
|
||||
updatedAt: fields[17] as DateTime?,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, OrderModel obj) {
|
||||
writer
|
||||
..writeByte(18)
|
||||
..writeByte(0)
|
||||
..write(obj.orderId)
|
||||
..writeByte(1)
|
||||
..write(obj.orderNumber)
|
||||
..writeByte(2)
|
||||
..write(obj.userId)
|
||||
..writeByte(3)
|
||||
..write(obj.status)
|
||||
..writeByte(4)
|
||||
..write(obj.totalAmount)
|
||||
..writeByte(5)
|
||||
..write(obj.discountAmount)
|
||||
..writeByte(6)
|
||||
..write(obj.taxAmount)
|
||||
..writeByte(7)
|
||||
..write(obj.shippingFee)
|
||||
..writeByte(8)
|
||||
..write(obj.finalAmount)
|
||||
..writeByte(9)
|
||||
..write(obj.shippingAddress)
|
||||
..writeByte(10)
|
||||
..write(obj.billingAddress)
|
||||
..writeByte(11)
|
||||
..write(obj.expectedDeliveryDate)
|
||||
..writeByte(12)
|
||||
..write(obj.actualDeliveryDate)
|
||||
..writeByte(13)
|
||||
..write(obj.notes)
|
||||
..writeByte(14)
|
||||
..write(obj.cancellationReason)
|
||||
..writeByte(15)
|
||||
..write(obj.erpnextSalesOrder)
|
||||
..writeByte(16)
|
||||
..write(obj.createdAt)
|
||||
..writeByte(17)
|
||||
..write(obj.updatedAt);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is OrderModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
62
lib/features/orders/data/models/payment_line_model.dart
Normal file
62
lib/features/orders/data/models/payment_line_model.dart
Normal file
@@ -0,0 +1,62 @@
|
||||
import 'package:hive_ce/hive.dart';
|
||||
import 'package:worker/core/constants/storage_constants.dart';
|
||||
import 'package:worker/core/database/models/enums.dart';
|
||||
|
||||
part 'payment_line_model.g.dart';
|
||||
|
||||
@HiveType(typeId: HiveTypeIds.paymentLineModel)
|
||||
class PaymentLineModel extends HiveObject {
|
||||
PaymentLineModel({required this.paymentLineId, required this.invoiceId, required this.paymentNumber, required this.paymentDate, required this.amount, required this.paymentMethod, this.bankName, this.bankAccount, this.referenceNumber, this.notes, required this.status, this.receiptUrl, this.erpnextPaymentEntry, required this.createdAt, this.processedAt});
|
||||
|
||||
@HiveField(0) final String paymentLineId;
|
||||
@HiveField(1) final String invoiceId;
|
||||
@HiveField(2) final String paymentNumber;
|
||||
@HiveField(3) final DateTime paymentDate;
|
||||
@HiveField(4) final double amount;
|
||||
@HiveField(5) final PaymentMethod paymentMethod;
|
||||
@HiveField(6) final String? bankName;
|
||||
@HiveField(7) final String? bankAccount;
|
||||
@HiveField(8) final String? referenceNumber;
|
||||
@HiveField(9) final String? notes;
|
||||
@HiveField(10) final PaymentStatus status;
|
||||
@HiveField(11) final String? receiptUrl;
|
||||
@HiveField(12) final String? erpnextPaymentEntry;
|
||||
@HiveField(13) final DateTime createdAt;
|
||||
@HiveField(14) final DateTime? processedAt;
|
||||
|
||||
factory PaymentLineModel.fromJson(Map<String, dynamic> json) => PaymentLineModel(
|
||||
paymentLineId: json['payment_line_id'] as String,
|
||||
invoiceId: json['invoice_id'] as String,
|
||||
paymentNumber: json['payment_number'] as String,
|
||||
paymentDate: DateTime.parse(json['payment_date']?.toString() ?? ''),
|
||||
amount: (json['amount'] as num).toDouble(),
|
||||
paymentMethod: PaymentMethod.values.firstWhere((e) => e.name == json['payment_method']),
|
||||
bankName: json['bank_name'] as String?,
|
||||
bankAccount: json['bank_account'] as String?,
|
||||
referenceNumber: json['reference_number'] as String?,
|
||||
notes: json['notes'] as String?,
|
||||
status: PaymentStatus.values.firstWhere((e) => e.name == json['status']),
|
||||
receiptUrl: json['receipt_url'] as String?,
|
||||
erpnextPaymentEntry: json['erpnext_payment_entry'] as String?,
|
||||
createdAt: DateTime.parse(json['created_at']?.toString() ?? ''),
|
||||
processedAt: json['processed_at'] != null ? DateTime.parse(json['processed_at']?.toString() ?? '') : null,
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'payment_line_id': paymentLineId,
|
||||
'invoice_id': invoiceId,
|
||||
'payment_number': paymentNumber,
|
||||
'payment_date': paymentDate.toIso8601String(),
|
||||
'amount': amount,
|
||||
'payment_method': paymentMethod.name,
|
||||
'bank_name': bankName,
|
||||
'bank_account': bankAccount,
|
||||
'reference_number': referenceNumber,
|
||||
'notes': notes,
|
||||
'status': status.name,
|
||||
'receipt_url': receiptUrl,
|
||||
'erpnext_payment_entry': erpnextPaymentEntry,
|
||||
'created_at': createdAt.toIso8601String(),
|
||||
'processed_at': processedAt?.toIso8601String(),
|
||||
};
|
||||
}
|
||||
83
lib/features/orders/data/models/payment_line_model.g.dart
Normal file
83
lib/features/orders/data/models/payment_line_model.g.dart
Normal file
@@ -0,0 +1,83 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'payment_line_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class PaymentLineModelAdapter extends TypeAdapter<PaymentLineModel> {
|
||||
@override
|
||||
final typeId = 9;
|
||||
|
||||
@override
|
||||
PaymentLineModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return PaymentLineModel(
|
||||
paymentLineId: fields[0] as String,
|
||||
invoiceId: fields[1] as String,
|
||||
paymentNumber: fields[2] as String,
|
||||
paymentDate: fields[3] as DateTime,
|
||||
amount: (fields[4] as num).toDouble(),
|
||||
paymentMethod: fields[5] as PaymentMethod,
|
||||
bankName: fields[6] as String?,
|
||||
bankAccount: fields[7] as String?,
|
||||
referenceNumber: fields[8] as String?,
|
||||
notes: fields[9] as String?,
|
||||
status: fields[10] as PaymentStatus,
|
||||
receiptUrl: fields[11] as String?,
|
||||
erpnextPaymentEntry: fields[12] as String?,
|
||||
createdAt: fields[13] as DateTime,
|
||||
processedAt: fields[14] as DateTime?,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, PaymentLineModel obj) {
|
||||
writer
|
||||
..writeByte(15)
|
||||
..writeByte(0)
|
||||
..write(obj.paymentLineId)
|
||||
..writeByte(1)
|
||||
..write(obj.invoiceId)
|
||||
..writeByte(2)
|
||||
..write(obj.paymentNumber)
|
||||
..writeByte(3)
|
||||
..write(obj.paymentDate)
|
||||
..writeByte(4)
|
||||
..write(obj.amount)
|
||||
..writeByte(5)
|
||||
..write(obj.paymentMethod)
|
||||
..writeByte(6)
|
||||
..write(obj.bankName)
|
||||
..writeByte(7)
|
||||
..write(obj.bankAccount)
|
||||
..writeByte(8)
|
||||
..write(obj.referenceNumber)
|
||||
..writeByte(9)
|
||||
..write(obj.notes)
|
||||
..writeByte(10)
|
||||
..write(obj.status)
|
||||
..writeByte(11)
|
||||
..write(obj.receiptUrl)
|
||||
..writeByte(12)
|
||||
..write(obj.erpnextPaymentEntry)
|
||||
..writeByte(13)
|
||||
..write(obj.createdAt)
|
||||
..writeByte(14)
|
||||
..write(obj.processedAt);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is PaymentLineModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
273
lib/features/orders/domain/entities/invoice.dart
Normal file
273
lib/features/orders/domain/entities/invoice.dart
Normal file
@@ -0,0 +1,273 @@
|
||||
/// Domain Entity: Invoice
|
||||
///
|
||||
/// Represents an invoice for an order.
|
||||
library;
|
||||
|
||||
/// Invoice type enum
|
||||
enum InvoiceType {
|
||||
/// Standard invoice
|
||||
standard,
|
||||
|
||||
/// Proforma invoice
|
||||
proforma,
|
||||
|
||||
/// Credit note
|
||||
creditNote,
|
||||
|
||||
/// Debit note
|
||||
debitNote;
|
||||
}
|
||||
|
||||
/// Invoice status enum
|
||||
enum InvoiceStatus {
|
||||
/// Draft invoice
|
||||
draft,
|
||||
|
||||
/// Invoice has been submitted
|
||||
submitted,
|
||||
|
||||
/// Partially paid
|
||||
partiallyPaid,
|
||||
|
||||
/// Fully paid
|
||||
paid,
|
||||
|
||||
/// Overdue invoice
|
||||
overdue,
|
||||
|
||||
/// Cancelled invoice
|
||||
cancelled;
|
||||
|
||||
/// Get display name for status
|
||||
String get displayName {
|
||||
switch (this) {
|
||||
case InvoiceStatus.draft:
|
||||
return 'Draft';
|
||||
case InvoiceStatus.submitted:
|
||||
return 'Submitted';
|
||||
case InvoiceStatus.partiallyPaid:
|
||||
return 'Partially Paid';
|
||||
case InvoiceStatus.paid:
|
||||
return 'Paid';
|
||||
case InvoiceStatus.overdue:
|
||||
return 'Overdue';
|
||||
case InvoiceStatus.cancelled:
|
||||
return 'Cancelled';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Invoice Entity
|
||||
///
|
||||
/// Contains complete invoice information:
|
||||
/// - Invoice identification
|
||||
/// - Associated order
|
||||
/// - Amounts and calculations
|
||||
/// - Payment tracking
|
||||
/// - Status and dates
|
||||
class Invoice {
|
||||
/// Unique invoice identifier
|
||||
final String invoiceId;
|
||||
|
||||
/// Invoice number (human-readable)
|
||||
final String invoiceNumber;
|
||||
|
||||
/// User ID
|
||||
final String userId;
|
||||
|
||||
/// Order ID
|
||||
final String? orderId;
|
||||
|
||||
/// Invoice type
|
||||
final InvoiceType invoiceType;
|
||||
|
||||
/// Issue date
|
||||
final DateTime issueDate;
|
||||
|
||||
/// Due date
|
||||
final DateTime dueDate;
|
||||
|
||||
/// Currency code (e.g., VND, USD)
|
||||
final String currency;
|
||||
|
||||
/// Subtotal amount
|
||||
final double subtotalAmount;
|
||||
|
||||
/// Tax amount
|
||||
final double taxAmount;
|
||||
|
||||
/// Discount amount
|
||||
final double discountAmount;
|
||||
|
||||
/// Shipping amount
|
||||
final double shippingAmount;
|
||||
|
||||
/// Total amount
|
||||
final double totalAmount;
|
||||
|
||||
/// Amount paid so far
|
||||
final double amountPaid;
|
||||
|
||||
/// Amount remaining to be paid
|
||||
final double amountRemaining;
|
||||
|
||||
/// Invoice status
|
||||
final InvoiceStatus status;
|
||||
|
||||
/// Payment terms
|
||||
final String? paymentTerms;
|
||||
|
||||
/// Invoice notes
|
||||
final String? notes;
|
||||
|
||||
/// ERPNext invoice reference
|
||||
final String? erpnextInvoice;
|
||||
|
||||
/// Creation timestamp
|
||||
final DateTime createdAt;
|
||||
|
||||
/// Last update timestamp
|
||||
final DateTime updatedAt;
|
||||
|
||||
/// Last reminder sent timestamp
|
||||
final DateTime? lastReminderSent;
|
||||
|
||||
const Invoice({
|
||||
required this.invoiceId,
|
||||
required this.invoiceNumber,
|
||||
required this.userId,
|
||||
this.orderId,
|
||||
required this.invoiceType,
|
||||
required this.issueDate,
|
||||
required this.dueDate,
|
||||
required this.currency,
|
||||
required this.subtotalAmount,
|
||||
required this.taxAmount,
|
||||
required this.discountAmount,
|
||||
required this.shippingAmount,
|
||||
required this.totalAmount,
|
||||
required this.amountPaid,
|
||||
required this.amountRemaining,
|
||||
required this.status,
|
||||
this.paymentTerms,
|
||||
this.notes,
|
||||
this.erpnextInvoice,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
this.lastReminderSent,
|
||||
});
|
||||
|
||||
/// Check if invoice is fully paid
|
||||
bool get isPaid => status == InvoiceStatus.paid || amountRemaining <= 0;
|
||||
|
||||
/// Check if invoice is overdue
|
||||
bool get isOverdue =>
|
||||
status == InvoiceStatus.overdue ||
|
||||
(!isPaid && DateTime.now().isAfter(dueDate));
|
||||
|
||||
/// Check if invoice is partially paid
|
||||
bool get isPartiallyPaid =>
|
||||
amountPaid > 0 && amountPaid < totalAmount;
|
||||
|
||||
/// Get payment percentage
|
||||
double get paymentPercentage {
|
||||
if (totalAmount == 0) return 0;
|
||||
return (amountPaid / totalAmount) * 100;
|
||||
}
|
||||
|
||||
/// Get days until due
|
||||
int get daysUntilDue => dueDate.difference(DateTime.now()).inDays;
|
||||
|
||||
/// Get days overdue
|
||||
int get daysOverdue {
|
||||
if (!isOverdue) return 0;
|
||||
return DateTime.now().difference(dueDate).inDays;
|
||||
}
|
||||
|
||||
/// Copy with method for immutability
|
||||
Invoice copyWith({
|
||||
String? invoiceId,
|
||||
String? invoiceNumber,
|
||||
String? userId,
|
||||
String? orderId,
|
||||
InvoiceType? invoiceType,
|
||||
DateTime? issueDate,
|
||||
DateTime? dueDate,
|
||||
String? currency,
|
||||
double? subtotalAmount,
|
||||
double? taxAmount,
|
||||
double? discountAmount,
|
||||
double? shippingAmount,
|
||||
double? totalAmount,
|
||||
double? amountPaid,
|
||||
double? amountRemaining,
|
||||
InvoiceStatus? status,
|
||||
String? paymentTerms,
|
||||
String? notes,
|
||||
String? erpnextInvoice,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
DateTime? lastReminderSent,
|
||||
}) {
|
||||
return Invoice(
|
||||
invoiceId: invoiceId ?? this.invoiceId,
|
||||
invoiceNumber: invoiceNumber ?? this.invoiceNumber,
|
||||
userId: userId ?? this.userId,
|
||||
orderId: orderId ?? this.orderId,
|
||||
invoiceType: invoiceType ?? this.invoiceType,
|
||||
issueDate: issueDate ?? this.issueDate,
|
||||
dueDate: dueDate ?? this.dueDate,
|
||||
currency: currency ?? this.currency,
|
||||
subtotalAmount: subtotalAmount ?? this.subtotalAmount,
|
||||
taxAmount: taxAmount ?? this.taxAmount,
|
||||
discountAmount: discountAmount ?? this.discountAmount,
|
||||
shippingAmount: shippingAmount ?? this.shippingAmount,
|
||||
totalAmount: totalAmount ?? this.totalAmount,
|
||||
amountPaid: amountPaid ?? this.amountPaid,
|
||||
amountRemaining: amountRemaining ?? this.amountRemaining,
|
||||
status: status ?? this.status,
|
||||
paymentTerms: paymentTerms ?? this.paymentTerms,
|
||||
notes: notes ?? this.notes,
|
||||
erpnextInvoice: erpnextInvoice ?? this.erpnextInvoice,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
lastReminderSent: lastReminderSent ?? this.lastReminderSent,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other is Invoice &&
|
||||
other.invoiceId == invoiceId &&
|
||||
other.invoiceNumber == invoiceNumber &&
|
||||
other.userId == userId &&
|
||||
other.orderId == orderId &&
|
||||
other.invoiceType == invoiceType &&
|
||||
other.totalAmount == totalAmount &&
|
||||
other.amountPaid == amountPaid &&
|
||||
other.status == status;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return Object.hash(
|
||||
invoiceId,
|
||||
invoiceNumber,
|
||||
userId,
|
||||
orderId,
|
||||
invoiceType,
|
||||
totalAmount,
|
||||
amountPaid,
|
||||
status,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Invoice(invoiceId: $invoiceId, invoiceNumber: $invoiceNumber, '
|
||||
'status: $status, totalAmount: $totalAmount, amountPaid: $amountPaid, '
|
||||
'amountRemaining: $amountRemaining)';
|
||||
}
|
||||
}
|
||||
321
lib/features/orders/domain/entities/order.dart
Normal file
321
lib/features/orders/domain/entities/order.dart
Normal file
@@ -0,0 +1,321 @@
|
||||
/// Domain Entity: Order
|
||||
///
|
||||
/// Represents a customer order.
|
||||
library;
|
||||
|
||||
/// Order status enum
|
||||
enum OrderStatus {
|
||||
/// Order has been created but not confirmed
|
||||
draft,
|
||||
|
||||
/// Order has been confirmed
|
||||
confirmed,
|
||||
|
||||
/// Order is being processed
|
||||
processing,
|
||||
|
||||
/// Order is ready for shipping
|
||||
ready,
|
||||
|
||||
/// Order has been shipped
|
||||
shipped,
|
||||
|
||||
/// Order has been delivered
|
||||
delivered,
|
||||
|
||||
/// Order has been completed
|
||||
completed,
|
||||
|
||||
/// Order has been cancelled
|
||||
cancelled,
|
||||
|
||||
/// Order has been returned
|
||||
returned;
|
||||
|
||||
/// Get display name for status
|
||||
String get displayName {
|
||||
switch (this) {
|
||||
case OrderStatus.draft:
|
||||
return 'Draft';
|
||||
case OrderStatus.confirmed:
|
||||
return 'Confirmed';
|
||||
case OrderStatus.processing:
|
||||
return 'Processing';
|
||||
case OrderStatus.ready:
|
||||
return 'Ready';
|
||||
case OrderStatus.shipped:
|
||||
return 'Shipped';
|
||||
case OrderStatus.delivered:
|
||||
return 'Delivered';
|
||||
case OrderStatus.completed:
|
||||
return 'Completed';
|
||||
case OrderStatus.cancelled:
|
||||
return 'Cancelled';
|
||||
case OrderStatus.returned:
|
||||
return 'Returned';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Address information
|
||||
class Address {
|
||||
/// Recipient name
|
||||
final String? name;
|
||||
|
||||
/// Phone number
|
||||
final String? phone;
|
||||
|
||||
/// Street address
|
||||
final String? street;
|
||||
|
||||
/// Ward/commune
|
||||
final String? ward;
|
||||
|
||||
/// District
|
||||
final String? district;
|
||||
|
||||
/// City/province
|
||||
final String? city;
|
||||
|
||||
/// Postal code
|
||||
final String? postalCode;
|
||||
|
||||
const Address({
|
||||
this.name,
|
||||
this.phone,
|
||||
this.street,
|
||||
this.ward,
|
||||
this.district,
|
||||
this.city,
|
||||
this.postalCode,
|
||||
});
|
||||
|
||||
/// Get full address string
|
||||
String get fullAddress {
|
||||
final parts = [
|
||||
street,
|
||||
ward,
|
||||
district,
|
||||
city,
|
||||
postalCode,
|
||||
].where((part) => part != null && part.isNotEmpty).toList();
|
||||
|
||||
return parts.join(', ');
|
||||
}
|
||||
|
||||
/// Create from JSON map
|
||||
factory Address.fromJson(Map<String, dynamic> json) {
|
||||
return Address(
|
||||
name: json['name'] as String?,
|
||||
phone: json['phone'] as String?,
|
||||
street: json['street'] as String?,
|
||||
ward: json['ward'] as String?,
|
||||
district: json['district'] as String?,
|
||||
city: json['city'] as String?,
|
||||
postalCode: json['postal_code'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
/// Convert to JSON map
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'name': name,
|
||||
'phone': phone,
|
||||
'street': street,
|
||||
'ward': ward,
|
||||
'district': district,
|
||||
'city': city,
|
||||
'postal_code': postalCode,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Order Entity
|
||||
///
|
||||
/// Contains complete order information:
|
||||
/// - Order identification
|
||||
/// - Customer details
|
||||
/// - Pricing and discounts
|
||||
/// - Shipping information
|
||||
/// - Status tracking
|
||||
class Order {
|
||||
/// Unique order identifier
|
||||
final String orderId;
|
||||
|
||||
/// Human-readable order number
|
||||
final String orderNumber;
|
||||
|
||||
/// User ID who placed the order
|
||||
final String userId;
|
||||
|
||||
/// Current order status
|
||||
final OrderStatus status;
|
||||
|
||||
/// Total order amount before discounts
|
||||
final double totalAmount;
|
||||
|
||||
/// Discount amount applied
|
||||
final double discountAmount;
|
||||
|
||||
/// Tax amount
|
||||
final double taxAmount;
|
||||
|
||||
/// Shipping fee
|
||||
final double shippingFee;
|
||||
|
||||
/// Final amount to pay
|
||||
final double finalAmount;
|
||||
|
||||
/// Shipping address
|
||||
final Address? shippingAddress;
|
||||
|
||||
/// Billing address
|
||||
final Address? billingAddress;
|
||||
|
||||
/// Expected delivery date
|
||||
final DateTime? expectedDeliveryDate;
|
||||
|
||||
/// Actual delivery date
|
||||
final DateTime? actualDeliveryDate;
|
||||
|
||||
/// Order notes
|
||||
final String? notes;
|
||||
|
||||
/// Cancellation reason
|
||||
final String? cancellationReason;
|
||||
|
||||
/// ERPNext sales order reference
|
||||
final String? erpnextSalesOrder;
|
||||
|
||||
/// Order creation timestamp
|
||||
final DateTime createdAt;
|
||||
|
||||
/// Last update timestamp
|
||||
final DateTime updatedAt;
|
||||
|
||||
const Order({
|
||||
required this.orderId,
|
||||
required this.orderNumber,
|
||||
required this.userId,
|
||||
required this.status,
|
||||
required this.totalAmount,
|
||||
required this.discountAmount,
|
||||
required this.taxAmount,
|
||||
required this.shippingFee,
|
||||
required this.finalAmount,
|
||||
this.shippingAddress,
|
||||
this.billingAddress,
|
||||
this.expectedDeliveryDate,
|
||||
this.actualDeliveryDate,
|
||||
this.notes,
|
||||
this.cancellationReason,
|
||||
this.erpnextSalesOrder,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
});
|
||||
|
||||
/// Check if order is active (not cancelled or completed)
|
||||
bool get isActive =>
|
||||
status != OrderStatus.cancelled &&
|
||||
status != OrderStatus.completed &&
|
||||
status != OrderStatus.returned;
|
||||
|
||||
/// Check if order can be cancelled
|
||||
bool get canBeCancelled =>
|
||||
status == OrderStatus.draft ||
|
||||
status == OrderStatus.confirmed ||
|
||||
status == OrderStatus.processing;
|
||||
|
||||
/// Check if order is delivered
|
||||
bool get isDelivered =>
|
||||
status == OrderStatus.delivered || status == OrderStatus.completed;
|
||||
|
||||
/// Check if order is cancelled
|
||||
bool get isCancelled => status == OrderStatus.cancelled;
|
||||
|
||||
/// Get discount percentage
|
||||
double get discountPercentage {
|
||||
if (totalAmount == 0) return 0;
|
||||
return (discountAmount / totalAmount) * 100;
|
||||
}
|
||||
|
||||
/// Copy with method for immutability
|
||||
Order copyWith({
|
||||
String? orderId,
|
||||
String? orderNumber,
|
||||
String? userId,
|
||||
OrderStatus? status,
|
||||
double? totalAmount,
|
||||
double? discountAmount,
|
||||
double? taxAmount,
|
||||
double? shippingFee,
|
||||
double? finalAmount,
|
||||
Address? shippingAddress,
|
||||
Address? billingAddress,
|
||||
DateTime? expectedDeliveryDate,
|
||||
DateTime? actualDeliveryDate,
|
||||
String? notes,
|
||||
String? cancellationReason,
|
||||
String? erpnextSalesOrder,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
}) {
|
||||
return Order(
|
||||
orderId: orderId ?? this.orderId,
|
||||
orderNumber: orderNumber ?? this.orderNumber,
|
||||
userId: userId ?? this.userId,
|
||||
status: status ?? this.status,
|
||||
totalAmount: totalAmount ?? this.totalAmount,
|
||||
discountAmount: discountAmount ?? this.discountAmount,
|
||||
taxAmount: taxAmount ?? this.taxAmount,
|
||||
shippingFee: shippingFee ?? this.shippingFee,
|
||||
finalAmount: finalAmount ?? this.finalAmount,
|
||||
shippingAddress: shippingAddress ?? this.shippingAddress,
|
||||
billingAddress: billingAddress ?? this.billingAddress,
|
||||
expectedDeliveryDate: expectedDeliveryDate ?? this.expectedDeliveryDate,
|
||||
actualDeliveryDate: actualDeliveryDate ?? this.actualDeliveryDate,
|
||||
notes: notes ?? this.notes,
|
||||
cancellationReason: cancellationReason ?? this.cancellationReason,
|
||||
erpnextSalesOrder: erpnextSalesOrder ?? this.erpnextSalesOrder,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other is Order &&
|
||||
other.orderId == orderId &&
|
||||
other.orderNumber == orderNumber &&
|
||||
other.userId == userId &&
|
||||
other.status == status &&
|
||||
other.totalAmount == totalAmount &&
|
||||
other.discountAmount == discountAmount &&
|
||||
other.taxAmount == taxAmount &&
|
||||
other.shippingFee == shippingFee &&
|
||||
other.finalAmount == finalAmount;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return Object.hash(
|
||||
orderId,
|
||||
orderNumber,
|
||||
userId,
|
||||
status,
|
||||
totalAmount,
|
||||
discountAmount,
|
||||
taxAmount,
|
||||
shippingFee,
|
||||
finalAmount,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Order(orderId: $orderId, orderNumber: $orderNumber, status: $status, '
|
||||
'finalAmount: $finalAmount, createdAt: $createdAt)';
|
||||
}
|
||||
}
|
||||
117
lib/features/orders/domain/entities/order_item.dart
Normal file
117
lib/features/orders/domain/entities/order_item.dart
Normal file
@@ -0,0 +1,117 @@
|
||||
/// Domain Entity: Order Item
|
||||
///
|
||||
/// Represents a single line item in an order.
|
||||
library;
|
||||
|
||||
/// Order Item Entity
|
||||
///
|
||||
/// Contains item-level information in an order:
|
||||
/// - Product reference
|
||||
/// - Quantity and pricing
|
||||
/// - Discounts
|
||||
/// - Notes
|
||||
class OrderItem {
|
||||
/// Unique order item identifier
|
||||
final String orderItemId;
|
||||
|
||||
/// Order ID this item belongs to
|
||||
final String orderId;
|
||||
|
||||
/// Product ID
|
||||
final String productId;
|
||||
|
||||
/// Quantity ordered
|
||||
final double quantity;
|
||||
|
||||
/// Unit price at time of order
|
||||
final double unitPrice;
|
||||
|
||||
/// Discount percentage applied
|
||||
final double discountPercent;
|
||||
|
||||
/// Subtotal (quantity * unitPrice * (1 - discountPercent/100))
|
||||
final double subtotal;
|
||||
|
||||
/// Item notes
|
||||
final String? notes;
|
||||
|
||||
const OrderItem({
|
||||
required this.orderItemId,
|
||||
required this.orderId,
|
||||
required this.productId,
|
||||
required this.quantity,
|
||||
required this.unitPrice,
|
||||
required this.discountPercent,
|
||||
required this.subtotal,
|
||||
this.notes,
|
||||
});
|
||||
|
||||
/// Calculate subtotal before discount
|
||||
double get subtotalBeforeDiscount => quantity * unitPrice;
|
||||
|
||||
/// Calculate discount amount
|
||||
double get discountAmount =>
|
||||
subtotalBeforeDiscount * (discountPercent / 100);
|
||||
|
||||
/// Calculate subtotal after discount (for verification)
|
||||
double get calculatedSubtotal => subtotalBeforeDiscount - discountAmount;
|
||||
|
||||
/// Check if item has discount
|
||||
bool get hasDiscount => discountPercent > 0;
|
||||
|
||||
/// Copy with method for immutability
|
||||
OrderItem copyWith({
|
||||
String? orderItemId,
|
||||
String? orderId,
|
||||
String? productId,
|
||||
double? quantity,
|
||||
double? unitPrice,
|
||||
double? discountPercent,
|
||||
double? subtotal,
|
||||
String? notes,
|
||||
}) {
|
||||
return OrderItem(
|
||||
orderItemId: orderItemId ?? this.orderItemId,
|
||||
orderId: orderId ?? this.orderId,
|
||||
productId: productId ?? this.productId,
|
||||
quantity: quantity ?? this.quantity,
|
||||
unitPrice: unitPrice ?? this.unitPrice,
|
||||
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 OrderItem &&
|
||||
other.orderItemId == orderItemId &&
|
||||
other.orderId == orderId &&
|
||||
other.productId == productId &&
|
||||
other.quantity == quantity &&
|
||||
other.unitPrice == unitPrice &&
|
||||
other.discountPercent == discountPercent &&
|
||||
other.subtotal == subtotal;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return Object.hash(
|
||||
orderItemId,
|
||||
orderId,
|
||||
productId,
|
||||
quantity,
|
||||
unitPrice,
|
||||
discountPercent,
|
||||
subtotal,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'OrderItem(orderItemId: $orderItemId, productId: $productId, '
|
||||
'quantity: $quantity, unitPrice: $unitPrice, subtotal: $subtotal)';
|
||||
}
|
||||
}
|
||||
237
lib/features/orders/domain/entities/payment_line.dart
Normal file
237
lib/features/orders/domain/entities/payment_line.dart
Normal file
@@ -0,0 +1,237 @@
|
||||
/// Domain Entity: Payment Line
|
||||
///
|
||||
/// Represents a payment transaction for an invoice.
|
||||
library;
|
||||
|
||||
/// Payment method enum
|
||||
enum PaymentMethod {
|
||||
/// Cash payment
|
||||
cash,
|
||||
|
||||
/// Bank transfer
|
||||
bankTransfer,
|
||||
|
||||
/// Credit card
|
||||
creditCard,
|
||||
|
||||
/// E-wallet (Momo, ZaloPay, etc.)
|
||||
ewallet,
|
||||
|
||||
/// Check
|
||||
check,
|
||||
|
||||
/// Other method
|
||||
other;
|
||||
|
||||
/// Get display name for payment method
|
||||
String get displayName {
|
||||
switch (this) {
|
||||
case PaymentMethod.cash:
|
||||
return 'Cash';
|
||||
case PaymentMethod.bankTransfer:
|
||||
return 'Bank Transfer';
|
||||
case PaymentMethod.creditCard:
|
||||
return 'Credit Card';
|
||||
case PaymentMethod.ewallet:
|
||||
return 'E-Wallet';
|
||||
case PaymentMethod.check:
|
||||
return 'Check';
|
||||
case PaymentMethod.other:
|
||||
return 'Other';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Payment status enum
|
||||
enum PaymentStatus {
|
||||
/// Payment pending
|
||||
pending,
|
||||
|
||||
/// Payment is being processed
|
||||
processing,
|
||||
|
||||
/// Payment completed successfully
|
||||
completed,
|
||||
|
||||
/// Payment failed
|
||||
failed,
|
||||
|
||||
/// Payment refunded
|
||||
refunded,
|
||||
|
||||
/// Payment cancelled
|
||||
cancelled;
|
||||
|
||||
/// Get display name for status
|
||||
String get displayName {
|
||||
switch (this) {
|
||||
case PaymentStatus.pending:
|
||||
return 'Pending';
|
||||
case PaymentStatus.processing:
|
||||
return 'Processing';
|
||||
case PaymentStatus.completed:
|
||||
return 'Completed';
|
||||
case PaymentStatus.failed:
|
||||
return 'Failed';
|
||||
case PaymentStatus.refunded:
|
||||
return 'Refunded';
|
||||
case PaymentStatus.cancelled:
|
||||
return 'Cancelled';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Payment Line Entity
|
||||
///
|
||||
/// Contains payment transaction information:
|
||||
/// - Payment details
|
||||
/// - Payment method
|
||||
/// - Bank information
|
||||
/// - Status tracking
|
||||
class PaymentLine {
|
||||
/// Unique payment line identifier
|
||||
final String paymentLineId;
|
||||
|
||||
/// Invoice ID this payment is for
|
||||
final String invoiceId;
|
||||
|
||||
/// Payment number (human-readable)
|
||||
final String paymentNumber;
|
||||
|
||||
/// Payment date
|
||||
final DateTime paymentDate;
|
||||
|
||||
/// Payment amount
|
||||
final double amount;
|
||||
|
||||
/// Payment method
|
||||
final PaymentMethod paymentMethod;
|
||||
|
||||
/// Bank name (for bank transfer)
|
||||
final String? bankName;
|
||||
|
||||
/// Bank account number (for bank transfer)
|
||||
final String? bankAccount;
|
||||
|
||||
/// Reference number (transaction ID, check number, etc.)
|
||||
final String? referenceNumber;
|
||||
|
||||
/// Payment notes
|
||||
final String? notes;
|
||||
|
||||
/// Payment status
|
||||
final PaymentStatus status;
|
||||
|
||||
/// Receipt URL
|
||||
final String? receiptUrl;
|
||||
|
||||
/// ERPNext payment entry reference
|
||||
final String? erpnextPaymentEntry;
|
||||
|
||||
/// Creation timestamp
|
||||
final DateTime createdAt;
|
||||
|
||||
/// Processing timestamp
|
||||
final DateTime? processedAt;
|
||||
|
||||
const PaymentLine({
|
||||
required this.paymentLineId,
|
||||
required this.invoiceId,
|
||||
required this.paymentNumber,
|
||||
required this.paymentDate,
|
||||
required this.amount,
|
||||
required this.paymentMethod,
|
||||
this.bankName,
|
||||
this.bankAccount,
|
||||
this.referenceNumber,
|
||||
this.notes,
|
||||
required this.status,
|
||||
this.receiptUrl,
|
||||
this.erpnextPaymentEntry,
|
||||
required this.createdAt,
|
||||
this.processedAt,
|
||||
});
|
||||
|
||||
/// Check if payment is completed
|
||||
bool get isCompleted => status == PaymentStatus.completed;
|
||||
|
||||
/// Check if payment is pending
|
||||
bool get isPending => status == PaymentStatus.pending;
|
||||
|
||||
/// Check if payment is being processed
|
||||
bool get isProcessing => status == PaymentStatus.processing;
|
||||
|
||||
/// Check if payment failed
|
||||
bool get isFailed => status == PaymentStatus.failed;
|
||||
|
||||
/// Check if payment has receipt
|
||||
bool get hasReceipt => receiptUrl != null && receiptUrl!.isNotEmpty;
|
||||
|
||||
/// Copy with method for immutability
|
||||
PaymentLine copyWith({
|
||||
String? paymentLineId,
|
||||
String? invoiceId,
|
||||
String? paymentNumber,
|
||||
DateTime? paymentDate,
|
||||
double? amount,
|
||||
PaymentMethod? paymentMethod,
|
||||
String? bankName,
|
||||
String? bankAccount,
|
||||
String? referenceNumber,
|
||||
String? notes,
|
||||
PaymentStatus? status,
|
||||
String? receiptUrl,
|
||||
String? erpnextPaymentEntry,
|
||||
DateTime? createdAt,
|
||||
DateTime? processedAt,
|
||||
}) {
|
||||
return PaymentLine(
|
||||
paymentLineId: paymentLineId ?? this.paymentLineId,
|
||||
invoiceId: invoiceId ?? this.invoiceId,
|
||||
paymentNumber: paymentNumber ?? this.paymentNumber,
|
||||
paymentDate: paymentDate ?? this.paymentDate,
|
||||
amount: amount ?? this.amount,
|
||||
paymentMethod: paymentMethod ?? this.paymentMethod,
|
||||
bankName: bankName ?? this.bankName,
|
||||
bankAccount: bankAccount ?? this.bankAccount,
|
||||
referenceNumber: referenceNumber ?? this.referenceNumber,
|
||||
notes: notes ?? this.notes,
|
||||
status: status ?? this.status,
|
||||
receiptUrl: receiptUrl ?? this.receiptUrl,
|
||||
erpnextPaymentEntry: erpnextPaymentEntry ?? this.erpnextPaymentEntry,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
processedAt: processedAt ?? this.processedAt,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other is PaymentLine &&
|
||||
other.paymentLineId == paymentLineId &&
|
||||
other.invoiceId == invoiceId &&
|
||||
other.paymentNumber == paymentNumber &&
|
||||
other.amount == amount &&
|
||||
other.paymentMethod == paymentMethod &&
|
||||
other.status == status;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return Object.hash(
|
||||
paymentLineId,
|
||||
invoiceId,
|
||||
paymentNumber,
|
||||
amount,
|
||||
paymentMethod,
|
||||
status,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PaymentLine(paymentLineId: $paymentLineId, paymentNumber: $paymentNumber, '
|
||||
'amount: $amount, paymentMethod: $paymentMethod, status: $status)';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user