diff --git a/InvenTree/build/api.py b/InvenTree/build/api.py index 592ff5dc16..c0faee6c15 100644 --- a/InvenTree/build/api.py +++ b/InvenTree/build/api.py @@ -12,6 +12,7 @@ from rest_framework import generics, permissions from django.conf.urls import url, include from InvenTree.helpers import str2bool +from InvenTree.status_codes import BuildStatus from .models import Build, BuildItem from .serializers import BuildSerializer, BuildItemSerializer @@ -59,10 +60,18 @@ class BuildList(generics.ListCreateAPIView): status = self.request.query_params.get('status', None) if status is not None: - # Get status codes - codes = status.split('-') - # Filter by codes - queryset = queryset.filter(status__in=codes) + queryset = queryset.filter(status=status) + + # Filter by "active" status + active = self.request.query_params.get('active', None) + + if active is not None: + active = str2bool(active) + + if active: + queryset = queryset.filter(status__in=BuildStatus.ACTIVE_CODES) + else: + queryset = queryset.exclude(status__in=BuildStatus.ACTIVE_CODES) # Filter by associated part? part = self.request.query_params.get('part', None) diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index cf260d7bfa..9d9d56d253 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -405,26 +405,27 @@ class PartList(generics.ListCreateAPIView): except (ValueError, Part.DoesNotExist): pass - # Filter by latest part creation date - latest_parts = params.get('latest_parts', None) + # Filter by whether the BOM has been validated (or not) + bom_valid = params.get('bom_valid', None) - if latest_parts is not None: - # Get the last 5 created parts - queryset = queryset.order_by('-creation_date')[:5] + # TODO: Querying bom_valid status may be quite expensive + # TODO: (It needs to be profiled!) + # TODO: It might be worth caching the bom_valid status to a database column - # Filter invalid BOMs - bom_invalid = params.get('bom_invalid', None) + if bom_valid is not None: - if bom_invalid is not None: - # Get assemblies with invalid BOMs - assemblies = queryset.filter(active=True).filter(assembly=True) - valid_boms = [] + bom_valid = str2bool(bom_valid) - for part in assemblies: - if part.is_bom_valid: - valid_boms.append(part.pk) + # Limit queryset to active assemblies + queryset = queryset.filter(active=True, assembly=True) - queryset = assemblies.exclude(pk__in=valid_boms) + pks = [] + + for part in queryset: + if part.is_bom_valid() == bom_valid: + pks.append(part.pk) + + queryset = queryset.filter(pk__in=pks) # Filter by 'starred' parts? starred = params.get('starred', None) @@ -475,6 +476,7 @@ class PartList(generics.ListCreateAPIView): # Filter by whether the part has stock has_stock = params.get("has_stock", None) + if has_stock is not None: has_stock = str2bool(has_stock) @@ -501,6 +503,9 @@ class PartList(generics.ListCreateAPIView): # Filter by "parts which need stock to complete build" stock_to_build = params.get('stock_to_build', None) + # TODO: This is super expensive, database query wise... + # TODO: Need to figure out a cheaper way of making this filter query + if stock_to_build is not None: # Filter only active parts queryset = queryset.filter(active=True) @@ -514,6 +519,17 @@ class PartList(generics.ListCreateAPIView): queryset = queryset.filter(pk__in=parts_need_stock) + # Limit choices + limit = params.get('limit', None) + + if limit is not None: + try: + limit = int(limit) + if limit > 0: + queryset = queryset[:limit] + except ValueError: + pass + return queryset permission_classes = [ @@ -539,6 +555,7 @@ class PartList(generics.ListCreateAPIView): ordering_fields = [ 'name', + 'creation_date', ] # Default ordering diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index f1b0890cba..dc9c3102f0 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -845,7 +845,6 @@ class Part(MPTTModel): return str(hash.digest()) - @property def is_bom_valid(self): """ Check if the BOM is 'valid' - if the calculated checksum matches the stored value """ diff --git a/InvenTree/templates/InvenTree/bom_invalid.html b/InvenTree/templates/InvenTree/bom_invalid.html index 84f4fd7938..4a2fe5856c 100644 --- a/InvenTree/templates/InvenTree/bom_invalid.html +++ b/InvenTree/templates/InvenTree/bom_invalid.html @@ -4,7 +4,7 @@ {% block collapse_title %} -{% trans "BOM Waiting Validation" %}0 +{% trans "BOM Waiting Validation" %} {% endblock %} {% block collapse_content %} diff --git a/InvenTree/templates/InvenTree/build_pending.html b/InvenTree/templates/InvenTree/build_pending.html index 31a083cfc0..1b8ebc19c2 100644 --- a/InvenTree/templates/InvenTree/build_pending.html +++ b/InvenTree/templates/InvenTree/build_pending.html @@ -4,7 +4,7 @@ {% block collapse_title %} -{% trans "Pending Builds" %}0 +{% trans "Pending Builds" %} {% endblock %} {% block collapse_content %} diff --git a/InvenTree/templates/InvenTree/index.html b/InvenTree/templates/InvenTree/index.html index fa9818069e..df2ae1414a 100644 --- a/InvenTree/templates/InvenTree/index.html +++ b/InvenTree/templates/InvenTree/index.html @@ -55,58 +55,65 @@ InvenTree | Index {{ block.super }} -loadPartTable("#latest-parts-table", "{% url 'api-part-list' %}", { +loadSimplePartTable("#latest-parts-table", "{% url 'api-part-list' %}", { params: { - "latest_parts": true, - } + ordering: "-creation_date", + limit: 10, + }, + name: 'latest_parts', }); -loadPartTable("#starred-parts-table", "{% url 'api-part-list' %}", { +loadSimplePartTable("#starred-parts-table", "{% url 'api-part-list' %}", { params: { "starred": true, - } + }, + name: 'starred_parts', }); -loadPartTable("#bom-invalid-table", "{% url 'api-part-list' %}", { +loadSimplePartTable("#bom-invalid-table", "{% url 'api-part-list' %}", { params: { - "bom_invalid": true, - } + "bom_valid": false, + }, + name: 'bom_invalid_parts', }); loadBuildTable("#build-pending-table", { url: "{% url 'api-build-list' %}", params: { - "part_detail": true, - "status": "10-20", - } + part_detail: true, + active: true, + }, + disableFilters: true, }); -loadPartTable("#low-stock-table", "{% url 'api-part-list' %}", { +loadSimplePartTable("#low-stock-table", "{% url 'api-part-list' %}", { params: { - "low_stock": true, - } + low_stock: true, + }, + name: "low_stock_parts", }); -loadPartTable("#stock-to-build-table", "{% url 'api-part-list' %}", { +loadSimplePartTable("#stock-to-build-table", "{% url 'api-part-list' %}", { params: { - "stock_to_build": true, - } + stock_to_build: true, + }, + name: "to_build_parts", }); loadPurchaseOrderTable("#po-outstanding-table", { url: "{% url 'api-po-list' %}", params: { - "supplier_detail": true, - "oustanding": true, + supplier_detail: true, + outstanding: true, } }); loadSalesOrderTable("#so-outstanding-table", { url: "{% url 'api-so-list' %}", params: { - "customer_detail": true, - "oustanding": true, - } + customer_detail: true, + outstanding: true, + }, }); $("#latest-parts-table").on('load-success.bs.table', function() { diff --git a/InvenTree/templates/InvenTree/latest_parts.html b/InvenTree/templates/InvenTree/latest_parts.html index e9c9879740..35e55b7cd2 100644 --- a/InvenTree/templates/InvenTree/latest_parts.html +++ b/InvenTree/templates/InvenTree/latest_parts.html @@ -4,7 +4,7 @@ {% block collapse_title %} -{% trans "Latest Parts" %}0 +{% trans "Latest Parts" %} {% endblock %} {% block collapse_content %} diff --git a/InvenTree/templates/InvenTree/low_stock.html b/InvenTree/templates/InvenTree/low_stock.html index 333dbded27..e7a3dbddc7 100644 --- a/InvenTree/templates/InvenTree/low_stock.html +++ b/InvenTree/templates/InvenTree/low_stock.html @@ -4,7 +4,7 @@ {% block collapse_title %} -{% trans "Low Stock" %}0 +{% trans "Low Stock" %} {% endblock %} {% block collapse_content %} diff --git a/InvenTree/templates/InvenTree/parts_to_build.html b/InvenTree/templates/InvenTree/parts_to_build.html deleted file mode 100644 index 156e3dda22..0000000000 --- a/InvenTree/templates/InvenTree/parts_to_build.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends "collapse.html" %} -{% block collapse_title %} - -Parts to Build{{ to_build | length }} -{% endblock %} - -{% block collapse_heading %} -There are {{ to_build | length }} parts which need building. -{% endblock %} - -{% block collapse_content %} - -{% include "required_part_table.html" with parts=to_build table_id="to-build-table" %} - -{% endblock %} \ No newline at end of file diff --git a/InvenTree/templates/InvenTree/po_outstanding.html b/InvenTree/templates/InvenTree/po_outstanding.html index 063915a414..628695fa68 100644 --- a/InvenTree/templates/InvenTree/po_outstanding.html +++ b/InvenTree/templates/InvenTree/po_outstanding.html @@ -4,7 +4,7 @@ {% block collapse_title %} -{% trans "Outstanding Purchase Orders" %}0 +{% trans "Outstanding Purchase Orders" %} {% endblock %} {% block collapse_content %} diff --git a/InvenTree/templates/InvenTree/required_stock_build.html b/InvenTree/templates/InvenTree/required_stock_build.html index 8202766ec1..fd6ade4a4e 100644 --- a/InvenTree/templates/InvenTree/required_stock_build.html +++ b/InvenTree/templates/InvenTree/required_stock_build.html @@ -4,7 +4,7 @@ {% block collapse_title %} -{% trans "Require Stock To Complete Build" %}0 +{% trans "Require Stock To Complete Build" %} {% endblock %} {% block collapse_content %} diff --git a/InvenTree/templates/InvenTree/so_outstanding.html b/InvenTree/templates/InvenTree/so_outstanding.html index 023abb2b6a..29d0261b8b 100644 --- a/InvenTree/templates/InvenTree/so_outstanding.html +++ b/InvenTree/templates/InvenTree/so_outstanding.html @@ -4,7 +4,7 @@ {% block collapse_title %} -{% trans "Outstanding Sales Orders" %}0 +{% trans "Outstanding Sales Orders" %} {% endblock %} {% block collapse_content %} diff --git a/InvenTree/templates/InvenTree/starred_parts.html b/InvenTree/templates/InvenTree/starred_parts.html index 74f6edafb1..a0801566c2 100644 --- a/InvenTree/templates/InvenTree/starred_parts.html +++ b/InvenTree/templates/InvenTree/starred_parts.html @@ -4,7 +4,7 @@ {% block collapse_title %} -{% trans "Starred Parts" %}0 +{% trans "Starred Parts" %} {% endblock %} {% block collapse_content %} diff --git a/InvenTree/templates/js/build.html b/InvenTree/templates/js/build.html index 10c017a776..e36e15ddeb 100644 --- a/InvenTree/templates/js/build.html +++ b/InvenTree/templates/js/build.html @@ -5,7 +5,11 @@ function loadBuildTable(table, options) { var params = options.params || {}; - var filters = loadTableFilters("build"); + var filters = {}; + + if (!options.disableFilters) { + loadTableFilters("build"); + } for (var key in params) { filters[key] = params[key]; diff --git a/InvenTree/templates/js/part.html b/InvenTree/templates/js/part.html index 03c98e09a4..5576d91367 100644 --- a/InvenTree/templates/js/part.html +++ b/InvenTree/templates/js/part.html @@ -155,6 +155,14 @@ function loadPartVariantTable(table, partId, options) { } +function loadSimplePartTable(table, url, options={}) { + + options.disableFilters = true; + + loadPartTable(table, url, options); +} + + function loadPartTable(table, url, options={}) { /* Load part listing data into specified table. * @@ -332,7 +340,7 @@ function loadPartTable(table, url, options={}) { method: 'get', queryParams: filters, groupBy: false, - name: 'part', + name: options.name || 'part', original: params, formatNoMatches: function() { return "{% trans "No parts found" %}"; }, columns: columns, diff --git a/InvenTree/templates/js/table_filters.html b/InvenTree/templates/js/table_filters.html index 9050edba6f..8fdb6c391c 100644 --- a/InvenTree/templates/js/table_filters.html +++ b/InvenTree/templates/js/table_filters.html @@ -109,7 +109,10 @@ function getAvailableTableFilters(tableKey) { title: '{% trans "Build status" %}', options: buildCodes, }, - + pending: { + type: 'bool', + title: '{% trans "Pending" %}', + } }; }