mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Rework build allocation
- Each item renders as a collapsible panel with overview data at the top
This commit is contained in:
parent
7e7ac60a1a
commit
b6becbc570
@ -9,6 +9,10 @@
|
||||
|
||||
<hr>
|
||||
|
||||
{% for bom_item in bom_items.all %}
|
||||
{% include "build/allocation_item.html" with item=bom_item build=build %}
|
||||
{% endfor %}
|
||||
|
||||
<table class='table table-striped' id='build-table'>
|
||||
</table>
|
||||
|
||||
@ -28,14 +32,18 @@
|
||||
{% block js_ready %}
|
||||
{{ block.super }}
|
||||
|
||||
makeBuildTable($('#build-table'),
|
||||
{
|
||||
build: {{ build.pk }},
|
||||
part: {{ build.part.pk }},
|
||||
new_item_url: "{% url 'build-item-create' %}",
|
||||
}
|
||||
{% for bom_item in bom_items.all %}
|
||||
|
||||
loadAllocationTable(
|
||||
$("#allocate-table-id-{{ bom_item.sub_part.id }}"),
|
||||
"{% url 'api-build-item-list' %}?build={{ build.id }}&part={{ bom_item.sub_part.id }}",
|
||||
$("#new-item-{{ bom_item.sub_part.id }}")
|
||||
);
|
||||
|
||||
{% endfor %}
|
||||
|
||||
/*
|
||||
|
||||
$("#complete-build").on('click', function() {
|
||||
launchModalForm(
|
||||
"{% url 'build-complete' build.id %}",
|
||||
@ -45,5 +53,6 @@
|
||||
}
|
||||
);
|
||||
});
|
||||
*/
|
||||
|
||||
{% endblock %}
|
24
InvenTree/build/templates/build/allocation_item.html
Normal file
24
InvenTree/build/templates/build/allocation_item.html
Normal file
@ -0,0 +1,24 @@
|
||||
<div class='panel-group'>
|
||||
<div class='panel pane-default'>
|
||||
<div class='panel panel-heading'>
|
||||
<div class='row'>
|
||||
<div class='col-sm-6'>
|
||||
<div class='panel-title'>
|
||||
<a data-toggle='collapse' href='#collapse-item-{{ item.id }}'>{{ item.sub_part.name }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class='col-sm-6'>
|
||||
<div class='btn-group' style='float: right;'>
|
||||
<button class='btn btn-success btn-sm' id='new-item-{{ item.sub_part.id }}' url="{% url 'build-item-create' %}?part={{ item.sub_part.id }}&build={{ build.id }}">Allocate Parts</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id='collapse-item-{{ item.id }}' class='panel-collapse collapse'>
|
||||
<div class='panel-body'>
|
||||
<table class='table table-striped table-condensed' id='allocate-table-id-{{ item.sub_part.id }}'>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -111,6 +111,20 @@ class BuildAllocate(DetailView):
|
||||
context_object_name = 'build'
|
||||
template_name = 'build/allocate.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
""" Provide extra context information for the Build allocation page """
|
||||
|
||||
context = super(DetailView, self).get_context_data(**kwargs)
|
||||
|
||||
build = self.get_object()
|
||||
part = build.part
|
||||
bom_items = part.bom_items
|
||||
|
||||
context['part'] = part
|
||||
context['bom_items'] = bom_items
|
||||
|
||||
return context
|
||||
|
||||
|
||||
class BuildCreate(AjaxCreateView):
|
||||
""" View to create a new Build object """
|
||||
|
@ -72,7 +72,6 @@ class PartCreate(AjaxCreateView):
|
||||
def get_category_id(self):
|
||||
return self.request.GET.get('category', None)
|
||||
|
||||
# If a category is provided in the URL, pass that to the page context
|
||||
def get_context_data(self, **kwargs):
|
||||
""" Provide extra context information for the form to display:
|
||||
|
||||
|
@ -126,53 +126,53 @@ function loadBomTable(table, options) {
|
||||
}
|
||||
else {
|
||||
cols.push(
|
||||
{
|
||||
field: 'sub_part_detail.available_stock',
|
||||
title: 'Available',
|
||||
searchable: false,
|
||||
sortable: true,
|
||||
formatter: function(value, row, index, field) {
|
||||
var text = "";
|
||||
|
||||
if (row.quantity < row.sub_part_detail.available_stock)
|
||||
{
|
||||
text = "<span class='label label-success'>" + value + "</span>";
|
||||
}
|
||||
else
|
||||
{
|
||||
text = "<span class='label label-warning'>" + value + "</span>";
|
||||
}
|
||||
|
||||
return renderLink(text, row.sub_part.url + "stock/");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Part notes
|
||||
cols.push(
|
||||
{
|
||||
field: 'note',
|
||||
title: 'Notes',
|
||||
searchable: true,
|
||||
sortable: false,
|
||||
}
|
||||
);
|
||||
|
||||
// Configure the table (bootstrap-table)
|
||||
|
||||
table.bootstrapTable({
|
||||
{
|
||||
field: 'sub_part_detail.available_stock',
|
||||
title: 'Available',
|
||||
searchable: false,
|
||||
sortable: true,
|
||||
search: true,
|
||||
clickToSelect: true,
|
||||
queryParams: function(p) {
|
||||
return {
|
||||
part: options.parent_id,
|
||||
formatter: function(value, row, index, field) {
|
||||
var text = "";
|
||||
|
||||
if (row.quantity < row.sub_part_detail.available_stock)
|
||||
{
|
||||
text = "<span class='label label-success'>" + value + "</span>";
|
||||
}
|
||||
else
|
||||
{
|
||||
text = "<span class='label label-warning'>" + value + "</span>";
|
||||
}
|
||||
|
||||
return renderLink(text, row.sub_part.url + "stock/");
|
||||
}
|
||||
},
|
||||
columns: cols,
|
||||
url: options.bom_url
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Part notes
|
||||
cols.push(
|
||||
{
|
||||
field: 'note',
|
||||
title: 'Notes',
|
||||
searchable: true,
|
||||
sortable: false,
|
||||
}
|
||||
);
|
||||
|
||||
// Configure the table (bootstrap-table)
|
||||
|
||||
table.bootstrapTable({
|
||||
sortable: true,
|
||||
search: true,
|
||||
clickToSelect: true,
|
||||
queryParams: function(p) {
|
||||
return {
|
||||
part: options.parent_id,
|
||||
}
|
||||
},
|
||||
columns: cols,
|
||||
url: options.bom_url
|
||||
});
|
||||
|
||||
// In editing mode, attached editables to the appropriate table elements
|
||||
if (options.editable) {
|
||||
|
@ -1,150 +1,21 @@
|
||||
function makeBuildTable(build_table, options) {
|
||||
/* Construct a table for allocation items to a build.
|
||||
* Each row contains a sub_part for the BOM.
|
||||
* Each row can be expended to allocate stock items against that part.
|
||||
*
|
||||
* options:
|
||||
* build - ID of the build object
|
||||
* part - ID of the part object for the build
|
||||
* new_item_url - URL to create a new BuildItem
|
||||
*
|
||||
*/
|
||||
|
||||
build_table.bootstrapTable({
|
||||
sortable: false,
|
||||
detailView: true,
|
||||
showHeader: false,
|
||||
detailFormatter: function(index, row, element) {
|
||||
return makeAllocationTable({
|
||||
part: row.pk
|
||||
});
|
||||
},
|
||||
onExpandRow: function(index, row, $detail) {
|
||||
fillAllocationTable(
|
||||
$("#part-table-" + row.pk),
|
||||
index,
|
||||
row,
|
||||
{
|
||||
build: options.build
|
||||
},
|
||||
);
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
field: 'pk',
|
||||
title: 'ID',
|
||||
visible: false,
|
||||
},
|
||||
{
|
||||
field: 'sub_part_detail.name',
|
||||
title: 'Part',
|
||||
formatter: function(value, row, index, field) {
|
||||
return renderLink(value, row.sub_part_detail.url);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'allocated',
|
||||
title: 'Allocated to Build',
|
||||
formatter: function(value, row, index, field) {
|
||||
var html = "Allocated ";
|
||||
|
||||
var url = options.new_item_url;
|
||||
|
||||
url += "?build=" + options.build + "&part=" + row.sub_part;
|
||||
|
||||
if (value) {
|
||||
html += value;
|
||||
} else {
|
||||
html += "0";
|
||||
}
|
||||
|
||||
html += " of ";
|
||||
html += row.quantity;
|
||||
|
||||
html += "<div class='btn-group' style='float: right;'>";
|
||||
|
||||
html += "<button class='btn btn-success btn-sm new-item-button' type='button' url='" + url + "'>Allocate Parts</button>";
|
||||
|
||||
html += "</div>";
|
||||
|
||||
return html;
|
||||
}
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
getBomList(
|
||||
{
|
||||
part: options.part
|
||||
}).then(function(response) {
|
||||
build_table.bootstrapTable('load', response);
|
||||
});
|
||||
|
||||
// Button callbacks
|
||||
build_table.on('click', '.new-item-button', function() {
|
||||
var button = $(this);
|
||||
|
||||
launchModalForm(button.attr('url'), {
|
||||
success: function() {
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function makeAllocationTable(options) {
|
||||
/* Construct an allocation table for a single row
|
||||
* in the Build table.
|
||||
* Each allocation table is a 'detailView' of a parent Part row
|
||||
*
|
||||
* Options:
|
||||
* part: Primary key of the part item
|
||||
*/
|
||||
|
||||
var table = "<table class='table table-striped table-condensed' ";
|
||||
|
||||
table += "id ='part-table-" + options.part + "' part-id='" + options.part + "'>";
|
||||
table += "</table>";
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
function fillAllocationTable(table, index, parent_row, options) {
|
||||
/* Load data into an allocation table,
|
||||
* and update the total stock allocation count in the parent row.
|
||||
*
|
||||
* table - the part allocation table
|
||||
* index - row index in the parent table
|
||||
* parent_row - parent row data in the build allocation table
|
||||
* parent_table - the parent build table
|
||||
*
|
||||
* options:
|
||||
* build - pk of the Build object
|
||||
*/
|
||||
|
||||
function loadAllocationTable(table, url, button) {
|
||||
|
||||
// Load the allocation table
|
||||
table.bootstrapTable({
|
||||
formatNoMatches: function() { return 'No parts allocated for ' + parent_row.sub_part_detail.name; },
|
||||
url: url,
|
||||
sortable: false,
|
||||
columns: [
|
||||
{
|
||||
field: 'stock_item_detail',
|
||||
title: 'Stock Item',
|
||||
formatter: function(value, row, index, field) {
|
||||
return '' + value.quantity + ' x ' + value.part_name;
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'stock_item_detail.location_name',
|
||||
title: 'Location',
|
||||
},
|
||||
{
|
||||
field: 'stock_item_detail.quantity',
|
||||
title: 'Available',
|
||||
return '' + value.quantity + ' x ' + value.part_name + ' @ ' + value.location_name;
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'quantity',
|
||||
title: 'Allocated',
|
||||
formatter: function(value, row, index, field) {
|
||||
|
||||
var html = value;
|
||||
|
||||
var bEdit = "<button class='btn btn-success item-edit-button btn-sm' type='button' url='/build/item/" + row.pk + "/edit/'>Edit</button>";
|
||||
@ -156,7 +27,15 @@ function fillAllocationTable(table, index, parent_row, options) {
|
||||
}
|
||||
}
|
||||
],
|
||||
url: "/api/build/item?build=" + options.build + "&part=" + parent_row.sub_part,
|
||||
});
|
||||
|
||||
// Callback for 'new-item' button
|
||||
button.click(function() {
|
||||
launchModalForm(button.attr('url'), {
|
||||
success: function() {
|
||||
table.bootstrapTable('refresh');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Button callbacks for editing and deleting the allocations
|
||||
@ -180,24 +59,4 @@ function fillAllocationTable(table, index, parent_row, options) {
|
||||
});
|
||||
});
|
||||
|
||||
table.on('load-success.bs.table', function(data) {
|
||||
var allocated = 0;
|
||||
|
||||
var allocationData = table.bootstrapTable('getData');
|
||||
|
||||
// Calculate total allocation
|
||||
for (var i = 0; i < allocationData.length; i++) {
|
||||
allocated += allocationData[i].quantity;
|
||||
}
|
||||
|
||||
// Update the parent_row data
|
||||
parent_row.quantity = allocated;
|
||||
|
||||
/*parent_table.bootstrapTable('updateRow',
|
||||
{
|
||||
index: index,
|
||||
row: parent_row
|
||||
}
|
||||
);*/
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue
Block a user