diff --git a/assets/release_notes.md b/assets/release_notes.md index e4367d53..c72bd2c1 100644 --- a/assets/release_notes.md +++ b/assets/release_notes.md @@ -2,6 +2,7 @@ --- - Fixes barcode scanning bug which prevents scanning of DataMatrix codes +- Display "destination" information in PurchaseOrder detail view - Adds "assigned to me" filter for Purchase Order list - Adds "assigned to me" filter for Sales Order list diff --git a/lib/api.dart b/lib/api.dart index 704b7df1..d686e1b1 100644 --- a/lib/api.dart +++ b/lib/api.dart @@ -333,6 +333,10 @@ class InvenTreeAPI { // Ref: https://github.com/inventree/InvenTree/pull/7420 bool get supportsModernAttachments => isConnected() && apiVersion >= 207; + // Does the server support the "destination" field on the PurchaseOrder model? + // Ref: https://github.com/inventree/InvenTree/pull/8403 + bool get supportsPurchaseOrderDestination => isConnected() && apiVersion >= 276; + // Cached list of plugins (refreshed when we connect to the server) List _plugins = []; diff --git a/lib/inventree/purchase_order.dart b/lib/inventree/purchase_order.dart index e4723881..b224458d 100644 --- a/lib/inventree/purchase_order.dart +++ b/lib/inventree/purchase_order.dart @@ -40,6 +40,7 @@ class InvenTreePurchaseOrder extends InvenTreeOrder { "supplier_reference": {}, "description": {}, "project_code": {}, + "destination": {}, "target_date": {}, "link": {}, "responsible": {}, @@ -54,6 +55,10 @@ class InvenTreePurchaseOrder extends InvenTreeOrder { fields.remove("project_code"); } + if (!InvenTreeAPI().supportsPurchaseOrderDestination) { + fields.remove("destination"); + } + return fields; } @@ -87,6 +92,8 @@ class InvenTreePurchaseOrder extends InvenTreeOrder { String get supplierReference => getString("supplier_reference"); + int get destinationId => getInt("destination"); + bool get isOpen => api.PurchaseOrderStatus.isNameIn(status, ["PENDING", "PLACED", "ON_HOLD"]); bool get isPending => api.PurchaseOrderStatus.isNameIn(status, ["PENDING", "ON_HOLD"]); @@ -219,7 +226,7 @@ class InvenTreePOLineItem extends InvenTreeOrderLine { String get purchasePriceCurrency => getString("purchase_price_currency"); - int get destination => getInt("destination"); + int get destinationId => getInt("destination"); Map get destinationDetail => getMap("destination_detail"); } diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 3ce98666..72d5d92f 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -310,6 +310,9 @@ "description": "Description", "@description": {}, + "destination": "Destination", + "@destination": {}, + "destroyed": "Destroyed", "@destroyed": {}, diff --git a/lib/widget/company/company_detail.dart b/lib/widget/company/company_detail.dart index 65f65d10..c0ab4814 100644 --- a/lib/widget/company/company_detail.dart +++ b/lib/widget/company/company_detail.dart @@ -48,7 +48,15 @@ class _CompanyDetailState extends RefreshableState { int attachmentCount = 0; @override - String getAppBarTitle() => L10().company; + String getAppBarTitle() { + String title = L10().company; + + if (widget.company.name.isNotEmpty) { + title += " - ${widget.company.name}"; + } + + return title; + } @override List appBarActions(BuildContext context) { diff --git a/lib/widget/order/po_line_detail.dart b/lib/widget/order/po_line_detail.dart index bddeb4db..9dc178fc 100644 --- a/lib/widget/order/po_line_detail.dart +++ b/lib/widget/order/po_line_detail.dart @@ -5,14 +5,18 @@ import "package:flutter_tabler_icons/flutter_tabler_icons.dart"; import "package:inventree/api_form.dart"; import "package:inventree/app_colors.dart"; import "package:inventree/helpers.dart"; +import "package:inventree/inventree/model.dart"; import "package:inventree/l10.dart"; -import "package:inventree/widget/progress.dart"; -import "package:inventree/widget/part/part_detail.dart"; -import "package:inventree/widget/refreshable_state.dart"; import "package:inventree/inventree/company.dart"; import "package:inventree/inventree/part.dart"; import "package:inventree/inventree/purchase_order.dart"; +import "package:inventree/inventree/stock.dart"; + +import "package:inventree/widget/progress.dart"; +import "package:inventree/widget/part/part_detail.dart"; +import "package:inventree/widget/stock/location_display.dart"; +import "package:inventree/widget/refreshable_state.dart"; import "package:inventree/widget/snacks.dart"; import "package:inventree/widget/company/supplier_part_detail.dart"; @@ -38,6 +42,8 @@ class _POLineDetailWidgetState extends RefreshableState { _POLineDetailWidgetState(); + InvenTreeStockLocation? destination; + @override String getAppBarTitle() => L10().lineItem; @@ -84,6 +90,29 @@ class _POLineDetailWidgetState extends RefreshableState { @override Future request(BuildContext context) async { await widget.item.reload(); + + if (widget.item.destinationId > 0) { + InvenTreeStockLocation().get(widget.item.destinationId).then((InvenTreeModel? loc) { + if (mounted) { + if (loc != null && loc is InvenTreeStockLocation) { + setState(() { + destination = loc; + }); + } else { + setState(() { + destination = null; + }); + } + } + }); + } else { + if (mounted) { + setState(() { + destination = null; + }); + } + } + } // Callback to edit this line item @@ -199,6 +228,24 @@ class _POLineDetailWidgetState extends RefreshableState { ) ); + // Destination + if (destination != null) { + tiles.add(ListTile( + title: Text(L10().destination), + subtitle: Text(destination!.name), + leading: Icon(TablerIcons.map_pin, color: COLOR_ACTION), + onTap: () => + { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => LocationDisplayWidget(destination) + ) + ) + } + )); + } + // Received quantity tiles.add( ListTile( diff --git a/lib/widget/order/purchase_order_detail.dart b/lib/widget/order/purchase_order_detail.dart index 29dc68bf..f4a45d07 100644 --- a/lib/widget/order/purchase_order_detail.dart +++ b/lib/widget/order/purchase_order_detail.dart @@ -1,8 +1,6 @@ import "package:flutter/material.dart"; import "package:flutter_speed_dial/flutter_speed_dial.dart"; import "package:flutter_tabler_icons/flutter_tabler_icons.dart"; -import "package:inventree/widget/dialogs.dart"; -import "package:inventree/widget/order/po_line_list.dart"; import "package:inventree/app_colors.dart"; import "package:inventree/barcode/barcode.dart"; @@ -10,8 +8,16 @@ import "package:inventree/barcode/purchase_order.dart"; import "package:inventree/helpers.dart"; import "package:inventree/l10.dart"; +import "package:inventree/inventree/model.dart"; import "package:inventree/inventree/company.dart"; +import "package:inventree/inventree/stock.dart"; import "package:inventree/inventree/purchase_order.dart"; + +import "package:inventree/widget/dialogs.dart"; +import "package:inventree/widget/stock/location_display.dart"; +import "package:inventree/widget/order/po_line_list.dart"; + + import "package:inventree/widget/attachment_widget.dart"; import "package:inventree/widget/company/company_detail.dart"; import "package:inventree/widget/notes_widget.dart"; @@ -42,6 +48,8 @@ class _PurchaseOrderDetailState extends RefreshableState lines = []; + InvenTreeStockLocation? destination; + int completedLines = 0; int attachmentCount = 0; @@ -50,7 +58,15 @@ class _PurchaseOrderDetailState extends RefreshableState L10().purchaseOrder; + String getAppBarTitle() { + String title = L10().purchaseOrder; + + if (widget.order.reference.isNotEmpty) { + title += " - ${widget.order.reference}"; + } + + return title; + } @override List appBarActions(BuildContext context) { @@ -258,6 +274,28 @@ class _PurchaseOrderDetailState extends RefreshableState 0) { + InvenTreeStockLocation().get(widget.order.destinationId).then((InvenTreeModel? loc) { + if (mounted) { + if (loc != null && loc is InvenTreeStockLocation) { + setState(() { + destination = loc; + }); + } else { + setState(() { + destination = null; + }); + } + } + }); + } else { + if (mounted) { + setState(() { + destination = null; + }); + } + } } // Edit the currently displayed PurchaseOrder @@ -348,6 +386,23 @@ class _PurchaseOrderDetailState extends RefreshableState { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => LocationDisplayWidget(destination) + ) + ) + } + )); + } + Color lineColor = completedLines < widget.order.lineItemCount ? COLOR_WARNING : COLOR_SUCCESS; tiles.add(ListTile( @@ -444,5 +499,4 @@ class _PurchaseOrderDetailState extends RefreshableState { int attachmentCount = 0; @override - String getAppBarTitle() => L10().salesOrder; + String getAppBarTitle() { + String title = L10().salesOrder; + + if (widget.order.reference.isNotEmpty) { + title += " - ${widget.order.reference}"; + } + + return title; + } @override List appBarActions(BuildContext context) {