2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-08-06 20:11:37 +00:00

Build on order (#10111)

* add DecimalColumn component

* Adds more production information to build lines

* Bump API version

* Improve rendering
This commit is contained in:
Oliver
2025-08-01 15:34:39 +10:00
committed by GitHub
parent e494aef1ff
commit bc382cd883
8 changed files with 75 additions and 33 deletions

View File

@@ -1,12 +1,15 @@
"""InvenTree API version information.""" """InvenTree API version information."""
# InvenTree API version # InvenTree API version
INVENTREE_API_VERSION = 377 INVENTREE_API_VERSION = 378
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" """Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
INVENTREE_API_TEXT = """ INVENTREE_API_TEXT = """
v378 -> 2025-08-01 : https://github.com/inventree/InvenTree/pull/10111
- Adds "scheduled_to_build" annotated field to BuildLine serializer
v377 -> 2025-08-01 : https://github.com/inventree/InvenTree/pull/10109 v377 -> 2025-08-01 : https://github.com/inventree/InvenTree/pull/10109
- Allow email records to be deleted via the API - Allow email records to be deleted via the API

View File

@@ -1308,6 +1308,7 @@ class BuildLineSerializer(DataImportExportSerializerMixin, InvenTreeModelSeriali
# Annotated fields # Annotated fields
'allocated', 'allocated',
'in_production', 'in_production',
'scheduled_to_build',
'on_order', 'on_order',
'available_stock', 'available_stock',
'available_substitute_stock', 'available_substitute_stock',
@@ -1438,13 +1439,12 @@ class BuildLineSerializer(DataImportExportSerializerMixin, InvenTreeModelSeriali
) )
# Annotated (calculated) fields # Annotated (calculated) fields
# Total quantity of allocated stock
allocated = serializers.FloatField(label=_('Allocated Stock'), read_only=True) allocated = serializers.FloatField(label=_('Allocated Stock'), read_only=True)
on_order = serializers.FloatField(label=_('On Order'), read_only=True) on_order = serializers.FloatField(label=_('On Order'), read_only=True)
in_production = serializers.FloatField(label=_('In Production'), read_only=True) in_production = serializers.FloatField(label=_('In Production'), read_only=True)
scheduled_to_build = serializers.FloatField(
label=_('Scheduled to Build'), read_only=True
)
external_stock = serializers.FloatField(read_only=True, label=_('External Stock')) external_stock = serializers.FloatField(read_only=True, label=_('External Stock'))
available_stock = serializers.FloatField(read_only=True, label=_('Available Stock')) available_stock = serializers.FloatField(read_only=True, label=_('Available Stock'))
@@ -1464,6 +1464,7 @@ class BuildLineSerializer(DataImportExportSerializerMixin, InvenTreeModelSeriali
- available: Total stock available for allocation against this build line - available: Total stock available for allocation against this build line
- on_order: Total stock on order for this build line - on_order: Total stock on order for this build line
- in_production: Total stock currently in production for this build line - in_production: Total stock currently in production for this build line
- scheduled_to_build: Total stock scheduled to be built for this build line
Arguments: Arguments:
queryset: The queryset to annotate queryset: The queryset to annotate
@@ -1573,7 +1574,10 @@ class BuildLineSerializer(DataImportExportSerializerMixin, InvenTreeModelSeriali
# Annotate the "in_production" quantity # Annotate the "in_production" quantity
queryset = queryset.annotate( queryset = queryset.annotate(
in_production=part.filters.annotate_in_production_quantity(reference=ref) in_production=part.filters.annotate_in_production_quantity(reference=ref),
scheduled_to_build=part.filters.annotate_scheduled_to_build_quantity(
reference=ref
),
) )
# Annotate the "on_order" quantity # Annotate the "on_order" quantity

View File

@@ -19,7 +19,11 @@ import type { TableColumn, TableColumnProps } from '@lib/types/Tables';
import { Thumbnail } from '../components/images/Thumbnail'; import { Thumbnail } from '../components/images/Thumbnail';
import { TableStatusRenderer } from '../components/render/StatusRenderer'; import { TableStatusRenderer } from '../components/render/StatusRenderer';
import { RenderOwner, RenderUser } from '../components/render/User'; import { RenderOwner, RenderUser } from '../components/render/User';
import { formatCurrency, formatDate } from '../defaults/formatters'; import {
formatCurrency,
formatDate,
formatDecimal
} from '../defaults/formatters';
import { import {
useGlobalSettingsState, useGlobalSettingsState,
useUserSettingsState useUserSettingsState
@@ -212,6 +216,16 @@ export function BooleanColumn(props: TableColumn): TableColumn {
}; };
} }
export function DecimalColumn(props: TableColumn): TableColumn {
return {
render: (record: any) => {
const value = resolveItem(record, props.accessor ?? '');
return formatDecimal(value);
},
...props
};
}
export function DescriptionColumn(props: TableColumnProps): TableColumn { export function DescriptionColumn(props: TableColumnProps): TableColumn {
return { return {
accessor: 'description', accessor: 'description',

View File

@@ -10,7 +10,6 @@ import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
import { ModelType } from '@lib/enums/ModelType'; import { ModelType } from '@lib/enums/ModelType';
import { UserRoles } from '@lib/enums/Roles'; import { UserRoles } from '@lib/enums/Roles';
import { apiUrl } from '@lib/functions/Api'; import { apiUrl } from '@lib/functions/Api';
import { formatDecimal } from '@lib/functions/Formatting';
import type { TableFilter } from '@lib/types/Filters'; import type { TableFilter } from '@lib/types/Filters';
import type { TableColumn } from '@lib/types/Tables'; import type { TableColumn } from '@lib/types/Tables';
import type { StockOperationProps } from '../../forms/StockForms'; import type { StockOperationProps } from '../../forms/StockForms';
@@ -22,6 +21,7 @@ import { useStockAdjustActions } from '../../hooks/UseStockAdjustActions';
import { useTable } from '../../hooks/UseTable'; import { useTable } from '../../hooks/UseTable';
import { useUserState } from '../../states/UserState'; import { useUserState } from '../../states/UserState';
import { import {
DecimalColumn,
LocationColumn, LocationColumn,
PartColumn, PartColumn,
ReferenceColumn, ReferenceColumn,
@@ -131,19 +131,16 @@ export default function BuildAllocatedStockTable({
switchable: true, switchable: true,
render: (record: any) => record?.stock_item_detail?.batch render: (record: any) => record?.stock_item_detail?.batch
}, },
{ DecimalColumn({
accessor: 'available', accessor: 'available',
title: t`Available Quantity`, title: t`Available Quantity`
render: (record: any) => }),
formatDecimal(record?.stock_item_detail?.quantity) DecimalColumn({
},
{
accessor: 'quantity', accessor: 'quantity',
title: t`Allocated Quantity`, title: t`Allocated Quantity`,
sortable: true, sortable: true,
switchable: false, switchable: false
render: (record: any) => formatDecimal(record?.quantity) }),
},
LocationColumn({ LocationColumn({
accessor: 'location_detail', accessor: 'location_detail',
switchable: true, switchable: true,

View File

@@ -42,6 +42,7 @@ import { useTable } from '../../hooks/UseTable';
import { useUserState } from '../../states/UserState'; import { useUserState } from '../../states/UserState';
import { import {
BooleanColumn, BooleanColumn,
DecimalColumn,
DescriptionColumn, DescriptionColumn,
LocationColumn, LocationColumn,
PartColumn PartColumn
@@ -445,6 +446,26 @@ export default function BuildLineTable({
switchable: false, switchable: false,
render: renderAvailableColumn render: renderAvailableColumn
}, },
{
accessor: 'in_production',
render: (record: any) => {
if (record.scheduled_to_build > 0) {
return (
<ProgressBar
progressLabel={true}
value={record.in_production}
maximum={record.scheduled_to_build}
/>
);
} else {
return record.part_detail?.is_assembly ? 0 : '-';
}
}
},
DecimalColumn({
accessor: 'on_order',
defaultVisible: false
}),
{ {
accessor: 'allocated', accessor: 'allocated',
switchable: false, switchable: false,

View File

@@ -12,7 +12,7 @@ import type { ApiEndpoints } from '@lib/enums/ApiEndpoints';
import type { UserRoles } from '@lib/enums/Roles'; import type { UserRoles } from '@lib/enums/Roles';
import { apiUrl } from '@lib/functions/Api'; import { apiUrl } from '@lib/functions/Api';
import type { TableColumn } from '@lib/types/Tables'; import type { TableColumn } from '@lib/types/Tables';
import { formatCurrency, formatDecimal } from '../../defaults/formatters'; import { formatCurrency } from '../../defaults/formatters';
import { extraLineItemFields } from '../../forms/CommonForms'; import { extraLineItemFields } from '../../forms/CommonForms';
import { import {
useCreateApiFormModal, useCreateApiFormModal,
@@ -21,7 +21,12 @@ import {
} from '../../hooks/UseForm'; } from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable'; import { useTable } from '../../hooks/UseTable';
import { useUserState } from '../../states/UserState'; import { useUserState } from '../../states/UserState';
import { DescriptionColumn, LinkColumn, NoteColumn } from '../ColumnRenderers'; import {
DecimalColumn,
DescriptionColumn,
LinkColumn,
NoteColumn
} from '../ColumnRenderers';
import { InvenTreeTable } from '../InvenTreeTable'; import { InvenTreeTable } from '../InvenTreeTable';
export default function ExtraLineItemTable({ export default function ExtraLineItemTable({
@@ -47,11 +52,10 @@ export default function ExtraLineItemTable({
switchable: false switchable: false
}, },
DescriptionColumn({}), DescriptionColumn({}),
{ DecimalColumn({
accessor: 'quantity', accessor: 'quantity',
switchable: false, switchable: false
render: (record: any) => formatDecimal(record.quantity) }),
},
{ {
accessor: 'price', accessor: 'price',
title: t`Unit Price`, title: t`Unit Price`,

View File

@@ -12,7 +12,6 @@ import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
import { ModelType } from '@lib/enums/ModelType'; import { ModelType } from '@lib/enums/ModelType';
import { UserRoles } from '@lib/enums/Roles'; import { UserRoles } from '@lib/enums/Roles';
import { apiUrl } from '@lib/functions/Api'; import { apiUrl } from '@lib/functions/Api';
import { formatDecimal } from '@lib/index';
import type { TableFilter } from '@lib/types/Filters'; import type { TableFilter } from '@lib/types/Filters';
import type { TableColumn } from '@lib/types/Tables'; import type { TableColumn } from '@lib/types/Tables';
import { useSupplierPartFields } from '../../forms/CompanyForms'; import { useSupplierPartFields } from '../../forms/CompanyForms';
@@ -26,6 +25,7 @@ import { useUserState } from '../../states/UserState';
import { import {
BooleanColumn, BooleanColumn,
CompanyColumn, CompanyColumn,
DecimalColumn,
DescriptionColumn, DescriptionColumn,
LinkColumn, LinkColumn,
NoteColumn, NoteColumn,
@@ -90,11 +90,10 @@ export function SupplierPartTable({
switchable: true, switchable: true,
defaultVisible: false defaultVisible: false
}), }),
{ DecimalColumn({
accessor: 'in_stock', accessor: 'in_stock',
sortable: true, sortable: true
render: (record: any) => formatDecimal(record.in_stock) }),
},
{ {
accessor: 'packaging', accessor: 'packaging',
sortable: true, sortable: true,

View File

@@ -29,7 +29,7 @@ import type { TableFilter } from '@lib/types/Filters';
import type { TableColumn } from '@lib/types/Tables'; import type { TableColumn } from '@lib/types/Tables';
import { RenderPart } from '../../components/render/Part'; import { RenderPart } from '../../components/render/Part';
import OrderPartsWizard from '../../components/wizards/OrderPartsWizard'; import OrderPartsWizard from '../../components/wizards/OrderPartsWizard';
import { formatCurrency, formatDecimal } from '../../defaults/formatters'; import { formatCurrency } from '../../defaults/formatters';
import { useBuildOrderFields } from '../../forms/BuildForms'; import { useBuildOrderFields } from '../../forms/BuildForms';
import { import {
useAllocateToSalesOrderForm, useAllocateToSalesOrderForm,
@@ -45,6 +45,7 @@ import { useTable } from '../../hooks/UseTable';
import { useUserState } from '../../states/UserState'; import { useUserState } from '../../states/UserState';
import { import {
DateColumn, DateColumn,
DecimalColumn,
DescriptionColumn, DescriptionColumn,
LinkColumn, LinkColumn,
PartColumn PartColumn
@@ -102,11 +103,10 @@ export default function SalesOrderLineItemTable({
sortable: false, sortable: false,
switchable: true switchable: true
}, },
{ DecimalColumn({
accessor: 'quantity', accessor: 'quantity',
sortable: true, sortable: true
render: (record: any) => formatDecimal(record.quantity) }),
},
{ {
accessor: 'sale_price', accessor: 'sale_price',
render: (record: any) => render: (record: any) =>