diff --git a/assets/local/localization_en.json b/assets/local/localization_en.json index c699960..b0b40fa 100644 --- a/assets/local/localization_en.json +++ b/assets/local/localization_en.json @@ -294,7 +294,8 @@ "box.carton_size.name":"Name", "box.cargo_total_title":"Edit Total Weight", "box.new_carton_btn":"Create new carton", - "box.select.cargo.title":"Select cargos", + "box.select.cargo.title":"Cargo Types", + "box.select.cargo.special":"Special Cargos", "box.complete.packaging":"Complete Packaging", "box.mix_caton_title":"Mix cartons", "box.min_caton.form.title":"Mix Carton", @@ -543,6 +544,8 @@ "receiving.delete.confirm":"Delete this receiving?", "receiving.return.btn":"Return package", "receiving.return.confirm":"Return package?", + "receiving.consignee.name":"Consignee name", + "receiving.shipper.name":"Sender name", "Receiving End ================================================================":"", "Processing Start ================================================================":"", diff --git a/lib/domain/entities/package.dart b/lib/domain/entities/package.dart index e63a9b5..9eb3249 100644 --- a/lib/domain/entities/package.dart +++ b/lib/domain/entities/package.dart @@ -20,6 +20,7 @@ class Package { String shipmentNumber; String senderFCSID; String senderName; + String senderPhoneNumber; String boxNumber; String cargoDesc; String market; @@ -68,6 +69,7 @@ class Package { this.deliveryAddress, this.isChecked = false, this.photoFiles, + this.senderPhoneNumber }); factory Package.fromMap(Map map, String docID) { @@ -92,6 +94,9 @@ class Package { remark: map['remark'], desc: map['desc'], status: map['status'], + senderFCSID: map['sender_fcs_id'], + senderName: map['sender_name'], + senderPhoneNumber: map['sender_phone_number'], deliveryAddress: _da, currentStatusDate: _currentStatusDate != null ? _currentStatusDate.toDate().toLocal() @@ -118,6 +123,9 @@ class Package { market: json['market'], userName: json['user_name'], phoneNumber: json['phone_number'], + senderFCSID: json['sender_fcs_id'], + senderName: json['sender_name'], + senderPhoneNumber: json['sender_phone_number'], status: json['status'], currentStatusDate: DateTime.parse(json['status_date'])); } diff --git a/lib/pages/carton/cargo_type_addtion.dart b/lib/pages/carton/cargo_type_addtion.dart index 8aec5b4..9cf3e11 100644 --- a/lib/pages/carton/cargo_type_addtion.dart +++ b/lib/pages/carton/cargo_type_addtion.dart @@ -1,8 +1,6 @@ import 'package:fcs/domain/entities/cargo_type.dart'; -import 'package:fcs/domain/entities/custom_duty.dart'; import 'package:fcs/helpers/theme.dart'; import 'package:fcs/pages/main/util.dart'; -import 'package:fcs/pages/rates/custom_list.dart'; import 'package:fcs/pages/rates/model/shipment_rate_model.dart'; import 'package:fcs/pages/widgets/local_text.dart'; import 'package:fcs/pages/widgets/local_title.dart'; @@ -20,19 +18,31 @@ class _CargoTypeAdditionState extends State { bool _isLoading = false; List cargos = []; + List specialCargos = []; @override void initState() { super.initState(); var shipmentRateModel = Provider.of(context, listen: false); - cargos = List.from(shipmentRateModel.rate.cargoTypes); + + cargos = shipmentRateModel.rate.cargoTypes.map((e) => e.clone()).toList(); + specialCargos = List.from(shipmentRateModel.rate.customDuties); + specialCargos = + shipmentRateModel.rate.customDuties.map((e) => e.clone()).toList(); + cargos.forEach((p) { p.isChecked = false; p.isCutomDuty = false; p.weight = 0; p.qty = null; }); + specialCargos.forEach((p) { + p.isChecked = false; + p.isCutomDuty = true; + p.weight = 0; + p.qty = 1; + }); } @override @@ -42,40 +52,31 @@ class _CargoTypeAdditionState extends State { @override Widget build(BuildContext context) { - List getCargoRowList() { - return cargos.map((c) { + List getCargoRowList(List _c) { + return _c.map((c) { return Container( child: Container( padding: EdgeInsets.only(left: 10.0, right: 5.0, top: 3.0, bottom: 3.0), - child: Row( - children: [ - Checkbox( - value: c.isChecked, - activeColor: primaryColor, - onChanged: (bool check) { - setState(() { - c.isChecked = check; - }); - }), - new Text(c.name, style: textStyle), - c.isCutomDuty - ? Padding( - padding: const EdgeInsets.only(left: 15), - child: IconButton( - onPressed: () { - setState(() { - cargos.removeWhere((t) => t.name == c.name); - }); - }, - icon: Icon( - Icons.remove_circle, - color: Colors.black45, - ), - ), - ) - : Container(), - ], + child: InkWell( + onTap: () { + setState(() { + c.isChecked = !c.isChecked; + }); + }, + child: Row( + children: [ + Checkbox( + value: c.isChecked, + activeColor: primaryColor, + onChanged: (bool check) { + setState(() { + c.isChecked = check; + }); + }), + new Text(c.name, style: textStyle), + ], + ), ), ), ); @@ -88,6 +89,9 @@ class _CargoTypeAdditionState extends State { callack: () { List _cargos = this.cargos.where((c) => c.isChecked).toList(); + List _scargos = + this.specialCargos.where((c) => c.isChecked).toList(); + _cargos.addAll(_scargos); Navigator.pop(context, _cargos); }, ); @@ -117,21 +121,15 @@ class _CargoTypeAdditionState extends State { children: [ LocalTitle( textKey: "box.select.cargo.title", - trailing: IconButton( - icon: Icon( - Icons.add_circle, - color: primaryColor, - ), - onPressed: () async { - CargoType customDuty = await Navigator.of(context).push( - CupertinoPageRoute( - builder: (context) => - CustomList(selected: true))); - _addCustom(customDuty); - }), ), Column( - children: getCargoRowList(), + children: getCargoRowList(cargos), + ), + LocalTitle( + textKey: "box.select.cargo.title", + ), + Column( + children: getCargoRowList(specialCargos), ), SizedBox(height: 30), saveBtn, @@ -142,21 +140,4 @@ class _CargoTypeAdditionState extends State { ), ); } - - _addCustom(CargoType customDuty) { - if (customDuty == null) return; - - if (cargos.any((c) => c.name == customDuty.name)) return; - - // setState(() { - // cargos.add(CargoType( - // name: customDuty.productType, isCutomDuty: true, qty: 1, weight: 0)); - // }); - - setState(() { - customDuty.qty = 1; - customDuty.isChecked = false; - cargos.add(customDuty); - }); - } } diff --git a/lib/pages/carton/cargo_type_editor.dart b/lib/pages/carton/cargo_type_editor.dart index 78c4b32..fb6376b 100644 --- a/lib/pages/carton/cargo_type_editor.dart +++ b/lib/pages/carton/cargo_type_editor.dart @@ -1,6 +1,5 @@ import 'package:fcs/domain/entities/cargo_type.dart'; import 'package:fcs/helpers/theme.dart'; -import 'package:fcs/pages/main/model/main_model.dart'; import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/rates/model/shipment_rate_model.dart'; import 'package:fcs/pages/widgets/input_text.dart'; diff --git a/lib/pages/carton/carton_cargo_table.dart b/lib/pages/carton/carton_cargo_table.dart index 67df836..d67eda5 100644 --- a/lib/pages/carton/carton_cargo_table.dart +++ b/lib/pages/carton/carton_cargo_table.dart @@ -7,19 +7,17 @@ import 'package:fcs/pages/widgets/my_data_table.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'cargo_type_editor.dart'; - -typedef OnAdd(CargoType cargoType); typedef OnRemove(CargoType cargoType); +typedef OnUpdate(CargoType cargoType); class CargoTable extends StatefulWidget { final List cargoTypes; final bool isNew; - final OnAdd onAdd; final OnRemove onRemove; + final OnUpdate onUpdate; const CargoTable( - {Key key, this.cargoTypes, this.isNew, this.onAdd, this.onRemove}) + {Key key, this.cargoTypes, this.isNew, this.onRemove, this.onUpdate}) : super(key: key); @override @@ -28,26 +26,23 @@ class CargoTable extends StatefulWidget { class _CargoTableState extends State { double totalWeight = 0; - List _cargos = []; - double remainingWeight = 0; - List _list = []; - List _types = []; + List cargoTypes; @override void initState() { + cargoTypes = widget.cargoTypes; if (!widget.isNew) { - totalWeight = widget.cargoTypes - .fold(0, (previous, current) => previous + current.weight); + totalWeight = + cargoTypes.fold(0, (previous, current) => previous + current.weight); } + super.initState(); } @override Widget build(BuildContext context) { - remainingWeight = - widget.cargoTypes.length == 0 ? this.totalWeight : remainingWeight; - this._cargos = widget.cargoTypes.length == 0 ? [] : this._cargos; - + print("Cargotypes:${cargoTypes.length}"); + return SingleChildScrollView( scrollDirection: Axis.horizontal, child: MyDataTable( @@ -82,13 +77,10 @@ class _CargoTableState extends State { } List getCargoRows(BuildContext context) { - if (widget.cargoTypes == null) { + if (cargoTypes == null) { return []; } - - CargoType cargo; - - var rows = widget.cargoTypes.map((c) { + var rows = cargoTypes.map((c) { return MyDataRow( onSelectChanged: (bool selected) async {}, cells: [ @@ -109,8 +101,9 @@ class _CargoTableState extends State { if (_t == null) return; setState(() { - c.qty = int.parse(_t); + c.qty = int.tryParse(_t) ?? 0; }); + if (widget.onUpdate != null) widget.onUpdate(c); }, child: Center( child: Container( @@ -155,37 +148,12 @@ class _CargoTableState extends State { if (_t == null) return; setState(() { - c.weight = double.parse(_t); + c.weight = double.tryParse(_t) ?? 0; }); - - cargo = c; - this._cargos.add(cargo); - if (this.remainingWeight <= 0) return; - this.remainingWeight -= cargo.weight; - - this._cargos.forEach((c) { - _list.add(c.name); - }); - - widget.cargoTypes.forEach((c) { - _types.add(c.name); - }); - - if (this._cargos.length == widget.cargoTypes.length - 1) { - _types.forEach((t) { - if (!_list.contains(t)) { - widget.cargoTypes.forEach((c) { - if (c.name == t) { - c.weight = this.remainingWeight; - setState(() { - this._cargos = []; - }); - } - }); - } - }); - this.remainingWeight = this.totalWeight; + if (c.weight != 0) { + _cal(); } + if (widget.onUpdate != null) widget.onUpdate(c); }, child: Container( padding: const EdgeInsets.all(7.0), @@ -246,9 +214,9 @@ class _CargoTableState extends State { if (_t == null) return; setState(() { - totalWeight = double.parse(_t); - remainingWeight = totalWeight; + totalWeight = double.tryParse(_t) ?? 0; }); + _cal(); }, child: Container( padding: const EdgeInsets.all(7.0), @@ -268,77 +236,29 @@ class _CargoTableState extends State { return rows; } - List _getCargoRows(BuildContext context) { - if (widget.cargoTypes == null) { - return []; - } - double total = 0; - var rows = widget.cargoTypes.map((c) { - total += c.weight; - return MyDataRow( - onSelectChanged: (bool selected) async { - CargoType cargo = await Navigator.push( - context, - CupertinoPageRoute( - builder: (context) => CargoTypeEditor( - cargo: c, - ))); - if (widget.onAdd != null) widget.onAdd(cargo); - }, - cells: [ - MyDataCell(new Text( - c.name == null ? "" : c.name, - style: textStyle, - )), - MyDataCell( - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Text(c.weight == null ? "0" : c.weight.toStringAsFixed(2), - style: textStyle), - widget.onRemove == null - ? SizedBox( - width: 50, - ) - : IconButton( - icon: Icon( - Icons.remove_circle, - color: primaryColor, - ), - onPressed: () { - if (widget.onRemove != null) widget.onRemove(c); - }) - ], - ), - ), - ], - ); - }).toList(); + _cal() { + var cargoType = autoCalWeight(cargoTypes, totalWeight); + if (cargoType == null) return; - var totalRow = MyDataRow( - onSelectChanged: (bool selected) {}, - cells: [ - MyDataCell(Align( - alignment: Alignment.centerRight, - child: LocalText( - context, - "shipment.cargo.total", - color: Colors.black87, - fontWeight: FontWeight.bold, - ), - )), - MyDataCell( - Padding( - padding: const EdgeInsets.only(right: 48.0), - child: Align( - alignment: Alignment.centerRight, - child: Text(total.toStringAsFixed(2), - style: TextStyle(fontWeight: FontWeight.bold))), - ), - ), - ], - ); - rows.add(totalRow); - return rows; + setState(() { + cargoTypes.remove(cargoType); + cargoTypes.add(cargoType); + }); + + if (widget.onUpdate != null) { + widget.onUpdate(cargoType); + } } } + +CargoType autoCalWeight(List cargoTypes, double total) { + if ((cargoTypes?.length ?? 0) == 0 || total == 0) return null; + List noWeight = cargoTypes.where((c) => c.weight == 0).toList(); + if (noWeight.length != 1) return null; + + var _existing = + cargoTypes.fold(0, (previous, current) => previous + current.weight); + + noWeight[0].weight = total - _existing; + return noWeight[0]; +} diff --git a/lib/pages/carton/carton_editor.dart b/lib/pages/carton/carton_editor.dart index 64d5c65..ca72b34 100644 --- a/lib/pages/carton/carton_editor.dart +++ b/lib/pages/carton/carton_editor.dart @@ -76,6 +76,8 @@ class _CartonEditorState extends State { User sender; List _cartonsFromCartons = []; + double totalWeight; + @override void initState() { super.initState(); @@ -410,8 +412,8 @@ class _CartonEditorState extends State { CupertinoPageRoute(builder: (context) => CargoTypeAddition())); if (cargos == null) return; setState(() { - _cargoTypes.clear(); - _cargoTypes.addAll(cargos); + _cargoTypes.addAll( + cargos.where((e) => !_cargoTypes.contains(e)).toList()); }); }), ); @@ -419,8 +421,8 @@ class _CartonEditorState extends State { final cargoTableBox = CargoTable( isNew: _isNew, cargoTypes: _cargoTypes, - onAdd: (c) => _addCargo(c), onRemove: (c) => _removeCargo(c), + onUpdate: (c) => _updateCargo(c), ); final lengthBox = LengthPicker( @@ -779,20 +781,23 @@ class _CartonEditorState extends State { ); } - _addCargo(CargoType cargo) { - if (cargo == null) return; - setState(() { - _cargoTypes.remove(cargo); - _cargoTypes.add(cargo); - }); - } - _removeCargo(CargoType cargo) { setState(() { _cargoTypes.remove(cargo); }); } + _updateCargo(CargoType cargo) { + setState(() { + var _c = + _cargoTypes.firstWhere((e) => e.id == cargo.id, orElse: () => null); + if (_c != null) { + _c.weight = cargo.weight; + _c.qty = cargo.qty; + } + }); + } + _addCarton() async { bool isFromPackages = _selectedCartonType == carton_from_packages; bool isFromCartons = _selectedCartonType == carton_from_cartons; @@ -931,6 +936,10 @@ class _CartonEditorState extends State { showMsgDialog(context, "Error", "Expect at least one cargo type"); return; } + if (_cargoTypes.where((c) => c.weight <= 0).isNotEmpty) { + showMsgDialog(context, "Error", "Invalid cargo weight"); + return; + } double l = double.parse(_lengthController.text, (s) => 0); double w = double.parse(_widthController.text, (s) => 0); double h = double.parse(_heightController.text, (s) => 0); diff --git a/lib/pages/carton/package_carton_editor.dart b/lib/pages/carton/package_carton_editor.dart index 92367fa..87f48e4 100644 --- a/lib/pages/carton/package_carton_editor.dart +++ b/lib/pages/carton/package_carton_editor.dart @@ -138,9 +138,10 @@ class _PackageCartonEditorState extends State { context, CupertinoPageRoute(builder: (context) => CargoTypeAddition())); if (cargos == null) return; + if (cargos == null) return; setState(() { - _cargoTypes.clear(); - _cargoTypes.addAll(cargos); + _cargoTypes.addAll( + cargos.where((e) => !_cargoTypes.contains(e)).toList()); }); }), ); @@ -148,8 +149,8 @@ class _PackageCartonEditorState extends State { final cargoTableBox = CargoTable( isNew: widget.isNew, cargoTypes: _cargoTypes, - onAdd: (c) => _addCargo(c), onRemove: (c) => _removeCargo(c), + onUpdate: (c) => _updateCargo(c), ); return LocalProgress( @@ -286,20 +287,23 @@ class _PackageCartonEditorState extends State { ); } - _addCargo(CargoType cargo) { - if (cargo == null) return; - setState(() { - _cargoTypes.remove(cargo); - _cargoTypes.add(cargo); - }); - } - _removeCargo(CargoType cargo) { setState(() { _cargoTypes.remove(cargo); }); } + _updateCargo(CargoType cargo) { + setState(() { + var _c = + _cargoTypes.firstWhere((e) => e.id == cargo.id, orElse: () => null); + if (_c != null) { + _c.weight = cargo.weight; + _c.qty = cargo.qty; + } + }); + } + _creatCarton() async { if ((_cargoTypes?.length ?? 0) == 0) { showMsgDialog(context, "Error", "Expect at least one cargo type"); diff --git a/lib/pages/processing/processing_info.dart b/lib/pages/processing/processing_info.dart index 55aab36..735de59 100644 --- a/lib/pages/processing/processing_info.dart +++ b/lib/pages/processing/processing_info.dart @@ -2,7 +2,6 @@ import 'package:fcs/domain/entities/package.dart'; import 'package:fcs/helpers/theme.dart'; import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/package/model/package_model.dart'; -import 'package:fcs/pages/widgets/bottom_up_page_route.dart'; import 'package:fcs/pages/widgets/display_text.dart'; import 'package:fcs/pages/widgets/fcs_id_icon.dart'; import 'package:fcs/pages/widgets/local_text.dart'; @@ -71,7 +70,22 @@ class _ProcessingInfoState extends State { ); final customerNameBox = DisplayText( text: _package.userName, - labelTextKey: "processing.name", + labelTextKey: "processing.consignee.name", + iconData: Icons.perm_identity, + ); + var senderFcsIDBox = DisplayText( + text: _package.senderFCSID, + labelTextKey: "processing.fcs.id", + icon: FcsIDIcon(), + ); + final senderPhoneNumberBox = DisplayText( + text: _package.senderPhoneNumber, + labelTextKey: "processing.phone", + iconData: Icons.phone, + ); + final senderNameBox = DisplayText( + text: _package.senderName, + labelTextKey: "processing.shipper.name", iconData: Icons.perm_identity, ); final marketBox = DisplayText( @@ -95,6 +109,24 @@ class _ProcessingInfoState extends State { title: "Receipt File", ); + final consigneeBox = Container( + child: Column( + children: [ + fcsIDBox, + phoneNumberBox, + customerNameBox, + ], + ), + ); + final shipperBox = Container( + child: Column( + children: [ + senderFcsIDBox, + senderPhoneNumberBox, + senderNameBox, + ], + ), + ); return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( @@ -131,9 +163,12 @@ class _ProcessingInfoState extends State { padding: const EdgeInsets.all(10.0), child: ListView(children: [ trackingIdBox, - fcsIDBox, - customerNameBox, - phoneNumberBox, + Row( + children: [ + Flexible(child: consigneeBox), + Flexible(child: shipperBox) + ], + ), marketBox, descBox, remarkBox, diff --git a/lib/pages/receiving/receiving_editor.dart b/lib/pages/receiving/receiving_editor.dart index 0d99f66..b8ccc7a 100644 --- a/lib/pages/receiving/receiving_editor.dart +++ b/lib/pages/receiving/receiving_editor.dart @@ -125,7 +125,7 @@ class _ReceivingEditorState extends State { ); final namebox = DisplayText( text: user != null ? user.name : "", - labelTextKey: "receiving.name", + labelTextKey: "receiving.consignee.name", iconData: Icons.person, );