Merge pull request #767 from SchrodingersGat/fix

Fix for BOM table display
This commit is contained in:
Oliver 2020-04-28 23:31:52 +10:00 committed by GitHub
commit 86c00f54b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 46 additions and 29 deletions

View File

@ -133,11 +133,14 @@ function loadBomTable(table, options) {
title: 'Part', title: 'Part',
sortable: true, sortable: true,
formatter: function(value, row, index, field) { formatter: function(value, row, index, field) {
var html = imageHoverIcon(row.sub_part_detail.thumbnail) + renderLink(row.sub_part_detail.full_name, row.sub_part_detail.url); var url = `/part/${row.sub_part}/`;
var html = imageHoverIcon(row.sub_part_detail.thumbnail) + renderLink(row.sub_part_detail.full_name, url);
// Display an extra icon if this part is an assembly // Display an extra icon if this part is an assembly
if (row.sub_part_detail.assembly) { if (row.sub_part_detail.assembly) {
html += "<a href='" + row.sub_part_detail.url + "bom'><span title='Open subassembly' class='fas fa-stream label-right'></span></a>"; var text = `<span title='Open subassembly' class='fas fa-stream label-right'></span>`;
html += renderLink(text, `/part/${row.sub_part}/bom/`);
} }
return html; return html;
@ -185,26 +188,20 @@ function loadBomTable(table, options) {
if (!options.editable) { if (!options.editable) {
cols.push( cols.push(
{ {
field: 'sub_part_detail.total_stock', field: 'sub_part_detail.stock',
title: 'Available', title: 'Available',
searchable: false, searchable: false,
sortable: true, sortable: true,
formatter: function(value, row, index, field) { formatter: function(value, row, index, field) {
var text = "";
var url = `/part/${row.sub_part_detail.pk}/stock/`;
if (row.quantity < row.sub_part_detail.total_stock) var text = value;
{
text = "<span class='label label-success'>" + value + "</span>"; if (value == null || value <= 0) {
text = `<span class='label label-warning'>No Stock</span>`;
} }
else
{ return renderLink(text, url);
if (!value) {
value = 'No Stock';
}
text = "<span class='label label-warning'>" + value + "</span>";
}
return renderLink(text, row.sub_part_detail.url + "stock/");
} }
}); });

View File

@ -468,15 +468,15 @@ class BomList(generics.ListCreateAPIView):
# Do we wish to include extra detail? # Do we wish to include extra detail?
try: try:
part_detail = str2bool(self.request.GET.get('part_detail', None)) kwargs['part_detail'] = str2bool(self.request.GET.get('part_detail', None))
sub_part_detail = str2bool(self.request.GET.get('sub_part_detail', None))
except AttributeError: except AttributeError:
part_detail = None pass
sub_part_detail = None
kwargs['part_detail'] = part_detail
kwargs['sub_part_detail'] = sub_part_detail
try:
kwargs['sub_part_detail'] = str2bool(self.request.GET.get('sub_part_detail', None))
except AttributeError:
pass
# Ensure the request context is passed through! # Ensure the request context is passed through!
kwargs['context'] = self.get_serializer_context() kwargs['context'] = self.get_serializer_context()
@ -486,6 +486,12 @@ class BomList(generics.ListCreateAPIView):
queryset = BomItem.objects.all() queryset = BomItem.objects.all()
queryset = self.get_serializer_class().setup_eager_loading(queryset) queryset = self.get_serializer_class().setup_eager_loading(queryset)
return queryset
def filter_queryset(self, queryset):
queryset = super().filter_queryset(queryset)
# Filter by part? # Filter by part?
part = self.request.query_params.get('part', None) part = self.request.query_params.get('part', None)

View File

@ -1242,6 +1242,17 @@ class BomItem(models.Model):
child=self.sub_part.full_name, child=self.sub_part.full_name,
n=helpers.decimal2string(self.quantity)) n=helpers.decimal2string(self.quantity))
def available_stock(self):
"""
Return the available stock items for the referenced sub_part
"""
query = self.sub_part.stock_items.filter(StockModels.StockItem.IN_STOCK_FILTER).aggregate(
available=Coalesce(Sum('quantity'), 0)
)
return query['available']
def get_overage_quantity(self, quantity): def get_overage_quantity(self, quantity):
""" Calculate overage quantity """ Calculate overage quantity
""" """

View File

@ -54,6 +54,8 @@ class PartBriefSerializer(InvenTreeModelSerializer):
thumbnail = serializers.CharField(source='get_thumbnail_url', read_only=True) thumbnail = serializers.CharField(source='get_thumbnail_url', read_only=True)
stock = serializers.FloatField(source='total_stock')
class Meta: class Meta:
model = Part model = Part
fields = [ fields = [
@ -65,6 +67,7 @@ class PartBriefSerializer(InvenTreeModelSerializer):
'assembly', 'assembly',
'purchaseable', 'purchaseable',
'salable', 'salable',
'stock',
'virtual', 'virtual',
] ]

View File

@ -1,10 +1,10 @@
{% extends "part/part_base.html" %} {% extends "part/part_base.html" %}
{% load i18n %}
{% block details %} {% block details %}
{% include 'part/tabs.html' with tab='used' %} {% include 'part/tabs.html' with tab='used' %}
<h4>Assemblies</h4> <h4>{% trans "Assemblies" %}</h4>
<hr> <hr>
@ -35,10 +35,11 @@
title: 'Part', title: 'Part',
sortable: true, sortable: true,
formatter: function(value, row, index, field) { formatter: function(value, row, index, field) {
var html = imageHoverIcon(row.part_detail.thumbnail) + renderLink(value.full_name, value.url + 'bom/'); var link = `/part/${value.pk}/bom/`;
var html = imageHoverIcon(row.part_detail.thumbnail) + renderLink(value.full_name, link);
if (!row.part_detail.active) { if (!row.part_detail.active) {
html += "<span class='label label-warning' style='float: right;'>INACTIVE</span>"; html += "<span class='label label-warning' style='float: right;'>{% trans "INACTIVE" %}</span>";
} }
return html; return html;

View File

@ -137,7 +137,6 @@ class StockItem(MPTTModel):
sales_order=None, sales_order=None,
build_order=None, build_order=None,
belongs_to=None, belongs_to=None,
status__in=StockStatus.AVAILABLE_CODES
) )
def save(self, *args, **kwargs): def save(self, *args, **kwargs):