From 382eaf6ab8568bc4a3db856c3a94b053740fe8b7 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 4 Mar 2026 08:07:40 +0000 Subject: [PATCH 1/8] Allow parameters for StockItem objects --- src/backend/InvenTree/stock/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/backend/InvenTree/stock/models.py b/src/backend/InvenTree/stock/models.py index b9f2c298a266..0a536434b4f6 100644 --- a/src/backend/InvenTree/stock/models.py +++ b/src/backend/InvenTree/stock/models.py @@ -400,6 +400,7 @@ class StockItemReportContext(report.mixins.BaseReportContext): class StockItem( InvenTree.models.PluginValidationMixin, + InvenTree.models.InvenTreeParameterMixin, InvenTree.models.InvenTreeAttachmentMixin, InvenTree.models.InvenTreeBarcodeMixin, InvenTree.models.InvenTreeNotesMixin, From 2590427faeeca6dba2ca7530e71abb51bf46fd73 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 4 Mar 2026 08:07:51 +0000 Subject: [PATCH 2/8] Update API serializer --- src/backend/InvenTree/stock/serializers.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/backend/InvenTree/stock/serializers.py b/src/backend/InvenTree/stock/serializers.py index 11ac344e1e49..ee1d3c3fd9dd 100644 --- a/src/backend/InvenTree/stock/serializers.py +++ b/src/backend/InvenTree/stock/serializers.py @@ -378,6 +378,7 @@ class Meta: 'stale', 'tracking_items', 'tags', + 'parameters', # Detail fields (FK relationships) 'supplier_part_detail', 'part_detail', @@ -657,6 +658,8 @@ def annotate_queryset(queryset): tags = common.filters.enable_tags_filter() + parameters = common.filters.enable_parameters_filter() + class SerializeStockItemSerializer(serializers.Serializer): """A DRF serializer for "serializing" a StockItem. From d934385b1040dbf6b0a3b5621729ece72537f57c Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 4 Mar 2026 08:11:03 +0000 Subject: [PATCH 3/8] Implement frontend panel --- src/frontend/src/pages/stock/StockDetail.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/frontend/src/pages/stock/StockDetail.tsx b/src/frontend/src/pages/stock/StockDetail.tsx index 6b39b8396496..e026a5cd334b 100644 --- a/src/frontend/src/pages/stock/StockDetail.tsx +++ b/src/frontend/src/pages/stock/StockDetail.tsx @@ -61,6 +61,7 @@ import AttachmentPanel from '../../components/panels/AttachmentPanel'; import NotesPanel from '../../components/panels/NotesPanel'; import type { PanelType } from '../../components/panels/Panel'; import { PanelGroup } from '../../components/panels/PanelGroup'; +import ParametersPanel from '../../components/panels/ParametersPanel'; import LocateItemButton from '../../components/plugins/LocateItemButton'; import { StatusRenderer } from '../../components/render/StatusRenderer'; import OrderPartsWizard from '../../components/wizards/OrderPartsWizard'; @@ -617,6 +618,11 @@ export default function StockDetail() { ) }, + ParametersPanel({ + model_type: ModelType.stockitem, + model_id: stockitem.pk, + hidden: !stockitem.pk + }), AttachmentPanel({ model_type: ModelType.stockitem, model_id: stockitem.pk From 3382833ad22ce56d2de127d7157731c33b801c03 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 4 Mar 2026 09:15:26 +0000 Subject: [PATCH 4/8] Add parametric view for stock items --- .../src/pages/stock/LocationDetail.tsx | 44 ++++++++++---- .../tables/stock/ParametricStockItemTable.tsx | 59 +++++++++++++++++++ 2 files changed, 90 insertions(+), 13 deletions(-) create mode 100644 src/frontend/src/tables/stock/ParametricStockItemTable.tsx diff --git a/src/frontend/src/pages/stock/LocationDetail.tsx b/src/frontend/src/pages/stock/LocationDetail.tsx index 1cdd66d5b579..0ea6b5b804ec 100644 --- a/src/frontend/src/pages/stock/LocationDetail.tsx +++ b/src/frontend/src/pages/stock/LocationDetail.tsx @@ -49,6 +49,7 @@ import { useInstance } from '../../hooks/UseInstance'; import { useStockAdjustActions } from '../../hooks/UseStockAdjustActions'; import { useUserState } from '../../states/UserState'; import { PartListTable } from '../../tables/part/PartTable'; +import ParametricStockItemTable from '../../tables/stock/ParametricStockItemTable'; import { StockItemTable } from '../../tables/stock/StockItemTable'; import StockLocationParametricTable from '../../tables/stock/StockLocationParametricTable'; import { StockLocationTable } from '../../tables/stock/StockLocationTable'; @@ -171,6 +172,7 @@ export default function Stock() { }, [location, instanceQuery]); const [sublocationView, setSublocationView] = useState('table'); + const [stockView, setStockView] = useState('table'); const locationPanels: PanelType[] = useMemo(() => { return [ @@ -206,20 +208,36 @@ export default function Stock() { } ] }), - { - name: 'stock-items', + SegmentedControlPanel({ + name: 'stockitems', label: t`Stock Items`, icon: , - content: ( - - ) - }, + hidden: !user.hasViewPermission(ModelType.stockitem), + selection: stockView, + onChange: setStockView, + options: [ + { + value: 'table', + label: t`Table View`, + icon: , + content: ( + + ) + }, + { + value: 'parametric', + label: t`Parametric View`, + icon: , + content: + } + ] + }), { name: 'default_parts', label: t`Default Parts`, @@ -241,7 +259,7 @@ export default function Stock() { hidden: !location.pk }) ]; - }, [sublocationView, location, id]); + }, [sublocationView, stockView, location, id]); const editLocation = useEditApiFormModal({ url: ApiEndpoints.stock_location_list, diff --git a/src/frontend/src/tables/stock/ParametricStockItemTable.tsx b/src/frontend/src/tables/stock/ParametricStockItemTable.tsx new file mode 100644 index 000000000000..0c0161d3d1ea --- /dev/null +++ b/src/frontend/src/tables/stock/ParametricStockItemTable.tsx @@ -0,0 +1,59 @@ +import { ApiEndpoints, ModelType } from '@lib/index'; +import type { TableFilter } from '@lib/types/Filters'; +import type { TableColumn } from '@lib/types/Tables'; +import { t } from '@lingui/core/macro'; +import { useMemo } from 'react'; +import { + DescriptionColumn, + IPNColumn, + PartColumn, + StockColumn +} from '../ColumnRenderers'; +import ParametricDataTable from '../general/ParametricDataTable'; + +export default function ParametricStockItemTable({ + locationId +}: Readonly<{ + locationId?: any; +}>) { + const customFilters: TableFilter[] = useMemo(() => { + // Custom filters for the parametric stock item table + return []; + }, []); + + const customColumns: TableColumn[] = useMemo(() => { + return [ + PartColumn({ + part: 'part_detail', + switchable: false + }), + IPNColumn({}), + DescriptionColumn({ + accessor: 'part_detail.description' + }), + StockColumn({ + accessor: '', + title: t`Stock`, + sortable: true, + ordering: 'stock' + }) + ]; + }, []); + + return ( + + ); +} From ebce83c5acc9ab2638643cc8924e5107a0c718c9 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 4 Mar 2026 09:56:39 +0000 Subject: [PATCH 5/8] Docs updates --- docs/docs/concepts/parameters.md | 12 ++++++------ docs/docs/concepts/units.md | 4 ++-- docs/docs/concepts/user_interface.md | 2 +- docs/docs/part/create.md | 2 +- docs/docs/part/index.md | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/docs/concepts/parameters.md b/docs/docs/concepts/parameters.md index ca44989dab64..b4e76a490282 100644 --- a/docs/docs/concepts/parameters.md +++ b/docs/docs/concepts/parameters.md @@ -40,9 +40,9 @@ Parameter templates are created and edited via the [admin interface](../settings To create a template: - Navigate to the "Settings" page -- Click on the "Part Parameters" tab +- Click on the "Parameters" tab - Click on the "New Parameter" button -- Fill out the `Create Part Parameter Template` form: `Name` (required) and `Units` (optional) fields +- Fill out the `Create Parameter Template` form: `Name` (required) and `Units` (optional) fields - Click on the "Submit" button. An existing template can be edited by clicking on the "Edit" button associated with that template: @@ -53,9 +53,9 @@ An existing template can be edited by clicking on the "Edit" button associated w After [creating a template](#create-template) or using the existing templates, you can add parameters to any part. -To add a parameter, navigate to a specific part detail page, click on the "Parameters" tab then click on the "New Parameters" button, the `Create Part Parameter` form will be displayed: +To add a parameter, navigate to a specific part detail page, click on the "Parameters" tab then click on the "New Parameters" button, the `Create Parameter` form will be displayed: -{{ image("part/create_part_parameter.png", "Create Part Parameter Form") }} +{{ image("part/create_part_parameter.png", "Create Parameter Form") }} Select the parameter `Template` you would like to use for this parameter, fill-out the `Data` field (value of this specific parameter) and click the "Submit" button. @@ -132,7 +132,7 @@ The in-built conversion functionality means that parameter values can be input i ### Incompatible Units -If a part parameter is created with a value which is incompatible with the units specified for the template, it will be rejected: +If a parameter is created with a value which is incompatible with the units specified for the template, it will be rejected: {{ image("part/part_invalid_units.png", "Invalid Parameter Units") }} @@ -151,4 +151,4 @@ Selection Lists can be used to add a large number of predefined values to a para It is possible that plugins lock selection lists to ensure a known state. -Administration of lists can be done through the Part Parameter section in the [Admin Center](../settings/admin.md#admin-center) or via the API. +Administration of lists can be done through the Parameters section in the [Admin Center](../settings/admin.md#admin-center) or via the API. diff --git a/docs/docs/concepts/units.md b/docs/docs/concepts/units.md index ce7101245539..9e1c1a50d7a9 100644 --- a/docs/docs/concepts/units.md +++ b/docs/docs/concepts/units.md @@ -8,7 +8,7 @@ Support for real-world "physical" units of measure is implemented using the [pin - Ensures consistent use of real units for your inventory management - Convert between compatible units of measure from suppliers -- Enforce use of compatible units when creating part parameters +- Enforce use of compatible units when creating parameters - Enable custom units as required ### Unit Conversion @@ -61,7 +61,7 @@ The [supplier part](../part/index.md/#supplier-parts) model uses real-world unit ### Parameter -The [parameter template](../concepts/parameters.md#parameter-templates) model can specify units of measure, and part parameters can be specified against these templates with compatible units +The [parameter template](../concepts/parameters.md#parameter-templates) model can specify units of measure, and parameters can be specified against these templates with compatible units ## Custom Units diff --git a/docs/docs/concepts/user_interface.md b/docs/docs/concepts/user_interface.md index 665b9fcf02f7..b9a171d4c06b 100644 --- a/docs/docs/concepts/user_interface.md +++ b/docs/docs/concepts/user_interface.md @@ -202,7 +202,7 @@ This will display the data in a calendar format: ## Parametric Views -Some [table views](#table-views) can be switched to a parametric view, which provides a visual representation of data based on specific parameters or attributes. The parametric view allows users to easily see and interact with data that is organized by certain characteristics, such as categories, types, or other relevant attributes. +Some [table views](#table-views) can be switched to a parametric view, which provides a visual representation of data based on specific [parameters attributes](./parameters.md). The parametric view allows users to easily see and interact with data that is organized by certain characteristics, such as categories, types, or other relevant attributes. To switch to the "parametric view" (for a table which supports it), click on the "parametric view" button located above and to the right of the table view: diff --git a/docs/docs/part/create.md b/docs/docs/part/create.md index d9b984e0e679..6d5796839061 100644 --- a/docs/docs/part/create.md +++ b/docs/docs/part/create.md @@ -20,7 +20,7 @@ New parts can be created manually by selecting the *Create Part* option from the {{ image("part/part_create_form.png", "New part form") }} -Fill out the required part parameters and then press *Submit* to create the new part. If there are any form errors, you must fix these before the form can be successfully submitted. +Fill out the required part attributes and then press *Submit* to create the new part. If there are any form errors, you must fix these before the form can be successfully submitted. Once the form is completed, the browser window is redirected to the new part detail page. diff --git a/docs/docs/part/index.md b/docs/docs/part/index.md index e4848ece1f44..076da58b2551 100644 --- a/docs/docs/part/index.md +++ b/docs/docs/part/index.md @@ -81,7 +81,7 @@ Parts can be locked to prevent them from being modified. This is useful for part - Locked parts cannot be deleted - BOM items cannot be created, edited, or deleted when they are part of a locked assembly -- Part parameters linked to a locked part cannot be created, edited or deleted +- Parameters linked to a locked part cannot be created, edited or deleted ## Active Parts From b242016056ab9af8740d1e3038babcc362c4bfbd Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 4 Mar 2026 10:53:00 +0000 Subject: [PATCH 6/8] Additional playwright tests --- src/frontend/tests/pages/pui_stock.spec.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/frontend/tests/pages/pui_stock.spec.ts b/src/frontend/tests/pages/pui_stock.spec.ts index 7bebed2b0081..1dcf67564b2e 100644 --- a/src/frontend/tests/pages/pui_stock.spec.ts +++ b/src/frontend/tests/pages/pui_stock.spec.ts @@ -5,7 +5,9 @@ import { loadTab, navigate, openFilterDrawer, - setTableChoiceFilter + setTableChoiceFilter, + showParametricView, + showTableView } from '../helpers.js'; import { doCachedLogin } from '../login.js'; @@ -36,6 +38,10 @@ test('Stock - Basic Tests', async ({ browser }) => { await loadTab(page, 'Test Results'); await page.getByText('395c6d5586e5fb656901d047be27e1f7').waitFor(); await loadTab(page, 'Installed Items'); + + await loadTab(page, 'Parameters'); + await loadTab(page, 'Attachments'); + await loadTab(page, 'Notes'); }); test('Stock - Location Tree', async ({ browser }) => { @@ -479,7 +485,15 @@ test('Stock - Location', async ({ browser }) => { await loadTab(page, 'Default Parts'); await loadTab(page, 'Stock Items'); + + await showParametricView(page); + await showTableView(page); + await loadTab(page, 'Sublocations'); + + await showParametricView(page); + await showTableView(page); + await loadTab(page, 'Location Details'); await page.getByLabel('action-menu-barcode-actions').click(); From 643c7be30a5d695e8918dc033e1748c80eb12f64 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 4 Mar 2026 10:55:00 +0000 Subject: [PATCH 7/8] Bump API version --- src/backend/InvenTree/InvenTree/api_version.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/backend/InvenTree/InvenTree/api_version.py b/src/backend/InvenTree/InvenTree/api_version.py index a41015e398b9..d69f6da4e157 100644 --- a/src/backend/InvenTree/InvenTree/api_version.py +++ b/src/backend/InvenTree/InvenTree/api_version.py @@ -1,11 +1,14 @@ """InvenTree API version information.""" # InvenTree API version -INVENTREE_API_VERSION = 460 +INVENTREE_API_VERSION = 461 """Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" INVENTREE_API_TEXT = """ +v461 -> 2026-03-04 : https://github.com/inventree/InvenTree/pull/11459 + - Adds "parameter" support for StockItem API endpoints + v460 -> 2026-02-25 : https://github.com/inventree/InvenTree/pull/11374 - Adds "updated_at" field to PurchaseOrder, SalesOrder and ReturnOrder API endpoints - Adds "updated_before" and "updated_after" date filters to all three order list endpoints From 874b316e38ef3d6287882878a58969be183e3551 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 4 Mar 2026 10:56:58 +0000 Subject: [PATCH 8/8] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7970539d254..c7d0e204f904 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#10887](https://github.com/inventree/InvenTree/pull/10887) adds the ability to auto-allocate tracked items against specific build outputs. Currently, this will only allocate items where the serial number of the tracked item matches the serial number of the build output, but in future this may be extended to allow for more flexible allocation rules. - [#11372](https://github.com/inventree/InvenTree/pull/11372) adds backup metadata setter and restore metadata validator functions to ensure common footguns are harder to trigger when using the backup and restore functionality. - [#11374](https://github.com/inventree/InvenTree/pull/11374) adds `updated_at` field on purchase, sales and return orders. +- [#11459](https://github.com/inventree/InvenTree/pull/11459) adds parameter support for the StockItem model ### Changed