905 lines
27 KiB
Dart
905 lines
27 KiB
Dart
import 'dart:typed_data';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/widgets.dart';
|
|
import 'package:image_picker/image_picker.dart';
|
|
import 'package:intl/intl.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'package:quiver/async.dart';
|
|
import 'package:fcs/model/do_model.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/do/photo_page.dart';
|
|
import 'package:fcs/theme/theme.dart';
|
|
import 'package:fcs/vo/do.dart';
|
|
import 'package:fcs/vo/po.dart';
|
|
import 'package:fcs/widget/img_file.dart';
|
|
import 'package:fcs/widget/local_text.dart';
|
|
import 'package:fcs/widget/localization/app_translations.dart';
|
|
import 'package:fcs/widget/my_data_table.dart';
|
|
import 'package:fcs/widget/number_cell.dart';
|
|
import 'package:fcs/widget/progress.dart';
|
|
|
|
import '../document_log_page.dart';
|
|
import '../util.dart';
|
|
import 'do_files.dart';
|
|
import 'do_storage_item.dart';
|
|
|
|
class DOApproval extends StatefulWidget {
|
|
final DOSubmission doSubmission;
|
|
const DOApproval({this.doSubmission});
|
|
@override
|
|
_DOApprovalState createState() => _DOApprovalState();
|
|
}
|
|
|
|
class _DOApprovalState extends State<DOApproval> {
|
|
var dateFormatter = new DateFormat('dd MMM yyyy');
|
|
final numberFormatter = new NumberFormat("#,###");
|
|
var doDateFormatter = new DateFormat('dd MMM yyyy - hh:mm a');
|
|
|
|
bool _isLoading = false;
|
|
TextEditingController _date = new TextEditingController();
|
|
TextEditingController _doDate = new TextEditingController();
|
|
TextEditingController _number = new TextEditingController();
|
|
TextEditingController _licence = new TextEditingController();
|
|
TextEditingController _driver = new TextEditingController();
|
|
TextEditingController _carNo = new TextEditingController();
|
|
TextEditingController _type = new TextEditingController();
|
|
TextEditingController _name = new TextEditingController();
|
|
TextEditingController _bizName = new TextEditingController();
|
|
TextEditingController _storage = new TextEditingController();
|
|
TextEditingController _comment = new TextEditingController();
|
|
DOSubmission doObj = DOSubmission();
|
|
int _count;
|
|
DateTime _result;
|
|
DOFiles files = DOFiles();
|
|
List<DOLine> doLines = new List();
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
var mainModel = Provider.of<MainModel>(context, listen: false);
|
|
var doModel = Provider.of<DOModel>(context, listen: false);
|
|
|
|
doObj = widget.doSubmission;
|
|
_date.text = doObj.deliveryDate != null
|
|
? dateFormatter.format(doObj.deliveryDate)
|
|
: "";
|
|
_doDate.text =
|
|
doObj.doDate != null ? doDateFormatter.format(doObj.doDate) : "";
|
|
_number.text = doObj.doNumber.toString();
|
|
_licence.text = doObj.driverLicenseNumber;
|
|
_driver.text = doObj.driverName;
|
|
_carNo.text = doObj.carNo;
|
|
_type.text = doObj.type;
|
|
_name.text = doObj.userName;
|
|
_bizName.text = doObj.bizName;
|
|
_storage.text = doObj.storageCharge == null
|
|
? ""
|
|
: numberFormatter.format(doObj.storageCharge);
|
|
_comment.text = doObj.comment;
|
|
|
|
if (doObj.deliveryStatus == 'initiated') {
|
|
_count = doModel.timber;
|
|
|
|
Duration diff = DateTime.now().difference(doObj.deliveryInitiatedTime);
|
|
|
|
if (diff.inMinutes < mainModel.setting.deliveryStartWaitMin) {
|
|
var time = mainModel.setting.deliveryStartWaitMin - diff.inMinutes;
|
|
new CountdownTimer(
|
|
new Duration(minutes: time), new Duration(seconds: 1))
|
|
.listen((data) {
|
|
if (mounted) {
|
|
setState(() {
|
|
_count = data.remaining.inSeconds;
|
|
doModel.addTimber(_count);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
} else {
|
|
_count = 0;
|
|
}
|
|
|
|
_load();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
MainModel mainModel = Provider.of<MainModel>(context);
|
|
bool isBuyer = mainModel.user.isBuyer();
|
|
var logModel = Provider.of<LogModel>(context);
|
|
String formattedTime;
|
|
if (doObj.deliveryStatus == 'initiated') {
|
|
_result = DateTime(
|
|
doObj.deliveryInitiatedTime.year,
|
|
doObj.deliveryInitiatedTime.month,
|
|
doObj.deliveryInitiatedTime.day,
|
|
doObj.deliveryInitiatedTime.hour,
|
|
doObj.deliveryInitiatedTime.minute,
|
|
_count);
|
|
formattedTime = DateFormat.ms().format(_result);
|
|
}
|
|
|
|
final doDateBox = Container(
|
|
padding: EdgeInsets.only(left: 20, top: 15),
|
|
child: Row(
|
|
children: <Widget>[
|
|
LocalText(context, "do.do_date"),
|
|
Container(
|
|
padding: EdgeInsets.only(left: 10),
|
|
child: Text(
|
|
_doDate.text,
|
|
style: textStyle,
|
|
),
|
|
)
|
|
],
|
|
),
|
|
);
|
|
|
|
final dateBox = Container(
|
|
padding: EdgeInsets.only(left: 20, top: 8),
|
|
child: Row(
|
|
children: <Widget>[
|
|
LocalText(context, "do.date"),
|
|
Container(
|
|
padding: EdgeInsets.only(left: 10),
|
|
child: Text(
|
|
_date.text,
|
|
style: textStyle,
|
|
),
|
|
)
|
|
],
|
|
),
|
|
);
|
|
|
|
final numberBox = Container(
|
|
padding: EdgeInsets.only(left: 20, top: 5),
|
|
child: Row(
|
|
children: <Widget>[
|
|
LocalText(context, "do.do_num"),
|
|
Container(
|
|
padding: EdgeInsets.only(left: 10),
|
|
child: Text(
|
|
_number.text,
|
|
style: textStyle,
|
|
),
|
|
)
|
|
],
|
|
),
|
|
);
|
|
final driverBox = Container(
|
|
padding: EdgeInsets.only(left: 20, top: 5),
|
|
child: Row(
|
|
children: <Widget>[
|
|
LocalText(context, "do.driver"),
|
|
Container(
|
|
padding: EdgeInsets.only(left: 10),
|
|
child: Text(
|
|
_driver.text,
|
|
style: textStyle,
|
|
),
|
|
)
|
|
],
|
|
),
|
|
);
|
|
final carNoBox = Container(
|
|
padding: EdgeInsets.only(left: 20, top: 5),
|
|
child: Row(
|
|
children: <Widget>[
|
|
LocalText(context, "do.car"),
|
|
Container(
|
|
padding: EdgeInsets.only(left: 10),
|
|
child: Text(
|
|
_carNo.text,
|
|
style: textStyle,
|
|
),
|
|
)
|
|
],
|
|
),
|
|
);
|
|
final licenceBox = Container(
|
|
padding: EdgeInsets.only(left: 20, top: 5),
|
|
child: Row(
|
|
children: <Widget>[
|
|
LocalText(context, "do.licence"),
|
|
ImageFile(
|
|
enabled: false,
|
|
title: "Image",
|
|
initialImgUrl: doObj.driverLicenceUrl,
|
|
onFile: (file) {}),
|
|
],
|
|
),
|
|
);
|
|
final statusBox = Container(
|
|
padding: EdgeInsets.only(left: 20, top: 5),
|
|
child: Row(
|
|
children: <Widget>[
|
|
LocalText(context, "do.status"),
|
|
Container(
|
|
padding: EdgeInsets.only(left: 10),
|
|
child: Text(
|
|
doObj.status,
|
|
style: doObj.isPending
|
|
? textHighlightBlueStyle
|
|
: doObj.isApproved
|
|
? textHighlightGreenStyle
|
|
: textHighlightRedStyle,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
final deliveryStatusBox = Container(
|
|
padding: EdgeInsets.only(left: 20, top: 5),
|
|
child: Row(
|
|
children: <Widget>[
|
|
LocalText(context, "do.delivery.status"),
|
|
Container(
|
|
padding: EdgeInsets.only(left: 10, right: 15),
|
|
child: Text(
|
|
doObj.getDeliveryStatus,
|
|
style: textStyle,
|
|
),
|
|
),
|
|
doObj.deliveryStatus == 'initiated'
|
|
? Text(
|
|
"(can start in $formattedTime)",
|
|
style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold),
|
|
)
|
|
: Container()
|
|
],
|
|
),
|
|
);
|
|
|
|
final typeBox = Container(
|
|
padding: EdgeInsets.only(left: 20, top: 5),
|
|
child: Row(
|
|
children: <Widget>[
|
|
LocalText(context, "do.type"),
|
|
Container(
|
|
padding: EdgeInsets.only(left: 20),
|
|
child: Text(
|
|
_type.text,
|
|
style: textStyle,
|
|
),
|
|
)
|
|
],
|
|
),
|
|
);
|
|
|
|
final userNameBox = Container(
|
|
padding: EdgeInsets.only(top: 5, left: 20),
|
|
child: Row(
|
|
children: <Widget>[
|
|
LocalText(context, "do.name"),
|
|
Container(
|
|
padding: EdgeInsets.only(left: 20),
|
|
child: Text(
|
|
_name.text,
|
|
style: textStyle,
|
|
),
|
|
)
|
|
],
|
|
),
|
|
);
|
|
|
|
final bizNameBox = Container(
|
|
padding: EdgeInsets.only(left: 20, top: 5),
|
|
child: Row(
|
|
children: <Widget>[
|
|
LocalText(context, "do.biz"),
|
|
Container(
|
|
padding: EdgeInsets.only(left: 20),
|
|
child: Text(
|
|
_bizName.text,
|
|
style: textStyle,
|
|
),
|
|
)
|
|
],
|
|
),
|
|
);
|
|
|
|
final driverImgUrlBox = Container(
|
|
padding: EdgeInsets.only(left: 20),
|
|
child: Row(children: <Widget>[
|
|
LocalText(context, "do.driver.image"),
|
|
Container(
|
|
padding: EdgeInsets.only(left: 10),
|
|
child: ImageFile(
|
|
enabled: !isBuyer && doObj.deliveryStatus == null,
|
|
initialImgUrl: doObj.driverImgUrl,
|
|
title: "Image",
|
|
imageSource: ImageSource.camera,
|
|
onFile: (file) {
|
|
doObj.driverImg = file;
|
|
}),
|
|
),
|
|
]));
|
|
|
|
final receiptImagebox = Container(
|
|
padding: EdgeInsets.only(left: 20, top: 0),
|
|
child: Row(children: <Widget>[
|
|
LocalText(context, "do.receipt"),
|
|
Container(
|
|
padding: EdgeInsets.only(left: 10),
|
|
child: ImageFile(
|
|
enabled: false,
|
|
initialImgUrl: doObj.doReceiptUrl,
|
|
title: "Receipt",
|
|
),
|
|
),
|
|
]));
|
|
|
|
final deliveryInitTimeBox = Container(
|
|
padding: EdgeInsets.only(left: 20, top: 5),
|
|
child: Row(
|
|
children: <Widget>[
|
|
LocalText(context, "do.delivery.init.time"),
|
|
Container(
|
|
padding: EdgeInsets.only(left: 10),
|
|
child: Text(
|
|
doObj.deliveryInitTime,
|
|
style: textStyle,
|
|
),
|
|
)
|
|
],
|
|
),
|
|
);
|
|
|
|
final storageBox = Container(
|
|
padding: EdgeInsets.only(left: 20),
|
|
child: Row(
|
|
children: <Widget>[
|
|
LocalText(context, "do.storage_charge"),
|
|
Container(
|
|
padding: EdgeInsets.only(left: 10),
|
|
child: Text(
|
|
_storage.text,
|
|
style: textStyle,
|
|
),
|
|
)
|
|
],
|
|
),
|
|
);
|
|
final storagePaymentBox = Container(
|
|
padding: EdgeInsets.only(left: 20),
|
|
child: Row(children: <Widget>[
|
|
LocalText(context, "do.storage_receipt"),
|
|
ImageFile(
|
|
enabled: mainModel.user.isBuyer() ? true : false,
|
|
title: "Receipt File",
|
|
initialImgUrl: this.doObj.storageReceiptUrl,
|
|
onFile: (file) {
|
|
this.files.setStorageChargeFile = file;
|
|
}),
|
|
]));
|
|
|
|
final commentBox = Container(
|
|
padding: EdgeInsets.only(top: 5, left: 20),
|
|
child: Row(
|
|
children: <Widget>[
|
|
LocalText(context, "do.comment"),
|
|
Container(
|
|
padding: EdgeInsets.only(left: 10),
|
|
child: Text(
|
|
_comment.text,
|
|
style: textStyle,
|
|
),
|
|
)
|
|
],
|
|
),
|
|
);
|
|
return LocalProgress(
|
|
inAsyncCall: _isLoading,
|
|
child: Scaffold(
|
|
appBar: AppBar(
|
|
backgroundColor: primaryColor,
|
|
title: Text(AppTranslations.of(context).text("do"),
|
|
style: Provider.of<LanguageModel>(context).isEng
|
|
? TextStyle(fontSize: 18)
|
|
: TextStyle(fontSize: 18, fontFamily: 'MyanmarUnicode')),
|
|
actions: <Widget>[
|
|
mainModel.showHistoryBtn()
|
|
? IconButton(
|
|
icon: Icon(Icons.history),
|
|
onPressed: () {
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (context) =>
|
|
DocumentLogPage(docID: doObj.id)),
|
|
);
|
|
},
|
|
)
|
|
: Container(),
|
|
isBuyer
|
|
? doObj.isPending
|
|
? PopupMenuButton(
|
|
onSelected: _selectBuyer,
|
|
itemBuilder: (context) => List<PopupMenuEntry>.from([
|
|
PopupMenuItem(
|
|
enabled: this.doObj.isPending &&
|
|
this.doObj.storageCharge > 0,
|
|
value: 1,
|
|
child: Text("Update DO"),
|
|
),
|
|
PopupMenuItem(
|
|
enabled: this.doObj.isPending,
|
|
value: 2,
|
|
child: Text("Cancel DO"),
|
|
),
|
|
]))
|
|
: Container()
|
|
: PopupMenuButton(
|
|
onSelected: _select,
|
|
itemBuilder: (context) => List<PopupMenuEntry>.from([
|
|
PopupMenuItem(
|
|
enabled: this.doObj.isPending,
|
|
value: 1,
|
|
child: Text("Approve DO"),
|
|
),
|
|
PopupMenuItem(
|
|
enabled: this.doObj.isPending,
|
|
value: 2,
|
|
child: Text("Reject DO"),
|
|
),
|
|
PopupMenuItem(
|
|
enabled:
|
|
this.doObj.isApproved && mainModel.user.isOwner(),
|
|
value: 6,
|
|
child: Text("Cancel DO"),
|
|
)
|
|
]),
|
|
),
|
|
],
|
|
),
|
|
body: Container(
|
|
padding:
|
|
EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10),
|
|
child: Card(
|
|
elevation: 23,
|
|
child: ListView(
|
|
children: <Widget>[
|
|
Column(
|
|
children: <Widget>[
|
|
doDateBox,
|
|
Divider(),
|
|
dateBox,
|
|
Divider(),
|
|
numberBox,
|
|
Divider(),
|
|
userNameBox,
|
|
Divider(),
|
|
bizNameBox,
|
|
Divider(),
|
|
typeBox,
|
|
Divider(),
|
|
statusBox,
|
|
Divider(),
|
|
doObj.comment == null || doObj.comment == ''
|
|
? Container()
|
|
: commentBox,
|
|
doObj.comment == null || doObj.comment == ''
|
|
? Container()
|
|
: Divider(),
|
|
driverBox,
|
|
Divider(),
|
|
carNoBox,
|
|
Divider(),
|
|
licenceBox,
|
|
Divider(),
|
|
receiptImagebox,
|
|
Divider(),
|
|
doObj.hasStorageCharge() ? storageBox : Container(),
|
|
doObj.hasStorageCharge() ? Divider() : Container(),
|
|
doObj.hasStorageCharge()
|
|
? storagePaymentBox
|
|
: Container(),
|
|
doObj.isApproved || doObj.isClosed
|
|
? deliveryStatusBox
|
|
: Container(),
|
|
doObj.isApproved || doObj.isClosed
|
|
? Divider()
|
|
: Container(),
|
|
Container(
|
|
padding: EdgeInsets.only(top: 10),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
Center(
|
|
child: LocalText(
|
|
context,
|
|
'do.products',
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.bold,
|
|
underline: true,
|
|
color: secondaryColor,
|
|
),
|
|
),
|
|
SingleChildScrollView(
|
|
scrollDirection: Axis.horizontal,
|
|
child: MyDataTable(
|
|
headingRowHeight: 40,
|
|
columnSpacing: 40,
|
|
columns: [
|
|
MyDataColumn(
|
|
label: LocalText(context, "do.product"),
|
|
),
|
|
MyDataColumn(
|
|
label: LocalText(context, "do.storage"),
|
|
),
|
|
MyDataColumn(
|
|
label: LocalText(context, "do.quantity"),numeric: true
|
|
),
|
|
],
|
|
rows: getProductRow(doObj.doLines),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
SizedBox(
|
|
height: 15,
|
|
),
|
|
getPOProductTable()
|
|
],
|
|
),
|
|
],
|
|
),
|
|
)),
|
|
));
|
|
}
|
|
|
|
List<MyDataRow> getProductRow(List<DOLine> doLines) {
|
|
MainModel mainModel = Provider.of<MainModel>(context);
|
|
ProductModel productModel = Provider.of<ProductModel>(context);
|
|
bool isBuyer = mainModel.user.isBuyer();
|
|
|
|
if (doLines.isNotEmpty) {
|
|
doLines.forEach((d) {
|
|
productModel.products.forEach((p) {
|
|
if (p.id == d.productID) {
|
|
d.displayOrder = p.displayOrder;
|
|
} else {
|
|
return;
|
|
}
|
|
});
|
|
});
|
|
|
|
doLines.sort((p1, p2) => p1.displayOrder.compareTo(p2.displayOrder));
|
|
}
|
|
return doLines.map((d) {
|
|
return MyDataRow(
|
|
onSelectChanged: (bool selected) async {
|
|
if (isBuyer) return;
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (context) => DOStorageItem(
|
|
doLine: d,
|
|
onSave: (storageID, storageName) {
|
|
setState(() {
|
|
d.storageID = storageID;
|
|
d.storageName = storageName;
|
|
});
|
|
},
|
|
)),
|
|
);
|
|
},
|
|
cells: [
|
|
MyDataCell(
|
|
new Text(
|
|
d.productName,
|
|
style: textStyle,
|
|
),
|
|
),
|
|
MyDataCell(
|
|
new Text(d.storageName, style: textStyle),
|
|
),
|
|
MyDataCell(NumberCell(d.qty)),
|
|
],
|
|
);
|
|
}).toList();
|
|
}
|
|
|
|
Widget getPOProductTable() {
|
|
return Container(
|
|
padding: EdgeInsets.only(top: 10),
|
|
child: Column(
|
|
children: <Widget>[
|
|
Center(
|
|
child: LocalText(context, 'po.info',
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.bold,
|
|
underline: true,
|
|
color: secondaryColor),
|
|
),
|
|
SingleChildScrollView(
|
|
scrollDirection: Axis.horizontal,
|
|
child: MyDataTable(
|
|
headingRowHeight: 40,
|
|
columnSpacing: 20,
|
|
columns: [
|
|
MyDataColumn(label: LocalText(context, "po.number")),
|
|
MyDataColumn(label: LocalText(context, "po.product")),
|
|
MyDataColumn(
|
|
label: LocalText(context, "do.po_qty"),numeric: true,
|
|
),
|
|
MyDataColumn(
|
|
label: LocalText(context, "do.po_balance_qty"),numeric: true,
|
|
),
|
|
MyDataColumn(
|
|
label: LocalText(context, "po.retrieved.amount"),numeric: true,
|
|
),
|
|
MyDataColumn(
|
|
label: LocalText(context, "do.do_qty"),numeric: true,
|
|
),
|
|
],
|
|
rows: getPOProductRow(),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
List<MyDataRow> getPOProductRow() {
|
|
ProductModel productModel = Provider.of<ProductModel>(context);
|
|
if (doObj.dopoLies.isNotEmpty) {
|
|
doObj.dopoLies.sort((p1, p2) => p1.poNumber.compareTo(p2.poNumber));
|
|
|
|
doObj.dopoLies.forEach((d) {
|
|
productModel.products.forEach((p) {
|
|
if (p.id == d.productID) {
|
|
d.displayOrder = p.displayOrder;
|
|
} else {
|
|
return;
|
|
}
|
|
});
|
|
});
|
|
|
|
doObj.dopoLies.sort((p1, p2) {
|
|
if (p1.displayOrder != p2.displayOrder)
|
|
return p1.displayOrder.compareTo(p2.displayOrder);
|
|
return p1.poNumber.compareTo(p2.poNumber);
|
|
});
|
|
}
|
|
return doObj.dopoLies.map((d) {
|
|
return MyDataRow(
|
|
cells: [
|
|
MyDataCell(
|
|
new Text(
|
|
d.poNumber,
|
|
style: textStyle,
|
|
),
|
|
),
|
|
MyDataCell(
|
|
new Text(
|
|
d.productName,
|
|
style: textStyle,
|
|
),
|
|
),
|
|
MyDataCell(NumberCell(d.poQty)),
|
|
MyDataCell(NumberCell(d.poBalAtCreate)),
|
|
MyDataCell(NumberCell(d.getPoBalanceQtyAtCreate)),
|
|
MyDataCell(NumberCell(d.doQty)),
|
|
],
|
|
);
|
|
}).toList();
|
|
}
|
|
|
|
_select(s) {
|
|
if (s == 1) {
|
|
showConfirmDialog(context, "do.approve.confirm", () {
|
|
_approve();
|
|
});
|
|
} else if (s == 2) {
|
|
showCommentDialog(context, (comment) {
|
|
doObj.comment = comment;
|
|
_reject();
|
|
});
|
|
} else if (s == 5) {
|
|
showConfirmDialog(context, "do.end.confirm", () {
|
|
_endDelivery();
|
|
});
|
|
} else if (s == 6) {
|
|
showConfirmDialog(context, "do.cancel.confirm", () {
|
|
_cancelDelivery();
|
|
});
|
|
}
|
|
}
|
|
|
|
_selectBuyer(s) {
|
|
if (s == 1) {
|
|
showConfirmDialog(context, "do.confirm", () {
|
|
_submit();
|
|
});
|
|
} else if (s == 2) {
|
|
showConfirmDialog(context, "do.cancel.confirm", () {
|
|
_cancelDelivery();
|
|
});
|
|
}
|
|
}
|
|
|
|
Future<void> _load() async {
|
|
POSubmissionModel poModel =
|
|
Provider.of<POSubmissionModel>(context, listen: false);
|
|
DOModel doModel = Provider.of<DOModel>(context, listen: false);
|
|
|
|
var _doSub = await poModel.loadDOLines(doObj);
|
|
_doSub = await doModel.loadDOPOLines(_doSub);
|
|
// set po balance
|
|
List<String> pos = _doSub.getPOs();
|
|
for (var po in pos) {
|
|
List<POLine> poLines = await poModel.loadPOLines(po);
|
|
_doSub.setDOPOLineBalance(po, poLines);
|
|
}
|
|
if (mounted) {
|
|
setState(() {
|
|
doObj.doLines = _doSub.doLines;
|
|
doObj.dopoLies = _doSub.dopoLies;
|
|
});
|
|
}
|
|
}
|
|
|
|
_approve() async {
|
|
if (doObj.doLines.any((l) => l.storageID.isEmpty)) {
|
|
showMsgDialog(context, "Error", "Storage required for every product");
|
|
return;
|
|
}
|
|
setState(() {
|
|
_isLoading = true;
|
|
});
|
|
try {
|
|
DOModel doModel = Provider.of<DOModel>(context);
|
|
await doModel.approveDO(doObj);
|
|
Navigator.pop(context);
|
|
} catch (e) {
|
|
showMsgDialog(context, "Error", e.toString());
|
|
} finally {
|
|
setState(() {
|
|
_isLoading = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
_reject() async {
|
|
setState(() {
|
|
_isLoading = true;
|
|
});
|
|
try {
|
|
DOModel doModel = Provider.of<DOModel>(context);
|
|
await doModel.rejectDO(doObj);
|
|
Navigator.pop(context);
|
|
} catch (e) {
|
|
showMsgDialog(context, "Error", e.toString());
|
|
} finally {
|
|
setState(() {
|
|
_isLoading = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
_initDelivery() async {
|
|
if (doObj.driverImg == null) {
|
|
showMsgDialog(context, "Error", "Please attach driver image");
|
|
return;
|
|
}
|
|
setState(() {
|
|
_isLoading = true;
|
|
});
|
|
try {
|
|
DOModel doModel = Provider.of<DOModel>(context);
|
|
await doModel.initDelivery(doObj);
|
|
Navigator.pop(context);
|
|
} catch (e) {
|
|
showMsgDialog(context, "Error", e.toString());
|
|
} finally {
|
|
setState(() {
|
|
_isLoading = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
_startDelivery() async {
|
|
MainModel mainModel = Provider.of<MainModel>(context);
|
|
Duration diff = DateTime.now().difference(doObj.deliveryInitiatedTime);
|
|
if (diff.inMinutes < mainModel.setting.deliveryStartWaitMin) {
|
|
showMsgDialog(context, "Waiting...",
|
|
"Can not start delivery, wait for ${mainModel.setting.deliveryStartWaitMin} minutes");
|
|
return;
|
|
}
|
|
setState(() {
|
|
_isLoading = true;
|
|
});
|
|
try {
|
|
DOModel doModel = Provider.of<DOModel>(context);
|
|
await doModel.startDelivery(doObj);
|
|
Navigator.pop(context);
|
|
} catch (e) {
|
|
showMsgDialog(context, "Error", e.toString());
|
|
} finally {
|
|
setState(() {
|
|
_isLoading = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
_endDelivery() async {
|
|
var photo = await Navigator.push(
|
|
context,
|
|
MaterialPageRoute(builder: (context) => PhotoPage()),
|
|
);
|
|
if (photo == null) {
|
|
return;
|
|
}
|
|
Uint8List bytesPhoto = photo.readAsBytesSync() as Uint8List;
|
|
|
|
setState(() {
|
|
_isLoading = true;
|
|
});
|
|
try {
|
|
DOModel doModel = Provider.of<DOModel>(context);
|
|
await doModel.endDelivery(doObj, bytesPhoto);
|
|
Navigator.pop(context);
|
|
} catch (e) {
|
|
showMsgDialog(context, "Error", e.toString());
|
|
} finally {
|
|
setState(() {
|
|
_isLoading = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
_cancelDelivery() async {
|
|
setState(() {
|
|
_isLoading = true;
|
|
});
|
|
try {
|
|
DOModel doModel = Provider.of<DOModel>(context);
|
|
await doModel.cancelDO(doObj);
|
|
Navigator.pop(context);
|
|
} catch (e) {
|
|
showMsgDialog(context, "Error", e.toString());
|
|
} finally {
|
|
setState(() {
|
|
_isLoading = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
_submit() async {
|
|
if (doObj.hasStorageCharge()) {
|
|
if (files.storageChargeFile == null && doObj.storageReceiptUrl == '') {
|
|
showMsgDialog(context, "Error", "Please insert storage receipt");
|
|
return;
|
|
}
|
|
}
|
|
|
|
setState(() {
|
|
_isLoading = true;
|
|
});
|
|
try {
|
|
DOModel doModel = Provider.of<DOModel>(context);
|
|
await doModel.updateDO(doObj, files);
|
|
Navigator.pop<bool>(context, true);
|
|
} catch (e) {
|
|
showMsgDialog(context, "Error", e.toString());
|
|
} finally {
|
|
setState(() {
|
|
_isLoading = false;
|
|
});
|
|
}
|
|
}
|
|
}
|