From 6dd79af0b6de8e1779515fda03f3ad28fac556db Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 22 Apr 2020 10:11:40 +1000 Subject: [PATCH] Expose "is_allocated" parameter on StockItem API --- .../static/script/inventree/stock.js | 8 +++++++- InvenTree/InvenTree/status_codes.py | 12 ++++++++++++ InvenTree/stock/api.py | 11 +++++++++++ .../migrations/0029_auto_20200421_2359.py | 19 +++++++++++++++++++ InvenTree/stock/models.py | 10 ++++++++++ InvenTree/stock/serializers.py | 3 +++ InvenTree/templates/table_filters.html | 7 ++++++- 7 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 InvenTree/stock/migrations/0029_auto_20200421_2359.py diff --git a/InvenTree/InvenTree/static/script/inventree/stock.js b/InvenTree/InvenTree/static/script/inventree/stock.js index 3fe11ed087..ef8e5ab761 100644 --- a/InvenTree/InvenTree/static/script/inventree/stock.js +++ b/InvenTree/InvenTree/static/script/inventree/stock.js @@ -228,8 +228,14 @@ function loadStockTable(table, options) { } else { url = `/part/${row.part}/`; } + + html = imageHoverIcon(thumb) + renderLink(name, url); + + if (row.allocated) { + html += ``; + } - return imageHoverIcon(thumb) + renderLink(name, url); + return html; } }, { diff --git a/InvenTree/InvenTree/status_codes.py b/InvenTree/InvenTree/status_codes.py index a07a8d6f99..fa2a4d9bfd 100644 --- a/InvenTree/InvenTree/status_codes.py +++ b/InvenTree/InvenTree/status_codes.py @@ -119,6 +119,13 @@ class StockStatus(StatusCode): DAMAGED = 55 # Item is damaged DESTROYED = 60 # Item is destroyed LOST = 70 # Item has been lost + RETURNED = 85 # Item has been returned from a customer + + # Any stock code above 100 means that the stock item is not "in stock" + # This can be used as a quick check for filtering + NOT_IN_STOCK = 100 + + SHIPPED = 110 # Item has been shipped to a customer options = { OK: _("OK"), @@ -126,12 +133,15 @@ class StockStatus(StatusCode): DAMAGED: _("Damaged"), DESTROYED: _("Destroyed"), LOST: _("Lost"), + SHIPPED: _("Shipped"), + RETURNED: _("Returned"), } labels = { OK: 'success', ATTENTION: 'warning', DAMAGED: 'danger', + DESTROYED: 'danger', } # The following codes correspond to parts that are 'available' or 'in stock' @@ -139,12 +149,14 @@ class StockStatus(StatusCode): OK, ATTENTION, DAMAGED, + RETURNED, ] # The following codes correspond to parts that are 'unavailable' UNAVAILABLE_CODES = [ DESTROYED, LOST, + SHIPPED, ] diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py index 450f6e95f1..c144316c70 100644 --- a/InvenTree/stock/api.py +++ b/InvenTree/stock/api.py @@ -367,6 +367,17 @@ class StockList(generics.ListCreateAPIView): # Filter out parts which are not actually "in stock" stock_list = stock_list.filter(customer=None, belongs_to=None) + # Filter by 'allocated' patrs? + allocated = self.request.query_params.get('allocated', None) + + if allocated is not None: + allocated = str2bool(allocated) + + if allocated: + stock_list = stock_list.exclude(Q(sales_order_line=None)) + else: + stock_list = stock_list.filter(Q(sales_order_line=None)) + # Do we wish to filter by "active parts" active = self.request.query_params.get('active', None) diff --git a/InvenTree/stock/migrations/0029_auto_20200421_2359.py b/InvenTree/stock/migrations/0029_auto_20200421_2359.py new file mode 100644 index 0000000000..1b89a9d143 --- /dev/null +++ b/InvenTree/stock/migrations/0029_auto_20200421_2359.py @@ -0,0 +1,19 @@ +# Generated by Django 3.0.5 on 2020-04-21 23:59 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('stock', '0028_auto_20200421_0724'), + ] + + operations = [ + migrations.AlterField( + model_name='stockitem', + name='status', + field=models.PositiveIntegerField(choices=[(10, 'OK'), (50, 'Attention needed'), (55, 'Damaged'), (60, 'Destroyed'), (70, 'Lost'), (110, 'Shipped'), (85, 'Returned')], default=10, validators=[django.core.validators.MinValueValidator(0)]), + ), + ] diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index e34bbcfb11..a29018fb88 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -397,6 +397,16 @@ class StockItem(MPTTModel): infinite = models.BooleanField(default=False) + def is_allocated(self): + """ + Return True if this StockItem is allocated to a SalesOrder or a Build + """ + + # TODO - For now this only checks if the StockItem is allocated to a SalesOrder + # TODO - In future, once the "build" is working better, check this too + + return self.sales_order_line is not None + def can_delete(self): """ Can this stock item be deleted? It can NOT be deleted under the following circumstances: diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py index 616755b11b..e0176f5192 100644 --- a/InvenTree/stock/serializers.py +++ b/InvenTree/stock/serializers.py @@ -90,6 +90,8 @@ class StockItemSerializer(InvenTreeModelSerializer): tracking_items = serializers.IntegerField(source='tracking_info_count', read_only=True) + allocated = serializers.BooleanField(source='is_allocated', read_only=True) + def __init__(self, *args, **kwargs): part_detail = kwargs.pop('part_detail', False) @@ -110,6 +112,7 @@ class StockItemSerializer(InvenTreeModelSerializer): class Meta: model = StockItem fields = [ + 'allocated', 'batch', 'in_stock', 'link', diff --git a/InvenTree/templates/table_filters.html b/InvenTree/templates/table_filters.html index 322acedb33..8dff5ed1be 100644 --- a/InvenTree/templates/table_filters.html +++ b/InvenTree/templates/table_filters.html @@ -27,11 +27,16 @@ function getAvailableTableFilters(tableKey) { title: '{% trans "Active parts" %}', description: '{% trans "Show stock for active parts" %}', }, - 'status': { + status: { options: stockCodes, title: '{% trans "Stock status" %}', description: '{% trans "Stock status" %}', }, + allocated: { + type: 'bool', + title: '{% trans "Is allocated" %}', + description: '{% trans "Item has been alloacted" %}', + }, }; }