import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:fcs/domain/entities/discount_by_weight.dart'; import 'package:fcs/domain/entities/rate.dart'; import 'package:fcs/domain/entities/shipment.dart'; import 'package:fcs/domain/vo/shipment_status.dart'; import 'package:fcs/domain/vo/delivery_address.dart'; import 'cargo_type.dart'; import 'package.dart'; class Carton { String? id; String? cartonNumber; String? fcsShipmentID; String? fcsShipmentNumber; String? senderID; String? senderFCSID; String? senderName; String? consigneeFCSID; String? consigneeName; String? consigneeID; double width; double height; double length; String? status; String? cargoDesc; String? desc; int? shipmentWeight; bool? isChecked; bool? isShipmentCarton; String? cartonType; String? mixCartonNumber; String? lastMile; String? cartonSizeType; double cartonWeight; String? billTo; bool isSelected; int rate; int weight; String? packageType; String? pickUpID; List photoUrls; String? remark; DateTime? arrivedDate; List packageIDs; List packages; List cargoTypes = []; List surchareItems = []; DeliveryAddress? deliveryAddress; Shipment? shipment; //for mix carton List cartons; List cartonIDs; int get amount => (rate * weight); // String get packageNumber => // shipmentNumber + "-" + receiverNumber + " #" + boxNumber; double get actualWeight => cargoTypes.isEmpty ? 0 : cargoTypes.fold(0, (p, e) => e.weight + p); int getShipmentWeight(double volumetricRatio) { if (length <= 0 || width <= 0 || height <= 0 || volumetricRatio <= 0) return 0; return ((length * width * height) / volumetricRatio).round(); } /// getCargoTypeForCalWeight returns carton with shipment weight List getCargoTypeForCalWeight(double volumetricRatio) { // get shipment weight double volume = length * width * height; double sw = volume / volumetricRatio; // get actual weight double aw = cargoTypes.fold(0.0, (p, c) => p + c.weight); if (aw == 0 || sw == 0) return []; cargoTypes.forEach((e) { double calWeight = aw > sw ? e.weight : (e.weight / aw) * sw; e.calWeight = calWeight; }); return cargoTypes; } /// calAmount returns total amount double calAmount(Rate rate) { // get shipment weight int sw = getShipmentWeight(rate.volumetricRatio); // get actual weight double aw = cargoTypes.fold(0.0, (p, c) => p + c.weight); if (aw == 0 || sw == 0) return 0; double wd = sw - aw; wd = wd - rate.diffDiscountWeight; double wdAmount = wd > 0 ? wd * rate.diffWeightRate : 0; DiscountByWeight discountByWeight = rate.getDiscountByWeight(aw); double total = 0; cargoTypes.forEach((e) { double r = e.rate - (discountByWeight.discount); double amount = e.weight * r; total += amount; }); return total + wdAmount; } List shipmentHistory; Carton( {this.id, this.senderID, this.senderFCSID, this.senderName, this.desc, this.width = 0, this.height = 0, this.length = 0, this.shipmentWeight, this.isChecked = false, this.cartonType, this.consigneeFCSID, this.consigneeID, this.consigneeName, this.rate = 0, this.weight = 0, this.packageType, this.pickUpID, this.remark, this.status, this.arrivedDate, this.cargoDesc, this.shipmentHistory = const [], this.packages = const [], this.cargoTypes = const [], this.surchareItems = const [], this.cartonNumber, this.billTo, this.fcsShipmentID, this.fcsShipmentNumber, this.packageIDs = const [], this.mixCartonNumber, this.isShipmentCarton = false, this.deliveryAddress, this.cartonSizeType, this.lastMile, this.cartons = const [], this.cartonIDs = const [], this.cartonWeight = 0, this.photoUrls = const [], this.isSelected = false}); Map toMap() { var _types = cargoTypes.where((t) => t.weight != 0).toList(); var _cargoTypes = _types.map((c) => c.toMapForCargo()).toList(); var _packagesIds = packages.map((c) => c.id).toList(); var _surchareItems = surchareItems.map((c) => c.toMapForSurcharge()).toList(); return { 'id': id, 'carton_type': cartonType, 'fcs_shipment_id': fcsShipmentID, 'sender_user_id': senderID, 'consignee_user_id': consigneeID, 'bill_to': billTo, 'last_mile': lastMile, 'length': length, 'width': width, 'height': height, 'package_ids': _packagesIds, 'cargo_types': _cargoTypes, 'surcharge_items': _surchareItems, }; } Map toMapForMix() { var _cartonIds = cartons.map((c) => c.id).toList(); return { 'id': id, 'carton_type': cartonType, 'fcs_shipment_id': fcsShipmentID, 'length': length, 'width': width, 'height': height, 'carton_ids': _cartonIds, }; } factory Carton.fromMap(Map map, String docID) { var _arrivedDate = map['arrived_date'] == null ? null : (map['arrived_date'] as Timestamp); var da = map['delivery_address']; var _da = da != null ? DeliveryAddress.fromMap(da, da["id"]) : null; var cargoTypesMaps = List>.from(map['cargo_types'] ?? []); var cargoTypes = cargoTypesMaps .map((e) => CargoType.fromMapForCargo(e, e["id"])) .toList(); var surchargeItemMaps = List>.from(map['surcharge_items'] ?? []); var surchageItems = surchargeItemMaps .map((e) => CargoType.fromMapForsurcharge(e, e["id"])) .toList(); List _photoUrls = map['photo_urls'] == null ? [] : List.from(map['photo_urls']); return Carton( id: docID, arrivedDate: _arrivedDate != null ? _arrivedDate.toDate() : null, length: double.tryParse(map['length'].toString()) ?? 0, width: double.tryParse(map['width'].toString()) ?? 0, height: double.tryParse(map['height'].toString()) ?? 0, cartonType: map['carton_type'], cartonNumber: map['carton_number'], fcsShipmentID: map['fcs_shipment_id'], fcsShipmentNumber: map['fcs_shipment_number'], status: map['status'], packageIDs: List.from(map['package_ids'] ?? []), deliveryAddress: _da, cargoTypes: cargoTypes, surchareItems: surchageItems, senderID: map['sender_user_id'], senderFCSID: map['sender_fcs_id'], senderName: map['sender_user_name'], consigneeID: map['consignee_user_id'], consigneeName: map['consignee_user_name'], consigneeFCSID: map['consignee_fcs_id'], cartonIDs: List.from(map['carton_ids'] ?? []), cartonWeight: (map['carton_weight'] ?? 0).toDouble(), photoUrls: _photoUrls, billTo: map['bill_to'] ?? '', lastMile: map['last_mile'] ?? ""); } @override bool operator ==(Object other) => other is Carton && other.id == id; @override int get hashCode => id.hashCode; }