From 617fbf2f0225530ee444338530db382310714318 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 21 Apr 2020 08:57:13 +1000 Subject: [PATCH] Moar stuffs: - Expose part_detail and order_detail to SOLineItem serializer - Update SalesOrder line item table --- InvenTree/order/admin.py | 1 + InvenTree/order/api.py | 36 ++++++++++++++++--- InvenTree/order/serializers.py | 22 +++++++++++- .../templates/order/sales_order_detail.html | 13 +++++++ InvenTree/order/urls.py | 6 ++++ 5 files changed, 72 insertions(+), 6 deletions(-) diff --git a/InvenTree/order/admin.py b/InvenTree/order/admin.py index 5ad1a6541d..459b7a3821 100644 --- a/InvenTree/order/admin.py +++ b/InvenTree/order/admin.py @@ -80,6 +80,7 @@ class SalesOrderLineItemAdmin(ImportExportModelAdmin): list_display = ( 'order', + 'part', 'quantity', 'reference' ) diff --git a/InvenTree/order/api.py b/InvenTree/order/api.py index 6d6d16ff6f..7efd277544 100644 --- a/InvenTree/order/api.py +++ b/InvenTree/order/api.py @@ -20,7 +20,7 @@ from .models import PurchaseOrder, PurchaseOrderLineItem from .serializers import POSerializer, POLineItemSerializer from .models import SalesOrder, SalesOrderLineItem -from .serializers import SalseOrderSerializer, SOLineItemSerializer +from .serializers import SalesOrderSerializer, SOLineItemSerializer class POList(generics.ListCreateAPIView): @@ -196,7 +196,7 @@ class SOList(generics.ListCreateAPIView): """ queryset = SalesOrder.objects.all() - serializer_class = SalseOrderSerializer + serializer_class = SalesOrderSerializer def get_serializer(self, *args, **kwargs): @@ -219,7 +219,7 @@ class SOList(generics.ListCreateAPIView): 'lines' ) - queryset = SalseOrderSerializer.annotate_queryset(queryset) + queryset = SalesOrderSerializer.annotate_queryset(queryset) return queryset @@ -269,7 +269,7 @@ class SODetail(generics.RetrieveUpdateAPIView): """ queryset = SalesOrder.objects.all() - serializer_class = SalseOrderSerializer + serializer_class = SalesOrderSerializer def get_serializer(self, *args, **kwargs): @@ -288,7 +288,7 @@ class SODetail(generics.RetrieveUpdateAPIView): queryset = queryset.prefetch_related('customer', 'lines') - queryset = SalseOrderSerializer.annotate_queryset(queryset) + queryset = SalesOrderSerializer.annotate_queryset(queryset) return queryset @@ -303,6 +303,32 @@ class SOLineItemList(generics.ListCreateAPIView): queryset = SalesOrderLineItem.objects.all() serializer_class = SOLineItemSerializer + def get_serializer(self, *args, **kwargs): + + try: + kwargs['part_detail'] = str2bool(self.request.query_params.get('part_detail', False)) + except AttributeError: + pass + + try: + kwargs['order_detail'] = str2bool(self.request.query_params.get('order_detail', False)) + except AttributeError: + pass + + kwargs['context'] = self.get_serializer_context() + + return self.serializer_class(*args, **kwargs) + + def get_queryset(self, *args, **kwargs): + + queryset = super().get_queryset(*args, **kwargs) + + return queryset.prefetch_related( + 'part', + 'part__stock_items', + 'order', + ) + permission_classes = [permissions.IsAuthenticated] filter_backends = [DjangoFilterBackend] diff --git a/InvenTree/order/serializers.py b/InvenTree/order/serializers.py index 69c0969c32..6e482d019e 100644 --- a/InvenTree/order/serializers.py +++ b/InvenTree/order/serializers.py @@ -11,6 +11,7 @@ from django.db.models import Count from InvenTree.serializers import InvenTreeModelSerializer from company.serializers import CompanyBriefSerializer +from part.serializers import PartBriefSerializer from .models import PurchaseOrder, PurchaseOrderLineItem from .models import SalesOrder, SalesOrderLineItem @@ -86,7 +87,7 @@ class POLineItemSerializer(InvenTreeModelSerializer): ] -class SalseOrderSerializer(InvenTreeModelSerializer): +class SalesOrderSerializer(InvenTreeModelSerializer): """ Serializers for the SalesOrder object """ @@ -145,6 +146,22 @@ class SalseOrderSerializer(InvenTreeModelSerializer): class SOLineItemSerializer(InvenTreeModelSerializer): """ Serializer for a SalesOrderLineItem object """ + def __init__(self, *args, **kwargs): + + part_detail = kwargs.pop('part_detail', False) + order_detail = kwargs.pop('order_detail', False) + + super().__init__(*args, **kwargs) + + if part_detail is not True: + self.fields.pop('part_detail') + + if order_detail is not True: + self.fields.pop('order_detail') + + order_detail = SalesOrderSerializer(source='order', many=False, read_only=True) + part_detail = PartBriefSerializer(source='part', many=False, read_only=True) + class Meta: model = SalesOrderLineItem @@ -154,4 +171,7 @@ class SOLineItemSerializer(InvenTreeModelSerializer): 'reference', 'notes', 'order', + 'order_detail', + 'part', + 'part_detail', ] diff --git a/InvenTree/order/templates/order/sales_order_detail.html b/InvenTree/order/templates/order/sales_order_detail.html index 8a47b9d044..3fa9a918d4 100644 --- a/InvenTree/order/templates/order/sales_order_detail.html +++ b/InvenTree/order/templates/order/sales_order_detail.html @@ -32,6 +32,7 @@ $("#so-lines-table").inventreeTable({ formatNoMatches: function() { return "No matching line items"; }, queryParams: { order: {{ order.id }}, + part_detail: true, }, url: "{% url 'api-so-line-list' %}", columns: [ @@ -40,6 +41,18 @@ $("#so-lines-table").inventreeTable({ title: 'ID', visible: false, }, + { + sortable: true, + field: 'part', + title: 'Part', + formatter: function(value, row, index, field) { + if (row.part) { + return imageHoverIcon(row.part_detail.thumbnail) + renderLink(row.part_detail.full_name, `/part/${value}/`); + } else { + return '-'; + } + } + }, { sortable: true, field: 'reference', diff --git a/InvenTree/order/urls.py b/InvenTree/order/urls.py index 21ab912492..c3fdac407b 100644 --- a/InvenTree/order/urls.py +++ b/InvenTree/order/urls.py @@ -61,6 +61,10 @@ purchase_order_urls = [ url(r'^.*$', views.PurchaseOrderIndex.as_view(), name='po-index'), ] +so_line_urls = [ + url(r'^new/', views.SOLineItemCreate.as_view(), name='so-line-item-create'), +] + sales_order_detail_urls = [ url(r'^edit/', views.SalesOrderEdit.as_view(), name='so-edit'), @@ -75,6 +79,8 @@ sales_order_urls = [ url(r'^new/', views.SalesOrderCreate.as_view(), name='so-create'), + url(r'^line/', include(so_line_urls)), + # Display detail view for a single SalesOrder url(r'^(?P\d+)/', include(sales_order_detail_urls)),