From 25e5a64cee334a704746d1a7eaf4d731b66797e4 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 9 Dec 2019 21:19:35 +1100 Subject: [PATCH] Improve filtering / ordering / sorting for purchase-order API --- InvenTree/InvenTree/status_codes.py | 9 +++ InvenTree/company/api.py | 1 + InvenTree/order/api.py | 60 +++++++++++++++++++ .../templates/order/purchase_orders.html | 52 ++++++++++++++++ 4 files changed, 122 insertions(+) diff --git a/InvenTree/InvenTree/status_codes.py b/InvenTree/InvenTree/status_codes.py index f772943ef0..e49f9a9824 100644 --- a/InvenTree/InvenTree/status_codes.py +++ b/InvenTree/InvenTree/status_codes.py @@ -12,6 +12,15 @@ class StatusCode: """ Return the status code label associated with the provided value """ return cls.options.get(value, value) + @classmethod + def value(cls, label): + """ Return the value associated with the provided label """ + for k in cls.options.keys(): + if cls.options[k].lower() == label.lower(): + return k + + raise ValueError("Label not found") + class OrderStatus(StatusCode): diff --git a/InvenTree/company/api.py b/InvenTree/company/api.py index e1b02a76fa..8b777dd947 100644 --- a/InvenTree/company/api.py +++ b/InvenTree/company/api.py @@ -31,6 +31,7 @@ class CompanyList(generics.ListCreateAPIView): serializer_class = CompanySerializer queryset = Company.objects.all() + permission_classes = [ permissions.IsAuthenticated, ] diff --git a/InvenTree/order/api.py b/InvenTree/order/api.py index e1396cb54c..56273ae018 100644 --- a/InvenTree/order/api.py +++ b/InvenTree/order/api.py @@ -7,9 +7,16 @@ from __future__ import unicode_literals from django_filters.rest_framework import DjangoFilterBackend from rest_framework import generics, permissions +from rest_framework import filters +from rest_framework.response import Response +from django.conf import settings from django.conf.urls import url +from InvenTree.status_codes import OrderStatus + +import os + from .models import PurchaseOrder, PurchaseOrderLineItem from .serializers import POSerializer, POLineItemSerializer @@ -24,18 +31,71 @@ class POList(generics.ListCreateAPIView): queryset = PurchaseOrder.objects.all() serializer_class = POSerializer + def list(self, request, *args, **kwargs): + + queryset = self.get_queryset().prefetch_related('supplier', 'lines') + + queryset = self.filter_queryset(queryset) + + # Special filtering for 'status' field + if 'status' in request.GET: + status = request.GET['status'] + + # 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 + + data = queryset.values( + 'pk', + 'supplier', + 'supplier__name', + 'supplier__image', + 'reference', + 'description', + 'URL', + '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) + permission_classes = [ permissions.IsAuthenticated, ] filter_backends = [ DjangoFilterBackend, + filters.SearchFilter, + filters.OrderingFilter, ] filter_fields = [ 'supplier', ] + ordering_fields = [ + 'creation_date', + 'reference', + ] + + ordering = '-creation_date' + class PODetail(generics.RetrieveUpdateAPIView): """ API endpoint for detail view of a PurchaseOrder object """ diff --git a/InvenTree/order/templates/order/purchase_orders.html b/InvenTree/order/templates/order/purchase_orders.html index 6e6e45cdfd..a85398c0ad 100644 --- a/InvenTree/order/templates/order/purchase_orders.html +++ b/InvenTree/order/templates/order/purchase_orders.html @@ -1,6 +1,7 @@ {% extends "base.html" %} {% load static %} +{% load i18n %} {% block page_title %} InvenTree | Purchase Orders @@ -19,6 +20,9 @@ InvenTree | Purchase Orders {% include "order/po_table.html" with toolbar='#table-buttons' %} + +
+ {% endblock %} {% block js_ready %} @@ -35,4 +39,52 @@ $("#po-create").click(function() { $("#po-table").inventreeTable({ }); +$("#purchase-order-table").inventreeTable({ + url: "{% url 'api-po-list' %}", + formatNoMatches: function() { return "{% trans "No purchase orders found" %}"; }, + columns: [ + { + field: 'pk', + title: 'ID', + visible: false, + }, + { + sortable: true, + field: 'supplier', + title: 'Supplier', + formatter: function(value, row, index, field) { + return imageHoverIcon(row.supplier__image) + renderLink(row.supplier__name, '/company/' + value + '/'); + } + }, + { + sortable: true, + field: 'reference', + title: 'Reference', + formatter: function(value, row, index, field) { + return renderLink(value, "/order/purchase-order/" + row.pk + "/"); + } + }, + { + sortable: true, + field: 'creation_date', + title: 'Date', + }, + { + sortable: true, + field: 'description', + title: 'Description', + }, + { + sortable: true, + field: 'status_text', + title: 'Status', + }, + { + sortable: true, + field: 'lines', + title: 'Items' + }, + ], +}); + {% endblock %} \ No newline at end of file