Expose "is_allocated" parameter on StockItem API

This commit is contained in:
Oliver Walters 2020-04-22 10:11:40 +10:00
parent 12daf15406
commit 6dd79af0b6
7 changed files with 68 additions and 2 deletions

View File

@ -228,8 +228,14 @@ function loadStockTable(table, options) {
} else { } else {
url = `/part/${row.part}/`; url = `/part/${row.part}/`;
} }
html = imageHoverIcon(thumb) + renderLink(name, url);
if (row.allocated) {
html += `<span class='fas fa-bookmark label-right' title='StockItem has been allocated'></span>`;
}
return imageHoverIcon(thumb) + renderLink(name, url); return html;
} }
}, },
{ {

View File

@ -119,6 +119,13 @@ class StockStatus(StatusCode):
DAMAGED = 55 # Item is damaged DAMAGED = 55 # Item is damaged
DESTROYED = 60 # Item is destroyed DESTROYED = 60 # Item is destroyed
LOST = 70 # Item has been lost 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 = { options = {
OK: _("OK"), OK: _("OK"),
@ -126,12 +133,15 @@ class StockStatus(StatusCode):
DAMAGED: _("Damaged"), DAMAGED: _("Damaged"),
DESTROYED: _("Destroyed"), DESTROYED: _("Destroyed"),
LOST: _("Lost"), LOST: _("Lost"),
SHIPPED: _("Shipped"),
RETURNED: _("Returned"),
} }
labels = { labels = {
OK: 'success', OK: 'success',
ATTENTION: 'warning', ATTENTION: 'warning',
DAMAGED: 'danger', DAMAGED: 'danger',
DESTROYED: 'danger',
} }
# The following codes correspond to parts that are 'available' or 'in stock' # The following codes correspond to parts that are 'available' or 'in stock'
@ -139,12 +149,14 @@ class StockStatus(StatusCode):
OK, OK,
ATTENTION, ATTENTION,
DAMAGED, DAMAGED,
RETURNED,
] ]
# The following codes correspond to parts that are 'unavailable' # The following codes correspond to parts that are 'unavailable'
UNAVAILABLE_CODES = [ UNAVAILABLE_CODES = [
DESTROYED, DESTROYED,
LOST, LOST,
SHIPPED,
] ]

View File

@ -367,6 +367,17 @@ class StockList(generics.ListCreateAPIView):
# Filter out parts which are not actually "in stock" # Filter out parts which are not actually "in stock"
stock_list = stock_list.filter(customer=None, belongs_to=None) 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" # Do we wish to filter by "active parts"
active = self.request.query_params.get('active', None) active = self.request.query_params.get('active', None)

View File

@ -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)]),
),
]

View File

@ -397,6 +397,16 @@ class StockItem(MPTTModel):
infinite = models.BooleanField(default=False) 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): def can_delete(self):
""" Can this stock item be deleted? It can NOT be deleted under the following circumstances: """ Can this stock item be deleted? It can NOT be deleted under the following circumstances:

View File

@ -90,6 +90,8 @@ class StockItemSerializer(InvenTreeModelSerializer):
tracking_items = serializers.IntegerField(source='tracking_info_count', read_only=True) 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): def __init__(self, *args, **kwargs):
part_detail = kwargs.pop('part_detail', False) part_detail = kwargs.pop('part_detail', False)
@ -110,6 +112,7 @@ class StockItemSerializer(InvenTreeModelSerializer):
class Meta: class Meta:
model = StockItem model = StockItem
fields = [ fields = [
'allocated',
'batch', 'batch',
'in_stock', 'in_stock',
'link', 'link',

View File

@ -27,11 +27,16 @@ function getAvailableTableFilters(tableKey) {
title: '{% trans "Active parts" %}', title: '{% trans "Active parts" %}',
description: '{% trans "Show stock for active parts" %}', description: '{% trans "Show stock for active parts" %}',
}, },
'status': { status: {
options: stockCodes, options: stockCodes,
title: '{% trans "Stock status" %}', title: '{% trans "Stock status" %}',
description: '{% trans "Stock status" %}', description: '{% trans "Stock status" %}',
}, },
allocated: {
type: 'bool',
title: '{% trans "Is allocated" %}',
description: '{% trans "Item has been alloacted" %}',
},
}; };
} }