2
0
mirror of https://github.com/inventree/InvenTree.git synced 2026-05-23 01:25:45 +00:00

Merge remote-tracking branch 'inventree/master'

This commit is contained in:
Oliver Walters
2022-09-22 08:39:52 +10:00
36 changed files with 16984 additions and 16295 deletions
@@ -839,6 +839,11 @@ input[type="submit"] {
padding: 10px;
}
.card-thumb {
max-width: 64px;
max-height: 64px;
}
.float-right {
float: right;
}
+15
View File
@@ -490,6 +490,21 @@ class OverallocationChoice():
class BuildCompleteSerializer(serializers.Serializer):
"""DRF serializer for marking a BuildOrder as complete."""
def get_context_data(self):
"""Retrieve extra context data for this serializer.
This is so we can determine (at run time) whether the build is ready to be completed.
"""
build = self.context['build']
return {
'overallocated': build.has_overallocated_parts(),
'allocated': build.are_untracked_parts_allocated(),
'remaining': build.remaining,
'incomplete': build.incomplete_count,
}
accept_overallocated = serializers.ChoiceField(
label=_('Overallocated Stock'),
choices=list(OverallocationChoice.OPTIONS.items()),
@@ -228,11 +228,7 @@ src="{% static 'img/blank_image.png' %}"
});
$("#build-complete").on('click', function() {
completeBuildOrder({{ build.pk }}, {
overallocated: {% if build.has_overallocated_parts %}true{% else %}false{% endif %},
allocated: {% if build.are_untracked_parts_allocated %}true{% else %}false{% endif %},
completed: {% if build.remaining == 0 %}true{% else %}false{% endif %},
});
completeBuildOrder({{ build.pk }});
});
{% endif %}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+14
View File
@@ -1605,6 +1605,20 @@ class PartParameterList(ListCreateAPI):
queryset = PartParameter.objects.all()
serializer_class = part_serializers.PartParameterSerializer
def get_serializer(self, *args, **kwargs):
"""Return the serializer instance for this API endpoint.
If requested, extra detail fields are annotated to the queryset:
- template_detail
"""
try:
kwargs['template_detail'] = str2bool(self.request.GET.get('template_detail', True))
except AttributeError:
pass
return self.serializer_class(*args, **kwargs)
filter_backends = [
DjangoFilterBackend
]
+13
View File
@@ -247,6 +247,19 @@ class PartParameterTemplateSerializer(InvenTreeModelSerializer):
class PartParameterSerializer(InvenTreeModelSerializer):
"""JSON serializers for the PartParameter model."""
def __init__(self, *args, **kwargs):
"""Custom initialization method for the serializer.
Allows us to optionally include or exclude particular information
"""
template_detail = kwargs.pop('template_detail', False)
super().__init__(*args, **kwargs)
if not template_detail:
self.fields.pop('template_detail')
template_detail = PartParameterTemplateSerializer(source='template', many=False, read_only=True)
class Meta:
@@ -813,7 +813,6 @@
onPanelLoad("part-parameters", function() {
loadPartParameterTable(
'#parameter-table',
'{% url "api-part-parameter-list" %}',
{
params: {
part: {{ part.pk }},
+39 -23
View File
@@ -201,7 +201,9 @@ function cancelBuildOrder(build_id, options={}) {
/* Construct a form to "complete" (finish) a build order */
function completeBuildOrder(build_id, options={}) {
var url = `/api/build/${build_id}/finish/`;
constructForm(`/api/build/${build_id}/finish/`, {
fieldsFunction: function(opts) {
var ctx = opts.context || {};
var fields = {
accept_unallocated: {},
@@ -209,12 +211,40 @@ function completeBuildOrder(build_id, options={}) {
accept_incomplete: {},
};
// Hide "accept overallocated" field if the build is *not* overallocated
if (!ctx.overallocated) {
delete fields.accept_overallocated;
}
// Hide "accept incomplete" field if the build has been completed
if (!ctx.remaining || ctx.remaining == 0) {
delete fields.accept_incomplete;
}
// Hide "accept unallocated" field if the build is fully allocated
if (ctx.allocated) {
delete fields.accept_unallocated;
}
return fields;
},
preFormContent: function(opts) {
var ctx = opts.context || {};
var html = '';
if (options.allocated && options.completed) {
if (ctx.allocated && ctx.remaining == 0 && ctx.incomplete == 0) {
html += `
<div class='alert alert-block alert-success'>
{% trans "Build order is ready to be completed" %}
{% trans "Build order is ready to be completed" %}'
</div>`;
} else {
if (ctx.incomplete > 0) {
html += `
<div class='alert alert-block alert-danger'>
<strong>{% trans "Build order has incomplete outputs" %}</strong><br>
{% trans "This build order cannot be completed as there are incomplete outputs" %}
</div>`;
} else {
html += `
@@ -222,37 +252,23 @@ function completeBuildOrder(build_id, options={}) {
<strong>{% trans "Build Order is incomplete" %}</strong>
</div>
`;
}
if (!options.allocated) {
if (!ctx.allocated) {
html += `<div class='alert alert-block alert-warning'>{% trans "Required stock has not been fully allocated" %}</div>`;
}
if (!options.completed) {
if (ctx.remaining > 0) {
html += `<div class='alert alert-block alert-warning'>{% trans "Required build quantity has not been completed" %}</div>`;
}
}
// Hide particular fields if they are not required
if (options.allocated) {
delete fields.accept_unallocated;
}
if (options.completed) {
delete fields.accept_incomplete;
}
if (!options.overallocated) {
delete fields.accept_overallocated;
}
constructForm(url, {
fields: fields,
return html;
},
reload: true,
confirm: true,
method: 'POST',
title: '{% trans "Complete Build Order" %}',
preFormContent: html,
method: 'POST',
});
}
+2 -1
View File
@@ -1727,7 +1727,8 @@ function initializeRelatedField(field, fields, options={}) {
var query = field.filters || {};
// Add search and pagination options
query.search = params.term;
query.search = sanitizeInputString(params.term);
query.offset = offset;
query.limit = pageSize;
+5 -1
View File
@@ -258,7 +258,7 @@ function renderLink(text, url, options={}) {
return text;
}
var max_length = options.max_length || 100;
var max_length = options.max_length || 0;
if (max_length > 0) {
text = shortenString(text, {
@@ -379,6 +379,10 @@ function setupNotesField(element, url, options={}) {
*/
function sanitizeInputString(s, options={}) {
if (!s) {
return s;
}
// Remove ASCII control characters
s = s.replace(/[\x01-\x1F]+/g, '');
+6 -7
View File
@@ -803,7 +803,7 @@ function loadSimplePartTable(table, url, options={}) {
}
function loadPartParameterTable(table, url, options) {
function loadPartParameterTable(table, options) {
var params = options.params || {};
@@ -819,7 +819,7 @@ function loadPartParameterTable(table, url, options) {
setupFilterList('part-parameters', $(table), filterTarget);
$(table).inventreeTable({
url: url,
url: '{% url "api-part-parameter-list" %}',
original: params,
queryParams: filters,
name: 'partparameters',
@@ -1292,13 +1292,12 @@ function loadParametricPartTable(table, options={}) {
},
columns: columns,
showColumns: true,
// filterControl: true,
sidePagination: 'server',
idField: 'pk',
uniqueId: 'pk',
onLoadSuccess: function() {
onLoadSuccess: function(response) {
var data = $(table).bootstrapTable('getData');
var data = response.results;
for (var idx = 0; idx < data.length; idx++) {
var row = data[idx];
@@ -1309,7 +1308,7 @@ function loadParametricPartTable(table, options={}) {
row[`parameter_${parameter.template}`] = parameter.data;
});
$(table).bootstrapTable('updateRow', pk, row);
$(table).bootstrapTable('updateByUniqueId', pk, row);
}
}
});
@@ -1356,7 +1355,7 @@ function partGridTile(part) {
<div class='panel-content'>
<div class='row'>
<div class='col-sm-4'>
<img src='${part.thumbnail}' style='width: 100%;' class='card-thumb' onclick='showModalImage("${part.image}")'>
<img src='${part.thumbnail}' class='card-thumb' onclick='showModalImage("${part.image}")'>
</div>
<div class='col-sm-8'>
<table class='table table-striped table-condensed'>