import 'dart:io'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:intl/intl.dart'; import 'po.dart'; import 'setting.dart'; class DOSubmission { final dateFormatter = new DateFormat('dd MMM yyyy hh:mm a'); String id; String poID; String doNumber; DateTime deliveryDate; DateTime doDate; String driverLicenseNumber; String driverName; String carNo; String status; String deliveryStatus; DateTime deliveryInitiatedTime; String comment; String userID; String userName; String type; String bizName; String driverImgUrl; String doReceiptUrl; int storageCharge = 0; String storageReceiptUrl; String driverLicenceUrl; int totalQty; File driverImg; List doLines = List(); List pos = List(); List dopoLies = List(); get isApproved => status != null && status == "approved"; get isClosed => status != null && status == "closed"; get isPending => status == "pending"; get getDeliveryStatus => deliveryStatus == null ? "You can initiate delivery" : deliveryStatus; get deliveryInitTime => deliveryInitiatedTime == null ? "" : dateFormatter.format(deliveryInitiatedTime); bool hasStorageCharge() { return this.storageCharge != null && this.storageCharge > 0; } DOSubmission( {this.id, this.doNumber, this.deliveryDate, this.doDate, this.driverLicenseNumber, this.driverName, this.carNo, this.status, this.comment, this.type, this.userName, this.bizName, this.deliveryStatus, this.driverImgUrl, this.deliveryInitiatedTime, this.poID, this.doReceiptUrl, this.storageCharge, this.storageReceiptUrl, this.driverLicenceUrl, this.totalQty}); void loadPOs() { this.doLines.clear(); var isSingle = type == "single"; pos.forEach((p) => p.poLines.forEach((l) { var dl = DOLine( productID: l.productID, productName: l.productName, qty: isSingle ? l.balanceQty : 0, poBalQty: l.balanceQty); if (this.doLines.contains(dl)) { this.doLines[this.doLines.indexOf(dl)].qty += dl.qty; this.doLines[this.doLines.indexOf(dl)].poBalQty += dl.poBalQty; } else { this.doLines.add(dl); } })); dopoLies.clear(); pos.forEach((p) => p.poLines.forEach((l) => dopoLies.add(DOPOLine( poID: p.id, productID: l.productID, productName: l.productName, poNumber: p.poNumber, poQty: l.qty, poBalQty: l.balanceQty, doQty: isSingle ? l.balanceQty : 0, poApproveDate: p.poApproveDate, )))); dopoLies.sort((l1, l2) => l1.poNumber.compareTo(l2.poNumber)); } void updateDoline(String productID, int qty) { var _doLine = this.doLines.firstWhere((l) => l.productID == productID); if (qty < 0) { throw Exception("invalid number, must be greater than or equal to zero"); } if (_doLine.poBalQty < qty) { throw Exception( "invalid number,must be less than or equal to PO balance qty"); } if (_doLine != null && _doLine.poBalQty >= qty) { _doLine.qty = qty; var _dopoLines = dopoLies.where((l) => l.productID == productID).toList(); // clear _dopoLines.forEach((l) => l.doQty = 0); // add var poBalQty = qty; _dopoLines.forEach((l) { if (poBalQty == 0) return; var _qty = poBalQty > l.poBalQty ? l.poBalQty : poBalQty; l.doQty = _qty; poBalQty -= _qty; }); } } void updateStorageCharge(Setting setting) { if (deliveryDate == null) { storageCharge = 0; return; } var _deliveryDate = DateTime(deliveryDate.year, deliveryDate.month, deliveryDate.day); storageCharge = 0; dopoLies.forEach((l) { var _approveDate = DateTime( l.poApproveDate.year, l.poApproveDate.month, l.poApproveDate.day); int diff = _deliveryDate.difference(_approveDate).inDays; if (diff > setting.firstStorageChargeIn) { storageCharge += l.doQty * setting.firstStorageCharge; } if (diff > setting.secondStorageChargeIn) { storageCharge += l.doQty * setting.secondStorageCharge; } }); } List getPOs() { return this.dopoLies.map((l) => l.poID).toList(); } void setDOPOLineBalance(String poID, List poLines) { poLines.forEach((poLine) { this.dopoLies.forEach((l) { if (l.poID == poID && l.productID == poLine.productID) { l.poBalQty = poLine.balanceQty; } }); }); } Map toMap() { List lines = doLines.map((l) => l.toMap()).toList(); List doPOlines = dopoLies.map((l) => l.toMap()).toList(); return { "id": id, 'delivery_date': deliveryDate?.toUtc()?.toIso8601String(), 'do_number': doNumber, 'po_id': poID, 'car_number': carNo, 'driver_name': driverName, 'driver_license_number': driverLicenseNumber, 'do_lines': lines, 'do_po_lines': doPOlines, 'comment': comment, 'user_id': userID, 'user_name': userName, 'type': type, 'driver_img_url': driverImgUrl, 'driver_sign_url': doReceiptUrl, 'delivery_status': deliveryStatus, 'storage_charge': storageCharge, 'storage_receipt_url': storageReceiptUrl, 'driver_license_url': driverLicenceUrl, }; } factory DOSubmission.fromMap(Map map, String id) { var ts = (map['delivery_date'] as Timestamp); var dt = (map['delivery_initiated_time'] as Timestamp); var dots = (map['do_date'] as Timestamp); return DOSubmission( id: id, deliveryDate: ts == null ? null : ts.toDate(), deliveryInitiatedTime: dt == null ? null : dt.toDate(), doDate: dots == null ? null : dots.toDate(), doNumber: map['do_number'], status: map['status'], comment: map["comment"], driverName: map["driver_name"], driverLicenseNumber: map["driver_license_number"], driverImgUrl: map["driver_img_url"], doReceiptUrl: map["driver_sign_url"], carNo: map["car_number"], type: map["type"], userName: map['user_name'], bizName: map['biz_name'], deliveryStatus: map['delivery_status'], poID: map['po_id'], storageCharge: map['storage_charge'], storageReceiptUrl: map['storage_receipt_url'], driverLicenceUrl: map['driver_license_url'], totalQty: map['total_qty']); } @override String toString() { return 'DOSubmission{id:$id, deliveryDate:$deliveryDate,driverLicenseNumber:$driverLicenseNumber,driverName:$driverName,carNo:$carNo,status:$status,doLines:$doLines}'; } } class DOLine { String id; String productID; String productName; int qty; int amount; int price; String storageID; String storageName; String action; int displayOrder; int poBalQty; // only for UI DOLine( {this.id, this.productID, this.productName, this.qty, this.amount, this.price, this.storageID, this.storageName, this.action, this.poBalQty, this.displayOrder}); factory DOLine.fromMap(Map map) { return DOLine( id: map['id'], productID: map['product_id'], productName: map['product_name'], qty: map['quantity'], amount: map['amount'], price: map['price'], storageID: map['storage_id'], storageName: map['storage_name'], ); } Map toMap() { return { 'id': id, 'product_id': productID, 'product_name': productName, 'quantity': qty, 'price': price, 'amount': amount, 'storage_id': storageID, 'storage_name': storageName, }; } @override bool operator ==(other) { if (identical(this, other)) { return true; } return other.productID == this.productID; } @override int get hashCode { int result = 17; result = 37 * result + productID.hashCode; return result; } @override String toString() { return 'DOLine{productID:$productID,productName:$productName,qty:$qty,amount:$amount,price:$price,storageID:$storageID,displayOrder:$displayOrder}'; } } class DOPOLine { String id; String poID; String poNumber; DateTime poApproveDate; String productID; String productName; int poQty; int poBalQty; int doQty; int poBalAtCreate; DateTime poApprovedDate; int displayOrder; get getPoBalanceQty => poBalQty - doQty; get getPoBalanceQtyAtCreate => poBalAtCreate == null ? 0 : (poBalAtCreate - doQty); DOPOLine( {this.id, this.poID, this.poNumber, this.productID, this.productName, this.poQty, this.poBalQty, this.doQty, this.poApproveDate, this.displayOrder, this.poBalAtCreate}); factory DOPOLine.fromMap(Map map) { return DOPOLine( id: map['id'], poID: map['po_id'], poNumber: map['po_number'], productID: map['product_id'], productName: map['product_name'], doQty: map['do_quantity'], poQty: map['po_quantity'], poBalQty: map['po_bal_quantity'], poBalAtCreate: map['po_balance_at_create']); } Map toMap() { return { 'id': id, 'po_id': poID, 'po_number': poNumber, 'product_id': productID, 'product_name': productName, 'do_quantity': doQty, 'po_quantity': poQty, 'po_bal_quantity': poBalQty, 'po_balance_at_create': poBalQty, }; } @override bool operator ==(other) { if (identical(this, other)) { return true; } return other.productID == this.productID && other.poID == this.poID; } @override int get hashCode { int result = 17; result = 37 * result + poID.hashCode; result = 37 * result + productID.hashCode; return result; } @override String toString() { return 'DOLine{productID:$productID,productName:$productName,doQty:$doQty}'; } }