import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:fcs/domain/entities/cargo_type.dart'; import 'package:fcs/domain/entities/carton.dart'; import 'package:fcs/domain/entities/custom_duty.dart'; import 'package:fcs/domain/entities/discount.dart'; import 'package:fcs/domain/entities/discount_by_weight.dart'; import 'package:fcs/domain/entities/payment.dart'; import 'package:fcs/domain/entities/payment_method.dart'; import 'package:fcs/domain/entities/rate.dart'; import 'package:fcs/domain/entities/shipment.dart'; class Invoice { String? id; String? invoiceNumber; DateTime? invoiceDate; String? fcsShipmentID; String? userID; String? fcsID; String? userName; String? phoneNumber; String? status; double handlingFee; double deliveryFee; double paidAmount; double amount; List customDuties; List cartons; List cargoTypes; List? shipments; List payments; Discount? discount; PaymentMethod? paymentMethod; String? invoiceURL; List getCargoTypes(Rate rate) { if (cargoTypes.isNotEmpty) return cargoTypes; List _cargoTypes = []; double totalCalWeight = 0; cartons.forEach((carton) { if (carton.isChecked ?? false) { var _cartonsTypes = carton.getCargoTypeForCalWeight(rate.volumetricRatio); _cartonsTypes.forEach((ct) { if (_cargoTypes.contains(ct)) { CargoType existing = _cargoTypes.firstWhere((wc) => wc.id == ct.id); existing.calWeight += ct.calWeight; } else { _cargoTypes.add(ct.clone()); } totalCalWeight += ct.calWeight; }); } }); DiscountByWeight discountByWeight = rate.getDiscountByWeight(totalCalWeight); _cargoTypes.forEach((e) { double r = e.rate - discountByWeight.discount; e.calRate = r; }); return _cargoTypes; } double getTotal(Rate rate) { List cargoTypes = getCargoTypes(rate); double total = cargoTypes.fold(0.0, (p, c) => c.calAmount + p); return total; } double get balance => amount - paidAmount; double getNetAmount(Rate rate) { List cargoTypes = getCargoTypes(rate); double total = cargoTypes.fold(0.0, (p, c) => c.calAmount + p); total += getCustomFee(); total += getDeliveryFee(); total += getHandlingFee(); total -= getDiscount(); return total; } double getHandlingFee() { return shipments! .where((sh) => sh!.isSelected) .fold(0, (p, s) => p + (s!.handlingFee - s.paidHandlingFee)); } double getTotalBalance(Rate rate) { return getNetAmount(rate) - paidAmount; } double getCustomFee() { return customDuties.isEmpty ? 0 : customDuties.fold(0, (p, d) => p + d.fee); } double getDeliveryFee() { return deliveryFee; } double getDiscount() => discount == null ? 0 : discount!.amount; Invoice( {this.id, this.invoiceNumber, this.invoiceDate, this.fcsID, this.userName, this.phoneNumber, this.amount = 0, this.paidAmount = 0, this.discount, this.status, this.customDuties = const [], this.cartons = const [], this.cargoTypes = const [], this.handlingFee = 0, this.deliveryFee = 0, this.fcsShipmentID, this.shipments = const [], this.invoiceURL, this.payments = const [], this.paymentMethod}); factory Invoice.fromMap(Map map, String docID) { var invd = (map['invoice_date'] as Timestamp); var cargoTypesMaps = List>.from(map['cargo_types'] ?? []); var cargoTypes = cargoTypesMaps.map((e) => CargoType.fromMap(e, e["id"])).toList(); var customDutiesMap = List>.from(map['custom_duties'] ?? []); var customDuties = customDutiesMap.map((e) => CustomDuty.fromMap(e, e["id"])).toList(); var handlingShipmentsMap = List>.from(map['handling_fee_shipments'] ?? []); var handingShipments = handlingShipmentsMap.map((e) => Shipment.fromMap(e, e["id"])).toList(); var cartonsMap = List>.from(map['cartons'] ?? []); var cartons = cartonsMap.map((e) => Carton.fromMap(e, e["id"])).toList(); var paymentMethodMap = map['payment_method']; var paymentMethod = paymentMethodMap != null ? PaymentMethod.fromMap(paymentMethodMap, paymentMethodMap['id']) : null; var discountMap = map['discount']; var discount = Discount.fromMap(discountMap, discountMap['id']); var paymentMaps = List>.from(map['payments'] ?? []); var payments = paymentMaps.map((e) => Payment.fromMap(e, e["id"])).toList(); return Invoice( id: docID, invoiceNumber: map['invoice_number'], invoiceDate: invd.toDate(), userName: map['user_name'], fcsID: map['fcs_id'], phoneNumber: map['phone_number'], amount: map['amount'], paidAmount: double.tryParse(map['paid_amount'].toString()) ?? 0, status: map['status'], cartons: cartons, cargoTypes: cargoTypes, shipments: handingShipments, customDuties: customDuties, deliveryFee: map['delivery_fee'], invoiceURL: map['invoice_url'], paymentMethod: paymentMethod, discount: discount, payments: payments, ); } Map toMap() { List _cargoTypes = cargoTypes.map((c) => c.toMap()).toList(); List _customDuties = customDuties.map((c) => c.toMap()).toList(); List _cartons = cartons.map((c) => c.toMap()).toList(); List _shipments = shipments!.map((s) => s!.toMap()).toList(); return { "id": id, "invoice_date": invoiceDate?.toUtc().toIso8601String(), "user_id": userID, "user_name": userName, "invoice_number": invoiceNumber, 'fcs_shipment_id': fcsShipmentID, 'cargo_types': _cargoTypes, 'custom_duties': _customDuties, 'handling_fee_shipments': _shipments, 'cartons': _cartons, 'discount': discount?.toMap(), 'amount': amount, 'handling_fee': handlingFee, 'delivery_fee': deliveryFee, 'invoice_url': invoiceURL, 'payment_method': paymentMethod?.toMap(), }; } }