From 33e176e4e7f71fb83684d46a32bbbcdef388112c Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 10 Mar 2021 17:09:37 +1100 Subject: [PATCH] Add list view API endpoints --- InvenTree/report/api.py | 168 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/InvenTree/report/api.py b/InvenTree/report/api.py index 313d4de88d..58376c4b33 100644 --- a/InvenTree/report/api.py +++ b/InvenTree/report/api.py @@ -18,14 +18,19 @@ from stock.models import StockItem import build.models import part.models +import order.models from .models import TestReport from .models import BuildReport from .models import BillOfMaterialsReport +from .models import PurchaseOrderReport +from .models import SalesOrderReport from .serializers import TestReportSerializer from .serializers import BuildReportSerializer from .serializers import BOMReportSerializer +from .serializers import POReportSerializer +from .serializers import SOReportSerializer class ReportListView(generics.ListAPIView): @@ -113,6 +118,40 @@ class BuildReportMixin: return build.models.Build.objects.filter(pk__in=valid_ids) +class OrderReportMixin: + """ + Mixin for extracting order items from query params + + requires the OrderModel class attribute to be set! + """ + + def get_orders(self): + """ + Return a list of order objects + """ + + orders = [] + + params = self.request.query_params + + for key in ['order', 'order[]', 'orders', 'orders[]']: + if key in params: + orders = params.getlist(key, []) + break + + valid_ids = [] + + for order in orders: + try: + valid_ids.append(int(order)) + except (ValueError): + pass + + valid_orders = self.OrderModel.objects.filter(pk__in=valid_ids) + + return valid_orders + + class PartReportMixin: """ Mixin for extracting part items from query params @@ -481,8 +520,137 @@ class BuildReportPrint(generics.RetrieveAPIView, BuildReportMixin, ReportPrintMi return self.print(request, builds) +class POReportList(ReportListView, OrderReportMixin): + + OrderModel = order.models.PurchaseOrder + + queryset = PurchaseOrderReport.objects.all() + serializer_class = POReportSerializer + + def filter_queryset(self, queryset): + + queryset = super().filter_queryset(queryset) + + orders = self.get_orders() + + if len(orders) > 0: + """ + We wish to filter by purchase orders + + We need to compare the 'filters' string of each report, + and see if it matches against each of the specified orders. + + TODO: In the future, perhaps there is a way to make this more efficient. + """ + + valid_report_ids = set() + + for report in queryset.all(): + + matches = True + + # Filter string defined for the report object + try: + filters = InvenTree.helpers.validateFilterString(report.filters) + except: + continue + + for order in orders: + order_query = order.models.PurchaseOrder.objects.filter(pk=order.pk) + + try: + if not order_query.filter(**filters).exists(): + matches = False + break + except FieldError: + matches = False + break + + if matches: + valid_report_ids.add(report.pk) + else: + continue + + # Reduce queryset to only valid matches + queryset = queryset.filter(pk__in=[pk for pk in valid_report_ids]) + + return queryset + + +class SOReportList(ReportListView, OrderReportMixin): + + OrderModel = order.models.SalesOrder + + queryset = SalesOrderReport.objects.all() + serializer_class = SOReportSerializer + + def filter_queryset(self, queryset): + + queryset = super().filter_queryset(queryset) + + orders = self.get_orders() + + if len(orders) > 0: + """ + We wish to filter by purchase orders + + We need to compare the 'filters' string of each report, + and see if it matches against each of the specified orders. + + TODO: In the future, perhaps there is a way to make this more efficient. + """ + + valid_report_ids = set() + + for report in queryset.all(): + + matches = True + + # Filter string defined for the report object + try: + filters = InvenTree.helpers.validateFilterString(report.filters) + except: + continue + + for order in orders: + order_query = order.models.SalesOrder.objects.filter(pk=order.pk) + + try: + if not order_query.filter(**filters).exists(): + matches = False + break + except FieldError: + matches = False + break + + if matches: + valid_report_ids.add(report.pk) + else: + continue + + # Reduce queryset to only valid matches + queryset = queryset.filter(pk__in=[pk for pk in valid_report_ids]) + + return queryset + + report_api_urls = [ + # Purchase order reports + url(r'po/', include([ + # Detail views. + + # List view + url(r'^$', POReportList.as_view(), name='api-po-report-list'), + ])), + + # Sales order reports + url(r'so/', include([ + # Detail views + + url(r'^$', SOReportList.as_view(), name='api-so-report-list'), + ])), + # Build reports url(r'build/', include([ # Detail views