[PUI] Sub builds table (#7932)

* Allow table filters to be marked "inactive"

* Allow build orders to be filtering by 'cascading' parent

* Update build order table

* Bump API version
This commit is contained in:
Oliver 2024-08-20 11:21:38 +10:00 committed by GitHub
parent 6591286e27
commit 7cbaeb159e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 117 additions and 68 deletions

View File

@ -1,14 +1,19 @@
"""InvenTree API version information."""
# InvenTree API version
INVENTREE_API_VERSION = 241
INVENTREE_API_VERSION = 242
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
INVENTREE_API_TEXT = """
v241 - 2024-09-18 : https://github.com/inventree/InvenTree/pull/7906
v242 - 2024-08-20 : https://github.com/inventree/InvenTree/pull/7932
- Adds "level" attribute to BuildOrder serializer
- Allow ordering of BuildOrder API by "level" attribute
- Allow "parent" filter for BuildOrder API to have "cascade=True" option
v241 - 2024-08-18 : https://github.com/inventree/InvenTree/pull/7906
- Adjusts required fields for the MeUserDetail endpoint
v240 - 2024-08-16 : https://github.com/inventree/InvenTree/pull/7900

View File

@ -34,7 +34,6 @@ class BuildFilter(rest_filters.FilterSet):
"""Metaclass options."""
model = Build
fields = [
'parent',
'sales_order',
'part',
]
@ -49,6 +48,35 @@ class BuildFilter(rest_filters.FilterSet):
return queryset.filter(status__in=BuildStatusGroups.ACTIVE_CODES)
return queryset.exclude(status__in=BuildStatusGroups.ACTIVE_CODES)
cascade = rest_filters.BooleanFilter(label=_('Cascade'), method='filter_cascade')
def filter_cascade(self, queryset, name, value):
"""Filter by whether or not the build is a 'cascade' build.
Note: this only applies when the 'parent' field filter is specified.
"""
# No filtering here, see 'filter_parent'
return queryset
parent = rest_filters.ModelChoiceFilter(
queryset=Build.objects.all(),
label=_('Parent Build'),
field_name='parent',
method='filter_parent'
)
def filter_parent(self, queryset, name, parent):
"""Filter by 'parent' build order."""
cascade = str2bool(self.data.get('cascade', False))
if cascade:
builds = parent.get_descendants(include_self=False)
return queryset.filter(pk__in=[b.pk for b in builds])
return queryset.filter(parent=parent)
overdue = rest_filters.BooleanFilter(label='Build is overdue', method='filter_overdue')
def filter_overdue(self, queryset, name, value):
@ -175,6 +203,7 @@ class BuildList(DataExportViewMixin, BuildMixin, ListCreateAPI):
'responsible',
'project_code',
'priority',
'level',
]
ordering_field_aliases = {

View File

@ -76,6 +76,7 @@ class BuildSerializer(NotesFieldMixin, DataImportExportSerializerMixin, InvenTre
'responsible',
'responsible_detail',
'priority',
'level',
]
read_only_fields = [
@ -84,8 +85,11 @@ class BuildSerializer(NotesFieldMixin, DataImportExportSerializerMixin, InvenTre
'completion_data',
'status',
'status_text',
'level',
]
level = serializers.IntegerField(label=_('Build Level'), read_only=True)
url = serializers.CharField(source='get_absolute_url', read_only=True)
status_text = serializers.CharField(source='get_status_display', read_only=True)

View File

@ -28,6 +28,7 @@ export type TableFilter = {
defaultValue?: any;
value?: any;
displayValue?: any;
active?: boolean;
};
/**

View File

@ -164,7 +164,9 @@ export function InvenTreeTable<T = any>({
// Construct table filters - note that we can introspect filter labels from column names
const filters: TableFilter[] = useMemo(() => {
return (
props.tableFilters?.map((filter) => {
props.tableFilters
?.filter((f: any) => f.active != false)
?.map((filter) => {
return {
...filter,
label: filter.label ?? fieldNames[filter.name] ?? `${filter.name}`

View File

@ -27,10 +27,19 @@ import {
import { StatusFilterOptions, TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
/**
* Construct a list of columns for the build order table
/*
* Construct a table of build orders, according to the provided parameters
*/
function buildOrderTableColumns(): TableColumn[] {
export function BuildOrderTable({
partId,
parentBuildId,
salesOrderId
}: {
partId?: number;
parentBuildId?: number;
salesOrderId?: number;
}) {
const tableColumns = useMemo(() => {
return [
ReferenceColumn({}),
{
@ -63,6 +72,12 @@ function buildOrderTableColumns(): TableColumn[] {
},
StatusColumn({ model: ModelType.build }),
ProjectCodeColumn({}),
{
accessor: 'level',
sortable: true,
switchable: true,
hidden: !parentBuildId
},
{
accessor: 'priority',
sortable: true
@ -82,21 +97,7 @@ function buildOrderTableColumns(): TableColumn[] {
},
ResponsibleColumn({})
];
}
/*
* Construct a table of build orders, according to the provided parameters
*/
export function BuildOrderTable({
partId,
parentBuildId,
salesOrderId
}: {
partId?: number;
parentBuildId?: number;
salesOrderId?: number;
}) {
const tableColumns = useMemo(() => buildOrderTableColumns(), []);
}, [parentBuildId]);
const projectCodeFilters = useProjectCodeFilters();
const ownerFilters = useOwnerFilters();
@ -109,6 +110,13 @@ export function BuildOrderTable({
label: t`Active`,
description: t`Show active orders`
},
{
name: 'cascade',
type: 'boolean',
label: t`Cascade`,
description: t`Display recursive child orders`,
active: !!parentBuildId
},
{
name: 'status',
label: t`Status`,
@ -151,7 +159,7 @@ export function BuildOrderTable({
choices: ownerFilters.choices
}
];
}, [projectCodeFilters.choices, ownerFilters.choices]);
}, [parentBuildId, projectCodeFilters.choices, ownerFilters.choices]);
const user = useUserState();