mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Add ability to specify "source location" for stock allocations
- Defaults to build.take_from - User-selectable at run-time - Selected value affects select2 query
This commit is contained in:
parent
76668b0d54
commit
563deb5ffa
@ -317,6 +317,9 @@ var buildInfo = {
|
||||
quantity: {{ build.quantity }},
|
||||
completed: {{ build.completed }},
|
||||
part: {{ build.part.pk }},
|
||||
{% if build.take_from %}
|
||||
source_location: {{ build.take_from.pk }},
|
||||
{% endif %}
|
||||
};
|
||||
|
||||
{% for item in build.incomplete_outputs %}
|
||||
@ -412,13 +415,6 @@ $('#edit-notes').click(function() {
|
||||
});
|
||||
});
|
||||
|
||||
var buildInfo = {
|
||||
pk: {{ build.pk }},
|
||||
quantity: {{ build.quantity }},
|
||||
completed: {{ build.completed }},
|
||||
part: {{ build.part.pk }},
|
||||
};
|
||||
|
||||
{% if build.has_untracked_bom_items %}
|
||||
// Load allocation table for un-tracked parts
|
||||
loadBuildOutputAllocationTable(buildInfo, null);
|
||||
@ -453,6 +449,9 @@ $("#btn-auto-allocate").on('click', function() {
|
||||
{{ build.part.pk }},
|
||||
incomplete_bom_items,
|
||||
{
|
||||
{% if build.take_from %}
|
||||
source_location: {{ build.take_from.pk }},
|
||||
{% endif %}
|
||||
success: function(data) {
|
||||
$('#allocation-table-untracked').bootstrapTable('refresh');
|
||||
}
|
||||
@ -479,6 +478,9 @@ $('#allocate-selected-items').click(function() {
|
||||
{{ build.part.pk }},
|
||||
bom_items,
|
||||
{
|
||||
{% if build.take_from %}
|
||||
source_location: {{ build.take_from.pk }},
|
||||
{% endif %}
|
||||
success: function(data) {
|
||||
$('#allocation-table-untracked').bootstrapTable('refresh');
|
||||
}
|
||||
|
@ -821,7 +821,7 @@ class StockList(generics.ListCreateAPIView):
|
||||
if loc_id is not None:
|
||||
|
||||
# Filter by 'null' location (i.e. top-level items)
|
||||
if isNull(loc_id):
|
||||
if isNull(loc_id) and not cascade:
|
||||
queryset = queryset.filter(location=None)
|
||||
else:
|
||||
try:
|
||||
|
@ -172,6 +172,7 @@ function makeBuildOutputActionButtons(output, buildInfo, lines) {
|
||||
partId,
|
||||
bom_items,
|
||||
{
|
||||
source_location: buildInfo.source_location,
|
||||
output: outputId,
|
||||
success: reloadTable,
|
||||
}
|
||||
@ -407,6 +408,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
|
||||
row,
|
||||
],
|
||||
{
|
||||
source_location: buildInfo.source_location,
|
||||
success: function(data) {
|
||||
$(table).bootstrapTable('refresh');
|
||||
},
|
||||
@ -824,7 +826,8 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
|
||||
* - bom_items: A list of BomItem objects to be allocated
|
||||
*
|
||||
* options:
|
||||
* - outputId: ID / PK of the associated build output (or null for untracked items)
|
||||
* - output: ID / PK of the associated build output (or null for untracked items)
|
||||
* - source_location: ID / PK of the top-level StockLocation to take parts from (or null)
|
||||
*/
|
||||
function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
|
||||
|
||||
@ -837,6 +840,8 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
|
||||
sub_part_trackable: output_id != null
|
||||
};
|
||||
|
||||
var source_location = options.source_location;
|
||||
|
||||
function renderBomItemRow(bom_item, quantity) {
|
||||
|
||||
var pk = bom_item.pk;
|
||||
@ -936,8 +941,22 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
|
||||
return;
|
||||
}
|
||||
|
||||
var html = ``;
|
||||
|
||||
// Render a "take from" input
|
||||
html += constructField(
|
||||
'take_from',
|
||||
{
|
||||
type: 'related field',
|
||||
label: '{% trans "Source Location" %}',
|
||||
help_text: '{% trans "Select source location (leave blank to take from all locations)" %}',
|
||||
required: false,
|
||||
},
|
||||
{},
|
||||
);
|
||||
|
||||
// Create table of parts
|
||||
var html = `
|
||||
html += `
|
||||
<table class='table table-striped table-condensed' id='stock-allocation-table'>
|
||||
<thead>
|
||||
<tr>
|
||||
@ -964,7 +983,26 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
|
||||
title: '{% trans "Allocate Stock Items to Build Order" %}',
|
||||
afterRender: function(fields, options) {
|
||||
|
||||
// Initialize select2 fields
|
||||
var take_from_field = {
|
||||
name: 'take_from',
|
||||
model: 'stocklocation',
|
||||
api_url: '{% url "api-location-list" %}',
|
||||
required: false,
|
||||
type: 'related field',
|
||||
value: source_location,
|
||||
noResults: function(query) {
|
||||
return '{% trans "No matching stock locations" %}';
|
||||
},
|
||||
};
|
||||
|
||||
// Initialize "take from" field
|
||||
initializeRelatedField(
|
||||
take_from_field,
|
||||
null,
|
||||
options,
|
||||
);
|
||||
|
||||
// Initialize stock item fields
|
||||
bom_items.forEach(function(bom_item) {
|
||||
initializeRelatedField(
|
||||
{
|
||||
@ -981,6 +1019,21 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
|
||||
render_part_detail: false,
|
||||
render_location_detail: true,
|
||||
auto_fill: true,
|
||||
adjustFilters: function(filters) {
|
||||
// Restrict query to the selected location
|
||||
var location = getFormFieldValue(
|
||||
'take_from',
|
||||
{},
|
||||
{
|
||||
modal: options.modal,
|
||||
}
|
||||
);
|
||||
|
||||
filters.location = location;
|
||||
filters.cascade = true;
|
||||
|
||||
return filters;
|
||||
},
|
||||
noResults: function(query) {
|
||||
return '{% trans "No matching stock items" %}';
|
||||
}
|
||||
@ -990,6 +1043,13 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
|
||||
);
|
||||
});
|
||||
|
||||
// Add callback to "clear" button for take_from field
|
||||
addClearCallback(
|
||||
"take_from",
|
||||
take_from_field,
|
||||
options,
|
||||
);
|
||||
|
||||
// Add button callbacks
|
||||
$(options.modal).find('.button-row-remove').click(function() {
|
||||
var pk = $(this).attr('pk');
|
||||
|
@ -728,10 +728,17 @@ function updateFieldValues(fields, options) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Update the value of a named field
|
||||
*/
|
||||
function updateFieldValue(name, value, field, options) {
|
||||
var el = $(options.modal).find(`#id_${name}`);
|
||||
|
||||
if (!el) {
|
||||
console.log(`WARNING: updateFieldValue could not find field '${name}'`);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (field.type) {
|
||||
case 'boolean':
|
||||
el.prop('checked', value);
|
||||
@ -1105,7 +1112,14 @@ function addClearCallbacks(fields, options) {
|
||||
|
||||
function addClearCallback(name, field, options) {
|
||||
|
||||
$(options.modal).find(`#clear_${name}`).click(function() {
|
||||
var el = $(options.modal).find(`#clear_${name}`);
|
||||
|
||||
if (!el) {
|
||||
console.log(`WARNING: addClearCallback could not find field '${name}'`);
|
||||
return;
|
||||
}
|
||||
|
||||
el.click(function() {
|
||||
updateFieldValue(name, null, field, options);
|
||||
});
|
||||
}
|
||||
@ -1333,6 +1347,11 @@ function initializeRelatedField(field, fields, options) {
|
||||
query.offset = offset;
|
||||
query.limit = pageSize;
|
||||
|
||||
// Allow custom run-time filter augmentation
|
||||
if ("adjustFilters" in field) {
|
||||
query = field.adjustFilters(query);
|
||||
}
|
||||
|
||||
return query;
|
||||
},
|
||||
processResults: function(response) {
|
||||
@ -1453,7 +1472,6 @@ function initializeRelatedField(field, fields, options) {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user