// ignore_for_file: unnecessary_null_comparison 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/fcs_shipment.dart'; import 'package:fcs/domain/entities/invoice.dart'; import 'package:fcs/domain/entities/payment_method.dart'; import 'package:fcs/domain/entities/shipment.dart'; import 'package:fcs/domain/entities/user.dart'; import 'package:fcs/helpers/theme.dart'; import 'package:fcs/pages/carton/model/carton_model.dart'; import 'package:fcs/pages/discount/model/discount_model.dart'; import 'package:fcs/pages/invoice/editor/invoice_carton_table.dart'; import 'package:fcs/pages/invoice/editor/invoice_discount_list.dart'; import 'package:fcs/pages/invoice/editor/invoice_handling_fee_list.dart'; import 'package:fcs/pages/invoice/invoice_table.dart'; import 'package:fcs/pages/invoice/model/invoice_model.dart'; import 'package:fcs/pages/main/model/main_model.dart'; import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/payment_methods/model/payment_method_model.dart'; import 'package:fcs/pages/rates/custom_list.dart'; import 'package:fcs/pages/rates/model/shipment_rate_model.dart'; import 'package:fcs/pages/shipment/model/shipment_model.dart'; import 'package:fcs/pages/widgets/display_text.dart'; import 'package:fcs/pages/widgets/fcs_icons.dart'; import 'package:fcs/pages/widgets/local_app_bar.dart'; import 'package:fcs/pages/widgets/local_button.dart'; import 'package:fcs/pages/widgets/local_dropdown.dart'; import 'package:fcs/pages/widgets/local_popup_menu_button.dart'; import 'package:fcs/pages/widgets/local_popupmenu.dart'; import 'package:fcs/pages/widgets/progress.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; class InvoiceEditor extends StatefulWidget { final Invoice? invoice; final User? customer; final FcsShipment? fcsShipment; InvoiceEditor({this.invoice, this.customer, this.fcsShipment}); @override _InvoiceEditorState createState() => _InvoiceEditorState(); } class _InvoiceEditorState extends State { var dateFormatter = new DateFormat('dd MMM yyyy'); Invoice? _invoice; bool _isLoading = false; bool _isNew = false; User? _user; bool _showCartons = false; @override void initState() { super.initState(); _isNew = widget.invoice == null; if (widget.invoice != null) { _invoice = widget.invoice; } else { _invoice = Invoice( customDuties: [], cartons: [], shipments: [], invoiceDate: DateTime.now()); } _user = widget.customer; _loadAll(); } _loadAll() async { setState(() { _isLoading = true; }); try { await _loadCartons(); await _loadShipments(); await _loadDiscount(); } catch (e) { } finally { setState(() { _isLoading = false; }); } } _loadCartons() async { CartonModel cartonModel = Provider.of(context, listen: false); List cartons = await cartonModel.getCartonsForInvoice( widget.fcsShipment!.id!, widget.customer!.id!); cartons.forEach((c) { c.isChecked = true; }); setState(() { _invoice!.cartons = cartons; }); } _loadShipments() async { ShipmentModel shipmentModel = Provider.of(context, listen: false); List? shipments = await shipmentModel.getShipmentWithHandlingFee( widget.fcsShipment!.id!, widget.customer!.id!); shipments!.forEach((s) { s!.isSelected = true; }); setState(() { _invoice!.shipments = shipments; }); } List discounts = []; _loadDiscount() async { DiscountModel discountModel = Provider.of(context, listen: false); discounts = (await discountModel.getDiscount(widget.customer!.id!))!; if (discounts.isNotEmpty) { setState(() { _invoice!.discount = discounts.first; }); } } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { var mainModel = Provider.of(context); var paymentMethodModel = Provider.of(context); var rateModel = Provider.of(context); var rate = rateModel.rate; final invoiceNumberBox = DisplayText( labelTextKey: 'invoice.number', iconData: FontAwesomeIcons.fileInvoice, text: _invoice?.invoiceNumber ?? ""); final statusBox = DisplayText( text: _invoice?.status ?? "", iconData: Icons.av_timer, labelTextKey: 'invoice.status'); final cartonTable = InvoiceCartonTable( cartons: _invoice!.cartons, rate: rate, onSelect: (c, checked) { setState(() { c.isChecked = checked; }); }, ); final paymentTypesBox = LocalDropdown( callback: (v) { setState(() { _invoice!.paymentMethod = v; }); }, labelKey: "invoice.payment_method", iconData: FontAwesome.money, display: (u) => u.name, selectedValue: _invoice!.paymentMethod, values: paymentMethodModel.paymentMethods, ); final invoiceTableBox = InvoiceTable( invoice: _invoice!, rate: rate, deliveryFeeSelected: (selected) { setState(() { if (selected) { _invoice!.deliveryFee = rate.deliveryFee; } else { _invoice!.deliveryFee = 0; } }); }, discountSelected: (discount) { setState(() { _invoice!.discount = discount; }); }, onRemove: (i) { if (i.invoiceDataType == InvoiceDataType.CustomFeeDataType) { _removeCustom(i.data); } if (i.invoiceDataType == InvoiceDataType.DiscountDataType) { setState(() { _invoice!.discount = new Discount(); }); } if (i.invoiceDataType == InvoiceDataType.DeliveryFeeType) { setState(() { _invoice!.deliveryFee = 0; }); } if (i.invoiceDataType == InvoiceDataType.HandlingFeeType) { setState(() { _removeShipment(i.data); }); } }, ); final toggleButtonsBox = ToggleButtons( color: Colors.black45, selectedColor: Colors.black45, disabledColor: Colors.grey, selectedBorderColor: primaryColor, borderColor: Colors.transparent, fillColor: Colors.transparent, highlightColor: Colors.black45, children: [ Icon(cartonIconData), ], onPressed: (int index) { setState(() { _showCartons = !_showCartons; }); }, isSelected: [_showCartons], ); final popupMenu = LocalPopupMenuButton( buttonIcon: Icons.add_circle, selectable: false, buttonColor: Colors.black45, popmenus: [ LocalPopupMenu( id: 1, textKey: "invoice.add.custom.fee.menu", ), LocalPopupMenu( id: 2, textKey: "invoice.add.handling.fee.menu", ), LocalPopupMenu( id: 3, textKey: "invoice.add.discount.menu", ), LocalPopupMenu( id: 4, textKey: "invoice.delivery_fee", ) ], popupMenuCallback: (p) async { if (p.id == 1) { CargoType? customDuty = await Navigator.of(context).push( CupertinoPageRoute( builder: (context) => CustomList(selected: true))); if (customDuty == null) return; // _addCustom(customDuty); } else if (p.id == 2) { Shipment? shipment = await Navigator.of(context).push( CupertinoPageRoute( builder: (context) => InvoiceHandlingFeeList(shipments: _invoice!.shipments))); if (shipment == null) return; _addShipment(shipment); } else if (p.id == 3) { Discount? discount = await Navigator.of(context).push( CupertinoPageRoute( builder: (context) => InvoiceDiscountList(discounts: discounts))); if (discount != null) { setState(() { _invoice!.discount = discount; }); } } else if (p.id == 4) { setState(() { _invoice!.deliveryFee = rate.deliveryFee; }); } }, ); final headerBox = Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(dateFormatter.format(_invoice!.invoiceDate!)), SizedBox( height: 10, ), Text(_user?.name ?? ""), Text( _user?.fcsID ?? "", style: TextStyle(fontSize: 12), ) ], ), Spacer(), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ toggleButtonsBox, popupMenu, ], ), ], ); final createBtn = LocalButton( textKey: "invoice.issue.btn", callBack: _save, ); return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( appBar: LocalAppBar( labelKey: 'invoice.form.title', backgroundColor: Colors.white, labelColor: primaryColor, arrowColor: primaryColor), body: Padding( padding: const EdgeInsets.all(8.0), child: ListView( children: [ headerBox, _isNew ? Container() : invoiceNumberBox, _isNew ? Container() : statusBox, _showCartons ? cartonTable : Container(), _showCartons ? Divider(color: primaryColor, thickness: 2) : Container(), invoiceTableBox, SizedBox( height: 10, ), paymentTypesBox, SizedBox( height: 10, ), _isNew ? createBtn : mainModel.isCustomer() ? Container() : Container( child: Column( children: [ fcsButton(context, getLocalString(context, 'invoice.btn_save')) ], )), _isNew ? Container() : fcsButton(context, getLocalString(context, 'invoice.btn_payment_receipt')) ], ), ), ), ); } _addCustom(CustomDuty customDuty) { if (customDuty == null) return; setState(() { _invoice!.customDuties.remove(customDuty); _invoice!.customDuties.add(customDuty); }); } _addShipment(Shipment shipment) { if (shipment == null) return; shipment.isSelected = true; setState(() { _invoice!.shipments!.remove(shipment); _invoice!.shipments!.add(shipment); }); } _removeShipment(Shipment shipment) { if (shipment == null) return; shipment.isSelected = false; setState(() { _invoice!.shipments!.remove(shipment); _invoice!.shipments!.add(shipment); }); } _removeCustom(CustomDuty customDuty) { setState(() { _invoice!.customDuties.remove(customDuty); }); } _save() async { var rateModel = Provider.of(context, listen: false); double amount = _invoice!.getNetAmount(rateModel.rate); if (_invoice!.paymentMethod == null) { showMsgDialog(context, "Error", "Payment method required"); return; } List cargoTypes = _invoice!.getCargoTypes(rateModel.rate); if (cargoTypes == null || cargoTypes.length == 0) { showMsgDialog(context, "Error", "Expected at least one cargo type"); return; } if ((amount) <= 0) { showMsgDialog(context, "Error", "Expected positive amount"); return; } setState(() { _isLoading = true; }); try { InvoiceModel invoiceModel = Provider.of(context, listen: false); Invoice invoice = Invoice(); invoice.cargoTypes = cargoTypes; invoice.amount = amount; invoice.handlingFee = _invoice!.getHandlingFee(); invoice.cartons = _invoice!.cartons.where((c) => c.isChecked!).toList(); invoice.shipments = _invoice!.shipments!.where((s) => s!.isSelected).toList(); invoice.discount = _invoice!.discount; invoice.deliveryFee = _invoice!.deliveryFee; invoice.userID = widget.customer!.id; invoice.fcsShipmentID = widget.fcsShipment!.id; invoice.invoiceDate = _invoice!.invoiceDate; invoice.paymentMethod = _invoice!.paymentMethod; invoice.customDuties = _invoice!.customDuties; await invoiceModel.createInvoice(invoice); Navigator.pop(context, true); } catch (e) { showMsgDialog(context, "Error", e.toString()); } finally { setState(() { _isLoading = false; }); } } }