import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import 'package:fcs/model/language_model.dart'; import 'package:fcs/model/log_model.dart'; import 'package:fcs/model/main_model.dart'; import 'package:fcs/model/po_model.dart'; import 'package:fcs/model/product_model.dart'; import 'package:fcs/pages/po/po_item.dart'; import 'package:fcs/theme/theme.dart'; import 'package:fcs/vo/attach.dart'; import 'package:fcs/vo/po.dart'; import 'package:fcs/widget/img_file.dart'; import 'package:fcs/widget/label_widgets.dart'; import 'package:fcs/widget/local_text.dart'; import 'package:fcs/widget/localization/app_translations.dart'; import 'package:fcs/widget/multi_img_controller.dart'; import 'package:fcs/widget/multi_img_file.dart'; import 'package:fcs/widget/my_data_table.dart'; import 'package:fcs/widget/number_cell.dart'; import 'package:fcs/widget/progress.dart'; import '../../util.dart'; import '../document_log_page.dart'; import '../util.dart'; import 'po_files.dart'; class POSubmissionForm extends StatefulWidget { final POSubmission poSubmission; POSubmissionForm({this.poSubmission}); @override _POSubmissionFormState createState() => _POSubmissionFormState(); } class _POSubmissionFormState extends State { final numberFormatter = new NumberFormat("#,###"); var dateFormatter = new DateFormat('dd MMM yyyy - hh:mm a'); MultiImgController multiImgController = MultiImgController(); TextEditingController _numberController = new TextEditingController(); TextEditingController _storage = new TextEditingController(); TextEditingController _comment = new TextEditingController(); TextEditingController _name = new TextEditingController(); TextEditingController _bizName = new TextEditingController(); List poLines = new List(); bool _isLoading = false; bool _isNew = true; int _amount = 0; String _date = "", _status = ""; POSubmission poSubmission = POSubmission(); AttachFile attachFile; POFiles files = POFiles(); @override void initState() { super.initState(); if (widget.poSubmission != null) { _isNew = false; poSubmission = widget.poSubmission; _date = dateFormatter.format(poSubmission.poDate); _numberController.text = poSubmission.poNumber.toString(); _comment.text = poSubmission.comment; _name.text = poSubmission.userName; _bizName.text = poSubmission.bizName; poLines = poSubmission.poLines; _status = poSubmission.status; _storage.text = poSubmission.storageCharge.toString(); multiImgController.setImageUrls = poSubmission.poReceiptUrls; Provider.of(context, listen: false) .loadPOLines(poSubmission.id) .then((poLines) { setState(() { this.poSubmission.poLines = poLines; _amount = poSubmission.getAmount; }); }); } else { _amount = 0; _date = dateFormatter.format(DateTime.now()); var productModel = Provider.of(context, listen: false); productModel.products.forEach((p) { var _poLine = POLine( productID: p.id, productName: p.name, price: p.price, balanceQty: 0, qty: 0, amount: 0); poSubmission.poLines.add(_poLine); }); } } @override Widget build(BuildContext context) { MainModel mainModel = Provider.of(context); bool isBuyer = mainModel.user.isBuyer(); var logModel = Provider.of(context); final dateBox = Container( padding: EdgeInsets.only(top: 15, left: 20, bottom: 5), child: Row( children: [ LocalText(context, "po.date"), Container( padding: EdgeInsets.only(left: 10), child: Text(_date, style: textStyle), ), ], ), ); final numberBox = Container( padding: EdgeInsets.only(top: 5, left: 20, bottom: 5), child: Row( children: [ LocalText(context, "po.number"), Container( padding: EdgeInsets.only(left: 10), child: Text( _numberController.text, style: textStyle, ), ) ], ), ); final userNameBox = Container( padding: EdgeInsets.only(top: 5, left: 20, bottom: 5), child: Row( children: [ LocalText(context, "po.name"), Container( padding: EdgeInsets.only(left: 20), child: Text( _name.text, style: textStyle, ), ) ], ), ); final bizNameBox = Container( padding: EdgeInsets.only(top: 5, left: 20, bottom: 5), child: Row( children: [ LocalText(context, "po.biz"), Container( padding: EdgeInsets.only(left: 20), child: Text( _bizName.text, style: textStyle, ), ) ], ), ); final statusBox = Container( padding: EdgeInsets.only(top: 5, left: 20), child: Row( children: [ LocalText(context, "po.status"), Container( padding: EdgeInsets.only(left: 10), child: Text( _status, style: textStyle, ), ) ], ), ); final commentBox = Container( padding: EdgeInsets.only(top: 5, left: 20), child: Row( children: [ LocalText(context, "po.comment"), Container( padding: EdgeInsets.only(left: 10), child: Text( _comment.text, style: textStyle, ), ) ], ), ); final amountBox = Container( padding: EdgeInsets.only(top: 5, left: 10), child: labeledText(context, formatNumber(_amount), "po.amount", number: true)); final storageBox = Container( padding: EdgeInsets.only(top: 5, left: 20), child: Row( children: [ LocalText(context, "po.storage_charge"), Container( padding: EdgeInsets.only(left: 10), child: Text( _storage.text, style: textStyle, ), ) ], ), ); final poPaymentBox = Container( padding: EdgeInsets.only(left: 20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ LocalText(context, "po.po_payment_receipt"), MultiImageFile( enabled: isBuyer ? _isNew || this.poSubmission.isPending() ? true : false : false, controller: multiImgController, title: "Receipt File", ) ])); final storagePaymentBox = Container( padding: EdgeInsets.only(left: 20), child: Row(children: [ LocalText(context, "po.storage_receipt"), ImageFile( enabled: isBuyer ? _isNew || this.poSubmission.isPending() ? true : false : false, initialImgUrl: this.poSubmission.storageReceiptUrl, title: "Receipt File", onFile: (file) { this.files.setStorageChargeFile = file; }), ])); return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( appBar: AppBar( backgroundColor: primaryColor, title: Text(AppTranslations.of(context).text("po"), style: Provider.of(context).isEng ? TextStyle(fontSize: 18) : TextStyle(fontSize: 18, fontFamily: 'MyanmarUnicode')), actions: [ _isNew || !mainModel.showHistoryBtn() ? Container() : IconButton( icon: Icon(Icons.history), onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (context) => DocumentLogPage(docID: poSubmission.id)), ); }, ), isBuyer && (_isNew || poSubmission.isPending()) ? IconButton( icon: Icon(Icons.send), onPressed: () { showConfirmDialog(context, "po.confirm", () { _submit(); }); }, ) : Container(), isBuyer ? Container() : PopupMenuButton( onSelected: _select, itemBuilder: (context) => [ PopupMenuItem( enabled: poSubmission.isPending(), value: 1, child: Text("Approve PO"), ), PopupMenuItem( enabled: poSubmission.isPending(), value: 2, child: Text("Reject PO"), ), PopupMenuItem( enabled: mainModel.user.isOwner() && poSubmission.isApproved(), value: 3, child: Text("Cancel PO"), ), ], ), ], ), // floatingActionButton: isBuyer && (_isNew || poSubmission.isPending()) // ? FloatingActionButton( // backgroundColor: primaryColor, // child: Icon(Icons.add), // onPressed: () async { // final POLine poLine = await Navigator.push( // context, // MaterialPageRoute(builder: (context) => POItem()), // ); // _save(poLine); // }, // ) // : null, body: Container( child: ListView( children: [ dateBox, Divider(), _isNew ? Container() : numberBox, _isNew ? Container() : Divider(), _isNew ? Container() : userNameBox, _isNew ? Container() : Divider(), _isNew ? Container() : bizNameBox, _isNew ? Container() : Divider(), _isNew ? Container() : statusBox, _isNew || widget.poSubmission.comment == null || widget.poSubmission.comment == '' ? Container() : Divider(), _isNew || widget.poSubmission.comment == null || widget.poSubmission.comment == '' ? Container() : commentBox, _isNew ? Container() : Divider(), amountBox, Divider(), poPaymentBox, Divider(), _isNew || !poSubmission.hasStorageCharge() ? Container() : storageBox, _isNew || !poSubmission.hasStorageCharge() ? Container() : Divider(), _isNew || !poSubmission.hasStorageCharge() ? Container() : storagePaymentBox, _isNew || !poSubmission.hasStorageCharge() ? Container() : Divider(), Container( child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: MyDataTable( headingRowHeight: 40, columnSpacing: 7, columns: _isNew ? [ MyDataColumn( label: LocalText(context, "po.product")), MyDataColumn( label: LocalText(context, "po.price"), numeric: true), MyDataColumn( label: LocalText(context, "po.volume"), numeric: true), MyDataColumn( label: LocalText(context, "po.amount"), numeric: true), ] : [ MyDataColumn( label: LocalText(context, "po.product")), MyDataColumn( label: LocalText(context, "po.price"), numeric: true), MyDataColumn( label: LocalText(context, "po.balance.volume"), numeric: true), MyDataColumn( label: LocalText(context, "po.volume"), numeric: true), MyDataColumn( label: LocalText(context, "po.amount"), numeric: true), ], rows: getProductRow(poSubmission.poLines), ), ), ), ], ), ), ), ); } _select(s) { if (s == 1) { showConfirmDialog(context, "po.approve.confirm", () { _approve(); }); } else if (s == 2) { showCommentDialog(context, (comment) { this.poSubmission.comment = comment; _reject(); }); } else if (s == 3) { showConfirmDialog(context, "po.cancel.confirm", () { _cancel(); }); } } List getProductRow(List poLines) { MainModel mainModel = Provider.of(context); bool isBuyer = mainModel.user.isBuyer(); ProductModel productModel = Provider.of(context); if (poLines.isNotEmpty) { poLines.forEach((d) { productModel.products.forEach((p) { if (p.id == d.productID) { d.displayOrder = p.displayOrder; } else { return; } }); }); poLines.sort((p1, p2) => p1.displayOrder.compareTo(p2.displayOrder)); } return poLines.map((p) { return MyDataRow( onSelectChanged: (bool selected) async { if (!isBuyer) return; if (_isNew || this.poSubmission.isPending()) { var poLine = await Navigator.push( context, MaterialPageRoute( builder: (context) => POItem( poLine: p, )), ); _save(poLine); } }, cells: _isNew ? [ MyDataCell( new Text( p.productName, style: textStyle, ), ), MyDataCell(NumberCell(p.price)), MyDataCell( Container( alignment: Alignment.centerRight, width: 100, child: NumberCell( p.qty, textStyle: textStyleOdd, ), ), ), MyDataCell(NumberCell(p.amount)), ] : [ MyDataCell( new Text( p.productName, style: textStyle, ), ), MyDataCell(NumberCell(p.price)), MyDataCell(NumberCell(p.balanceQty)), MyDataCell(NumberCell(p.qty)), MyDataCell(NumberCell(p.amount)), ], ); }).toList(); } _save(POLine poLine) { if (poLine == null) return; if (poLine.action == "create") { if (poSubmission.poLines.contains(poLine)) { showMsgDialog(context, "Error", "Duplicate line"); return; } poSubmission.poLines.add(poLine); } else if (poLine.action == "delete") { poSubmission.poLines.remove(poLine); } setState(() { _amount = poSubmission.getAmount; }); } _submit() async { if (poSubmission.poLines.length == 0) { showMsgDialog(context, "Error", "No product line"); return; } List _poLines = []; poSubmission.poLines.forEach((p) => p.qty <= 0 ? _poLines.add(p) : p); poSubmission.poLines.removeWhere((p) => p.qty <= 0); setState(() { _isLoading = true; }); try { POSubmissionModel poModel = Provider.of(context); if (_isNew) { await poModel.createPO(poSubmission, multiImgController.getAddedFile); } else { if (poSubmission.hasStorageCharge()) { if (files.storageChargeFile == null) { showMsgDialog( context, "Error", "Please insert storage charge file"); return; } } await poModel.updatePO(poSubmission, multiImgController.getAddedFile, multiImgController.getDeletedUrl); } Navigator.pop(context); } catch (e) { showMsgDialog(context, "Error", e.toString()); } finally { setState(() { _isLoading = false; _poLines.forEach((e) { if (!poSubmission.poLines.contains(e)) poSubmission.poLines.add(e); }); }); } } _approve() async { setState(() { _isLoading = true; }); var oldStatus = poSubmission.status; try { POSubmissionModel poModel = Provider.of(context); poSubmission.status = "approved"; await poModel.approvePO(poSubmission); Navigator.pop(context); } catch (e) { poSubmission.status = oldStatus; showMsgDialog(context, "Error", e.toString()); } finally { setState(() { _isLoading = false; }); } } _reject() async { setState(() { _isLoading = true; }); try { POSubmissionModel poModel = Provider.of(context); await poModel.rejectPO(poSubmission); Navigator.pop(context); } catch (e) { showMsgDialog(context, "Error", e.toString()); } finally { setState(() { _isLoading = false; }); } } _cancel() async { setState(() { _isLoading = true; }); try { POSubmissionModel poModel = Provider.of(context); await poModel.cancelPO(poSubmission); Navigator.pop(context); } catch (e) { showMsgDialog(context, "Error", e.toString()); } finally { setState(() { _isLoading = false; }); } } }