From a50ecb24c1272d52c8f7746a337dab2ca9ba6750 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 13 Apr 2020 19:16:57 +1000 Subject: [PATCH] Fix "supplier parts" tab for Company display Also PEP fixes --- .../static/script/inventree/company.js | 97 +++++++++++++++++++ InvenTree/company/api.py | 9 +- InvenTree/company/models.py | 4 +- .../templates/company/detail_part.html | 83 ++-------------- InvenTree/company/urls.py | 2 - InvenTree/company/views.py | 3 +- 6 files changed, 115 insertions(+), 83 deletions(-) diff --git a/InvenTree/InvenTree/static/script/inventree/company.js b/InvenTree/InvenTree/static/script/inventree/company.js index 3dc5041a87..64022b2989 100644 --- a/InvenTree/InvenTree/static/script/inventree/company.js +++ b/InvenTree/InvenTree/static/script/inventree/company.js @@ -72,3 +72,100 @@ function loadCompanyTable(table, url, options={}) { ], }); } + + +function loadSupplierPartTable(table, url, options) { + /* + * Load supplier part table + * + */ + + // Query parameters + var params = options.params || {}; + + // Load 'user' filters + var filters = loadTableFilters("supplier-part"); + + for (var key in params) { + filters[key] = params[key]; + } + + setupFilterList("supplier-part", $(table)); + + $(table).inventreeTable({ + url: url, + method: 'get', + queryParams: filters, + groupBy: false, + formatNoMatches: function() { return "No supplier parts found"; }, + columns: [ + { + checkbox: true, + }, + { + sortable: true, + field: 'part_detail.full_name', + title: 'Part', + formatter: function(value, row, index, field) { + + var url = `/part/${row.part}/`; + + var html = imageHoverIcon(row.part_detail.thumbnail) + renderLink(value, url); + + if (row.part_detail.is_template) { + html += ``; + } + + if (row.part_detail.assembly) { + html += ``; + } + + if (!row.part_detail.active) { + html += `INACTIVE`; + } + + return html; + } + }, + { + sortable: true, + field: 'SKU', + title: "Supplier Part", + formatter: function(value, row, index, field) { + return renderLink(value, row.url); + } + }, + { + sortable: true, + field: 'manufacturer', + title: '"Manufacturer"', + formatter: function(value, row, index, field) { + if (value) { + var name = row.manufacturer_detail.name; + var html = imageHoverIcon(row.manufacturer_detail.image) + renderLink(name, '/company/' + value + '/'); + + return html; + } else { + return "-"; + } + } + }, + { + sortable: true, + field: 'MPN', + title: 'MPN', + }, + { + field: 'link', + title: 'Link', + formatter: function(value, row, index, field) { + if (value) { + return renderLink(value, value); + } else { + return ''; + } + } + }, + ], + }); +} \ No newline at end of file diff --git a/InvenTree/company/api.py b/InvenTree/company/api.py index 824558a810..fcc724e5fd 100644 --- a/InvenTree/company/api.py +++ b/InvenTree/company/api.py @@ -10,6 +10,7 @@ from rest_framework import filters from rest_framework import generics, permissions from django.conf.urls import url, include +from django.db.models import Q from InvenTree.helpers import str2bool @@ -95,6 +96,8 @@ class SupplierPartList(generics.ListCreateAPIView): if company is not None: queryset = queryset.filter(Q(manufacturer=company) | Q(supplier=company)) + return queryset + def get_serializer(self, *args, **kwargs): # Do we wish to include extra detail? @@ -177,15 +180,15 @@ supplier_part_api_urls = [ url(r'^(?P\d+)/?', SupplierPartDetail.as_view(), name='api-supplier-part-detail'), # Catch anything else - url(r'^.*$', SupplierPartList.as_view(), name='api-part-supplier-list'), + url(r'^.*$', SupplierPartList.as_view(), name='api-supplier-part-list'), ] company_api_urls = [ - url(r'^part/?', include(supplier_part_api_urls)), + url(r'^part/', include(supplier_part_api_urls)), - url(r'^price-break/?', SupplierPriceBreakList.as_view(), name='api-part-supplier-price'), + url(r'^price-break/', SupplierPriceBreakList.as_view(), name='api-part-supplier-price'), url(r'^(?P\d+)/?', CompanyDetail.as_view(), name='api-company-detail'), diff --git a/InvenTree/company/models.py b/InvenTree/company/models.py index e0b995255a..66089dacb9 100644 --- a/InvenTree/company/models.py +++ b/InvenTree/company/models.py @@ -280,7 +280,9 @@ class SupplierPart(models.Model): SKU = models.CharField(max_length=100, help_text=_('Supplier stock keeping unit')) - manufacturer = models.ForeignKey(Company, on_delete=models.SET_NULL, + manufacturer = models.ForeignKey( + Company, + on_delete=models.SET_NULL, related_name='manufactured_parts', limit_choices_to={'is_manufacturer': True}, help_text=_('Select manufacturer'), diff --git a/InvenTree/company/templates/company/detail_part.html b/InvenTree/company/templates/company/detail_part.html index bb758330e1..537f7b07c3 100644 --- a/InvenTree/company/templates/company/detail_part.html +++ b/InvenTree/company/templates/company/detail_part.html @@ -47,85 +47,18 @@ }); }); - $("#part-table").inventreeTable({ - formatNoMatches: function() { return "No supplier parts found for {{ company.name }}"; }, - queryParams: function(p) { - return { - supplier: {{ company.id }}, + loadSupplierPartTable( + "#part-table", + "{% url 'api-supplier-part-list' %}", + { + params: { part_detail: true, supplier_detail: true, manufacturer_detail: true, - } - }, - columns: [ - { - checkbox: true, + company: {{ company.id }}, }, - { - sortable: true, - field: 'part_detail.full_name', - title: '{% trans "Part" %}', - formatter: function(value, row, index, field) { - - var html = imageHoverIcon(row.part_detail.thumbnail) + renderLink(value, '/part/' + row.part + '/suppliers/'); - - if (row.part_detail.is_template) { - html += ``; - } - - if (row.part_detail.assembly) { - html += ``; - } - - if (!row.part_detail.active) { - html += `INACTIVE`; - } - - return html; - } - }, - { - sortable: true, - field: 'SKU', - title: '{% trans "SKU" %}', - formatter: function(value, row, index, field) { - return renderLink(value, row.url); - } - }, - { - sortable: true, - field: 'manufacturer', - title: '{% trans "Manufacturer" %}', - formatter: function(value, row, index, field) { - if (value) { - var name = row.manufacturer_detail.name; - var html = imageHoverIcon(row.manufacturer_detail.image) + renderLink(name, '/company/' + value + '/'); - - return html; - } else { - return "-"; - } - } - }, - { - sortable: true, - field: 'MPN', - title: 'MPN', - }, - { - field: 'link', - title: '{% trans "Link" %}', - formatter: function(value, row, index, field) { - if (value) { - return renderLink(value, value); - } else { - return ''; - } - } - }, - ], - url: "{% url 'api-part-supplier-list' %}" - }); + } + ); $("#multi-part-delete").click(function() { var selections = $("#part-table").bootstrapTable("getSelections"); diff --git a/InvenTree/company/urls.py b/InvenTree/company/urls.py index afa4252bae..3140b7c2d7 100644 --- a/InvenTree/company/urls.py +++ b/InvenTree/company/urls.py @@ -2,9 +2,7 @@ URL lookup for Company app """ - from django.conf.urls import url, include -from django.views.generic.base import RedirectView from . import views diff --git a/InvenTree/company/views.py b/InvenTree/company/views.py index e4242e5f4c..e7bb2eaf57 100644 --- a/InvenTree/company/views.py +++ b/InvenTree/company/views.py @@ -85,12 +85,11 @@ class CompanyIndex(ListView): if context is None: context = default - for key,value in context.items(): + for key, value in context.items(): ctx[key] = value return ctx - def get_queryset(self): """ Retrieve the Company queryset based on HTTP request parameters.