Merge remote-tracking branch 'inventree/master'

This commit is contained in:
Oliver 2021-07-09 13:59:11 +10:00
commit f00a7cb6ef
5 changed files with 106 additions and 111 deletions

View File

@ -489,7 +489,8 @@ class PartFilter(rest_filters.FilterSet):
class PartList(generics.ListCreateAPIView): class PartList(generics.ListCreateAPIView):
""" API endpoint for accessing a list of Part objects """
API endpoint for accessing a list of Part objects
- GET: Return list of objects - GET: Return list of objects
- POST: Create a new Part object - POST: Create a new Part object
@ -840,14 +841,54 @@ class PartParameterDetail(generics.RetrieveUpdateDestroyAPIView):
serializer_class = part_serializers.PartParameterSerializer serializer_class = part_serializers.PartParameterSerializer
class BomFilter(rest_filters.FilterSet):
"""
Custom filters for the BOM list
"""
# Boolean filters for BOM item
optional = rest_filters.BooleanFilter(label='BOM line is optional')
inherited = rest_filters.BooleanFilter(label='BOM line is inherited')
allow_variants = rest_filters.BooleanFilter(label='Variants are allowed')
validated = rest_filters.BooleanFilter(label='BOM line has been validated', method='filter_validated')
def filter_validated(self, queryset, name, value):
# Work out which lines have actually been validated
pks = []
for bom_item in queryset.all():
if bom_item.is_line_valid():
pks.append(bom_item.pk)
if str2bool(value):
queryset = queryset.filter(pk__in=pks)
else:
queryset = queryset.exclude(pk__in=pks)
return queryset
# Filters for linked 'part'
part_active = rest_filters.BooleanFilter(label='Master part is active', field_name='part__active')
part_trackable = rest_filters.BooleanFilter(label='Master part is trackable', field_name='part__trackable')
# Filters for linked 'sub_part'
sub_part_trackable = rest_filters.BooleanFilter(label='Sub part is trackable', field_name='sub_part__trackable')
sub_part_assembly = rest_filters.BooleanFilter(label='Sub part is an assembly', field_name='sub_part__assembly')
class BomList(generics.ListCreateAPIView): class BomList(generics.ListCreateAPIView):
""" API endpoint for accessing a list of BomItem objects. """
API endpoint for accessing a list of BomItem objects.
- GET: Return list of BomItem objects - GET: Return list of BomItem objects
- POST: Create a new BomItem object - POST: Create a new BomItem object
""" """
serializer_class = part_serializers.BomItemSerializer serializer_class = part_serializers.BomItemSerializer
queryset = BomItem.objects.all()
filterset_class = BomFilter
def list(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):
@ -894,30 +935,6 @@ class BomList(generics.ListCreateAPIView):
params = self.request.query_params params = self.request.query_params
# Filter by "optional" status?
optional = params.get('optional', None)
if optional is not None:
optional = str2bool(optional)
queryset = queryset.filter(optional=optional)
# Filter by "inherited" status
inherited = params.get('inherited', None)
if inherited is not None:
inherited = str2bool(inherited)
queryset = queryset.filter(inherited=inherited)
# Filter by "allow_variants"
variants = params.get("allow_variants", None)
if variants is not None:
variants = str2bool(variants)
queryset = queryset.filter(allow_variants=variants)
# Filter by part? # Filter by part?
part = params.get('part', None) part = params.get('part', None)
@ -940,45 +957,6 @@ class BomList(generics.ListCreateAPIView):
except (ValueError, Part.DoesNotExist): except (ValueError, Part.DoesNotExist):
pass pass
# Filter by "active" status of the part
part_active = params.get('part_active', None)
if part_active is not None:
part_active = str2bool(part_active)
queryset = queryset.filter(part__active=part_active)
# Filter by "trackable" status of the part
part_trackable = params.get('part_trackable', None)
if part_trackable is not None:
part_trackable = str2bool(part_trackable)
queryset = queryset.filter(part__trackable=part_trackable)
# Filter by "trackable" status of the sub-part
sub_part_trackable = params.get('sub_part_trackable', None)
if sub_part_trackable is not None:
sub_part_trackable = str2bool(sub_part_trackable)
queryset = queryset.filter(sub_part__trackable=sub_part_trackable)
# Filter by whether the BOM line has been validated
validated = params.get('validated', None)
if validated is not None:
validated = str2bool(validated)
# Work out which lines have actually been validated
pks = []
for bom_item in queryset.all():
if bom_item.is_line_valid:
pks.append(bom_item.pk)
if validated:
queryset = queryset.filter(pk__in=pks)
else:
queryset = queryset.exclude(pk__in=pks)
# Annotate with purchase prices # Annotate with purchase prices
queryset = queryset.annotate( queryset = queryset.annotate(
purchase_price_min=Min('sub_part__stock_items__purchase_price'), purchase_price_min=Min('sub_part__stock_items__purchase_price'),

View File

@ -314,7 +314,7 @@ function setupFilterList(tableKey, table, target) {
// Only add the new filter if it is not empty! // Only add the new filter if it is not empty!
if (tag && tag.length > 0) { if (tag && tag.length > 0) {
var filters = addTableFilter(tableKey, tag, val); var filters = addTableFilter(tableKey, tag, val);
reloadTable(table, filters); reloadTableFilters(table, filters);
// Run this function again // Run this function again
setupFilterList(tableKey, table, target); setupFilterList(tableKey, table, target);
@ -333,7 +333,7 @@ function setupFilterList(tableKey, table, target) {
element.find(`#${clear}`).click(function() { element.find(`#${clear}`).click(function() {
var filters = clearTableFilters(tableKey); var filters = clearTableFilters(tableKey);
reloadTable(table, filters); reloadTableFilters(table, filters);
setupFilterList(tableKey, table, target); setupFilterList(tableKey, table, target);
}); });
@ -346,7 +346,7 @@ function setupFilterList(tableKey, table, target) {
var filters = removeTableFilter(tableKey, filter); var filters = removeTableFilter(tableKey, filter);
reloadTable(table, filters); reloadTableFilters(table, filters);
// Run this function again! // Run this function again!
setupFilterList(tableKey, table, target); setupFilterList(tableKey, table, target);

View File

@ -42,6 +42,10 @@ function getAvailableTableFilters(tableKey) {
type: 'bool', type: 'bool',
title: '{% trans "Trackable Part" %}' title: '{% trans "Trackable Part" %}'
}, },
sub_part_assembly: {
type: 'bool',
title: '{% trans "Assembled Part" %}',
},
validated: { validated: {
type: 'bool', type: 'bool',
title: '{% trans "Validated" %}', title: '{% trans "Validated" %}',

View File

@ -68,7 +68,7 @@ function isNumeric(n) {
* Reload a table which has already been made into a bootstrap table. * Reload a table which has already been made into a bootstrap table.
* New filters can be optionally provided, to change the query params. * New filters can be optionally provided, to change the query params.
*/ */
function reloadTable(table, filters) { function reloadTableFilters(table, filters) {
// Simply perform a refresh // Simply perform a refresh
if (filters == null) { if (filters == null) {
@ -94,16 +94,11 @@ function reloadTable(table, filters) {
} }
options.queryParams = function(tableParams) { options.queryParams = function(tableParams) {
return convertQueryParameters(tableParams, params);
for (key in params) { };
tableParams[key] = params[key];
}
return tableParams;
}
table.bootstrapTable('refreshOptions', options); table.bootstrapTable('refreshOptions', options);
table.bootstrapTable('refresh'); table.bootstrapTable('refresh', filters);
} }
@ -122,31 +117,10 @@ function visibleColumnString(columns) {
} }
/* Wrapper function for bootstrapTable. /*
* Sets some useful defaults, and manage persistent settings. * Convert bootstrap-table style parameters to "InvenTree" style
*/ */
$.fn.inventreeTable = function(options) { function convertQueryParameters(params, filters) {
var table = this;
var tableName = options.name || 'table';
var varName = tableName + '-pagesize';
// Pagingation options (can be server-side or client-side as specified by the caller)
if (!options.disablePagination) {
options.pagination = true;
options.paginationVAlign = options.paginationVAlign || 'both';
options.pageSize = inventreeLoad(varName, 25);
options.pageList = [25, 50, 100, 250, 'all'];
options.totalField = 'count';
options.dataField = 'results';
}
// Extract query params
var filters = options.queryParams || options.filters || {};
options.queryParams = function(params) {
// Override the way that we ask the server to sort results // Override the way that we ask the server to sort results
// It seems bootstrap-table does not offer a "native" way to do this... // It seems bootstrap-table does not offer a "native" way to do this...
@ -178,9 +152,48 @@ $.fn.inventreeTable = function(options) {
if ('order' in filters) { if ('order' in filters) {
params['order'] = filters['order']; params['order'] = filters['order'];
} }
return params;
// Remove searchable[] array (generated by bootstrap-table)
if ('searchable' in params) {
delete params['searchable'];
} }
if ('sortable' in params) {
delete params['sortable'];
}
return params;
}
/* Wrapper function for bootstrapTable.
* Sets some useful defaults, and manage persistent settings.
*/
$.fn.inventreeTable = function(options) {
var table = this;
var tableName = options.name || 'table';
var varName = tableName + '-pagesize';
// Pagingation options (can be server-side or client-side as specified by the caller)
if (!options.disablePagination) {
options.pagination = true;
options.paginationVAlign = options.paginationVAlign || 'both';
options.pageSize = inventreeLoad(varName, 25);
options.pageList = [25, 50, 100, 250, 'all'];
options.totalField = 'count';
options.dataField = 'results';
}
// Extract query params
var filters = options.queryParams || options.filters || {};
options.queryParams = function(params) {
return convertQueryParameters(params, filters);
};
options.rememberOrder = true; options.rememberOrder = true;
if (options.sortable == null) { if (options.sortable == null) {