2
0
mirror of https://github.com/inventree/InvenTree.git synced 2026-01-08 12:17:57 +00:00

Location parameters (#11084)

* Add parameter support for StockLocation model

* Serialize parameters for stock location

* Frontend support

* Bump API version

---------

Co-authored-by: Matthias Mair <code@mjmair.com>
This commit is contained in:
Oliver
2026-01-07 12:57:20 +11:00
committed by GitHub
parent 20c381f862
commit b478254e98
7 changed files with 110 additions and 8 deletions

View File

@@ -1,11 +1,14 @@
"""InvenTree API version information."""
# InvenTree API version
INVENTREE_API_VERSION = 436
INVENTREE_API_VERSION = 437
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
INVENTREE_API_TEXT = """
v437 -> 2026-01-07 : https://github.com/inventree/InvenTree/pull/11084
- Add generic parameter support for the StockLocation model
v436 -> 2026-01-06 : https://github.com/inventree/InvenTree/pull/11035
- Removes model-specific metadata endpoints and replaces them with redirects
- Adds new generic /api/metadata/<model_name>/ endpoint to retrieve metadata for any model

View File

@@ -120,6 +120,7 @@ class StockLocationReportContext(report.mixins.BaseReportContext):
class StockLocation(
InvenTree.models.PluginValidationMixin,
InvenTree.models.InvenTreeParameterMixin,
InvenTree.models.InvenTreeBarcodeMixin,
report.mixins.InvenTreeReportMixin,
InvenTree.models.PathStringMixin,

View File

@@ -1159,8 +1159,10 @@ class LocationSerializer(
'structural',
'external',
'location_type',
# Optional fields
'location_type_detail',
'tags',
'parameters',
]
read_only_fields = ['barcode_hash', 'icon', 'level', 'pathstring']
@@ -1205,6 +1207,8 @@ class LocationSerializer(
filter_name='path_detail',
)
parameters = common.filters.enable_parameters_filter()
# explicitly set this field, so it gets included for AutoSchema
icon = serializers.CharField(read_only=True)

View File

@@ -8,16 +8,19 @@ import type { PanelType } from './Panel';
export default function ParametersPanel({
model_type,
model_id,
hidden,
allowEdit = true
}: {
model_type: ModelType;
model_id: number | undefined;
hidden?: boolean;
allowEdit?: boolean;
}): PanelType {
return {
name: 'parameters',
label: t`Parameters`,
icon: <IconListDetails />,
hidden: hidden ?? false,
content:
model_type && model_id ? (
<ParameterTable

View File

@@ -6,7 +6,13 @@ import { getDetailUrl } from '@lib/functions/Navigation';
import type { StockOperationProps } from '@lib/types/Forms';
import { t } from '@lingui/core/macro';
import { Group, Skeleton, Stack, Text } from '@mantine/core';
import { IconInfoCircle, IconPackages, IconSitemap } from '@tabler/icons-react';
import {
IconInfoCircle,
IconListDetails,
IconPackages,
IconSitemap,
IconTable
} from '@tabler/icons-react';
import { useMemo, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { api } from '../../App';
@@ -30,6 +36,8 @@ import NavigationTree from '../../components/nav/NavigationTree';
import { PageDetail } from '../../components/nav/PageDetail';
import type { PanelType } from '../../components/panels/Panel';
import { PanelGroup } from '../../components/panels/PanelGroup';
import ParametersPanel from '../../components/panels/ParametersPanel';
import SegmentedControlPanel from '../../components/panels/SegmentedControlPanel';
import LocateItemButton from '../../components/plugins/LocateItemButton';
import { stockLocationFields } from '../../forms/StockForms';
import { InvenTreeIcon } from '../../functions/icons';
@@ -42,6 +50,7 @@ import { useStockAdjustActions } from '../../hooks/UseStockAdjustActions';
import { useUserState } from '../../states/UserState';
import { PartListTable } from '../../tables/part/PartTable';
import { StockItemTable } from '../../tables/stock/StockItemTable';
import StockLocationParametricTable from '../../tables/stock/StockLocationParametricTable';
import { StockLocationTable } from '../../tables/stock/StockLocationTable';
export default function Stock() {
@@ -161,6 +170,8 @@ export default function Stock() {
);
}, [location, instanceQuery]);
const [sublocationView, setSublocationView] = useState<string>('table');
const locationPanels: PanelType[] = useMemo(() => {
return [
{
@@ -169,12 +180,32 @@ export default function Stock() {
icon: <IconInfoCircle />,
content: detailsPanel
},
{
SegmentedControlPanel({
name: 'sublocations',
label: id ? t`Sublocations` : t`Stock Locations`,
icon: <IconSitemap />,
content: <StockLocationTable parentId={id} />
},
hidden: !user.hasViewPermission(ModelType.stocklocation),
selection: sublocationView,
onChange: setSublocationView,
options: [
{
value: 'table',
label: t`Table View`,
icon: <IconTable />,
content: <StockLocationTable parentId={id} />
},
{
value: 'parametric',
label: t`Parametric View`,
icon: <IconListDetails />,
content: (
<StockLocationParametricTable
queryParams={id ? { parent: id } : {}}
/>
)
}
]
}),
{
name: 'stock-items',
label: t`Stock Items`,
@@ -203,9 +234,14 @@ export default function Stock() {
}}
/>
)
}
},
ParametersPanel({
model_type: ModelType.stocklocation,
model_id: location.pk,
hidden: !location.pk
})
];
}, [location, id]);
}, [sublocationView, location, id]);
const editLocation = useEditApiFormModal({
url: ApiEndpoints.stock_location_list,

View File

@@ -1,8 +1,13 @@
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 { type ReactNode, useMemo } from 'react';
import { DescriptionColumn, ReferenceColumn } from '../ColumnRenderers';
import {
DescriptionColumn,
PartColumn,
ReferenceColumn
} from '../ColumnRenderers';
import { OrderStatusFilter, OutstandingFilter } from '../Filter';
import ParametricDataTable from '../general/ParametricDataTable';
@@ -16,6 +21,10 @@ export default function BuildOrderParametricTable({
ReferenceColumn({
switchable: false
}),
PartColumn({
part: 'part_detail',
title: t`Part`
}),
DescriptionColumn({
accessor: 'title'
})
@@ -33,6 +42,7 @@ export default function BuildOrderParametricTable({
customColumns={customColumns}
customFilters={customFilters}
queryParams={{
part_detail: true,
...queryParams
}}
/>

View File

@@ -0,0 +1,45 @@
import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
import { ModelType } from '@lib/enums/ModelType';
import type { TableColumn } from '@lib/types/Tables';
import { Group } from '@mantine/core';
import { type ReactNode, useMemo } from 'react';
import { ApiIcon } from '../../components/items/ApiIcon';
import { DescriptionColumn } from '../ColumnRenderers';
import ParametricDataTable from '../general/ParametricDataTable';
export default function StockLocationParametricTable({
queryParams
}: {
queryParams?: Record<string, any>;
}): ReactNode {
const customColumns: TableColumn[] = useMemo(() => {
return [
{
accessor: 'name',
switchable: false,
render: (record: any) => (
<Group gap='xs'>
{record.icon && <ApiIcon name={record.icon} />}
{record.name}
</Group>
)
},
DescriptionColumn({}),
{
accessor: 'pathstring',
sortable: true
}
];
}, []);
return (
<ParametricDataTable
modelType={ModelType.stocklocation}
endpoint={ApiEndpoints.stock_location_list}
customColumns={customColumns}
queryParams={{
...queryParams
}}
/>
);
}