From b6becbc5700c8f2ddadf3c6e69fb5eabe15b464c Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 1 May 2019 07:48:46 +1000 Subject: [PATCH] Rework build allocation - Each item renders as a collapsible panel with overview data at the top --- InvenTree/build/templates/build/allocate.html | 21 ++- .../templates/build/allocation_item.html | 24 +++ InvenTree/build/views.py | 14 ++ InvenTree/part/views.py | 1 - InvenTree/static/script/inventree/bom.js | 90 ++++----- InvenTree/static/script/inventree/build.js | 173 ++---------------- 6 files changed, 114 insertions(+), 209 deletions(-) create mode 100644 InvenTree/build/templates/build/allocation_item.html diff --git a/InvenTree/build/templates/build/allocate.html b/InvenTree/build/templates/build/allocate.html index ea33932d87..1b52a5a144 100644 --- a/InvenTree/build/templates/build/allocate.html +++ b/InvenTree/build/templates/build/allocate.html @@ -9,6 +9,10 @@
+{% for bom_item in bom_items.all %} +{% include "build/allocation_item.html" with item=bom_item build=build %} +{% endfor %} +
@@ -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 %} \ No newline at end of file diff --git a/InvenTree/build/templates/build/allocation_item.html b/InvenTree/build/templates/build/allocation_item.html new file mode 100644 index 0000000000..271ae94e3a --- /dev/null +++ b/InvenTree/build/templates/build/allocation_item.html @@ -0,0 +1,24 @@ +
+
+
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+
+
+
\ No newline at end of file diff --git a/InvenTree/build/views.py b/InvenTree/build/views.py index 31e25c017f..e23166322d 100644 --- a/InvenTree/build/views.py +++ b/InvenTree/build/views.py @@ -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 """ diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index a00e8f8e63..5adeafe500 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -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: diff --git a/InvenTree/static/script/inventree/bom.js b/InvenTree/static/script/inventree/bom.js index 1107c5986a..1b58b81a93 100644 --- a/InvenTree/static/script/inventree/bom.js +++ b/InvenTree/static/script/inventree/bom.js @@ -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 = "" + value + ""; - } - else - { - text = "" + value + ""; - } - - 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 = "" + value + ""; + } + else + { + text = "" + value + ""; + } + + 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) { diff --git a/InvenTree/static/script/inventree/build.js b/InvenTree/static/script/inventree/build.js index f5c41e7662..1ffc9fe1e5 100644 --- a/InvenTree/static/script/inventree/build.js +++ b/InvenTree/static/script/inventree/build.js @@ -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 += "
"; - - html += ""; - - html += "
"; - - 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 += "
"; - - 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 = ""; @@ -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 - } - );*/ - }); } \ No newline at end of file