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 != null) return cargoTypes; List _cargoTypes = []; double totalCalWeight = 0; cartons.forEach((carton) { if (carton.isChecked) { 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 != null ? discountByWeight.discount : 0); e.calRate = r; }); return _cargoTypes; } double getTotal(Rate rate) { List cargoTypes = getCargoTypes(rate); var total = cargoTypes.fold(0.0, (p, c) => c.calAmount + p); return total; } double get balance => (amount ?? 0) - (paidAmount ?? 0); double getNetAmount(Rate rate) { List cargoTypes = getCargoTypes(rate); var 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 ?? false)?.fold(0, (p, s) { return p + (s?.handlingFee ?? 0) - (s?.paidHandlingFee ?? 0); }); } double getTotalBalance(Rate rate) { return getNetAmount(rate) - (paidAmount ?? 0); } double getCustomFee() { return customDuties == null ? 0 : customDuties.fold(0, (p, d) => p + d.fee); } double getDeliveryFee() { return deliveryFee == null ? 0 : deliveryFee; } double getDiscount() => discount == null ? 0 : discount.amount; Invoice( {this.id, this.invoiceNumber, this.invoiceDate, this.fcsID, this.userName, this.phoneNumber, this.amount, this.paidAmount, this.discount, this.status, this.customDuties, this.cartons, this.cargoTypes, this.handlingFee, this.deliveryFee, this.fcsShipmentID, this.shipments, this.invoiceURL, this.payments, 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(), }; } }