From 42de3fd7d4b2c95d3fe4350c9222673512f1cacc Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 7 Aug 2024 21:11:40 +1000 Subject: [PATCH] Order hold (#515) * Add support for "ON_HOLD" status for orders * Bump version and release notes * Fix import --- assets/release_notes.md | 6 ++ lib/inventree/purchase_order.dart | 4 +- lib/inventree/sales_order.dart | 23 +++++++- lib/widget/order/purchase_order_detail.dart | 1 - lib/widget/order/sales_order_detail.dart | 65 +++++++++++++++++++-- pubspec.yaml | 2 +- 6 files changed, 92 insertions(+), 9 deletions(-) diff --git a/assets/release_notes.md b/assets/release_notes.md index b3c09075..a81cd42d 100644 --- a/assets/release_notes.md +++ b/assets/release_notes.md @@ -1,3 +1,9 @@ +### 0.16.2 - August 2024 +--- + +- Support "ON_HOLD" status for Purchase Orders +- Support "ON_HOLD" status for Sales Orders + ### 0.16.1 - July 2024 --- diff --git a/lib/inventree/purchase_order.dart b/lib/inventree/purchase_order.dart index ac8973dc..e4723881 100644 --- a/lib/inventree/purchase_order.dart +++ b/lib/inventree/purchase_order.dart @@ -87,9 +87,9 @@ class InvenTreePurchaseOrder extends InvenTreeOrder { String get supplierReference => getString("supplier_reference"); - bool get isOpen => api.PurchaseOrderStatus.isNameIn(status, ["PENDING", "PLACED"]); + bool get isOpen => api.PurchaseOrderStatus.isNameIn(status, ["PENDING", "PLACED", "ON_HOLD"]); - bool get isPending => api.PurchaseOrderStatus.isNameIn(status, ["PENDING"]); + bool get isPending => api.PurchaseOrderStatus.isNameIn(status, ["PENDING", "ON_HOLD"]); bool get isPlaced => api.PurchaseOrderStatus.isNameIn(status, ["PLACED"]); diff --git a/lib/inventree/sales_order.dart b/lib/inventree/sales_order.dart index 0002adcb..5bdd4849 100644 --- a/lib/inventree/sales_order.dart +++ b/lib/inventree/sales_order.dart @@ -78,6 +78,23 @@ class InvenTreeSalesOrder extends InvenTreeOrder { }; } + Future issueOrder() async { + if (!isPending) { + return; + } + + await api.post("${url}issue/", expectedStatusCode: 201); + } + + /// Mark this order as "cancelled" + Future cancelOrder() async { + if (!isOpen) { + return; + } + + await api.post("${url}cancel/", expectedStatusCode: 201); + } + int get customerId => getInt("customer"); InvenTreeCompany? get customer { @@ -92,7 +109,11 @@ class InvenTreeSalesOrder extends InvenTreeOrder { String get customerReference => getString("customer_reference"); - bool get isOpen => api.SalesOrderStatus.isNameIn(status, ["PENDING", "IN_PROGRESS"]); + bool get isOpen => api.SalesOrderStatus.isNameIn(status, ["PENDING", "IN_PROGRESS", "ON_HOLD"]); + + bool get isPending => api.SalesOrderStatus.isNameIn(status, ["PENDING", "ON_HOLD"]); + + bool get isInProgress => api.SalesOrderStatus.isNameIn(status, ["IN_PROGRESS"]); bool get isComplete => api.SalesOrderStatus.isNameIn(status, ["SHIPPED"]); diff --git a/lib/widget/order/purchase_order_detail.dart b/lib/widget/order/purchase_order_detail.dart index adc5b47e..ea0e308d 100644 --- a/lib/widget/order/purchase_order_detail.dart +++ b/lib/widget/order/purchase_order_detail.dart @@ -163,7 +163,6 @@ class _PurchaseOrderDetailState extends RefreshableState { ); } + /// Issue this order + Future _issueOrder(BuildContext context) async { + + confirmationDialog( + L10().issueOrder, "", + icon: FontAwesomeIcons.paperPlane, + color: Colors.blue, + acceptText: L10().issue, + onAccept: () async { + await widget.order.issueOrder().then((dynamic) { + refresh(context); + }); + } + ); + } + + /// Cancel this order + Future _cancelOrder(BuildContext context) async { + + confirmationDialog( + L10().cancelOrder, "", + icon: FontAwesomeIcons.circleXmark, + color: Colors.red, + acceptText: L10().cancel, + onAccept: () async { + await widget.order.cancelOrder().then((dynamic) { + refresh(context); + }); + } + ); + } + @override List actionButtons(BuildContext context) { List actions = []; + if (widget.order.isPending) { + actions.add( + SpeedDialChild( + child: FaIcon(FontAwesomeIcons.paperPlane, color: Colors.blue), + label: L10().issueOrder, + onTap: () async { + _issueOrder(context); + } + ) + ); + } + + if (widget.order.isOpen) { + actions.add( + SpeedDialChild( + child: FaIcon(FontAwesomeIcons.circleXmark, color: Colors.red), + label: L10().cancelOrder, + onTap: () async { + _cancelOrder(context); + } + ) + ); + } + // Add line item - if (widget.order.isOpen && InvenTreeSOLineItem().canCreate) { + if (widget.order.isInProgress && InvenTreeSOLineItem().canCreate) { actions.add( SpeedDialChild( - child: FaIcon(FontAwesomeIcons.circlePlus), + child: FaIcon(FontAwesomeIcons.circlePlus, color: Colors.green), label: L10().lineItemAdd, onTap: () async { _addLineItem(context); @@ -117,7 +174,7 @@ class _SalesOrderDetailState extends RefreshableState { actions.add( SpeedDialChild( - child: FaIcon(FontAwesomeIcons.circlePlus), + child: FaIcon(FontAwesomeIcons.truck, color: Colors.green), label: L10().shipmentAdd, onTap: () async { _addShipment(context); @@ -133,7 +190,7 @@ class _SalesOrderDetailState extends RefreshableState { List barcodeButtons(BuildContext context) { List actions = []; - if (widget.order.isOpen && InvenTreeSOLineItem().canCreate) { + if (widget.order.isInProgress && InvenTreeSOLineItem().canCreate) { actions.add( SpeedDialChild( child: Icon(Icons.barcode_reader), diff --git a/pubspec.yaml b/pubspec.yaml index 33bc9971..7fb87183 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: inventree description: InvenTree stock management -version: 0.16.1+86 +version: 0.16.2+87 environment: sdk: ">=2.19.5 <3.13.0"