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/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/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/order/api.py b/InvenTree/order/api.py index dba493baab..a7915878c5 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, SalesOrderStatus 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) @@ -259,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/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/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) 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), + ), + ] 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): 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) { 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); } diff --git a/InvenTree/templates/js/table_filters.html b/InvenTree/templates/js/table_filters.html index 298a034517..bec29b0487 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" %}', + }, }; } @@ -92,6 +97,10 @@ function getAvailableTableFilters(tableKey) { title: '{% trans "Order status" %}', options: salesOrderCodes, }, + outstanding: { + type: 'bool', + title: '{% trans "Outstanding" %}', + }, }; }