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_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/local_text.dart'; import 'package:fcs/pages/widgets/progress.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_icons/flutter_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; 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 != null && discounts.length > 0) { 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 = null; }); } 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) { CustomDuty customDuty = await Navigator.of(context).push( CupertinoPageRoute( builder: (context) => CustomList(selected: true))); _addCustom(customDuty); } else if (p.id == 2) { Shipment shipment = await Navigator.of(context).push( CupertinoPageRoute( builder: (context) => InvoiceHandlingFeeList(shipments: _invoice.shipments))); _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: AppBar( centerTitle: true, leading: new IconButton( icon: new Icon(CupertinoIcons.back, color: primaryColor), onPressed: () => Navigator.of(context).pop(), ), backgroundColor: Colors.white, shadowColor: Colors.transparent, title: LocalText(context, 'invoice.form.title', color: primaryColor, fontSize: 20), ), 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) <= 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; }); } } }