mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Refactor allocation form
- The data is already loaded in the main table! - Why would we want to throw that data away?
This commit is contained in:
parent
28509dbd68
commit
17df4ca91e
@ -191,7 +191,19 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<table class='table table-striped table-condensed' id='allocation-table-untracked'></table>
|
<div id='unallocated-toolbar'>
|
||||||
|
<div class='button-toolbar container-fluid' style='float: right;'>
|
||||||
|
<div class='btn-group'>
|
||||||
|
<button id='allocate-selected-items' class='btn btn-success' title='{% trans "Allocate selected items" %}'>
|
||||||
|
<span class='fas fa-sign-in-alt'></span>
|
||||||
|
</button>
|
||||||
|
<div class='filter-list' id='filter-list-build-items'>
|
||||||
|
<!-- Empty div for table filters-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<table class='table table-striped table-condensed' id='allocation-table-untracked' data-toolbar='#unallocated-toolbar'></table>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class='alert alert-block alert-info'>
|
<div class='alert alert-block alert-info'>
|
||||||
{% trans "This Build Order does not have any associated untracked BOM items" %}
|
{% trans "This Build Order does not have any associated untracked BOM items" %}
|
||||||
@ -419,9 +431,12 @@ function reloadTable() {
|
|||||||
{% if build.active %}
|
{% if build.active %}
|
||||||
$("#btn-auto-allocate").on('click', function() {
|
$("#btn-auto-allocate").on('click', function() {
|
||||||
|
|
||||||
|
var bom_items = $("#allocation-table-untracked").bootstrapTable("getData");
|
||||||
|
|
||||||
allocateStockToBuild(
|
allocateStockToBuild(
|
||||||
{{ build.pk }},
|
{{ build.pk }},
|
||||||
{{ build.part.pk }},
|
{{ build.part.pk }},
|
||||||
|
bom_items,
|
||||||
{
|
{
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
$('#allocation-table-untracked').bootstrapTable('refresh');
|
$('#allocation-table-untracked').bootstrapTable('refresh');
|
||||||
@ -439,6 +454,22 @@ $('#btn-unallocate').on('click', function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#allocate-selected-items').click(function() {
|
||||||
|
|
||||||
|
var bom_items = $("#allocation-table-untracked").bootstrapTable("getSelections");
|
||||||
|
|
||||||
|
allocateStockToBuild(
|
||||||
|
{{ build.pk }},
|
||||||
|
{{ build.part.pk }},
|
||||||
|
bom_items,
|
||||||
|
{
|
||||||
|
success: function(data) {
|
||||||
|
$('#allocation-table-untracked').bootstrapTable('refresh');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
$("#btn-order-parts").click(function() {
|
$("#btn-order-parts").click(function() {
|
||||||
launchModalForm("/order/purchase-order/order-parts/", {
|
launchModalForm("/order/purchase-order/order-parts/", {
|
||||||
data: {
|
data: {
|
||||||
|
@ -378,16 +378,24 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
|
|||||||
// Primary key of the 'sub_part'
|
// Primary key of the 'sub_part'
|
||||||
var pk = $(this).attr('pk');
|
var pk = $(this).attr('pk');
|
||||||
|
|
||||||
|
// Extract BomItem information from this row
|
||||||
|
var row = $(table).bootstrapTable('getRowByUniqueId', pk);
|
||||||
|
|
||||||
|
if (!row) {
|
||||||
|
console.log("WARNING: getRowByUniqueId returned null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
allocateStockToBuild(
|
allocateStockToBuild(
|
||||||
buildId,
|
buildId,
|
||||||
partId,
|
partId,
|
||||||
|
[
|
||||||
|
row,
|
||||||
|
],
|
||||||
{
|
{
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
// TODO: Reload table
|
// TODO: Reload table
|
||||||
},
|
},
|
||||||
parts: [
|
|
||||||
parseInt(pk),
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -798,19 +806,16 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
|
|||||||
* arguments:
|
* arguments:
|
||||||
* - buildId: ID / PK value for the build
|
* - buildId: ID / PK value for the build
|
||||||
* - partId: ID / PK value for the part being built
|
* - partId: ID / PK value for the part being built
|
||||||
|
* - bom_items: A list of BomItem objects to be allocated
|
||||||
*
|
*
|
||||||
* options:
|
* options:
|
||||||
* - outputId: ID / PK of the associated build output (or null for untracked items)
|
* - outputId: ID / PK of the associated build output (or null for untracked items)
|
||||||
* - parts: List of ID values for filtering against specific sub parts
|
|
||||||
*/
|
*/
|
||||||
function allocateStockToBuild(build_id, part_id, options={}) {
|
function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
|
||||||
|
|
||||||
// ID of the associated "build output" (or null)
|
// ID of the associated "build output" (or null)
|
||||||
var output_id = options.output || null;
|
var output_id = options.output || null;
|
||||||
|
|
||||||
// Extract list of BOM items (or empty list)
|
|
||||||
var sub_part_ids = options.parts || [];
|
|
||||||
|
|
||||||
var query_params = {
|
var query_params = {
|
||||||
part: part_id,
|
part: part_id,
|
||||||
sub_part_detail: true,
|
sub_part_detail: true,
|
||||||
@ -884,179 +889,156 @@ function allocateStockToBuild(build_id, part_id, options={}) {
|
|||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
inventreeGet(
|
var table_entries = "";
|
||||||
'{% url "api-bom-list" %}',
|
|
||||||
query_params,
|
|
||||||
{
|
|
||||||
success: function(response) {
|
|
||||||
|
|
||||||
// List of BOM item objects we are interested in
|
for (var idx = 0; idx < bom_items.length; idx++) {
|
||||||
var bom_items = [];
|
var bom_item = bom_items[idx];
|
||||||
|
|
||||||
var table_entries = "";
|
table_entries += renderBomItemRow(bom_item);
|
||||||
|
}
|
||||||
|
|
||||||
for (var idx = 0; idx < response.length; idx++) {
|
if (bom_items.length == 0) {
|
||||||
var item = response[idx];
|
|
||||||
|
|
||||||
var sub_part_id = item.sub_part;
|
showAlertDialog(
|
||||||
|
'{% trans "Select Parts" %}',
|
||||||
|
'{% trans "You must select at least one part to allocate" %}',
|
||||||
|
);
|
||||||
|
|
||||||
// Check if we are interested in this item
|
return;
|
||||||
if (sub_part_ids.length > 0 && !sub_part_ids.includes(sub_part_id)) {
|
}
|
||||||
continue;
|
|
||||||
|
// Create table of parts
|
||||||
|
var html = `
|
||||||
|
<table class='table table-striped table-condensed' id='stock-allocation-table'>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans "Part" %}</th>
|
||||||
|
<th style='min-width: 250px;'>{% trans "Stock Item" %}</th>
|
||||||
|
<th>{% trans "Allocated" %}</th>
|
||||||
|
<th>{% trans "Quantity" %}</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
${table_entries}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
`;
|
||||||
|
|
||||||
|
|
||||||
|
constructForm(`/api/build/${build_id}/allocate/`, {
|
||||||
|
method: 'POST',
|
||||||
|
fields: {},
|
||||||
|
preFormContent: html,
|
||||||
|
confirm: true,
|
||||||
|
confirmMessage: '{% trans "Confirm stock allocation" %}',
|
||||||
|
title: '{% trans "Allocate Stock Items to Build Order" %}',
|
||||||
|
afterRender: function(fields, options) {
|
||||||
|
|
||||||
|
// Initialize select2 fields
|
||||||
|
bom_items.forEach(function(bom_item) {
|
||||||
|
initializeRelatedField(
|
||||||
|
{
|
||||||
|
name: `items_stock_item_${bom_item.pk}`,
|
||||||
|
api_url: '{% url "api-stock-list" %}',
|
||||||
|
filters: {
|
||||||
|
part: bom_item.sub_part,
|
||||||
|
in_stock: true,
|
||||||
|
part_detail: false,
|
||||||
|
location_detail: true,
|
||||||
|
},
|
||||||
|
model: 'stockitem',
|
||||||
|
required: true,
|
||||||
|
render_part_detail: false,
|
||||||
|
render_location_detail: true,
|
||||||
|
auto_fill: true,
|
||||||
|
noResults: function(query) {
|
||||||
|
return '{% trans "No matching stock items" %}';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add button callbacks
|
||||||
|
$(options.modal).find('.button-row-remove').click(function() {
|
||||||
|
var pk = $(this).attr('pk');
|
||||||
|
|
||||||
|
$(options.modal).find(`#allocation_row_${pk}`).remove();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onSubmit: function(fields, options) {
|
||||||
|
|
||||||
|
// Extract elements from the form
|
||||||
|
var data = {
|
||||||
|
items: []
|
||||||
|
};
|
||||||
|
|
||||||
|
var item_pk_values = [];
|
||||||
|
|
||||||
|
bom_items.forEach(function(item) {
|
||||||
|
|
||||||
|
var quantity = getFormFieldValue(
|
||||||
|
`items_quantity_${item.pk}`,
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
modal: options.modal,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
var stock_item = getFormFieldValue(
|
||||||
|
`items_stock_item_${item.pk}`,
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
modal: options.modal,
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// TODO: Ignore items which are already fully allocated
|
if (quantity != null) {
|
||||||
|
data.items.push({
|
||||||
|
bom_item: item.pk,
|
||||||
|
stock_item: stock_item,
|
||||||
|
quantity: quantity
|
||||||
|
});
|
||||||
|
|
||||||
bom_items.push(item);
|
item_pk_values.push(item.pk);
|
||||||
|
|
||||||
// Add HTML
|
|
||||||
table_entries += renderBomItemRow(item);
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (bom_items.length == 0) {
|
// Provide nested values
|
||||||
|
options.nested = {
|
||||||
|
"items": item_pk_values
|
||||||
|
};
|
||||||
|
|
||||||
showAlertDialog(
|
inventreePut(
|
||||||
'{% trans "Select Parts" %}',
|
options.url,
|
||||||
'{% trans "You must select at least one part to allocate" %}',
|
data,
|
||||||
);
|
{
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create table of parts
|
|
||||||
var html = `
|
|
||||||
<table class='table table-striped table-condensed' id='stock-allocation-table'>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>{% trans "Part" %}</th>
|
|
||||||
<th style='min-width: 250px;'>{% trans "Stock Item" %}</th>
|
|
||||||
<th>{% trans "Allocated" %}</th>
|
|
||||||
<th>{% trans "Quantity" %}</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
${table_entries}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
`;
|
|
||||||
|
|
||||||
constructForm(`/api/build/${build_id}/allocate/`, {
|
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
fields: {},
|
success: function(response) {
|
||||||
preFormContent: html,
|
// Hide the modal
|
||||||
confirm: true,
|
$(options.modal).modal('hide');
|
||||||
confirmMessage: '{% trans "Confirm stock allocation" %}',
|
|
||||||
title: '{% trans "Allocate Stock Items to Build Order" %}',
|
|
||||||
afterRender: function(fields, options) {
|
|
||||||
|
|
||||||
// Initialize select2 fields
|
if (options.success) {
|
||||||
bom_items.forEach(function(bom_item) {
|
options.success(response);
|
||||||
initializeRelatedField(
|
}
|
||||||
{
|
|
||||||
name: `items_stock_item_${bom_item.pk}`,
|
|
||||||
api_url: '{% url "api-stock-list" %}',
|
|
||||||
filters: {
|
|
||||||
part: bom_item.sub_part,
|
|
||||||
in_stock: true,
|
|
||||||
part_detail: false,
|
|
||||||
location_detail: true,
|
|
||||||
},
|
|
||||||
model: 'stockitem',
|
|
||||||
required: true,
|
|
||||||
render_part_detail: false,
|
|
||||||
render_location_detail: true,
|
|
||||||
auto_fill: true,
|
|
||||||
noResults: function(query) {
|
|
||||||
return '{% trans "No matching stock items" %}';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add button callbacks
|
|
||||||
$(options.modal).find('.button-row-remove').click(function() {
|
|
||||||
var pk = $(this).attr('pk');
|
|
||||||
|
|
||||||
$(options.modal).find(`#allocation_row_${pk}`).remove();
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
onSubmit: function(fields, options) {
|
error: function(xhr) {
|
||||||
|
switch (xhr.status) {
|
||||||
// Extract elements from the form
|
case 400:
|
||||||
var data = {
|
handleFormErrors(xhr.responseJSON, fields, options);
|
||||||
items: []
|
break;
|
||||||
};
|
default:
|
||||||
|
$(options.modal).modal('hide');
|
||||||
var item_pk_values = [];
|
showApiError(xhr);
|
||||||
|
break;
|
||||||
bom_items.forEach(function(item) {
|
}
|
||||||
|
}
|
||||||
var quantity = getFormFieldValue(
|
}
|
||||||
`items_quantity_${item.pk}`,
|
);
|
||||||
{},
|
},
|
||||||
{
|
});
|
||||||
modal: options.modal,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
var stock_item = getFormFieldValue(
|
|
||||||
`items_stock_item_${item.pk}`,
|
|
||||||
{},
|
|
||||||
{
|
|
||||||
modal: options.modal,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (quantity != null) {
|
|
||||||
data.items.push({
|
|
||||||
bom_item: item.pk,
|
|
||||||
stock_item: stock_item,
|
|
||||||
quantity: quantity
|
|
||||||
});
|
|
||||||
|
|
||||||
item_pk_values.push(item.pk);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Provide nested values
|
|
||||||
options.nested = {
|
|
||||||
"items": item_pk_values
|
|
||||||
};
|
|
||||||
|
|
||||||
inventreePut(
|
|
||||||
options.url,
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
success: function(response) {
|
|
||||||
// Hide the modal
|
|
||||||
$(options.modal).modal('hide');
|
|
||||||
|
|
||||||
if (options.success) {
|
|
||||||
options.success(response);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function(xhr) {
|
|
||||||
switch (xhr.status) {
|
|
||||||
case 400:
|
|
||||||
handleFormErrors(xhr.responseJSON, fields, options);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$(options.modal).modal('hide');
|
|
||||||
showApiError(xhr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user