From 4ea4456517b607a8d38b36b75907819d0bdf1962 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 17 Feb 2021 23:56:47 +1100 Subject: [PATCH] Add API LIST endpoint for SalesOrderAllocations --- InvenTree/order/api.py | 84 ++++++++++++++++--- InvenTree/order/serializers.py | 14 ++-- .../templates/order/sales_order_detail.html | 4 +- 3 files changed, 82 insertions(+), 20 deletions(-) diff --git a/InvenTree/order/api.py b/InvenTree/order/api.py index ce75a47697..700b97f67a 100644 --- a/InvenTree/order/api.py +++ b/InvenTree/order/api.py @@ -22,10 +22,10 @@ from .models import PurchaseOrder, PurchaseOrderLineItem from .models import PurchaseOrderAttachment from .serializers import POSerializer, POLineItemSerializer, POAttachmentSerializer -from .models import SalesOrder, SalesOrderLineItem +from .models import SalesOrder, SalesOrderLineItem, SalesOrderAllocation from .models import SalesOrderAttachment from .serializers import SalesOrderSerializer, SOLineItemSerializer, SOAttachmentSerializer - +from .serializers import SalesOrderAllocationSerializer class POList(generics.ListCreateAPIView): """ API endpoint for accessing a list of PurchaseOrder objects @@ -427,6 +427,56 @@ class SOLineItemDetail(generics.RetrieveUpdateAPIView): serializer_class = SOLineItemSerializer +class SOAllocationList(generics.ListCreateAPIView): + """ + API endpoint for listing SalesOrderAllocation objects + """ + + queryset = SalesOrderAllocation.objects.all() + serializer_class = SalesOrderAllocationSerializer + + def filter_queryset(self, queryset): + + queryset = super().filter_queryset(queryset) + + # Filter by order + params = self.request.query_params + + # Filter by "part" reference + part = params.get('part', None) + + if part is not None: + queryset = queryset.filter(item__part=part) + + # Filter by "order" reference + order = params.get('order', None) + + if order is not None: + queryset = queryset.filter(line__order=order) + + # Filter by "outstanding" order status + outstanding = params.get('outstanding', None) + + if outstanding is not None: + outstanding = str2bool(outstanding) + + if outstanding: + queryset = queryset.filter(line__order__status__in=SalesOrderStatus.OPEN) + else: + queryset = queryset.exclude(line__order__status__in=SalesOrderStatus.OPEN) + + return queryset + + filter_backends = [ + DjangoFilterBackend, + ] + + # Default filterable fields + filter_fields = [ + 'item', + ] + + class POAttachmentList(generics.ListCreateAPIView, AttachmentMixin): """ API endpoint for listing (and creating) a PurchaseOrderAttachment (file upload) @@ -435,10 +485,6 @@ class POAttachmentList(generics.ListCreateAPIView, AttachmentMixin): queryset = PurchaseOrderAttachment.objects.all() serializer_class = POAttachmentSerializer - filter_fields = [ - 'order', - ] - order_api_urls = [ # API endpoints for purchase orders @@ -453,14 +499,26 @@ order_api_urls = [ url(r'^po-line/$', POLineItemList.as_view(), name='api-po-line-list'), # API endpoints for sales ordesr - url(r'^so/(?P\d+)/$', SODetail.as_view(), name='api-so-detail'), - url(r'so/attachment/', include([ - url(r'^.*$', SOAttachmentList.as_view(), name='api-so-attachment-list'), + url(r'^so/', include([ + url(r'^(?P\d+)/$', SODetail.as_view(), name='api-so-detail'), + url(r'attachment/', include([ + url(r'^.*$', SOAttachmentList.as_view(), name='api-so-attachment-list'), + ])), + + # List all sales orders + url(r'^.*$', SOList.as_view(), name='api-so-list'), ])), - url(r'^so/.*$', SOList.as_view(), name='api-so-list'), - # API endpoints for sales order line items - url(r'^so-line/(?P\d+)/$', SOLineItemDetail.as_view(), name='api-so-line-detail'), - url(r'^so-line/$', SOLineItemList.as_view(), name='api-so-line-list'), + url(r'^so-line/', include([ + url(r'^(?P\d+)/$', SOLineItemDetail.as_view(), name='api-so-line-detail'), + url(r'^$', SOLineItemList.as_view(), name='api-so-line-list'), + ])), + + # API endpoints for sales order allocations + url(r'^so-allocation', include([ + + # List all sales order allocations + url(r'^.*$', SOAllocationList.as_view(), name='api-so-allocation-list'), + ])), ] diff --git a/InvenTree/order/serializers.py b/InvenTree/order/serializers.py index a04798c303..51a0d6ebf0 100644 --- a/InvenTree/order/serializers.py +++ b/InvenTree/order/serializers.py @@ -232,10 +232,12 @@ class SalesOrderAllocationSerializer(InvenTreeModelSerializer): This includes some fields from the related model objects. """ - location_path = serializers.CharField(source='get_location_path') - location_id = serializers.IntegerField(source='get_location') - serial = serializers.CharField(source='get_serial') - quantity = serializers.FloatField() + location_path = serializers.CharField(source='get_location_path', read_only=True) + location = serializers.IntegerField(source='get_location', read_only=True) + part = serializers.PrimaryKeyRelatedField(source='item.part', read_only=True) + order = serializers.PrimaryKeyRelatedField(source='line.order', many=False, read_only=True) + serial = serializers.CharField(source='get_serial', read_only=True) + quantity = serializers.FloatField(read_only=True) class Meta: model = SalesOrderAllocation @@ -245,7 +247,9 @@ class SalesOrderAllocationSerializer(InvenTreeModelSerializer): 'line', 'serial', 'quantity', - 'location_id', + 'order', + 'part', + 'location', 'location_path', 'item', ] diff --git a/InvenTree/order/templates/order/sales_order_detail.html b/InvenTree/order/templates/order/sales_order_detail.html index 8e3128e1f3..d4a004a73c 100644 --- a/InvenTree/order/templates/order/sales_order_detail.html +++ b/InvenTree/order/templates/order/sales_order_detail.html @@ -78,10 +78,10 @@ function showAllocationSubTable(index, row, element) { }, }, { - field: 'location_id', + field: 'location', title: 'Location', formatter: function(value, row, index, field) { - return renderLink(row.location_path, `/stock/location/${row.location_id}/`); + return renderLink(row.location_path, `/stock/location/${row.location}/`); }, }, {