import 'package:fcs/domain/entities/box.dart'; import 'package:fcs/domain/entities/cargo.dart'; import 'package:fcs/domain/entities/custom.dart'; import 'package:fcs/domain/entities/discount.dart'; import 'package:fcs/domain/entities/invoice.dart'; import 'package:fcs/domain/entities/payment_method.dart'; import 'package:fcs/domain/entities/user.dart'; import 'package:fcs/helpers/theme.dart'; import 'package:fcs/localization/app_translations.dart'; import 'package:fcs/pages/discount/discount_list.dart'; import 'package:fcs/pages/discount/model/discount_model.dart'; import 'package:fcs/pages/invoice/invoice_editor.dart'; import 'package:fcs/pages/main/model/language_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/user_search/user_serach.dart'; import 'package:fcs/pages/widgets/bottom_up_page_route.dart'; import 'package:fcs/pages/widgets/discount_dropdown.dart'; import 'package:fcs/pages/widgets/display_text.dart'; import 'package:fcs/pages/widgets/fcs_id_icon.dart'; import 'package:fcs/pages/widgets/input_text.dart'; import 'package:fcs/pages/widgets/local_dropdown.dart'; import 'package:fcs/pages/widgets/local_text.dart'; import 'package:fcs/pages/widgets/local_title.dart'; import 'package:fcs/pages/widgets/multi_img_controller.dart'; import 'package:fcs/pages/widgets/multi_img_file.dart'; import 'package:fcs/pages/widgets/my_data_table.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'; import 'box_addition.dart'; class InvoiceInfoPage extends StatefulWidget { final Invoice invoice; InvoiceInfoPage({this.invoice}); @override _InvoiceInfoPageState createState() => _InvoiceInfoPageState(); } class _InvoiceInfoPageState extends State { User user; var dateFormatter = new DateFormat('dd MMM yyyy'); TextEditingController _invoiceNumberController = new TextEditingController(); TextEditingController _dateController = new TextEditingController(); TextEditingController _nameController = new TextEditingController(); TextEditingController _phoneController = new TextEditingController(); TextEditingController _discountController = new TextEditingController(); TextEditingController _amountController = new TextEditingController(); TextEditingController _statusController = new TextEditingController(); TextEditingController _handlingFeeController = new TextEditingController(); TextEditingController _customFeeController = new TextEditingController(); MultiImgController multiImgController = MultiImgController(); TextEditingController _descriptionController = new TextEditingController(); TextEditingController _balanceController = new TextEditingController(); Invoice _invoice; bool _isLoading = false; List _boxes = []; bool isSwitched = false; int deliveryfee = 0; int customFee = 0; double total = 0; Discount _discount; bool isNew = false; Discount selectedDiscount; int selectedDiscountAmt; PaymentMethod paymentMethod; double volumetricRatio = 0; List selectedBoxes = []; List customs = []; List _cargoTypes = [ Cargo(type: 'General Cargo', weight: 33, price: 6), Cargo(type: 'Medicine', weight: 33, price: 7), Cargo(type: 'Dangerous Cargo', weight: 33, price: 8) ]; List _receipts = [ "assets/buying_online_with_first_last_name.png", ]; @override void initState() { super.initState(); volumetricRatio = Provider.of(context, listen: false).setting.volumetricRatio; if (widget.invoice != null) { _invoice = widget.invoice; _invoiceNumberController.text = _invoice.invoiceNumber; _dateController.text = dateFormatter.format(_invoice.invoiceDate); _nameController.text = _invoice.customerName; _phoneController.text = _invoice.customerPhoneNumber; // _amountController.text = _invoice.getAmount.toString(); _amountController.text = _invoice.amount.toString(); _statusController.text = _invoice.status.toString(); _handlingFeeController.text = '0'; _customFeeController.text = '0'; // multiImgController.setImageUrls = _receipts; _descriptionController.text = 'For Electronics goods'; _balanceController.text = (_invoice.amount - _invoice.receipts[0].amount).toString(); // _boxes = _invoice.packages; } else { _dateController.text = dateFormatter.format(DateTime.now()); _amountController.text = '0'; _handlingFeeController.text = '0'; _customFeeController.text = '0'; _descriptionController.text = ''; _balanceController.text = '0'; setState(() { isNew = true; }); } _boxes = [ Box( shipmentNumber: "A202", receiverNumber: "3", receiverName: "Ko Myo Min", boxNumber: "1", rate: 7, packageType: "General", weight: 75, status: "Packed", receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon', cargoDesc: "Clothes", arrivedDate: DateTime(2020, 6, 1), width: 10, height: 10, length: 10, // packages: packages, // statusHistory: statusHistory, cargoTypes: [ Cargo(type: 'General Cargo', weight: 25), Cargo(type: 'Medicine', weight: 20), Cargo(type: 'Dangerous Cargo', weight: 30) ]), Box( shipmentNumber: "A202", receiverNumber: "3", receiverName: "Ko Myo Min", boxNumber: "2", rate: 7, packageType: "General", weight: 75, status: "Packed", cargoDesc: "Clothes", arrivedDate: DateTime(2020, 6, 1), width: 10, height: 10, length: 10, // statusHistory: statusHistory, // packages: packages, receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon', cargoTypes: [ Cargo(type: 'General Cargo', weight: 25), Cargo(type: 'Medicine', weight: 20), Cargo(type: 'Dangerous Cargo', weight: 30) ]) ]; } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { var mainModel = Provider.of(context); var discountModel = Provider.of(context); var paymentMethodModel = Provider.of(context); final nameBox = DisplayText( iconData: Feather.user, labelTextKey: 'invoice.customer_name', text: user != null ? user.name : ''); final fcsIDBox = Row( children: [ Expanded( child: DisplayText( text: user != null ? user.fcsID : "", labelTextKey: "box.fcs.id", icon: FcsIDIcon(), )), IconButton( icon: Icon(Icons.search, color: primaryColor), onPressed: () => searchUser(context, callbackUserSelect: (u) { setState(() { this.user = u; }); })), ], ); final statusBox = DisplayText( text: _statusController.text, iconData: Icons.av_timer, labelTextKey: 'invoice.status'); 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), actions: [ new IconButton( icon: Icon( Icons.delete, color: primaryColor, ), onPressed: () {}), new IconButton( icon: Icon( Icons.edit, color: primaryColor, ), onPressed: () { Navigator.of(context).push(CupertinoPageRoute( builder: (context) => InvoiceEditor(invoice: _invoice))); }) ], ), body: Padding( padding: const EdgeInsets.all(8.0), child: ListView( children: [ LocalTitle(textKey: "invoice.customer_info"), DisplayText( labelTextKey: 'invoice.date', iconData: Icons.date_range, text: _dateController.text), widget.invoice == null ? Container() : DisplayText( labelTextKey: 'invoice.number', iconData: FontAwesomeIcons.fileInvoice, text: _invoiceNumberController.text), fcsIDBox, nameBox, statusBox, LocalTitle(textKey: "invoice.box_info"), Center(child: Column(children: getCartonRows(context))), SizedBox(height: 20), LocalTitle(textKey: "invoice.custom_fee"), Column(children: getCustomFeeRows(context)), SizedBox(height: 20), LocalTitle(textKey: "invoice.cargo_type"), Column(children: getCargoTableByBox(context)), SizedBox(height: 20), Container( padding: EdgeInsets.only(top: 5, left: 18), child: Row( children: [ Expanded( child: LocalText(context, 'invoice.payment_method', fontSize: 16, color: Colors.grey, fontWeight: FontWeight.bold), ), Text( '${paymentMethod != null ? paymentMethod.accountName : "KBZ Bank"}', style: TextStyle(fontSize: 16)), ], ), ), SizedBox(height: 30), !isNew ? LocalTitle(textKey: "invoice.payment_attachment") : Container(), ], ), ), ), ); } getCartonRows(BuildContext context) { List dataRow = []; dataRow = _boxes.map((box) { return Container( height: 50, decoration: BoxDecoration( border: Border(bottom: BorderSide(color: Colors.grey))), padding: const EdgeInsets.only(left: 5.0, right: 5.0, top: 5.0, bottom: 5.0), child: Row( children: [ Expanded(flex: 2, child: Text(box.packageNumber)), Expanded( flex: 1, child: Text( box.length == null ? "" : box.length.toString() + ' x ' + box.length.toString() + ' x ' + box.height.toString(), textAlign: TextAlign.center)), Expanded( flex: 2, child: Center( child: Text( box.getShipmentWeight(volumetricRatio).toString()))), ], ), ); }).toList(); dataRow.insert( 0, Container( decoration: BoxDecoration( border: Border(bottom: BorderSide(color: Colors.grey))), padding: const EdgeInsets.only( left: 5.0, right: 5.0, top: 5.0, bottom: 15.0), child: Row( children: [ Expanded( flex: 2, child: LocalText( context, "invoice.box.number", color: Colors.grey, )), Expanded( flex: 1, child: Text('L x W x H', style: TextStyle(color: Colors.grey))), Expanded( flex: 2, child: LocalText( context, "invoice.shipment_weight", color: Colors.grey, )), ], ), )); return dataRow; } getCustomFeeRows(BuildContext context) { customFee = 0; List dataRow = []; dataRow = customs.map((custom) { customFee += custom.fee; return Container( decoration: BoxDecoration( border: Border(bottom: BorderSide(color: Colors.grey))), padding: const EdgeInsets.only(left: 5.0, right: 5.0, top: 5.0, bottom: 5.0), child: Row( children: [ Expanded(flex: 2, child: Text('${custom.productType}')), Expanded( flex: 1, child: Text('\$ ${custom.fee}', textAlign: TextAlign.center)), Expanded(child: SizedBox(height: 40)) ], ), ); }).toList(); dataRow.insert( 0, Container( decoration: BoxDecoration( border: Border(bottom: BorderSide(color: Colors.grey))), padding: const EdgeInsets.only( left: 5.0, right: 5.0, top: 15.0, bottom: 15.0), child: Row( children: [ Expanded( flex: 2, child: Text('Product', style: TextStyle(color: Colors.grey))), Expanded( flex: 1, child: Text('Fee', textAlign: TextAlign.center, style: TextStyle(color: Colors.grey))), Expanded(flex: 1, child: Container()) ], ), )); dataRow.insert( dataRow.length, Container( padding: const EdgeInsets.only( left: 5.0, right: 5.0, top: 15.0, bottom: 15.0), child: Row( children: [ Expanded( flex: 2, child: Center( child: LocalText( context, 'invoice.total_custom_fee', color: Colors.black, fontWeight: FontWeight.bold, ), ), ), Expanded( flex: 1, child: Center( child: Text('\$ $customFee', textAlign: TextAlign.center, style: TextStyle(fontWeight: FontWeight.bold)))), Expanded( child: Container(), ) ], ), )); return dataRow; } getCargoTableByBox(BuildContext context) { total = 0; List dataRow = _cargoTypes.map((cargo) { var amount = cargo.weight * cargo.price; total += amount; return Container( decoration: BoxDecoration( border: Border(bottom: BorderSide(color: Colors.grey))), padding: const EdgeInsets.only( left: 5.0, right: 5.0, top: 15.0, bottom: 15.0), child: Row( children: [ Expanded(flex: 2, child: Text('${cargo.type}')), Expanded( flex: 2, child: Text('${cargo.weight} x ${cargo.price}', textAlign: TextAlign.center)), Expanded( child: Text('\$ $amount', textAlign: TextAlign.end, style: TextStyle( fontSize: 15, fontWeight: FontWeight.bold, ))) ], ), ); }).toList(); dataRow.insert( 0, Container( padding: const EdgeInsets.only( left: 5.0, right: 5.0, top: 15.0, bottom: 15.0), decoration: BoxDecoration( border: Border(bottom: BorderSide(color: Colors.grey))), child: Row( children: [ Expanded( flex: 2, child: Text(getLocalString(context, 'invoice.box.cargo_type'), style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: Colors.grey))), Expanded( flex: 2, child: Text( getLocalString(context, 'cargo.weight') + ' x ' + getLocalString(context, 'cargo.rate'), textAlign: TextAlign.center, style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: Colors.grey))), Expanded( child: Text(getLocalString(context, 'invoice.amount'), textAlign: TextAlign.end, style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: Colors.grey))) ], ), )); dataRow.insert( dataRow.length, Container( padding: const EdgeInsets.only( left: 5.0, right: 5.0, top: 10.0, bottom: 10.0), child: Row( children: [ Expanded( flex: 2, child: Center( child: LocalText( context, 'invoice.total', color: Colors.black, ), ), ), Expanded( child: Text( '\$ $total', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), textAlign: TextAlign.end, )) ], ), )); dataRow.insert( dataRow.length, Container( padding: const EdgeInsets.only(left: 5.0, right: 5.0), child: Row( children: [ Expanded( flex: 2, child: Center( child: LocalText( context, 'invoice.discount_value', color: Colors.black, ), ), ), Expanded( child: Text( '\$ ${_discount != null ? _discount.amount.toInt() : 0}', textAlign: TextAlign.end, style: TextStyle( fontSize: 15, fontWeight: FontWeight.bold, ))) ], ), )); dataRow.insert( dataRow.length, Container( padding: const EdgeInsets.only( left: 5.0, right: 5.0, top: 10.0, bottom: 0.0), child: Row( children: [ Expanded( flex: 2, child: Center( child: LocalText( context, 'invoice.custom_fee', color: Colors.black, ), )), Expanded( child: Text('\$ $customFee', textAlign: TextAlign.end, style: TextStyle( fontSize: 15, fontWeight: FontWeight.bold, )), ), ], ), )); dataRow.insert( dataRow.length, Container( padding: const EdgeInsets.only( left: 5.0, right: 5.0, top: 20.0, bottom: 0.0), child: Row( children: [ Expanded( flex: 2, child: Center( child: LocalText( context, 'invoice.handling_fee', color: Colors.black, ), )), Expanded( child: Text('\$ $customFee', textAlign: TextAlign.end, style: TextStyle( fontSize: 15, fontWeight: FontWeight.bold, )), ), ], ), )); dataRow.insert( dataRow.length, Container( padding: const EdgeInsets.only( left: 5.0, right: 5.0, top: 10.0, bottom: 10.0), child: Row( children: [ Expanded( flex: 2, child: Center( child: LocalText( context, 'invoice.delivery_fee', color: Colors.black, ), ), ), Expanded( child: Text('\$ $deliveryfee', textAlign: TextAlign.end, style: TextStyle( fontSize: 15, fontWeight: FontWeight.bold, ))) ], ), )); dataRow.insert( dataRow.length, Container( child: Row( children: [ Expanded(child: Text('')), Expanded( flex: 2, child: Divider( thickness: 3, )), ], ))); dataRow.insert( dataRow.length, Container( padding: const EdgeInsets.only( left: 5.0, right: 5.0, top: 10.0, bottom: 10.0), child: Row( children: [ Expanded( flex: 2, child: Center( child: LocalText( context, 'invoice.net_amount', color: Colors.black, fontSize: 15, fontWeight: FontWeight.bold, ), ), ), Expanded( child: Text('\$ ${getTotalBalance(total)}', textAlign: TextAlign.end, style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: primaryColor))) ], ), )); dataRow.insert( dataRow.length, Container( padding: const EdgeInsets.only( left: 5.0, right: 5.0, top: 10.0, bottom: 10.0), child: Row( children: [ Expanded( flex: 2, child: Center( child: LocalText( context, 'invoice.balance', color: Colors.black, fontSize: 15, fontWeight: FontWeight.bold, ), ), ), Expanded( child: Text('\$ ${getTotalBalance(total)}', textAlign: TextAlign.end, style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: primaryColor))) ], ), )); return dataRow; } getTotalBalance(total) { double balance = 0; double custom = customFee != 0 ? customFee.toDouble() : 0; double deliveryFee = deliveryfee != 0 ? deliveryfee.toDouble() : 0; double discount = _discount != null ? _discount.amount.toDouble() : 0; balance = (total + custom + deliveryFee) - discount; return balance; } List getBoxRow(BuildContext context) { return _boxes.map((p) { p.cargoTypes.map((cargo) { _cargoTypes.asMap().map((index, _cargo) { if (_cargo.type == cargo.type) { setState(() { _cargoTypes[index].weight += cargo.weight; }); } }); }); return MyDataRow( onSelectChanged: (bool selected) {}, cells: [ MyDataCell(Checkbox( value: true, onChanged: (value) { selectedBoxes.add(p); }, )), MyDataCell(new Text( p.boxNumber == null ? "" : '${p.shipmentNumber}-${p.receiverNumber} #${p.boxNumber}', style: textStyle, )), MyDataCell(new Text( p.length == null ? "" : p.length.toString() + ' x ' + p.length.toString() + ' x ' + p.height.toString(), style: textStyle, )), ], ); }).toList(); } List getCargoDataRow(BuildContext context) { return _cargoTypes.asMap().entries.map((c) { var cargo = c.value; var amt = cargo.weight * cargo.price; return MyDataRow( onSelectChanged: (bool selected) {}, cells: [ MyDataCell(new Text( cargo.type, style: textStyle, )), MyDataCell(new Text( cargo.weight.toString() + ' x ' + cargo.price.toString(), style: textStyle, )), MyDataCell(new Text( "\$$amt", style: textStyle, )), ], ); }).toList() // .insert(_cargoTypes.length,MyDataRow(cells: [ // MyDataCell(new Text('')), // MyDataCell(new Text('Total')), // MyDataCell(new Text( // "\$5000", // style: textStyle, // )), // ]) // ) ; } }