diff --git a/InvenTree/order/api.py b/InvenTree/order/api.py index b8f54ba72b..26e6ed3546 100644 --- a/InvenTree/order/api.py +++ b/InvenTree/order/api.py @@ -7,6 +7,7 @@ from __future__ import unicode_literals from django.utils.translation import ugettext_lazy as _ from django.conf.urls import url, include +from django.db.models import Q, F from django_filters import rest_framework as rest_filters from rest_framework import generics @@ -251,6 +252,39 @@ class POReceive(generics.CreateAPIView): return order +class POLineItemFilter(rest_filters.FilterSet): + """ + Custom filters for the POLineItemList endpoint + """ + + class Meta: + model = PurchaseOrderLineItem + fields = [ + 'order', + 'part' + ] + + completed = rest_filters.BooleanFilter(label='completed', method='filter_completed') + + def filter_completed(self, queryset, name, value): + """ + Filter by lines which are "completed" (or "not" completed) + + A line is completed when received >= quantity + """ + + value = str2bool(value) + + q = Q(received__gte=F('quantity')) + + if value: + queryset = queryset.filter(q) + else: + queryset = queryset.exclude(q) + + return queryset + + class POLineItemList(generics.ListCreateAPIView): """ API endpoint for accessing a list of POLineItem objects @@ -260,6 +294,7 @@ class POLineItemList(generics.ListCreateAPIView): queryset = PurchaseOrderLineItem.objects.all() serializer_class = POLineItemSerializer + filterset_class = POLineItemFilter def get_queryset(self, *args, **kwargs): diff --git a/InvenTree/templates/js/translated/order.js b/InvenTree/templates/js/translated/order.js index 0bb6696f98..43d4b56936 100644 --- a/InvenTree/templates/js/translated/order.js +++ b/InvenTree/templates/js/translated/order.js @@ -566,12 +566,10 @@ function loadPurchaseOrderTable(table, options) { filters[key] = options.params[key]; } - options.url = options.url || '{% url "api-po-list" %}'; - setupFilterList('purchaseorder', $(table)); $(table).inventreeTable({ - url: options.url, + url: '{% url "api-po-list" %}', queryParams: filters, name: 'purchaseorder', groupBy: false, @@ -667,12 +665,15 @@ function loadPurchaseOrderLineItemTable(table, options={}) { options.params = options.params || {}; + options.params['order'] = options.order; + options.params['part_detail'] = true; + var filters = loadTableFilters('purchaseorderlineitem'); for (var key in options.params) { filters[key] = options.params[key]; } - + var target = options.filter_target || '#filter-list-purchase-order-lines'; setupFilterList('purchaseorderlineitem', $(table), target); @@ -751,10 +752,8 @@ function loadPurchaseOrderLineItemTable(table, options={}) { formatNoMatches: function() { return '{% trans "No line items found" %}'; }, - queryParams: { - order: options.order, - part_detail: true - }, + queryParams: filters, + original: options.params, url: '{% url "api-po-line-list" %}', showFooter: true, uniqueId: 'pk', diff --git a/InvenTree/templates/js/translated/table_filters.js b/InvenTree/templates/js/translated/table_filters.js index b94bc324c7..4d12f69780 100644 --- a/InvenTree/templates/js/translated/table_filters.js +++ b/InvenTree/templates/js/translated/table_filters.js @@ -274,7 +274,16 @@ function getAvailableTableFilters(tableKey) { }; } - // Filters for the "Order" table + // Filters for PurchaseOrderLineItem table + if (tableKey == 'purchaseorderlineitem') { + return { + completed: { + type: 'bool', + title: '{% trans "Completed" %}', + }, + }; + } + // Filters for the PurchaseOrder table if (tableKey == 'purchaseorder') { return {