mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-28 19:46:46 +00:00
Add server-side annotation for "can_build" (#7619)
* Add server-side annotation for "can_build" - This calculation now performed on the server (in the API) - Allows better table ordering, etc - Makes it available for data export * Bump API version
This commit is contained in:
parent
81ab7aa625
commit
2ebe6e0a8e
@ -1,12 +1,15 @@
|
|||||||
"""InvenTree API version information."""
|
"""InvenTree API version information."""
|
||||||
|
|
||||||
# InvenTree API version
|
# InvenTree API version
|
||||||
INVENTREE_API_VERSION = 217
|
INVENTREE_API_VERSION = 218
|
||||||
|
|
||||||
"""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 = """
|
||||||
|
v218 - 2024-07-11 : https://github.com/inventree/InvenTree/pull/7619
|
||||||
|
- Adds "can_build" field to the BomItem API
|
||||||
|
|
||||||
v217 - 2024-07-09 : https://github.com/inventree/InvenTree/pull/7599
|
v217 - 2024-07-09 : https://github.com/inventree/InvenTree/pull/7599
|
||||||
- Fixes bug in "project_code" field for order API endpoints
|
- Fixes bug in "project_code" field for order API endpoints
|
||||||
|
|
||||||
|
@ -1841,7 +1841,6 @@ class BomList(BomMixin, DataExportViewMixin, ListCreateDestroyAPIView):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
filterset_class = BomFilter
|
filterset_class = BomFilter
|
||||||
|
|
||||||
filter_backends = SEARCH_ORDER_FILTER_ALIAS
|
filter_backends = SEARCH_ORDER_FILTER_ALIAS
|
||||||
|
|
||||||
search_fields = [
|
search_fields = [
|
||||||
@ -1855,6 +1854,7 @@ class BomList(BomMixin, DataExportViewMixin, ListCreateDestroyAPIView):
|
|||||||
]
|
]
|
||||||
|
|
||||||
ordering_fields = [
|
ordering_fields = [
|
||||||
|
'can_build',
|
||||||
'quantity',
|
'quantity',
|
||||||
'sub_part',
|
'sub_part',
|
||||||
'available_stock',
|
'available_stock',
|
||||||
|
@ -1506,6 +1506,8 @@ class BomItemSerializer(
|
|||||||
'on_order',
|
'on_order',
|
||||||
# Annotated field describing quantity being built
|
# Annotated field describing quantity being built
|
||||||
'building',
|
'building',
|
||||||
|
# Annotate the total potential quantity we can build
|
||||||
|
'can_build',
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
@ -1560,6 +1562,8 @@ class BomItemSerializer(
|
|||||||
|
|
||||||
building = serializers.FloatField(label=_('In Production'), read_only=True)
|
building = serializers.FloatField(label=_('In Production'), read_only=True)
|
||||||
|
|
||||||
|
can_build = serializers.FloatField(label=_('Can Build'), read_only=True)
|
||||||
|
|
||||||
# Cached pricing fields
|
# Cached pricing fields
|
||||||
pricing_min = InvenTree.serializers.InvenTreeMoneySerializer(
|
pricing_min = InvenTree.serializers.InvenTreeMoneySerializer(
|
||||||
source='sub_part.pricing_data.overall_min', allow_null=True, read_only=True
|
source='sub_part.pricing_data.overall_min', allow_null=True, read_only=True
|
||||||
@ -1733,6 +1737,20 @@ class BomItemSerializer(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Annotate the "can_build" quantity
|
||||||
|
queryset = queryset.alias(
|
||||||
|
total_stock=ExpressionWrapper(
|
||||||
|
F('available_variant_stock')
|
||||||
|
+ F('available_substitute_stock')
|
||||||
|
+ F('available_stock'),
|
||||||
|
output_field=FloatField(),
|
||||||
|
)
|
||||||
|
).annotate(
|
||||||
|
can_build=ExpressionWrapper(
|
||||||
|
F('total_stock') / F('quantity'), output_field=FloatField()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
|
@ -247,19 +247,38 @@ export function BomTable({
|
|||||||
{
|
{
|
||||||
accessor: 'can_build',
|
accessor: 'can_build',
|
||||||
title: t`Can Build`,
|
title: t`Can Build`,
|
||||||
sortable: false, // TODO: Custom sorting via API
|
sortable: true,
|
||||||
render: (record: any) => {
|
render: (record: any) => {
|
||||||
|
if (record.can_build === null || record.can_build === undefined) {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isFinite(record.can_build) || isNaN(record.can_build)) {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
let can_build = Math.trunc(record.can_build);
|
||||||
|
let value = (
|
||||||
|
<Text
|
||||||
|
fs={record.consumable && 'italic'}
|
||||||
|
c={can_build <= 0 && !record.consumable ? 'red' : undefined}
|
||||||
|
>
|
||||||
|
{can_build}
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
|
||||||
|
let extra = [];
|
||||||
|
|
||||||
if (record.consumable) {
|
if (record.consumable) {
|
||||||
return (
|
extra.push(<Text key="consumable">{t`Consumable item`}</Text>);
|
||||||
<Text style={{ fontStyle: 'italic' }}>{t`Consumable item`}</Text>
|
} else if (can_build <= 0) {
|
||||||
|
extra.push(
|
||||||
|
<Text key="no-build" c="red">{t`No available stock`}</Text>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let can_build = availableStockQuantity(record) / record.quantity;
|
|
||||||
can_build = Math.trunc(can_build);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Text c={can_build <= 0 ? 'red' : undefined}>{can_build}</Text>
|
<TableHoverCard value={value} extra={extra} title={t`Can Build`} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user