2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-28 11:36:44 +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:
Oliver 2024-07-11 13:06:59 +10:00 committed by GitHub
parent 81ab7aa625
commit 2ebe6e0a8e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 49 additions and 9 deletions

View File

@ -1,12 +1,15 @@
"""InvenTree API version information."""
# 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."""
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
- Fixes bug in "project_code" field for order API endpoints

View File

@ -1841,7 +1841,6 @@ class BomList(BomMixin, DataExportViewMixin, ListCreateDestroyAPIView):
"""
filterset_class = BomFilter
filter_backends = SEARCH_ORDER_FILTER_ALIAS
search_fields = [
@ -1855,6 +1854,7 @@ class BomList(BomMixin, DataExportViewMixin, ListCreateDestroyAPIView):
]
ordering_fields = [
'can_build',
'quantity',
'sub_part',
'available_stock',

View File

@ -1506,6 +1506,8 @@ class BomItemSerializer(
'on_order',
# Annotated field describing quantity being built
'building',
# Annotate the total potential quantity we can build
'can_build',
]
def __init__(self, *args, **kwargs):
@ -1560,6 +1562,8 @@ class BomItemSerializer(
building = serializers.FloatField(label=_('In Production'), read_only=True)
can_build = serializers.FloatField(label=_('Can Build'), read_only=True)
# Cached pricing fields
pricing_min = InvenTree.serializers.InvenTreeMoneySerializer(
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

View File

@ -247,19 +247,38 @@ export function BomTable({
{
accessor: 'can_build',
title: t`Can Build`,
sortable: false, // TODO: Custom sorting via API
sortable: true,
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) {
return (
<Text style={{ fontStyle: 'italic' }}>{t`Consumable item`}</Text>
extra.push(<Text key="consumable">{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 (
<Text c={can_build <= 0 ? 'red' : undefined}>{can_build}</Text>
<TableHoverCard value={value} extra={extra} title={t`Can Build`} />
);
}
},