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:
@@ -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
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -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',
|
||||||
|
@@ -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,
|
||||||
|
@@ -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,
|
||||||
|
@@ -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`,
|
||||||
|
@@ -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,
|
||||||
|
@@ -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) =>
|
||||||
|
Reference in New Issue
Block a user