Further work on build output scripts

This commit is contained in:
Oliver 2021-10-17 11:25:53 +11:00
parent 283bf1682f
commit 9d2273c1cd
5 changed files with 60 additions and 319 deletions

View File

@ -153,8 +153,8 @@ src="{% static 'img/blank_image.png' %}"
</tr>
{% endif %}
<tr>
<td><span class='fas fa-spinner'></span></td>
<td>{% trans "Progress" %}</td>
<td><span class='fas fa-check-circle'></span></td>
<td>{% trans "Completed" %}</td>
<td> {{ build.completed }} / {{ build.quantity }}</td>
</tr>
{% if build.parent %}

View File

@ -63,10 +63,17 @@
<td>{% build_status_label build.status %}</td>
</tr>
<tr>
<td><span class='fas fa-spinner'></span></td>
<td>{% trans "Progress" %}</td>
<td><span class='fas fa-check-circle'></span></td>
<td>{% trans "Completed" %}</td>
<td>{{ build.completed }} / {{ build.quantity }}</td>
</tr>
{% if True or build.active and build.has_untracked_bom_items %}
<tr>
<td><span class='fas fa-list'></span></td>
<td>{% trans "Allocated Parts" %}</td>
<td id='output-progress-untracked'><span class='fas fa-spinner fa-spin'></span></td>
</tr>
{% endif %}
{% if build.batch %}
<tr>
<td><span class='fas fa-layer-group'></span></td>
@ -237,13 +244,6 @@
</div>
</div>
</div>
<div class="panel-group" id="build-output-accordion" role="tablist" aria-multiselectable="true">
{% for item in build.incomplete_outputs %}
{% include "build/allocation_card.html" with item=item tracked_items=build.has_tracked_bom_items %}
{% endfor %}
</div>
<table class='table table-striped table-condensed' id='build-output-table' data-toolbar='#build-output-toolbar'></table>
</div>
</div>
@ -371,23 +371,11 @@ inventreeGet(
});
{% endif %}
{% for item in build.incomplete_outputs %}
// Get the build output as a javascript object
inventreeGet('{% url 'api-stock-detail' item.pk %}', {},
{
success: function(response) {
loadBuildOutputAllocationTable(build_info, response);
}
}
);
{% endfor %}
{% if build.has_untracked_bom_items %}
{% if build.active and build.has_untracked_bom_items %}
// Load allocation table for un-tracked parts
loadBuildOutputAllocationTable(build_info, null);
{% endif %}
}
}
);

View File

@ -19,25 +19,25 @@
{% if build.active %}
<li class='list-group-item' title='{% trans "Allocate Stock" %}'>
<a href='#' id='select-allocate' class='nav-toggle'>
<span class='fas fa-tools sidebar-icon'></span>
<span class='fas fa-tasks sidebar-icon'></span>
{% trans "Allocate Stock" %}
</a>
</li>
{% endif %}
{% if not build.is_complete %}
<li class='list-group-item' title='{% trans "In Progress Items" %}'>
<li class='list-group-item' title='{% trans "Pending Outputs" %}'>
<a href='#' id='select-outputs' class='nav-toggle'>
<span class='fas fa-tasks sidebar-icon'></span>
{% trans "In Progress Items" %}
<span class='fas fa-tools sidebar-icon'></span>
{% trans "Pending Outputs" %}
</a>
</li>
{% endif %}
<li class='list-group-item' title='{% trans "Completed Items" %}'>
<li class='list-group-item' title='{% trans "Completed Outputs" %}'>
<a href='#' id='select-completed' class='nav-toggle'>
<span class='fas fa-boxes sidebar-icon'></span>
{% trans "Completed Items" %}
{% trans "Completed Outputs" %}
</a>
</li>

View File

@ -143,7 +143,6 @@
<!-- general InvenTree -->
<script type='text/javascript' src="{% static 'script/inventree/notification.js' %}"></script>
<script type='text/javascript' src="{% static 'script/inventree/sidenav.js' %}"></script>
<!-- dynamic javascript templates -->
<script type='text/javascript' src="{% url 'inventree.js' %}"></script>

View File

