Files
fcs/lib/pages/invoice/editor/invoice_editor.dart

455 lines
14 KiB
Dart
Raw Normal View History

2020-10-26 04:41:24 +06:30
import 'package:fcs/domain/entities/cargo_type.dart';
2020-10-22 04:14:53 +06:30
import 'package:fcs/domain/entities/carton.dart';
2020-10-15 03:06:13 +06:30
import 'package:fcs/domain/entities/custom_duty.dart';
2020-10-09 19:00:39 +06:30
import 'package:fcs/domain/entities/discount.dart';
2020-10-22 04:14:53 +06:30
import 'package:fcs/domain/entities/fcs_shipment.dart';
2020-10-07 02:33:06 +06:30
import 'package:fcs/domain/entities/invoice.dart';
import 'package:fcs/domain/entities/payment_method.dart';
2020-10-24 06:14:07 +06:30
import 'package:fcs/domain/entities/shipment.dart';
2020-10-09 19:00:39 +06:30
import 'package:fcs/domain/entities/user.dart';
2020-10-07 02:33:06 +06:30
import 'package:fcs/helpers/theme.dart';
2020-10-22 04:14:53 +06:30
import 'package:fcs/pages/carton/model/carton_model.dart';
2020-10-07 02:33:06 +06:30
import 'package:fcs/pages/discount/model/discount_model.dart';
2020-10-26 04:41:24 +06:30
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';
2020-10-24 06:14:07 +06:30
import 'package:fcs/pages/invoice/invoice_table.dart';
2020-10-26 04:41:24 +06:30
import 'package:fcs/pages/invoice/model/invoice_model.dart';
2020-10-07 02:33:06 +06:30
import 'package:fcs/pages/main/model/main_model.dart';
2020-10-09 19:00:39 +06:30
import 'package:fcs/pages/main/util.dart';
2020-10-13 18:38:00 +06:30
import 'package:fcs/pages/payment_methods/model/payment_method_model.dart';
2020-10-14 20:56:46 +06:30
import 'package:fcs/pages/rates/custom_list.dart';
2020-10-15 03:06:13 +06:30
import 'package:fcs/pages/rates/model/shipment_rate_model.dart';
2020-10-24 06:14:07 +06:30
import 'package:fcs/pages/shipment/model/shipment_model.dart';
2020-10-09 19:00:39 +06:30
import 'package:fcs/pages/widgets/display_text.dart';
2020-10-24 06:14:07 +06:30
import 'package:fcs/pages/widgets/fcs_icons.dart';
2020-10-26 04:41:24 +06:30
import 'package:fcs/pages/widgets/local_button.dart';
2020-10-13 18:38:00 +06:30
import 'package:fcs/pages/widgets/local_dropdown.dart';
2020-10-24 06:14:07 +06:30
import 'package:fcs/pages/widgets/local_popup_menu_button.dart';
import 'package:fcs/pages/widgets/local_popupmenu.dart';
2020-10-07 02:33:06 +06:30
import 'package:fcs/pages/widgets/local_text.dart';
import 'package:fcs/pages/widgets/progress.dart';
2020-10-14 13:54:42 +06:30
import 'package:flutter/cupertino.dart';
2020-06-02 14:56:51 +06:30
import 'package:flutter/material.dart';
2021-09-10 12:00:08 +06:30
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
2020-06-02 14:56:51 +06:30
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
class InvoiceEditor extends StatefulWidget {
2021-09-10 12:00:08 +06:30
final Invoice? invoice;
final User? customer;
final FcsShipment? fcsShipment;
2020-10-22 04:14:53 +06:30
InvoiceEditor({this.invoice, this.customer, this.fcsShipment});
2020-06-02 14:56:51 +06:30
@override
_InvoiceEditorState createState() => _InvoiceEditorState();
}
class _InvoiceEditorState extends State<InvoiceEditor> {
var dateFormatter = new DateFormat('dd MMM yyyy');
2021-09-10 12:00:08 +06:30
Invoice? _invoice;
2020-06-02 14:56:51 +06:30
bool _isLoading = false;
2021-09-10 12:00:08 +06:30
bool _isNew = false;
User? _user;
2020-06-02 14:56:51 +06:30
2020-10-24 06:14:07 +06:30
bool _showCartons = false;
2020-06-02 14:56:51 +06:30
@override
void initState() {
super.initState();
2020-10-24 06:14:07 +06:30
_isNew = widget.invoice == null;
2020-10-14 20:56:46 +06:30
2020-06-02 14:56:51 +06:30
if (widget.invoice != null) {
_invoice = widget.invoice;
2020-06-29 16:03:41 +06:30
} else {
2020-10-24 06:14:07 +06:30
_invoice = Invoice(
customDuties: [],
cartons: [],
shipments: [],
invoiceDate: DateTime.now());
2020-10-14 20:56:46 +06:30
}
2020-10-24 06:14:07 +06:30
_user = widget.customer;
_loadAll();
}
2020-10-14 20:56:46 +06:30
2020-10-24 06:14:07 +06:30
_loadAll() async {
setState(() {
_isLoading = true;
});
try {
await _loadCartons();
await _loadShipments();
await _loadDiscount();
} catch (e) {} finally {
2020-10-13 11:49:35 +06:30
setState(() {
2020-10-24 06:14:07 +06:30
_isLoading = false;
2020-10-13 11:49:35 +06:30
});
2020-06-29 16:03:41 +06:30
}
2020-10-22 04:14:53 +06:30
}
_loadCartons() async {
CartonModel cartonModel = Provider.of<CartonModel>(context, listen: false);
List<Carton> cartons = await cartonModel.getCartonsForInvoice(
2021-09-10 12:00:08 +06:30
widget.fcsShipment!.id, widget.customer!.id);
2020-10-24 06:14:07 +06:30
cartons.forEach((c) {
c.isChecked = true;
});
setState(() {
2021-09-10 12:00:08 +06:30
_invoice!.cartons = cartons;
2020-10-24 06:14:07 +06:30
});
}
_loadShipments() async {
ShipmentModel shipmentModel =
Provider.of<ShipmentModel>(context, listen: false);
List<Shipment> shipments = await shipmentModel.getShipmentWithHandlingFee(
2021-09-10 12:00:08 +06:30
widget.fcsShipment!.id, widget.customer!.id);
2020-10-24 06:14:07 +06:30
shipments.forEach((s) {
s.isSelected = true;
});
2020-10-22 04:14:53 +06:30
setState(() {
2021-09-10 12:00:08 +06:30
_invoice!.shipments = shipments;
2020-10-22 04:14:53 +06:30
});
2020-06-02 14:56:51 +06:30
}
2020-10-24 06:14:07 +06:30
List<Discount> discounts = [];
_loadDiscount() async {
DiscountModel discountModel =
Provider.of<DiscountModel>(context, listen: false);
2021-09-10 12:00:08 +06:30
discounts = await discountModel.getDiscount(widget.customer!.id);
2020-10-24 06:14:07 +06:30
if (discounts != null && discounts.length > 0) {
setState(() {
2021-09-10 12:00:08 +06:30
_invoice!.discount = discounts.first;
2020-10-24 06:14:07 +06:30
});
}
}
2020-06-02 14:56:51 +06:30
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
2020-06-04 01:36:49 +06:30
var mainModel = Provider.of<MainModel>(context);
2020-10-13 18:38:00 +06:30
var paymentMethodModel = Provider.of<PaymentMethodModel>(context);
2020-10-22 04:14:53 +06:30
var rateModel = Provider.of<ShipmentRateModel>(context);
var rate = rateModel.rate;
2020-10-13 18:38:00 +06:30
2020-10-26 04:41:24 +06:30
final invoiceNumberBox = DisplayText(
labelTextKey: 'invoice.number',
iconData: FontAwesomeIcons.fileInvoice,
text: _invoice?.invoiceNumber ?? "");
2020-10-14 20:56:46 +06:30
final statusBox = DisplayText(
2020-10-24 06:14:07 +06:30
text: _invoice?.status ?? "",
2020-10-14 20:56:46 +06:30
iconData: Icons.av_timer,
labelTextKey: 'invoice.status');
2020-10-22 04:14:53 +06:30
final cartonTable = InvoiceCartonTable(
2021-09-10 12:00:08 +06:30
cartons: _invoice!.cartons,
2020-10-22 05:27:03 +06:30
rate: rate,
2020-10-22 04:14:53 +06:30
onSelect: (c, checked) {
setState(() {
c.isChecked = checked;
});
},
);
2020-10-24 06:14:07 +06:30
final paymentTypesBox = LocalDropdown<PaymentMethod>(
2020-10-22 04:14:53 +06:30
callback: (v) {
setState(() {
2021-09-10 12:00:08 +06:30
_invoice!.paymentMethod = v;
2020-10-22 04:14:53 +06:30
});
},
labelKey: "invoice.payment_method",
iconData: FontAwesome.money,
display: (u) => u.name,
2021-09-10 12:00:08 +06:30
selectedValue: _invoice!.paymentMethod,
2020-10-22 04:14:53 +06:30
values: paymentMethodModel.paymentMethods,
);
2020-10-24 06:14:07 +06:30
final invoiceTableBox = InvoiceTable(
2021-09-10 12:00:08 +06:30
invoice: _invoice!,
2020-10-22 04:14:53 +06:30
rate: rate,
deliveryFeeSelected: (selected) {
setState(() {
if (selected) {
2021-09-10 12:00:08 +06:30
_invoice!.deliveryFee = rate.deliveryFee;
2020-10-22 04:14:53 +06:30
} else {
2021-09-10 12:00:08 +06:30
_invoice!.deliveryFee = 0;
2020-10-22 04:14:53 +06:30
}
});
},
discountSelected: (discount) {
setState(() {
2021-09-10 12:00:08 +06:30
_invoice!.discount = discount;
2020-10-22 04:14:53 +06:30
});
},
2020-10-24 06:14:07 +06:30
onRemove: (i) {
if (i.invoiceDataType == InvoiceDataType.CustomFeeDataType) {
_removeCustom(i.data);
}
if (i.invoiceDataType == InvoiceDataType.DiscountDataType) {
setState(() {
2021-09-10 12:00:08 +06:30
_invoice!.discount = new Discount();
2020-10-24 06:14:07 +06:30
});
}
if (i.invoiceDataType == InvoiceDataType.DeliveryFeeType) {
setState(() {
2021-09-10 12:00:08 +06:30
_invoice!.deliveryFee = 0;
2020-10-24 06:14:07 +06:30
});
}
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: <Widget>[
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) =>
2021-09-10 12:00:08 +06:30
InvoiceHandlingFeeList(shipments: _invoice!.shipments)));
2020-10-24 06:14:07 +06:30
_addShipment(shipment);
} else if (p.id == 3) {
Discount discount =
await Navigator.of(context).push(CupertinoPageRoute(
2020-10-26 04:41:24 +06:30
builder: (context) => InvoiceDiscountList(
2020-10-24 06:14:07 +06:30
discounts: discounts,
)));
if (discount != null) {
setState(() {
2021-09-10 12:00:08 +06:30
_invoice!.discount = discount;
2020-10-24 06:14:07 +06:30
});
}
} else if (p.id == 4) {
setState(() {
2021-09-10 12:00:08 +06:30
_invoice!.deliveryFee = rate.deliveryFee;
2020-10-24 06:14:07 +06:30
});
}
},
2020-10-22 04:14:53 +06:30
);
2020-06-04 01:36:49 +06:30
2020-10-26 04:41:24 +06:30
final headerBox = Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
2021-09-10 12:00:08 +06:30
Text(dateFormatter.format(_invoice!.invoiceDate)),
2020-10-26 04:41:24 +06:30
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,
);
2020-06-02 14:56:51 +06:30
return LocalProgress(
inAsyncCall: _isLoading,
child: Scaffold(
appBar: AppBar(
centerTitle: true,
leading: new IconButton(
2020-10-14 13:54:42 +06:30
icon: new Icon(CupertinoIcons.back, color: primaryColor),
onPressed: () {
Navigator.of(context).pop();
},
2020-06-02 14:56:51 +06:30
),
2020-10-09 19:00:39 +06:30
backgroundColor: Colors.white,
shadowColor: Colors.transparent,
2020-06-02 14:56:51 +06:30
title: LocalText(context, 'invoice.form.title',
2020-10-09 19:00:39 +06:30
color: primaryColor, fontSize: 20),
2020-06-02 14:56:51 +06:30
),
2020-10-14 10:33:14 +06:30
body: Padding(
padding: const EdgeInsets.all(8.0),
child: ListView(
2020-06-02 14:56:51 +06:30
children: <Widget>[
2020-10-26 04:41:24 +06:30
headerBox,
_isNew ? Container() : invoiceNumberBox,
2020-10-22 04:14:53 +06:30
_isNew ? Container() : statusBox,
2020-10-24 06:14:07 +06:30
_showCartons ? cartonTable : Container(),
_showCartons
? Divider(
color: primaryColor,
thickness: 2,
)
: Container(),
invoiceTableBox,
SizedBox(
height: 10,
),
2020-10-22 04:14:53 +06:30
paymentTypesBox,
2020-10-24 06:14:07 +06:30
SizedBox(
height: 10,
),
2020-10-22 04:14:53 +06:30
_isNew
2020-10-26 04:41:24 +06:30
? createBtn
2020-06-26 16:04:40 +06:30
: mainModel.isCustomer()
? Container()
: Container(
child: Column(
children: <Widget>[
2020-10-09 19:00:39 +06:30
fcsButton(context,
getLocalString(context, 'invoice.btn_save'))
2020-06-26 16:04:40 +06:30
],
)),
2020-10-22 04:14:53 +06:30
_isNew
2020-06-02 15:30:11 +06:30
? Container()
2020-10-09 19:00:39 +06:30
: fcsButton(context,
getLocalString(context, 'invoice.btn_payment_receipt'))
2020-06-02 14:56:51 +06:30
],
),
),
),
);
}
2020-10-22 04:14:53 +06:30
_addCustom(CustomDuty customDuty) {
if (customDuty == null) return;
setState(() {
2021-09-10 12:00:08 +06:30
_invoice!.customDuties.remove(customDuty);
_invoice!.customDuties.add(customDuty);
2020-10-22 04:14:53 +06:30
});
2020-06-26 16:04:40 +06:30
}
2020-10-24 06:14:07 +06:30
_addShipment(Shipment shipment) {
if (shipment == null) return;
shipment.isSelected = true;
setState(() {
2021-09-10 12:00:08 +06:30
_invoice!.shipments.remove(shipment);
_invoice!.shipments.add(shipment);
2020-10-24 06:14:07 +06:30
});
}
_removeShipment(Shipment shipment) {
if (shipment == null) return;
shipment.isSelected = false;
setState(() {
2021-09-10 12:00:08 +06:30
_invoice!.shipments.remove(shipment);
_invoice!.shipments.add(shipment);
2020-10-24 06:14:07 +06:30
});
}
2020-10-22 04:14:53 +06:30
_removeCustom(CustomDuty customDuty) {
setState(() {
2021-09-10 12:00:08 +06:30
_invoice!.customDuties.remove(customDuty);
2020-10-22 04:14:53 +06:30
});
2020-06-02 14:56:51 +06:30
}
2020-10-22 04:14:53 +06:30
2020-10-26 04:41:24 +06:30
_save() async {
var rateModel = Provider.of<ShipmentRateModel>(context, listen: false);
2021-09-10 12:00:08 +06:30
double amount = _invoice!.getNetAmount(rateModel.rate);
if (_invoice!.paymentMethod == null) {
2020-10-26 04:41:24 +06:30
showMsgDialog(context, "Error", "Payment method required");
return;
}
2021-09-10 12:00:08 +06:30
List<CargoType> cargoTypes = _invoice!.getCargoTypes(rateModel.rate);
2020-10-26 04:41:24 +06:30
if (cargoTypes == null || cargoTypes.length == 0) {
showMsgDialog(context, "Error", "Expected at least one cargo type");
return;
}
2021-09-10 12:00:08 +06:30
if ((amount ) <= 0) {
2020-10-26 04:41:24 +06:30
showMsgDialog(context, "Error", "Expected positive amount");
return;
}
setState(() {
_isLoading = true;
});
try {
InvoiceModel invoiceModel =
Provider.of<InvoiceModel>(context, listen: false);
Invoice invoice = Invoice();
invoice.cargoTypes = cargoTypes;
invoice.amount = amount;
2021-09-10 12:00:08 +06:30
invoice.handlingFee = _invoice!.getHandlingFee();
invoice.cartons = _invoice!.cartons.where((c) => c.isChecked).toList();
2020-10-26 04:41:24 +06:30
invoice.shipments =
2021-09-10 12:00:08 +06:30
_invoice!.shipments.where((s) => s.isSelected).toList();
invoice.discount = _invoice!.discount;
invoice.deliveryFee = _invoice!.deliveryFee;
2020-10-26 04:41:24 +06:30
2021-09-10 12:00:08 +06:30
invoice.userID = widget.customer!.id;
invoice.fcsShipmentID = widget.fcsShipment!.id;
invoice.invoiceDate = _invoice!.invoiceDate;
invoice.paymentMethod = _invoice!.paymentMethod;
invoice.customDuties = _invoice!.customDuties;
2020-10-26 04:41:24 +06:30
await invoiceModel.createInvoice(invoice);
Navigator.pop(context, true);
} catch (e) {
showMsgDialog(context, "Error", e.toString());
} finally {
setState(() {
_isLoading = false;
});
}
}
2020-06-02 14:56:51 +06:30
}