2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-07-18 02:36:31 +00:00

[UI] Build page tweak (#10027)

* Hide "consumed stock" panel if not required

* Docs updates

* Hide allocation fields if the build has no required parts

* Additional serializer options
This commit is contained in:
Oliver
2025-07-15 18:27:09 +10:00
committed by GitHub
parent 42abc61494
commit 75ab57bc0b
4 changed files with 62 additions and 22 deletions

View File

@@ -119,14 +119,33 @@ The *Build Details* panel provides an overview of the Build Order:
{{ image ("build/build_panel_details.png", title="Build Details") }}
### Line Items
### Required Parts
The *Line Items* panel displays all the line items (as defined by the [bill of materials](./bom.md)) required to complete the build order.
The *Required Parts* panel displays all the line items (as defined by the [bill of materials](./bom.md)) required to complete the build order.
{{ image("build/build_panel_line_items.png", title="Line Items") }}
The allocation table (as shown above) provides an interface to allocate required stock, and also shows the stock allocation progress for each line item in the build.
### Allocated Stock
The *Allocated Stock* tab displays all stock items which have been *allocated* to this build order. These stock items are reserved for this build, and will be consumed when the build is completed:
{{ image("build/allocated_stock_table.png", title="Allocated Stock Table") }}
!!! info "No BOM"
If the part being built does not have a BOM, then the *Allocated Stock* tab will not be displayed.
### Consumed Stock
The *Consumed Stock* tab displays all stock items which have been *consumed* by this build order. These stock items remain in the database after the build order has been completed, but are no longer available for use.
- [Tracked stock items](./allocate.md#tracked-stock) are consumed by specific build outputs
- [Untracked stock items](./allocate.md#untracked-stock) are consumed by the build order
!!! info "No BOM"
If the part being built does not have a BOM, then the *Consumed Stock* tab will not be displayed.
### Incomplete Outputs
The *Incomplete Outputs* panel shows the list of in-progress [build outputs](./output.md) (created stock items) associated with this build.
@@ -144,19 +163,6 @@ The *Incomplete Outputs* panel shows the list of in-progress [build outputs](./o
This panel displays all the completed build outputs (stock items) which have been created by this build order:
### Allocated Stock
The *Allocated Stock* tab displays all stock items which have been *allocated* to this build order. These stock items are reserved for this build, and will be consumed when the build is completed:
{{ image("build/allocated_stock_table.png", title="Allocated Stock Table") }}
### Consumed Stock
The *Consumed Stock* tab displays all stock items which have been *consumed* by this build order. These stock items remain in the database after the build order has been completed, but are no longer available for use.
- [Tracked stock items](./allocate.md#tracked-stock) are consumed by specific build outputs
- [Untracked stock items](./allocate.md#untracked-stock) are consumed by the build order
### Child Builds
If there exist any build orders which are *children* of the selected build order, they are displayed in the *Child Builds* tab:

View File

@@ -532,8 +532,10 @@ class BuildLineEndpoint:
try:
params = self.request.query_params
kwargs['bom_item_detail'] = str2bool(params.get('bom_item_detail', True))
kwargs['part_detail'] = str2bool(params.get('part_detail', True))
kwargs['build_detail'] = str2bool(params.get('build_detail', False))
kwargs['allocations'] = str2bool(params.get('allocations', True))
except AttributeError:
pass

View File

@@ -1328,19 +1328,27 @@ class BuildLineSerializer(DataImportExportSerializerMixin, InvenTreeModelSeriali
def __init__(self, *args, **kwargs):
"""Determine which extra details fields should be included."""
part_detail = kwargs.pop('part_detail', True)
bom_item_detail = kwargs.pop('bom_item_detail', True)
build_detail = kwargs.pop('build_detail', True)
allocations = kwargs.pop('allocations', True)
super().__init__(*args, **kwargs)
if isGeneratingSchema():
return
if not bom_item_detail:
self.fields.pop('bom_item_detail', None)
if not part_detail:
self.fields.pop('part_detail', None)
if not build_detail:
self.fields.pop('build_detail', None)
if not allocations:
self.fields.pop('allocations', None)
# Build info fields
build_reference = serializers.CharField(
source='build.reference', label=_('Build Reference'), read_only=True

View File

@@ -2,6 +2,7 @@ import { t } from '@lingui/core/macro';
import { Alert, Grid, Skeleton, Stack, Text } from '@mantine/core';
import {
IconChecklist,
IconCircleCheck,
IconClipboardCheck,
IconClipboardList,
IconInfoCircle,
@@ -19,6 +20,7 @@ import { ModelType } from '@lib/enums/ModelType';
import { UserRoles } from '@lib/enums/Roles';
import { apiUrl } from '@lib/functions/Api';
import { getDetailUrl } from '@lib/functions/Navigation';
import type { ApiFormFieldSet } from '@lib/types/Forms';
import AdminButton from '../../components/buttons/AdminButton';
import PrimaryActionButton from '../../components/buttons/PrimaryActionButton';
import { PrintingActions } from '../../components/buttons/PrintingActions';
@@ -130,6 +132,10 @@ export default function BuildDetail() {
endpoint: ApiEndpoints.build_line_list,
params: {
build: id,
allocations: false,
part_detail: false,
build_detail: false,
bom_item_detail: false,
limit: 1
},
disabled: !id,
@@ -417,7 +423,8 @@ export default function BuildDetail() {
icon: <IconList />,
hidden:
build.status == buildStatus.COMPLETE ||
build.status == buildStatus.CANCELLED,
build.status == buildStatus.CANCELLED ||
(buildLineData?.count ?? 0) <= 0, // Hide if no required parts
content: (
<BuildAllocationsPanel
build={build}
@@ -430,6 +437,7 @@ export default function BuildDetail() {
name: 'consumed-stock',
label: t`Consumed Stock`,
icon: <IconListCheck />,
hidden: (buildLineData?.count ?? 0) <= 0, // Hide if no required parts
content: (
<StockItemTable
allowAdd={false}
@@ -590,17 +598,33 @@ export default function BuildDetail() {
successMessage: t`Order issued`
});
const completeOrderFields: ApiFormFieldSet = useMemo(() => {
const hasBom = (buildLineData?.count ?? 0) > 0;
return {
accept_overallocated: {
hidden: !hasBom
},
accept_unallocated: {
hidden: !hasBom
},
accept_incomplete: {}
};
}, [buildLineData.count]);
const completeOrder = useCreateApiFormModal({
url: apiUrl(ApiEndpoints.build_order_complete, build.pk),
title: t`Complete Build Order`,
onFormSuccess: refreshInstance,
preFormWarning: t`Mark this order as complete`,
preFormContent: (
<Alert
color='green'
icon={<IconCircleCheck />}
title={t`Mark this order as complete`}
/>
),
successMessage: t`Order completed`,
fields: {
accept_overallocated: {},
accept_unallocated: {},
accept_incomplete: {}
}
fields: completeOrderFields
});
const buildActions = useMemo(() => {