update invoice

This commit is contained in:
Phuoc Nguyen
2025-12-02 15:58:10 +07:00
parent 49a41d24eb
commit 359c31a4d4
15 changed files with 3398 additions and 0 deletions

View File

@@ -0,0 +1,306 @@
/// Data Model: Invoice Model
///
/// Model for invoice data with API serialization.
/// Not stored in local database.
library;
import 'package:worker/features/invoices/domain/entities/invoice.dart';
/// Seller Info Model
class SellerInfoModel {
final String? phone;
final String? email;
final String? fax;
final String? taxCode;
final String? companyName;
final String? addressLine1;
final String? cityCode;
final String? wardCode;
final String? cityName;
final String? wardName;
const SellerInfoModel({
this.phone,
this.email,
this.fax,
this.taxCode,
this.companyName,
this.addressLine1,
this.cityCode,
this.wardCode,
this.cityName,
this.wardName,
});
factory SellerInfoModel.fromJson(Map<String, dynamic> json) {
return SellerInfoModel(
phone: json['phone'] as String?,
email: json['email'] as String?,
fax: json['fax'] as String?,
taxCode: json['tax_code'] as String?,
companyName: json['company_name'] as String?,
addressLine1: json['address_line1'] as String?,
cityCode: json['city_code'] as String?,
wardCode: json['ward_code'] as String?,
cityName: json['city_name'] as String?,
wardName: json['ward_name'] as String?,
);
}
Map<String, dynamic> toJson() => {
'phone': phone,
'email': email,
'fax': fax,
'tax_code': taxCode,
'company_name': companyName,
'address_line1': addressLine1,
'city_code': cityCode,
'ward_code': wardCode,
'city_name': cityName,
'ward_name': wardName,
};
SellerInfo toEntity() => SellerInfo(
phone: phone,
email: email,
fax: fax,
taxCode: taxCode,
companyName: companyName,
addressLine1: addressLine1,
cityCode: cityCode,
wardCode: wardCode,
cityName: cityName,
wardName: wardName,
);
}
/// Buyer Info Model
class BuyerInfoModel {
final String? name;
final String? addressTitle;
final String? addressLine1;
final String? phone;
final String? email;
final String? fax;
final String? taxCode;
final String? cityCode;
final String? wardCode;
final String? cityName;
final String? wardName;
const BuyerInfoModel({
this.name,
this.addressTitle,
this.addressLine1,
this.phone,
this.email,
this.fax,
this.taxCode,
this.cityCode,
this.wardCode,
this.cityName,
this.wardName,
});
factory BuyerInfoModel.fromJson(Map<String, dynamic> json) {
return BuyerInfoModel(
name: json['name'] as String?,
addressTitle: json['address_title'] as String?,
addressLine1: json['address_line1'] as String?,
phone: json['phone'] as String?,
email: json['email'] as String?,
fax: json['fax'] as String?,
taxCode: json['tax_code'] as String?,
cityCode: json['city_code'] as String?,
wardCode: json['ward_code'] as String?,
cityName: json['city_name'] as String?,
wardName: json['ward_name'] as String?,
);
}
Map<String, dynamic> toJson() => {
'name': name,
'address_title': addressTitle,
'address_line1': addressLine1,
'phone': phone,
'email': email,
'fax': fax,
'tax_code': taxCode,
'city_code': cityCode,
'ward_code': wardCode,
'city_name': cityName,
'ward_name': wardName,
};
BuyerInfo toEntity() => BuyerInfo(
name: name,
addressTitle: addressTitle,
addressLine1: addressLine1,
phone: phone,
email: email,
fax: fax,
taxCode: taxCode,
cityCode: cityCode,
wardCode: wardCode,
cityName: cityName,
wardName: wardName,
);
}
/// Invoice Item Model
class InvoiceItemModel {
final String itemName;
final String itemCode;
final double qty;
final double rate;
final double amount;
const InvoiceItemModel({
required this.itemName,
required this.itemCode,
required this.qty,
required this.rate,
required this.amount,
});
factory InvoiceItemModel.fromJson(Map<String, dynamic> json) {
return InvoiceItemModel(
itemName: json['item_name'] as String? ?? '',
itemCode: json['item_code'] as String? ?? '',
qty: (json['qty'] as num?)?.toDouble() ?? 0.0,
rate: (json['rate'] as num?)?.toDouble() ?? 0.0,
amount: (json['amount'] as num?)?.toDouble() ?? 0.0,
);
}
Map<String, dynamic> toJson() => {
'item_name': itemName,
'item_code': itemCode,
'qty': qty,
'rate': rate,
'amount': amount,
};
InvoiceItem toEntity() => InvoiceItem(
itemName: itemName,
itemCode: itemCode,
qty: qty,
rate: rate,
amount: amount,
);
}
/// Invoice Model
///
/// Model for API parsing only (no Hive storage).
class InvoiceModel {
final String name;
final String postingDate;
final String status;
final String statusColor;
final String? orderId;
final double grandTotal;
// Detail-only fields
final String? customerName;
final SellerInfoModel? sellerInfo;
final BuyerInfoModel? buyerInfo;
final List<InvoiceItemModel>? items;
final double? total;
final double? discountAmount;
const InvoiceModel({
required this.name,
required this.postingDate,
required this.status,
required this.statusColor,
this.orderId,
required this.grandTotal,
this.customerName,
this.sellerInfo,
this.buyerInfo,
this.items,
this.total,
this.discountAmount,
});
/// Create from JSON (API response - list item)
factory InvoiceModel.fromJson(Map<String, dynamic> json) {
return InvoiceModel(
name: json['name'] as String? ?? '',
postingDate: json['posting_date'] as String? ?? '',
status: json['status'] as String? ?? '',
statusColor: json['status_color'] as String? ?? 'Secondary',
orderId: json['order_id'] as String?,
grandTotal: (json['grand_total'] as num?)?.toDouble() ?? 0.0,
customerName: json['customer_name'] as String?,
sellerInfo: json['seller_info'] != null
? SellerInfoModel.fromJson(json['seller_info'] as Map<String, dynamic>)
: null,
buyerInfo: json['buyer_info'] != null
? BuyerInfoModel.fromJson(json['buyer_info'] as Map<String, dynamic>)
: null,
items: json['items'] != null
? (json['items'] as List<dynamic>)
.map((e) => InvoiceItemModel.fromJson(e as Map<String, dynamic>))
.toList()
: null,
total: (json['total'] as num?)?.toDouble(),
discountAmount: (json['discount_amount'] as num?)?.toDouble(),
);
}
/// Convert to JSON
Map<String, dynamic> toJson() => {
'name': name,
'posting_date': postingDate,
'status': status,
'status_color': statusColor,
'order_id': orderId,
'grand_total': grandTotal,
'customer_name': customerName,
'seller_info': sellerInfo?.toJson(),
'buyer_info': buyerInfo?.toJson(),
'items': items?.map((e) => e.toJson()).toList(),
'total': total,
'discount_amount': discountAmount,
};
/// Convert to domain entity
Invoice toEntity() {
return Invoice(
name: name,
postingDate: DateTime.tryParse(postingDate) ?? DateTime.now(),
status: status,
statusColor: statusColor,
orderId: orderId,
grandTotal: grandTotal,
customerName: customerName,
sellerInfo: sellerInfo?.toEntity(),
buyerInfo: buyerInfo?.toEntity(),
items: items?.map((e) => e.toEntity()).toList(),
total: total,
discountAmount: discountAmount,
);
}
/// Create from domain entity
factory InvoiceModel.fromEntity(Invoice entity) {
return InvoiceModel(
name: entity.name,
postingDate: entity.postingDate.toIso8601String().split('T').first,
status: entity.status,
statusColor: entity.statusColor,
orderId: entity.orderId,
grandTotal: entity.grandTotal,
customerName: entity.customerName,
total: entity.total,
discountAmount: entity.discountAmount,
);
}
@override
String toString() {
return 'InvoiceModel(name: $name, status: $status, grandTotal: $grandTotal)';
}
}