mirror of
https://github.com/inventree/InvenTree.git
synced 2025-09-14 14:41:33 +00:00
[PUI] Part allocations (#8458)
* Add new backend filters for BuildLine API * PUI: Better display of part allocations against build orders * Add 'order_outstanding' filter to SalesOrderLineItem API * Add new table showing outstanding SalesOrder allocations against a part * Update playwright test * Cleanup * Bump API version * Add more table columns * Tweak UsedInTable * Another table tweak * Tweak playwright tests
This commit is contained in:
@@ -1,13 +1,17 @@
|
||||
"""InvenTree API version information."""
|
||||
|
||||
# InvenTree API version
|
||||
INVENTREE_API_VERSION = 278
|
||||
INVENTREE_API_VERSION = 279
|
||||
|
||||
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
|
||||
|
||||
|
||||
INVENTREE_API_TEXT = """
|
||||
|
||||
v279 - 2024-11-09 : https://github.com/inventree/InvenTree/pull/8458
|
||||
- Adds "order_outstanding" and "part" filters to the BuildLine API endpoint
|
||||
- Adds "order_outstanding" filter to the SalesOrderLineItem API endpoint
|
||||
|
||||
v278 - 2024-11-07 : https://github.com/inventree/InvenTree/pull/8445
|
||||
- Updates to the SalesOrder API endpoints
|
||||
- Add "shipment count" information to the SalesOrder API endpoints
|
||||
|
@@ -357,6 +357,23 @@ class BuildLineFilter(rest_filters.FilterSet):
|
||||
tracked = rest_filters.BooleanFilter(label=_('Tracked'), field_name='bom_item__sub_part__trackable')
|
||||
testable = rest_filters.BooleanFilter(label=_('Testable'), field_name='bom_item__sub_part__testable')
|
||||
|
||||
part = rest_filters.ModelChoiceFilter(
|
||||
queryset=part.models.Part.objects.all(),
|
||||
label=_('Part'),
|
||||
field_name='bom_item__sub_part',
|
||||
)
|
||||
|
||||
order_outstanding = rest_filters.BooleanFilter(
|
||||
label=_('Order Outstanding'),
|
||||
method='filter_order_outstanding'
|
||||
)
|
||||
|
||||
def filter_order_outstanding(self, queryset, name, value):
|
||||
"""Filter by whether the associated BuildOrder is 'outstanding'."""
|
||||
if str2bool(value):
|
||||
return queryset.filter(build__status__in=BuildStatusGroups.ACTIVE_CODES)
|
||||
return queryset.exclude(build__status__in=BuildStatusGroups.ACTIVE_CODES)
|
||||
|
||||
allocated = rest_filters.BooleanFilter(label=_('Allocated'), method='filter_allocated')
|
||||
|
||||
def filter_allocated(self, queryset, name, value):
|
||||
@@ -383,12 +400,28 @@ class BuildLineFilter(rest_filters.FilterSet):
|
||||
return queryset.exclude(flt)
|
||||
|
||||
|
||||
|
||||
class BuildLineEndpoint:
|
||||
"""Mixin class for BuildLine API endpoints."""
|
||||
|
||||
queryset = BuildLine.objects.all()
|
||||
serializer_class = build.serializers.BuildLineSerializer
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
"""Return the serializer instance for this endpoint."""
|
||||
|
||||
kwargs['context'] = self.get_serializer_context()
|
||||
|
||||
try:
|
||||
params = self.request.query_params
|
||||
|
||||
kwargs['part_detail'] = str2bool(params.get('part_detail', True))
|
||||
kwargs['build_detail'] = str2bool(params.get('build_detail', False))
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
return self.serializer_class(*args, **kwargs)
|
||||
|
||||
def get_source_build(self) -> Build:
|
||||
"""Return the source Build object for the BuildLine queryset.
|
||||
|
||||
|
@@ -1278,8 +1278,6 @@ class BuildLineSerializer(DataImportExportSerializerMixin, InvenTreeModelSeriali
|
||||
'pk',
|
||||
'build',
|
||||
'bom_item',
|
||||
'bom_item_detail',
|
||||
'part_detail',
|
||||
'quantity',
|
||||
|
||||
# Build detail fields
|
||||
@@ -1315,6 +1313,11 @@ class BuildLineSerializer(DataImportExportSerializerMixin, InvenTreeModelSeriali
|
||||
# Extra fields only for data export
|
||||
'part_description',
|
||||
'part_category_name',
|
||||
|
||||
# Extra detail (related field) serializers
|
||||
'bom_item_detail',
|
||||
'part_detail',
|
||||
'build_detail',
|
||||
]
|
||||
|
||||
read_only_fields = [
|
||||
@@ -1323,6 +1326,19 @@ class BuildLineSerializer(DataImportExportSerializerMixin, InvenTreeModelSeriali
|
||||
'allocations',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Determine which extra details fields should be included"""
|
||||
part_detail = kwargs.pop('part_detail', True)
|
||||
build_detail = kwargs.pop('build_detail', False)
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
if not part_detail:
|
||||
self.fields.pop('part_detail', None)
|
||||
|
||||
if not build_detail:
|
||||
self.fields.pop('build_detail', None)
|
||||
|
||||
# Build info fields
|
||||
build_reference = serializers.CharField(source='build.reference', label=_('Build Reference'), read_only=True)
|
||||
|
||||
@@ -1362,6 +1378,7 @@ class BuildLineSerializer(DataImportExportSerializerMixin, InvenTreeModelSeriali
|
||||
)
|
||||
|
||||
part_detail = part_serializers.PartBriefSerializer(source='bom_item.sub_part', many=False, read_only=True, pricing=False)
|
||||
build_detail = BuildSerializer(source='build', part_detail=False, many=False, read_only=True)
|
||||
|
||||
# Annotated (calculated) fields
|
||||
|
||||
@@ -1404,9 +1421,13 @@ class BuildLineSerializer(DataImportExportSerializerMixin, InvenTreeModelSeriali
|
||||
"""
|
||||
queryset = queryset.select_related(
|
||||
'build',
|
||||
'build__part',
|
||||
'build__part__pricing_data',
|
||||
'bom_item',
|
||||
'bom_item__part',
|
||||
'bom_item__part__pricing_data',
|
||||
'bom_item__sub_part',
|
||||
'bom_item__sub_part__pricing_data'
|
||||
)
|
||||
|
||||
# Pre-fetch related fields
|
||||
|
@@ -816,6 +816,17 @@ class SalesOrderLineItemFilter(LineItemFilter):
|
||||
|
||||
return queryset.exclude(order__status__in=SalesOrderStatusGroups.COMPLETE)
|
||||
|
||||
order_outstanding = rest_filters.BooleanFilter(
|
||||
label=_('Order Outstanding'), method='filter_order_outstanding'
|
||||
)
|
||||
|
||||
def filter_order_outstanding(self, queryset, name, value):
|
||||
"""Filter by whether the order is 'outstanding' or not."""
|
||||
if str2bool(value):
|
||||
return queryset.filter(order__status__in=SalesOrderStatusGroups.OPEN)
|
||||
|
||||
return queryset.exclude(order__status__in=SalesOrderStatusGroups.OPEN)
|
||||
|
||||
|
||||
class SalesOrderLineItemMixin:
|
||||
"""Mixin class for SalesOrderLineItem endpoints."""
|
||||
|
Reference in New Issue
Block a user