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>
|
<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 class='table table-striped' id='build-table'>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@ -28,14 +32,18 @@
|
|||||||
{% block js_ready %}
|
{% block js_ready %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
|
|
||||||
makeBuildTable($('#build-table'),
|
{% for bom_item in bom_items.all %}
|
||||||
{
|
|
||||||
build: {{ build.pk }},
|
loadAllocationTable(
|
||||||
part: {{ build.part.pk }},
|
$("#allocate-table-id-{{ bom_item.sub_part.id }}"),
|
||||||
new_item_url: "{% url 'build-item-create' %}",
|
"{% 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() {
|
$("#complete-build").on('click', function() {
|
||||||
launchModalForm(
|
launchModalForm(
|
||||||
"{% url 'build-complete' build.id %}",
|
"{% url 'build-complete' build.id %}",
|
||||||
@ -45,5 +53,6 @@
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
{% endblock %}
|
{% 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'
|
context_object_name = 'build'
|
||||||
template_name = 'build/allocate.html'
|
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):
|
class BuildCreate(AjaxCreateView):
|
||||||
""" View to create a new Build object """
|
""" View to create a new Build object """
|
||||||
|
@ -72,7 +72,6 @@ class PartCreate(AjaxCreateView):
|
|||||||
def get_category_id(self):
|
def get_category_id(self):
|
||||||
return self.request.GET.get('category', None)
|
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):
|
def get_context_data(self, **kwargs):
|
||||||
""" Provide extra context information for the form to display:
|
""" Provide extra context information for the form to display:
|
||||||
|
|
||||||
|
@ -1,150 +1,21 @@
|
|||||||
function makeBuildTable(build_table, options) {
|
function loadAllocationTable(table, url, button) {
|
||||||
/* 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
// Load the allocation table
|
||||||
table.bootstrapTable({
|
table.bootstrapTable({
|
||||||
formatNoMatches: function() { return 'No parts allocated for ' + parent_row.sub_part_detail.name; },
|
url: url,
|
||||||
|
sortable: false,
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
field: 'stock_item_detail',
|
field: 'stock_item_detail',
|
||||||
title: 'Stock Item',
|
title: 'Stock Item',
|
||||||
formatter: function(value, row, index, field) {
|
formatter: function(value, row, index, field) {
|
||||||
return '' + value.quantity + ' x ' + value.part_name;
|
return '' + value.quantity + ' x ' + value.part_name + ' @ ' + value.location_name;
|
||||||
},
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'stock_item_detail.location_name',
|
|
||||||
title: 'Location',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'stock_item_detail.quantity',
|
|
||||||
title: 'Available',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'quantity',
|
field: 'quantity',
|
||||||
title: 'Allocated',
|
title: 'Allocated',
|
||||||
formatter: function(value, row, index, field) {
|
formatter: function(value, row, index, field) {
|
||||||
|
|
||||||
var html = value;
|
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>";
|
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
|
// 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