Skip to content

Commit

Permalink
[PUI] Sub builds table (#7932)
Browse files Browse the repository at this point in the history
* Allow table filters to be marked "inactive"

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

* Update build order table

* Bump API version
  • Loading branch information
SchrodingersGat authored Aug 20, 2024
1 parent 6591286 commit 7cbaeb1
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 68 deletions.
9 changes: 7 additions & 2 deletions src/backend/InvenTree/InvenTree/api_version.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down
31 changes: 30 additions & 1 deletion src/backend/InvenTree/build/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ class Meta:
"""Metaclass options."""
model = Build
fields = [
'parent',
'sales_order',
'part',
]
Expand All @@ -49,6 +48,35 @@ def filter_active(self, queryset, name, value):
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):
Expand Down Expand Up @@ -175,6 +203,7 @@ class BuildList(DataExportViewMixin, BuildMixin, ListCreateAPI):
'responsible',
'project_code',
'priority',
'level',
]

ordering_field_aliases = {
Expand Down
4 changes: 4 additions & 0 deletions src/backend/InvenTree/build/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class Meta:
'responsible',
'responsible_detail',
'priority',
'level',
]

read_only_fields = [
Expand All @@ -84,8 +85,11 @@ class Meta:
'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)
Expand Down
1 change: 1 addition & 0 deletions src/frontend/src/tables/Filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export type TableFilter = {
defaultValue?: any;
value?: any;
displayValue?: any;
active?: boolean;
};

/**
Expand Down
14 changes: 8 additions & 6 deletions src/frontend/src/tables/InvenTreeTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,14 @@ 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) => {
return {
...filter,
label: filter.label ?? fieldNames[filter.name] ?? `${filter.name}`
};
}) ?? []
props.tableFilters
?.filter((f: any) => f.active != false)
?.map((filter) => {
return {
...filter,
label: filter.label ?? fieldNames[filter.name] ?? `${filter.name}`
};
}) ?? []
);
}, [props.tableFilters, fieldNames]);

Expand Down
126 changes: 67 additions & 59 deletions src/frontend/src/tables/build/BuildOrderTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,63 +27,6 @@ import {
import { StatusFilterOptions, TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';

/**
* Construct a list of columns for the build order table
*/
function buildOrderTableColumns(): TableColumn[] {
return [
ReferenceColumn({}),
{
accessor: 'part',
sortable: true,
switchable: false,
render: (record: any) => PartColumn(record.part_detail)
},
{
accessor: 'part_detail.IPN',
sortable: true,
switchable: true,
title: t`IPN`
},
{
accessor: 'title',
sortable: false
},
{
accessor: 'completed',
sortable: true,
switchable: false,
render: (record: any) => (
<ProgressBar
progressLabel={true}
value={record.completed}
maximum={record.quantity}
/>
)
},
StatusColumn({ model: ModelType.build }),
ProjectCodeColumn({}),
{
accessor: 'priority',
sortable: true
},
CreationDateColumn({}),
TargetDateColumn({}),
DateColumn({
accessor: 'completion_date',
sortable: true
}),
{
accessor: 'issued_by',
sortable: true,
render: (record: any) => (
<RenderUser instance={record?.issued_by_detail} />
)
},
ResponsibleColumn({})
];
}

/*
* Construct a table of build orders, according to the provided parameters
*/
Expand All @@ -96,7 +39,65 @@ export function BuildOrderTable({
parentBuildId?: number;
salesOrderId?: number;
}) {
const tableColumns = useMemo(() => buildOrderTableColumns(), []);
const tableColumns = useMemo(() => {
return [
ReferenceColumn({}),
{
accessor: 'part',
sortable: true,
switchable: false,
render: (record: any) => PartColumn(record.part_detail)
},
{
accessor: 'part_detail.IPN',
sortable: true,
switchable: true,
title: t`IPN`
},
{
accessor: 'title',
sortable: false
},
{
accessor: 'completed',
sortable: true,
switchable: false,
render: (record: any) => (
<ProgressBar
progressLabel={true}
value={record.completed}
maximum={record.quantity}
/>
)
},
StatusColumn({ model: ModelType.build }),
ProjectCodeColumn({}),
{
accessor: 'level',
sortable: true,
switchable: true,
hidden: !parentBuildId
},
{
accessor: 'priority',
sortable: true
},
CreationDateColumn({}),
TargetDateColumn({}),
DateColumn({
accessor: 'completion_date',
sortable: true
}),
{
accessor: 'issued_by',
sortable: true,
render: (record: any) => (
<RenderUser instance={record?.issued_by_detail} />
)
},
ResponsibleColumn({})
];
}, [parentBuildId]);

const projectCodeFilters = useProjectCodeFilters();
const ownerFilters = useOwnerFilters();
Expand All @@ -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`,
Expand Down Expand Up @@ -151,7 +159,7 @@ export function BuildOrderTable({
choices: ownerFilters.choices
}
];
}, [projectCodeFilters.choices, ownerFilters.choices]);
}, [parentBuildId, projectCodeFilters.choices, ownerFilters.choices]);

const user = useUserState();

Expand Down

0 comments on commit 7cbaeb1

Please sign in to comment.