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<void> issueOrder() async { + if (!isPending) { + return; + } + + await api.post("${url}issue/", expectedStatusCode: 201); + } + + /// Mark this order as "cancelled" + Future<void> 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<PurchaseOrderDetailWidg acceptText: L10().cancel, onAccept: () async { await widget.order.cancelOrder().then((dynamic) { - print("callback"); refresh(context); }); } diff --git a/lib/widget/order/sales_order_detail.dart b/lib/widget/order/sales_order_detail.dart index 91d9efb1..05d49f4d 100644 --- a/lib/widget/order/sales_order_detail.dart +++ b/lib/widget/order/sales_order_detail.dart @@ -14,6 +14,7 @@ import "package:inventree/l10.dart"; import "package:inventree/app_colors.dart"; import "package:inventree/widget/attachment_widget.dart"; +import "package:inventree/widget/dialogs.dart"; import "package:inventree/widget/notes_widget.dart"; import "package:inventree/widget/snacks.dart"; import "package:inventree/widget/company/company_detail.dart"; @@ -99,15 +100,71 @@ class _SalesOrderDetailState extends RefreshableState<SalesOrderDetailWidget> { ); } + /// Issue this order + Future<void> _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<void> _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<SpeedDialChild> actionButtons(BuildContext context) { List<SpeedDialChild> 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<SalesOrderDetailWidget> { 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<SalesOrderDetailWidget> { List<SpeedDialChild> barcodeButtons(BuildContext context) { List<SpeedDialChild> 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"