From e301abebd84b83a04cae034765c10a10c22dbfa2 Mon Sep 17 00:00:00 2001 From: Oliver Date: Mon, 6 Jul 2026 23:18:51 +1000 Subject: [PATCH] display model pk entries (#851) --- android/app/build.gradle | 2 +- lib/l10n/app_en.arb | 9 +++++++++ lib/preferences.dart | 1 + lib/settings/app_settings.dart | 17 +++++++++++++++++ lib/widget/build/build_detail.dart | 4 ++++ lib/widget/build/build_item_detail.dart | 4 ++++ lib/widget/build/build_line_detail.dart | 4 ++++ lib/widget/company/company_detail.dart | 4 ++++ .../company/manufacturer_part_detail.dart | 4 ++++ lib/widget/company/supplier_part_detail.dart | 4 ++++ lib/widget/order/extra_line_detail.dart | 4 ++++ lib/widget/order/po_line_detail.dart | 4 ++++ lib/widget/order/purchase_order_detail.dart | 4 ++++ lib/widget/order/sales_order_detail.dart | 4 ++++ lib/widget/order/so_line_detail.dart | 4 ++++ lib/widget/order/so_shipment_detail.dart | 4 ++++ lib/widget/part/category_display.dart | 1 + lib/widget/part/part_detail.dart | 4 ++++ lib/widget/refreshable_state.dart | 18 ++++++++++++++++++ lib/widget/stock/location_display.dart | 1 + lib/widget/stock/stock_detail.dart | 4 ++++ 21 files changed, 104 insertions(+), 1 deletion(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 368e41b2..5b47490c 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -57,7 +57,7 @@ android { defaultConfig { applicationId "inventree.inventree_app" - minSdkVersion 23 + minSdkVersion flutter.minSdkVersion // Flutter now requires API 24+; hardcoding a lower value gets auto-rewritten on every build targetSdkVersion 35 versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index e4a40a8f..d84bb56c 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -406,6 +406,15 @@ "darkModeEnable": "Enable dark mode", "@darkModeEnable": {}, + "showPkValue": "Show ID", + "@showPkValue": {}, + + "showPkValueDetail": "Display the internal ID (PK) value for parts, stock items and other objects", + "@showPkValueDetail": {}, + + "pk": "ID", + "@pk": {}, + "delete": "Delete", "@delete": {}, diff --git a/lib/preferences.dart b/lib/preferences.dart index c1392183..7a6c21d3 100644 --- a/lib/preferences.dart +++ b/lib/preferences.dart @@ -17,6 +17,7 @@ const String INV_HOME_SHOW_CUSTOMERS = "homeShowCustomers"; const String INV_HOME_SHOW_SUPPLIERS = "homeShowSuppliers"; const String INV_SCREEN_ORIENTATION = "appScreenOrientation"; +const String INV_SHOW_PK = "showPk"; // Available screen orientation values const int SCREEN_ORIENTATION_SYSTEM = 0; diff --git a/lib/settings/app_settings.dart b/lib/settings/app_settings.dart index 2403d625..d91c18d0 100644 --- a/lib/settings/app_settings.dart +++ b/lib/settings/app_settings.dart @@ -35,6 +35,7 @@ class _InvenTreeAppSettingsState extends State { bool strictHttps = false; bool enableLabelPrinting = true; bool darkMode = false; + bool showPk = false; int screenOrientation = SCREEN_ORIENTATION_SYSTEM; @@ -74,6 +75,8 @@ class _InvenTreeAppSettingsState extends State { true, ) as bool; + showPk = + await InvenTreeSettingsManager().getValue(INV_SHOW_PK, false) as bool; darkMode = AdaptiveTheme.of(context).mode.isDark; @@ -194,6 +197,20 @@ class _InvenTreeAppSettingsState extends State { }, ), ), + ListTile( + title: Text(L10().showPkValue), + subtitle: Text(L10().showPkValueDetail), + leading: Icon(TablerIcons.hash), + trailing: Switch( + value: showPk, + onChanged: (bool value) { + InvenTreeSettingsManager().setValue(INV_SHOW_PK, value); + setState(() { + showPk = value; + }); + }, + ), + ), GestureDetector( child: ListTile( title: Text(L10().orientation), diff --git a/lib/widget/build/build_detail.dart b/lib/widget/build/build_detail.dart index 9eaf353f..926c43f7 100644 --- a/lib/widget/build/build_detail.dart +++ b/lib/widget/build/build_detail.dart @@ -385,6 +385,10 @@ class _BuildOrderDetailState extends RefreshableState { // Header tile tiles.add(headerTile(context)); + if (showPk) { + tiles.add(pkTile(widget.order.pk)); + } + // Part information if (widget.order.partDetail != null) { InvenTreePart part = widget.order.partDetail!; diff --git a/lib/widget/build/build_item_detail.dart b/lib/widget/build/build_item_detail.dart index a34fefdc..867c7cc0 100644 --- a/lib/widget/build/build_item_detail.dart +++ b/lib/widget/build/build_item_detail.dart @@ -125,6 +125,10 @@ class _BuildItemDetailWidgetState List getTiles(BuildContext context) { List tiles = []; + if (showPk) { + tiles.add(pkTile(widget.item.pk)); + } + // Stock item information if (widget.item.stockItem != null) { tiles.add( diff --git a/lib/widget/build/build_line_detail.dart b/lib/widget/build/build_line_detail.dart index 76054134..426020e3 100644 --- a/lib/widget/build/build_line_detail.dart +++ b/lib/widget/build/build_line_detail.dart @@ -57,6 +57,10 @@ class _BuildLineDetailWidgetState List getTiles(BuildContext context) { List tiles = []; + if (showPk) { + tiles.add(pkTile(widget.item.pk)); + } + // Reference to the part tiles.add( ListTile( diff --git a/lib/widget/company/company_detail.dart b/lib/widget/company/company_detail.dart index 9a6d233f..9accf9a0 100644 --- a/lib/widget/company/company_detail.dart +++ b/lib/widget/company/company_detail.dart @@ -239,6 +239,10 @@ class _CompanyDetailState extends RefreshableState { ), ); + if (showPk) { + tiles.add(pkTile(widget.company.pk)); + } + if (!widget.company.active) { tiles.add( ListTile( diff --git a/lib/widget/company/manufacturer_part_detail.dart b/lib/widget/company/manufacturer_part_detail.dart index 57a7e48f..588b8029 100644 --- a/lib/widget/company/manufacturer_part_detail.dart +++ b/lib/widget/company/manufacturer_part_detail.dart @@ -125,6 +125,10 @@ class _ManufacturerPartDisplayState List getTiles(BuildContext context) { List tiles = []; + if (showPk) { + tiles.add(pkTile(widget.manufacturerPart.pk)); + } + // Internal Part tiles.add( ListTile( diff --git a/lib/widget/company/supplier_part_detail.dart b/lib/widget/company/supplier_part_detail.dart index ed607483..97357d5e 100644 --- a/lib/widget/company/supplier_part_detail.dart +++ b/lib/widget/company/supplier_part_detail.dart @@ -146,6 +146,10 @@ class _SupplierPartDisplayState return tiles; } + if (showPk) { + tiles.add(pkTile(widget.supplierPart.pk)); + } + // Internal Part tiles.add( ListTile( diff --git a/lib/widget/order/extra_line_detail.dart b/lib/widget/order/extra_line_detail.dart index 490f8332..1272c982 100644 --- a/lib/widget/order/extra_line_detail.dart +++ b/lib/widget/order/extra_line_detail.dart @@ -68,6 +68,10 @@ class _ExtraLineDetailWidgetState List getTiles(BuildContext context) { List tiles = []; + if (showPk) { + tiles.add(pkTile(widget.item.pk)); + } + tiles.add( ListTile( title: Text(L10().reference), diff --git a/lib/widget/order/po_line_detail.dart b/lib/widget/order/po_line_detail.dart index 976e7629..a8a05329 100644 --- a/lib/widget/order/po_line_detail.dart +++ b/lib/widget/order/po_line_detail.dart @@ -139,6 +139,10 @@ class _POLineDetailWidgetState extends RefreshableState { List getTiles(BuildContext context) { List tiles = []; + if (showPk) { + tiles.add(pkTile(widget.item.pk)); + } + // Reference to the part tiles.add( ListTile( diff --git a/lib/widget/order/purchase_order_detail.dart b/lib/widget/order/purchase_order_detail.dart index a055ee15..add805d1 100644 --- a/lib/widget/order/purchase_order_detail.dart +++ b/lib/widget/order/purchase_order_detail.dart @@ -404,6 +404,10 @@ class _PurchaseOrderDetailState tiles.add(headerTile(context)); + if (showPk) { + tiles.add(pkTile(widget.order.pk)); + } + if (supportProjectCodes && widget.order.hasProjectCode) { tiles.add( ListTile( diff --git a/lib/widget/order/sales_order_detail.dart b/lib/widget/order/sales_order_detail.dart index 38fe225d..8844e6bd 100644 --- a/lib/widget/order/sales_order_detail.dart +++ b/lib/widget/order/sales_order_detail.dart @@ -344,6 +344,10 @@ class _SalesOrderDetailState extends RefreshableState { List orderTiles(BuildContext context) { List tiles = [headerTile(context)]; + if (showPk) { + tiles.add(pkTile(widget.order.pk)); + } + InvenTreeCompany? customer = widget.order.customer; if (supportsProjectCodes && widget.order.hasProjectCode) { diff --git a/lib/widget/order/so_line_detail.dart b/lib/widget/order/so_line_detail.dart index 73092212..5aaf488c 100644 --- a/lib/widget/order/so_line_detail.dart +++ b/lib/widget/order/so_line_detail.dart @@ -165,6 +165,10 @@ class _SOLineDetailWidgetState extends RefreshableState { List getTiles(BuildContext context) { List tiles = []; + if (showPk) { + tiles.add(pkTile(widget.item.pk)); + } + // Reference to the part tiles.add( ListTile( diff --git a/lib/widget/order/so_shipment_detail.dart b/lib/widget/order/so_shipment_detail.dart index 40a69e89..1a53aeb4 100644 --- a/lib/widget/order/so_shipment_detail.dart +++ b/lib/widget/order/so_shipment_detail.dart @@ -218,6 +218,10 @@ class _SOShipmentDetailWidgetState List shipmentTiles(BuildContext context) { List tiles = []; + if (showPk) { + tiles.add(pkTile(widget.shipment.pk)); + } + final bool checked = widget.shipment.isChecked; final bool shipped = widget.shipment.isShipped; final bool delivered = widget.shipment.isDelivered; diff --git a/lib/widget/part/category_display.dart b/lib/widget/part/category_display.dart index 34214aca..1d94f80d 100644 --- a/lib/widget/part/category_display.dart +++ b/lib/widget/part/category_display.dart @@ -198,6 +198,7 @@ class _CategoryDisplayState extends RefreshableState { List tiles = [ getCategoryDescriptionCard(), + if (showPk && widget.category != null) pkTile(widget.category!.pk), Expanded( child: PaginatedPartCategoryList(filters, title: L10().subcategories), flex: 10, diff --git a/lib/widget/part/part_detail.dart b/lib/widget/part/part_detail.dart index 08c6df54..b38d9e8a 100644 --- a/lib/widget/part/part_detail.dart +++ b/lib/widget/part/part_detail.dart @@ -355,6 +355,10 @@ class _PartDisplayState extends RefreshableState { return tiles; } + if (showPk) { + tiles.add(pkTile(part.pk)); + } + if (!part.isActive) { tiles.add( ListTile( diff --git a/lib/widget/refreshable_state.dart b/lib/widget/refreshable_state.dart index aa6954cd..3ce2f9c3 100644 --- a/lib/widget/refreshable_state.dart +++ b/lib/widget/refreshable_state.dart @@ -5,9 +5,12 @@ import "package:flutter_tabler_icons/flutter_tabler_icons.dart"; import "package:inventree/api.dart"; import "package:inventree/app_colors.dart"; import "package:inventree/barcode/barcode.dart"; +import "package:inventree/l10.dart"; +import "package:inventree/preferences.dart"; import "package:inventree/widget/back.dart"; import "package:inventree/widget/drawer.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/search.dart"; /* @@ -204,9 +207,22 @@ abstract class RefreshableState extends State bool get loaded => !loading; + // Whether to display the "pk" (primary key / ID) value of the loaded model + bool showPk = false; + // Helper function to return API instance InvenTreeAPI get api => InvenTreeAPI(); + // Construct a tile to display the "pk" (primary key / ID) value of a model + // Only rendered by callers when the "showPk" setting is enabled + Widget pkTile(int pk) { + return ListTile( + title: Text(L10().pk), + leading: Icon(TablerIcons.hash), + trailing: LargeText(pk.toString()), + ); + } + @override void initState() { super.initState(); @@ -234,6 +250,8 @@ abstract class RefreshableState extends State loading = true; }); + showPk = await InvenTreeSettingsManager().getBool(INV_SHOW_PK, false); + await request(context); // Escape if the widget is no longer loaded diff --git a/lib/widget/stock/location_display.dart b/lib/widget/stock/location_display.dart index 6a944abb..066da764 100644 --- a/lib/widget/stock/location_display.dart +++ b/lib/widget/stock/location_display.dart @@ -366,6 +366,7 @@ class _LocationDisplayState extends RefreshableState { List tiles = [ locationDescriptionCard(), + if (showPk && location != null) pkTile(location!.pk), Expanded( child: PaginatedStockLocationList(filters, title: L10().sublocations), flex: 10, diff --git a/lib/widget/stock/stock_detail.dart b/lib/widget/stock/stock_detail.dart index dfdf4762..8792ac12 100644 --- a/lib/widget/stock/stock_detail.dart +++ b/lib/widget/stock/stock_detail.dart @@ -525,6 +525,10 @@ class _StockItemDisplayState extends RefreshableState { return tiles; } + if (showPk) { + tiles.add(pkTile(widget.item.pk)); + } + // Location information if ((widget.item.locationId > 0) && (widget.item.locationName.isNotEmpty)) { tiles.add(