From 99fcbcc64657b20cdb5e4b691396a5647f605e42 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 20 Apr 2020 09:41:21 +1000 Subject: [PATCH] Consolidation of PurchaseOrder API --- InvenTree/order/api.py | 109 ++++++++++++++++++++------------- InvenTree/order/serializers.py | 39 +++++++++++- 2 files changed, 104 insertions(+), 44 deletions(-) diff --git a/InvenTree/order/api.py b/InvenTree/order/api.py index 18ba890127..cf546bee21 100644 --- a/InvenTree/order/api.py +++ b/InvenTree/order/api.py @@ -14,6 +14,7 @@ from django.conf import settings from django.conf.urls import url from InvenTree.status_codes import OrderStatus +from InvenTree.helpers import str2bool import os @@ -34,66 +35,67 @@ class POList(generics.ListCreateAPIView): queryset = PurchaseOrder.objects.all() serializer_class = POSerializer - def list(self, request, *args, **kwargs): + def get_serializer(self, *args, **kwargs): - queryset = self.get_queryset().prefetch_related('supplier', 'lines') + try: + kwargs['supplier_detail'] = str2bool(self.request.query_params.get('supplier_detail', False)) + except AttributeError: + pass - queryset = self.filter_queryset(queryset) + # Ensure the request context is passed through + kwargs['context'] = self.get_serializer_context() + + return self.serializer_class(*args, **kwargs) + + def get_queryset(self, *args, **kwargs): + + queryset = super().get_queryset(*args, **kwargs) + + queryset = queryset.prefetch_related( + 'supplier', + 'lines', + ) + + queryset = POSerializer.annotate_queryset(queryset) + + return queryset + + + def filter_queryset(self, queryset): + + # Perform basic filtering + queryset = super().filter_queryset(queryset) + + params = self.request.query_params # Special filtering for 'status' field - if 'status' in request.GET: - status = request.GET['status'] + status = params.get('status', None) + if status is not None: # First attempt to filter by integer value - try: - status = int(status) - queryset = queryset.filter(status=status) - except ValueError: - try: - value = OrderStatus.value(status) - queryset = queryset.filter(status=value) - except ValueError: - pass + queryset = queryset.filter(status=status) # Attempt to filter by part - if 'part' in request.GET: + part = params.get('part', None) + + if part is not None: try: - part = Part.objects.get(pk=request.GET['part']) + part = Part.objects.get(pk=part) queryset = queryset.filter(id__in=[p.id for p in part.purchase_orders()]) except (Part.DoesNotExist, ValueError): pass # Attempt to filter by supplier part - if 'supplier_part' in request.GET: + supplier_part = params.get('supplier_part', None) + + if supplier_part is not None: try: - supplier_part = SupplierPart.objects.get(pk=request.GET['supplier_part']) + supplier_part = SupplierPart.objects.get(pk=supplier_part) queryset = queryset.filter(id__in=[p.id for p in supplier_part.purchase_orders()]) except (ValueError, SupplierPart.DoesNotExist): pass - data = queryset.values( - 'pk', - 'supplier', - 'supplier_reference', - 'supplier__name', - 'supplier__image', - 'reference', - 'description', - 'link', - 'status', - 'notes', - 'creation_date', - ) - - for item in data: - - order = queryset.get(pk=item['pk']) - - item['supplier__image'] = os.path.join(settings.MEDIA_URL, item['supplier__image']) - item['status_text'] = OrderStatus.label(item['status']) - item['lines'] = order.lines.count() - - return Response(data) + return queryset permission_classes = [ permissions.IsAuthenticated, @@ -123,6 +125,31 @@ class PODetail(generics.RetrieveUpdateAPIView): queryset = PurchaseOrder.objects.all() serializer_class = POSerializer + def get_serializer(self, *args, **kwargs): + + try: + kwargs['supplier_detail'] = str2bool(self.request.query_params.get('supplier_detail', False)) + except AttributeError: + pass + + # Ensure the request context is passed through + kwargs['context'] = self.get_serializer_context() + + return self.serializer_class(*args, **kwargs) + + def get_queryset(self, *args, **kwargs): + + queryset = super().get_queryset(*args, **kwargs) + + queryset = queryset.prefetch_related( + 'supplier', + 'lines', + ) + + queryset = POSerializer.annotate_queryset(queryset) + + return queryset + permission_classes = [ permissions.IsAuthenticated ] diff --git a/InvenTree/order/serializers.py b/InvenTree/order/serializers.py index 9a8f1afee5..ab1471cdc1 100644 --- a/InvenTree/order/serializers.py +++ b/InvenTree/order/serializers.py @@ -5,7 +5,12 @@ JSON serializers for the Order API # -*- coding: utf-8 -*- from __future__ import unicode_literals +from rest_framework import serializers + +from django.db.models import Count + from InvenTree.serializers import InvenTreeModelSerializer +from company.serializers import CompanyBriefSerializer from .models import PurchaseOrder, PurchaseOrderLineItem @@ -13,17 +18,45 @@ from .models import PurchaseOrder, PurchaseOrderLineItem class POSerializer(InvenTreeModelSerializer): """ Serializes an Order object """ + def __init__(self, *args, **kwargs): + + supplier_detail = kwargs.pop('supplier_detail', False) + + super().__init__(*args, **kwargs) + + if supplier_detail is not True: + self.fields.pop('supplier_detail') + + @staticmethod + def annotate_queryset(queryset): + """ + Add extra information to the queryset + """ + + return queryset.annotate( + line_items=Count('lines'), + ) + + supplier_detail = CompanyBriefSerializer(source='supplier', many=False, read_only=True) + + line_items = serializers.IntegerField(read_only=True) + + status_text = serializers.CharField(source='get_status_display', read_only=True) + class Meta: model = PurchaseOrder fields = [ 'pk', - 'supplier', - 'supplier_reference', - 'reference', 'description', + 'line_items', 'link', + 'reference', + 'supplier', + 'supplier_detail', + 'supplier_reference', 'status', + 'status_text', 'notes', ]