From 408c6a40406fa9d57c6bf84acb6ef0f660166b41 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 5 Jun 2020 09:05:57 +1000 Subject: [PATCH 1/7] Filter stock list by "customer" --- InvenTree/stock/api.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py index 23d836b1e1..018b588c1f 100644 --- a/InvenTree/stock/api.py +++ b/InvenTree/stock/api.py @@ -471,6 +471,12 @@ class StockList(generics.ListCreateAPIView): if sales_order: queryset = queryset.filter(sales_order=sales_order) + # Filter by customer + customer = params.get('customer', None) + + if customer: + queryset = queryset.filter(customer=customer) + # Filter by "serialized" status? serialized = params.get('serialized', None) From 9f599546de270e5b306e2d7823f459d498aba7ce Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 5 Jun 2020 09:08:46 +1000 Subject: [PATCH 2/7] Use stock status for determining "in stock" --- InvenTree/stock/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index e59af0e2e9..736e2218bf 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -140,6 +140,7 @@ class StockItem(MPTTModel): sales_order=None, build_order=None, belongs_to=None, + status__in=StockStatus.AVAILABLE_CODES ) def save(self, *args, **kwargs): From 544e217347dead6b7bd3246759f91e0788675c45 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 5 Jun 2020 11:52:07 +1000 Subject: [PATCH 3/7] Add page to show stock which is assigned to a customer --- .../templates/company/assigned_stock.html | 29 +++++++++++++++++++ InvenTree/company/templates/company/tabs.html | 7 +++++ InvenTree/company/urls.py | 13 +++++---- InvenTree/templates/js/stock.html | 2 -- 4 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 InvenTree/company/templates/company/assigned_stock.html diff --git a/InvenTree/company/templates/company/assigned_stock.html b/InvenTree/company/templates/company/assigned_stock.html new file mode 100644 index 0000000000..53bc79b054 --- /dev/null +++ b/InvenTree/company/templates/company/assigned_stock.html @@ -0,0 +1,29 @@ +{% extends "company/company_base.html" %} +{% load static %} +{% load i18n %} + +{% block details %} + +{% include "company/tabs.html" with tab="assigned" %} + +

{% trans "Assigned Stock" %}

