Enhancement for the BuildItem API / serializer

- Add optional "part_detail" information
- Add optional "build_detail" information
- Add optional "location_detail" information
This commit is contained in:
Oliver 2021-06-18 19:08:54 +10:00
parent 10ecddf9b4
commit 245c9bfd28
3 changed files with 122 additions and 7 deletions

View File

@ -165,6 +165,16 @@ class BuildItemList(generics.ListCreateAPIView):
serializer_class = BuildItemSerializer serializer_class = BuildItemSerializer
def get_serializer(self, *args, **kwargs):
params = self.request.query_params
kwargs['part_detail'] = str2bool(params.get('part_detail', False))
kwargs['build_detail'] = str2bool(params.get('build_detail', False))
kwargs['location_detail'] = str2bool(params.get('location_detail', False))
return self.serializer_class(*args, **kwargs)
def get_queryset(self): def get_queryset(self):
""" Override the queryset method, """ Override the queryset method,
to allow filtering by stock_item.part to allow filtering by stock_item.part

View File

@ -13,7 +13,8 @@ from rest_framework import serializers
from InvenTree.serializers import InvenTreeModelSerializer from InvenTree.serializers import InvenTreeModelSerializer
from stock.serializers import StockItemSerializerBrief from stock.serializers import StockItemSerializerBrief
from part.serializers import PartBriefSerializer from stock.serializers import LocationSerializer
from part.serializers import PartSerializer, PartBriefSerializer
from .models import Build, BuildItem from .models import Build, BuildItem
@ -99,22 +100,45 @@ class BuildItemSerializer(InvenTreeModelSerializer):
bom_part = serializers.IntegerField(source='bom_item.sub_part.pk', read_only=True) bom_part = serializers.IntegerField(source='bom_item.sub_part.pk', read_only=True)
part = serializers.IntegerField(source='stock_item.part.pk', read_only=True) part = serializers.IntegerField(source='stock_item.part.pk', read_only=True)
part_name = serializers.CharField(source='stock_item.part.full_name', read_only=True) location = serializers.IntegerField(source='stock_item.location.pk', read_only=True)
part_thumb = serializers.CharField(source='getStockItemThumbnail', read_only=True)
# Extra (optional) detail fields
part_detail = PartSerializer(source='stock_item.part', many=False, read_only=True)
build_detail = BuildSerializer(source='build', many=False, read_only=True)
stock_item_detail = StockItemSerializerBrief(source='stock_item', read_only=True) stock_item_detail = StockItemSerializerBrief(source='stock_item', read_only=True)
location_detail = LocationSerializer(source='stock_item.location', read_only=True)
quantity = serializers.FloatField() quantity = serializers.FloatField()
def __init__(self, *args, **kwargs):
build_detail = kwargs.pop('build_detail', False)
part_detail = kwargs.pop('part_detail', False)
location_detail = kwargs.pop('location_detail', False)
super().__init__(*args, **kwargs)
if not build_detail:
self.fields.pop('build_detail')
if not part_detail:
self.fields.pop('part_detail')
if not location_detail:
self.fields.pop('location_detail')
class Meta: class Meta:
model = BuildItem model = BuildItem
fields = [ fields = [
'pk', 'pk',
'bom_part', 'bom_part',
'build', 'build',
'build_detail',
'install_into', 'install_into',
'location',
'location_detail',
'part', 'part',
'part_name', 'part_detail',
'part_thumb',
'stock_item', 'stock_item',
'stock_item_detail', 'stock_item_detail',
'quantity' 'quantity'

View File

@ -155,6 +155,85 @@ function makeBuildOutputActionButtons(output, buildInfo, lines) {
} }
function loadBuildOrderAllocationTable(table, options={}) {
/**
* Load a table showing all the BuildOrder allocations for a given part
*/
options.params['part_detail'] = true;
options.params['build_detail'] = true;
options.params['location_detail'] = true;
var filters = loadTableFilters("buildorderallocation");
for (var key in options.params) {
filters[key] = options.params[key];
}
setupFilterList("buildorderallocation", $(table));
$(table).inventreeTable({
url: '{% url "api-build-item-list" %}',
queryParams: filters,
name: 'buildorderallocation',
groupBy: false,
original: options.params,
formatNoMatches: function() {
return '{% trans "No build order allocations found" %}'
},
columns: [
{
field: 'pk',
visible: false,
switchable: false,
},
{
field: 'build',
title: '{% trans "Build Order" %}',
formatter: function(value, row) {
var prefix = "{% settings_value 'BUILDORDER_REFERENCE_PREFIX' %}";
var ref = `${prefix}${row.build_detail.reference}`;
return renderLink(ref, `/build/${row.build}/`);
}
},
{
field: 'item',
title: '{% trans "Stock Item" %}',
formatter: function(value, row) {
// Render a link to the particular stock item
var link = `/stock/item/${row.stock_item}/`;
var text = `{% trans "Stock Item" %} ${row.stock_item}`;
return renderLink(text, link);
}
},
{
field: 'location',
title: '{% trans "Location" %}',
formatter: function(value, row) {
if (!value) {
return '{% trans "Location not specified" %}';
}
var link = `/stock/location/${value}`;
var text = row.location_detail.description;
return renderLink(text, link);
}
},
{
field: 'quantity',
title: '{% trans "Quantity" %}',
}
]
});
}
function loadBuildOutputAllocationTable(buildInfo, output, options={}) { function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
/* /*
* Load the "allocation table" for a particular build output. * Load the "allocation table" for a particular build output.
@ -347,6 +426,8 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
var params = { var params = {
build: buildId, build: buildId,
part_detail: true,
location_detail: true,
} }
if (output) { if (output) {
@ -466,8 +547,8 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
title: '{% trans "Part" %}', title: '{% trans "Part" %}',
formatter: function(value, row) { formatter: function(value, row) {
var html = imageHoverIcon(row.part_thumb); var html = imageHoverIcon(row.part_detail.thumbnail);
html += renderLink(row.part_name, `/part/${value}/`); html += renderLink(row.part_detail.full_name, `/part/${value}/`);
return html; return html;
} }
}, },