@ -24,7 +24,6 @@
loadAllocationTable,
loadBuildOrderAllocationTable,
loadBuildOutputAllocationTable,
loadBuildPartsTable,
loadBuildTable,
*/
@ -243,21 +242,6 @@ function makeBuildOutputActionButtons(output, buildInfo, lines) {
);
});
$(panel).find(`#button-output-complete-${outputId}`).click(function() {
var pk = $(this).attr('pk');
launchModalForm(
`/build/${buildId}/complete-output/`,
{
data: {
output: pk,
},
reload: true,
}
);
});
$(panel).find(`#button-output-unallocate-${outputId}`).click(function() {
var pk = $(this).attr('pk');
@ -459,14 +443,13 @@ function completeBuildOutputs(build_id, outputs, options={}) {
)
}
});
}
/**
* Load a table showing all the BuildOrder allocations for a given part
*/
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;
@ -566,9 +549,12 @@ function loadBuildOutputTable(build_info, options={}) {
// Construct a list of "tracked" BOM items
var tracked_bom_items = [];
var has_tracked_items = false;
build_info.bom_items.forEach(function(bom_item) {
if (bom_item.sub_part_detail.trackable) {
tracked_bom_items.push(bom_item);
has_tracked_items = true;
};
});
@ -659,83 +645,26 @@ function loadBuildOutputTable(build_info, options={}) {
element.html(html);
var todo = "refactor the following fields, they are shared with the 'untracked' allocation table!";
$(`#${sub_table_id}`).bootstrapTable({
data: tracked_bom_items,
showHeader: true,
columns: [
{
field: 'part',
title: '{% trans "Required Part" %}',
formatter: function(value, row) {
var part = row.sub_part_detail;
var url = `/part/${part.pk}/`;
var thumb = part.thumbnail || row.image;
var name = part.full_name;
var html = imageHoverIcon(thumb) + renderLink(name, url) + makePartIcons(part);
if (row.substitutes && row.substitutes.length > 0) {
html += makeIconBadge('fa-exchange-alt', '{% trans "Substitute parts available" %}');
}
if (row.allow_variants) {
html += makeIconBadge('fa-sitemap', '{% trans "Variant stock allowed" %}');
}
return html;
}
},
{
field: 'reference',
title: '{% trans "Reference" %}',
sortable: true,
},
{
field: 'quantity',
title: '{% trans "Quantity Per Item" %}',
sortable: true,
},
{
field: 'allocated',
title: '{% trans "Allocated" %}',
formatter: function(value, row) {
// Render a "progress" row
return "todo";
}
},
{
field: 'actions',
title: '',
formatter: function(value, row) {
var html = `<div class='btn-group float-right' role='group'>`;
html += "todo";
html += `</div>`;
return html;
}
}
]
});
loadBuildOutputAllocationTable(
build_info,
row,
{
table: `#${sub_table_id}`,
}
);
}
$(table).inventreeTable({
url: '{% url "api-stock-list" %}',
queryParams: filters,
original: params,
showColumns: true,
showColumns: false,
uniqueId: 'pk',
name: 'build-outputs',
sortable: true,
search: true,
search: false,
sidePagination: 'server',
detailViewAlign: 'right',
detailView: build_info.tracked_parts || false,
detailView: has_tracked_items,
detailViewByClick: true,
detailFilter: function(index, row) {
return true;
@ -749,6 +678,9 @@ function loadBuildOutputTable(build_info, options={}) {
onPostBody: function() {
// Add callbacks for the buttons
setupBuildOutputButtonCallbacks();
$(table).bootstrapTable('expandAllRows');
// $(table).bootstrapTable('collapseAllRows');
},
columns: [
{
@ -786,14 +718,16 @@ function loadBuildOutputTable(build_info, options={}) {
},
{
field: 'allocated',
title: '{% trans "Allocated" %}',
title: '{% trans "Allocated Parts" %}',
visible: has_tracked_items,
formatter: function(value, row) {
return "TODO";
return `<div id='output-progress-${row.pk}'><span class='fas fa-spin fa-spinner'></span></div>`;
}
},
{
field: 'actions',
title: '',
switchable: false,
formatter: function(value, row) {
return makeBuildOutputButtons(
row.pk,
@ -986,6 +920,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
},
name: 'build-allocation',
uniqueId: 'sub_part',
search: options.search || false,
onPostBody: setupCallbacks,
onLoadSuccess: function(tableData) {
// Once the BOM data are loaded, request allocation data for this build output
@ -1062,23 +997,27 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) {
$(table).bootstrapTable('updateByUniqueId', key, tableRow, true);
}
// Update the total progress for this build output
var buildProgress = $(`#allocation-panel-${outputId}`).find($(`#output-progress-${outputId}`));
// Update the progress bar for this build output
var build_progress = $(`#output-progress-${outputId}`);
if (totalLines > 0) {
if (build_progress.exists()) {
if (totalLines > 0) {
var progress = makeProgressBar(
allocatedLines,
totalLines
);
buildProgress.html(progress);
var progress = makeProgressBar(
allocatedLines,
totalLines
);
build_progress.html(progress);
} else {
build_progress.html('');
}
} else {
buildProgress.html('');
console.log(`WARNING: Could not find progress bar for output ${outputId}`);
}
// Update the available actions for this build output
makeBuildOutputActionButtons(output, buildInfo, totalLines);
}
}
@ -1650,9 +1589,10 @@ function allocateStockToBuild(build_id, part_id, bom_items, options={}) {
}
/*
* Display a table of Build orders
*/
function loadBuildTable(table, options) {
// Display a table of Build objects
var params = options.params || {};
@ -1919,190 +1859,4 @@ function loadAllocationTable(table, part_id, part, url, required, button) {
}
});
});
}
function loadBuildPartsTable(table, options={}) {
/**
* Display a "required parts" table for build view.
*
* This is a simplified BOM view:
* - Does not display sub-bom items
* - Does not allow editing of BOM items
*
* Options:
*
* part: Part ID
* build: Build ID
* build_quantity: Total build quantity
* build_remaining: Number of items remaining
*/
// Query params
var params = {
sub_part_detail: true,
part: options.part,
};
var filters = {};
if (!options.disableFilters) {
filters = loadTableFilters('bom');
}
setupFilterList('bom', $(table));
for (var key in params) {
filters[key] = params[key];
}
function setupTableCallbacks() {
// Register button callbacks once the table data are loaded
// Callback for 'buy' button
$(table).find('.button-buy').click(function() {
var pk = $(this).attr('pk');
launchModalForm('{% url "order-parts" %}', {
data: {
parts: [
pk,
]
}
});
});
// Callback for 'build' button
$(table).find('.button-build').click(function() {
var pk = $(this).attr('pk');
newBuildOrder({
part: pk,
parent: options.build,
});
});
}
var columns = [
{
field: 'sub_part',
title: '{% trans "Part" %}',
switchable: false,
sortable: true,
formatter: function(value, row) {
var url = `/part/${row.sub_part}/`;
var html = imageHoverIcon(row.sub_part_detail.thumbnail) + renderLink(row.sub_part_detail.full_name, url);
var sub_part = row.sub_part_detail;
html += makePartIcons(row.sub_part_detail);
// Display an extra icon if this part is an assembly
if (sub_part.assembly) {
var text = `<span title='{% trans "Open subassembly" %}' class='fas fa-stream label-right'></span>`;
html += renderLink(text, `/part/${row.sub_part}/bom/`);
}
return html;
}
},
{
field: 'sub_part_detail.description',
title: '{% trans "Description" %}',
},
{
field: 'reference',
title: '{% trans "Reference" %}',
searchable: true,
sortable: true,
},
{
field: 'quantity',
title: '{% trans "Quantity" %}',
sortable: true
},
{
sortable: true,
switchable: false,
field: 'sub_part_detail.stock',
title: '{% trans "Available" %}',
formatter: function(value, row) {
return makeProgressBar(
value,
row.quantity * options.build_remaining,
{
id: `part-progress-${row.part}`
}
);
},
sorter: function(valA, valB, rowA, rowB) {
if (rowA.received == 0 && rowB.received == 0) {
return (rowA.quantity > rowB.quantity) ? 1 : -1;
}
var progressA = parseFloat(rowA.sub_part_detail.stock) / (rowA.quantity * options.build_remaining);
var progressB = parseFloat(rowB.sub_part_detail.stock) / (rowB.quantity * options.build_remaining);
return (progressA < progressB) ? 1 : -1;
}
},
{
field: 'actions',
title: '{% trans "Actions" %}',
switchable: false,
formatter: function(value, row) {
// Generate action buttons against the part
var html = `<div class='btn-group float-right' role='group'>`;
if (row.sub_part_detail.assembly) {
html += makeIconButton('fa-tools icon-blue', 'button-build', row.sub_part, '{% trans "Build stock" %}');
}
if (row.sub_part_detail.purchaseable) {
html += makeIconButton('fa-shopping-cart icon-blue', 'button-buy', row.sub_part, '{% trans "Order stock" %}');
}
html += `</div>`;
return html;
}
}
];
table.inventreeTable({
url: '{% url "api-bom-list" %}',
showColumns: true,
name: 'build-parts',
sortable: true,
search: true,
onPostBody: setupTableCallbacks,
rowStyle: function(row) {
var classes = [];
// Shade rows differently if they are for different parent parts
if (row.part != options.part) {
classes.push('rowinherited');
}
if (row.validated) {
classes.push('rowvalid');
} else {
classes.push('rowinvalid');
}
return {
classes: classes.join(' '),
};
},
formatNoMatches: function() {
return '{% trans "No BOM items found" %}';
},
clickToSelect: true,
queryParams: filters,
original: params,
columns: columns,
});
}