+
+ +
+ +{% endblock %} + +{% block js_ready %} +{{ block.super }} + +loadStockTable($("#stock-table"), { + params: { + test: 7, + customer: {{ company.id }}, + part_detail: true, + location_detail: true, + }, + url: "{% url 'api-stock-list' %}", +}); + +{% endblock %} \ No newline at end of file diff --git a/InvenTree/company/templates/company/tabs.html b/InvenTree/company/templates/company/tabs.html index 9fd00ceb11..ebd646b741 100644 --- a/InvenTree/company/templates/company/tabs.html +++ b/InvenTree/company/templates/company/tabs.html @@ -21,6 +21,13 @@ {% trans "Sales Orders" %} {{ company.sales_orders.count }} + + {% trans "Assigned Stock" %} + + {{ company.assigned_stock.count }} + + + {% endif %} {% trans "Notes" %}{% if company.notes %} {% endif %} diff --git a/InvenTree/company/urls.py b/InvenTree/company/urls.py index af8e1846e1..f5fbeede47 100644 --- a/InvenTree/company/urls.py +++ b/InvenTree/company/urls.py @@ -13,13 +13,14 @@ company_detail_urls = [ # url(r'orders/?', views.CompanyDetail.as_view(template_name='company/orders.html'), name='company-detail-orders'), - url(r'parts/', views.CompanyDetail.as_view(template_name='company/detail_part.html'), name='company-detail-parts'), - url(r'stock/?', views.CompanyDetail.as_view(template_name='company/detail_stock.html'), name='company-detail-stock'), - url(r'purchase-orders/?', views.CompanyDetail.as_view(template_name='company/purchase_orders.html'), name='company-detail-purchase-orders'), - url(r'sales-orders/?', views.CompanyDetail.as_view(template_name='company/sales_orders.html'), name='company-detail-sales-orders'), - url(r'notes/?', views.CompanyNotes.as_view(), name='company-notes'), + url(r'^parts/', views.CompanyDetail.as_view(template_name='company/detail_part.html'), name='company-detail-parts'), + url(r'^stock/', views.CompanyDetail.as_view(template_name='company/detail_stock.html'), name='company-detail-stock'), + url(r'^purchase-orders/', views.CompanyDetail.as_view(template_name='company/purchase_orders.html'), name='company-detail-purchase-orders'), + url(r'^assigned-stock/', views.CompanyDetail.as_view(template_name='company/assigned_stock.html'), name='company-detail-assigned-stock'), + url(r'^sales-orders/', views.CompanyDetail.as_view(template_name='company/sales_orders.html'), name='company-detail-sales-orders'), + url(r'^notes/', views.CompanyNotes.as_view(), name='company-notes'), - url(r'thumbnail/?', views.CompanyImage.as_view(), name='company-image'), + url(r'^thumbnail/', views.CompanyImage.as_view(), name='company-image'), # Any other URL url(r'^.*$', views.CompanyDetail.as_view(), name='company-detail'), diff --git a/InvenTree/templates/js/stock.html b/InvenTree/templates/js/stock.html index c0737dc250..14be8d9afe 100644 --- a/InvenTree/templates/js/stock.html +++ b/InvenTree/templates/js/stock.html @@ -351,8 +351,6 @@ function loadStockTable(table, options) { loc = "{% trans "Undefined location" %}"; } - console.log("Location: " + loc); - if (!locations.includes(loc)) { locations.push(loc); } From 6ebce2b2fde8795c13b1f9aab9eeb9401c8b58e9 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 5 Jun 2020 12:06:28 +1000 Subject: [PATCH 4/7] Add ability to filter purchase orders by "outstanding" status --- InvenTree/order/api.py | 12 ++++++++++++ InvenTree/templates/js/table_filters.html | 5 +++++ 2 files changed, 17 insertions(+) diff --git a/InvenTree/order/api.py b/InvenTree/order/api.py index dba493baab..0c1ef8b3ae 100644 --- a/InvenTree/order/api.py +++ b/InvenTree/order/api.py @@ -13,6 +13,7 @@ from django.conf.urls import url, include from InvenTree.helpers import str2bool from InvenTree.api import AttachmentMixin +from InvenTree.status_codes import PurchaseOrderStatus from part.models import Part from company.models import SupplierPart @@ -68,6 +69,17 @@ class POList(generics.ListCreateAPIView): params = self.request.query_params + # Filter by 'outstanding' status + outstanding = params.get('outstanding', None) + + if outstanding is not None: + outstanding = str2bool(outstanding) + + if outstanding: + queryset = queryset.filter(status__in=PurchaseOrderStatus.OPEN) + else: + queryset = queryset.exclude(status__in=PurchaseOrderStatus.OPEN) + # Special filtering for 'status' field status = params.get('status', None) diff --git a/InvenTree/templates/js/table_filters.html b/InvenTree/templates/js/table_filters.html index 298a034517..285abb36f9 100644 --- a/InvenTree/templates/js/table_filters.html +++ b/InvenTree/templates/js/table_filters.html @@ -78,11 +78,16 @@ function getAvailableTableFilters(tableKey) { // Filters for the "Order" table if (tableKey == "purchaseorder") { + return { status: { title: '{% trans "Order status" %}', options: purchaseOrderCodes, }, + outstanding: { + type: 'bool', + title: '{% trans "Outstanding" %}', + }, }; } From fcd588cb019c0282d96f0243d81ac282e0bd8cc4 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 5 Jun 2020 12:08:47 +1000 Subject: [PATCH 5/7] Filter SalesOrder by status --- InvenTree/InvenTree/status_codes.py | 5 +++++ InvenTree/order/api.py | 13 ++++++++++++- InvenTree/templates/js/table_filters.html | 4 ++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/InvenTree/InvenTree/status_codes.py b/InvenTree/InvenTree/status_codes.py index 2082eac70b..f8089cb5de 100644 --- a/InvenTree/InvenTree/status_codes.py +++ b/InvenTree/InvenTree/status_codes.py @@ -147,6 +147,11 @@ class SalesOrderStatus(StatusCode): RETURNED: 'yellow', } + # Open orders + OPEN = [ + PENDING, + ] + class StockStatus(StatusCode): diff --git a/InvenTree/order/api.py b/InvenTree/order/api.py index 0c1ef8b3ae..a7915878c5 100644 --- a/InvenTree/order/api.py +++ b/InvenTree/order/api.py @@ -13,7 +13,7 @@ from django.conf.urls import url, include from InvenTree.helpers import str2bool from InvenTree.api import AttachmentMixin -from InvenTree.status_codes import PurchaseOrderStatus +from InvenTree.status_codes import PurchaseOrderStatus, SalesOrderStatus from part.models import Part from company.models import SupplierPart @@ -271,6 +271,17 @@ class SOList(generics.ListCreateAPIView): params = self.request.query_params + # Filter by 'outstanding' status + outstanding = params.get('outstanding', None) + + if outstanding is not None: + outstanding = str2bool(outstanding) + + if outstanding: + queryset = queryset.filter(status__in=SalesOrderStatus.OPEN) + else: + queryset = queryset.exclude(status__in=SalesOrderStatus.OPEN) + status = params.get('status', None) if status is not None: diff --git a/InvenTree/templates/js/table_filters.html b/InvenTree/templates/js/table_filters.html index 285abb36f9..bec29b0487 100644 --- a/InvenTree/templates/js/table_filters.html +++ b/InvenTree/templates/js/table_filters.html @@ -97,6 +97,10 @@ function getAvailableTableFilters(tableKey) { title: '{% trans "Order status" %}', options: salesOrderCodes, }, + outstanding: { + type: 'bool', + title: '{% trans "Outstanding" %}', + }, }; } From 15817ce61a5a32d473dc67c02f3d3800564bce41 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 5 Jun 2020 19:26:41 +1000 Subject: [PATCH 6/7] Add "IPN" column to part table --- InvenTree/templates/js/part.html | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/InvenTree/templates/js/part.html b/InvenTree/templates/js/part.html index 1a40c7ad84..c9901cdb68 100644 --- a/InvenTree/templates/js/part.html +++ b/InvenTree/templates/js/part.html @@ -95,6 +95,8 @@ function loadPartTable(table, url, options={}) { field: 'pk', title: 'ID', visible: false, + switchable: false, + searchable: false, } ]; @@ -103,9 +105,16 @@ function loadPartTable(table, url, options={}) { checkbox: true, title: '{% trans 'Select' %}', searchable: false, + switchable: false, }); } + columns.push({ + field: 'IPN', + title: 'IPN', + sortable: true, + }), + columns.push({ field: 'name', title: '{% trans 'Part' %}', @@ -231,6 +240,7 @@ function loadPartTable(table, url, options={}) { original: params, formatNoMatches: function() { return "{% trans "No parts found" %}"; }, columns: columns, + showColumns: true, }); if (options.buttons) { From 16d261d956191fc563f7be8d55c2c1875d0726ce Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 5 Jun 2020 19:33:32 +1000 Subject: [PATCH 7/7] Make description fields optional --- InvenTree/InvenTree/models.py | 8 ++++--- .../migrations/0044_auto_20200605_0931.py | 24 +++++++++++++++++++ .../migrations/0045_auto_20200605_0932.py | 18 ++++++++++++++ .../migrations/0046_auto_20200605_0931.py | 24 +++++++++++++++++++ .../migrations/0047_auto_20200605_0932.py | 18 ++++++++++++++ 5 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 InvenTree/part/migrations/0044_auto_20200605_0931.py create mode 100644 InvenTree/part/migrations/0045_auto_20200605_0932.py create mode 100644 InvenTree/stock/migrations/0046_auto_20200605_0931.py create mode 100644 InvenTree/stock/migrations/0047_auto_20200605_0932.py diff --git a/InvenTree/InvenTree/models.py b/InvenTree/InvenTree/models.py index d0ed73f27a..cffe48cc0b 100644 --- a/InvenTree/InvenTree/models.py +++ b/InvenTree/InvenTree/models.py @@ -102,12 +102,14 @@ class InvenTreeTree(MPTTModel): name = models.CharField( blank=False, max_length=100, - validators=[validate_tree_name] + validators=[validate_tree_name], + help_text=_("Name"), ) description = models.CharField( - blank=False, - max_length=250 + blank=True, + max_length=250, + help_text=_("Description (optional)") ) # When a category is deleted, graft the children onto its parent diff --git a/InvenTree/part/migrations/0044_auto_20200605_0931.py b/InvenTree/part/migrations/0044_auto_20200605_0931.py new file mode 100644 index 0000000000..bdce0ebc02 --- /dev/null +++ b/InvenTree/part/migrations/0044_auto_20200605_0931.py @@ -0,0 +1,24 @@ +# Generated by Django 3.0.5 on 2020-06-05 09:31 + +import InvenTree.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('part', '0043_auto_20200527_0005'), + ] + + operations = [ + migrations.AlterField( + model_name='partcategory', + name='description', + field=models.CharField(blank=True, help_text='Description', max_length=250), + ), + migrations.AlterField( + model_name='partcategory', + name='name', + field=models.CharField(help_text='Name', max_length=100, validators=[InvenTree.validators.validate_tree_name]), + ), + ] diff --git a/InvenTree/part/migrations/0045_auto_20200605_0932.py b/InvenTree/part/migrations/0045_auto_20200605_0932.py new file mode 100644 index 0000000000..a9be054468 --- /dev/null +++ b/InvenTree/part/migrations/0045_auto_20200605_0932.py @@ -0,0 +1,18 @@ +# Generated by Django 3.0.5 on 2020-06-05 09:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('part', '0044_auto_20200605_0931'), + ] + + operations = [ + migrations.AlterField( + model_name='partcategory', + name='description', + field=models.CharField(blank=True, help_text='Description (optional)', max_length=250), + ), + ] diff --git a/InvenTree/stock/migrations/0046_auto_20200605_0931.py b/InvenTree/stock/migrations/0046_auto_20200605_0931.py new file mode 100644 index 0000000000..8c37c31453 --- /dev/null +++ b/InvenTree/stock/migrations/0046_auto_20200605_0931.py @@ -0,0 +1,24 @@ +# Generated by Django 3.0.5 on 2020-06-05 09:31 + +import InvenTree.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('stock', '0045_stockitem_customer'), + ] + + operations = [ + migrations.AlterField( + model_name='stocklocation', + name='description', + field=models.CharField(blank=True, help_text='Description', max_length=250), + ), + migrations.AlterField( + model_name='stocklocation', + name='name', + field=models.CharField(help_text='Name', max_length=100, validators=[InvenTree.validators.validate_tree_name]), + ), + ] diff --git a/InvenTree/stock/migrations/0047_auto_20200605_0932.py b/InvenTree/stock/migrations/0047_auto_20200605_0932.py new file mode 100644 index 0000000000..5ca509f13f --- /dev/null +++ b/InvenTree/stock/migrations/0047_auto_20200605_0932.py @@ -0,0 +1,18 @@ +# Generated by Django 3.0.5 on 2020-06-05 09:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('stock', '0046_auto_20200605_0931'), + ] + + operations = [ + migrations.AlterField( + model_name='stocklocation', + name='description', + field=models.CharField(blank=True, help_text='Description (optional)', max_length=250), + ), + ]