Add list view API endpoints

This commit is contained in:
Oliver Walters 2021-03-10 17:09:37 +11:00
parent 9b0595d232
commit 33e176e4e7

View File

@ -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