From 25e0de1ce78fe43a30800f4e8e35d8a64b048ddf Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 8 May 2018 22:06:28 +1000 Subject: [PATCH] Vast improvements to stocktake API endpoint - Also acts to ADD and REMOVE stock - Send 'action' field to specify which one to perform - Fixed add_stock and remove_stock funcs for StockItem model - Autoatically add transaction notes for all actions --- InvenTree/static/css/inventree.css | 4 + InvenTree/static/script/inventree/api.js | 8 - InvenTree/static/script/inventree/stock.js | 270 ++++++++++++++------- InvenTree/stock/api.py | 33 ++- InvenTree/stock/models.py | 47 ++-- 5 files changed, 252 insertions(+), 110 deletions(-) diff --git a/InvenTree/static/css/inventree.css b/InvenTree/static/css/inventree.css index 1a618945eb..cadb012959 100644 --- a/InvenTree/static/css/inventree.css +++ b/InvenTree/static/css/inventree.css @@ -124,4 +124,8 @@ .float-right { float: right; +} + +.warning-msg { + color: #e00; } \ No newline at end of file diff --git a/InvenTree/static/script/inventree/api.js b/InvenTree/static/script/inventree/api.js index c9b593f3b1..b45951ed03 100644 --- a/InvenTree/static/script/inventree/api.js +++ b/InvenTree/static/script/inventree/api.js @@ -95,14 +95,6 @@ function getPartCategories(filters={}, options={}) { return inventreeGet('/api/part/category/', filters, options); } -function getStock(filters={}, options={}) { - return inventreeGet('/api/stock/', filters, options); -} - -function getStockLocations(filters={}, options={}) { - return inventreeGet('/api/stock/location/', filters, options) -} - function getCompanies(filters={}, options={}) { return inventreeGet('/api/company/', filters, options); } diff --git a/InvenTree/static/script/inventree/stock.js b/InvenTree/static/script/inventree/stock.js index 56f457b53e..d984f075b6 100644 --- a/InvenTree/static/script/inventree/stock.js +++ b/InvenTree/static/script/inventree/stock.js @@ -1,11 +1,180 @@ +/* Stock API functions + * Requires api.js to be loaded first + */ + +function getStockList(filters={}, options={}) { + return inventreeGet('/api/stock/', filters, options); +} + +function getStockDetail(pk, options={}) { + return inventreeGet('/api/stock/' + pk + '/', {}, options) +} + +function getStockLocations(filters={}, options={}) { + return inventreeGet('/api/stock/location/', filters, options) +} + + +/* Present user with a dialog to update multiple stock items + * Possible actions: + * - Stocktake + * - Take stock + * - Add stock + */ +function updateStock(items, options={}) { + + if (!options.action) { + alert('No action supplied to stock update'); + return false; + } + + var modal = options.modal || '#modal-form'; + + if (items.length == 0) { + alert('No items selected'); + return; + } + + var html = ''; + + html += "\n"; + + html += ''; + html += ''; + html += ''; + html += ''; + + html += ''; + + for (idx=0; idx'; + html += ''; + html += ""; + + html += ''; + } + + html += '
ItemLocationQuantity
' + item.location.name + ' 0) { + html += "max='" + vMax + "' "; + } + + html += "type='number' id='q-" + item.pk + "'/>
'; + + html += "
"; + + html += "

Note field must be filled

"; + + var title = ''; + + if (options.action == 'stocktake') { + title = 'Stocktake'; + } + else if (options.action == 'remove') { + title = 'Remove stock items'; + } + else if (options.action == 'add') { + title = 'Add stock items'; + } + + openModal({ + modal: modal, + title: title, + content: html + }); + + $(modal).on('click', '#modal-form-submit', function() { + + var stocktake = []; + + var valid = true; + + // Form stocktake data + for (idx = 0; idx < items.length; idx++) { + var item = items[idx]; + + var q = $(modal).find("#q-" + item.pk).val(); + + stocktake.push({ + pk: item.pk, + quantity: q + }); + }; + + if (!valid) { + alert('Invalid data'); + return false; + } + + inventreeUpdate("/api/stock/stocktake/", + { + 'action': options.action, + 'items[]': stocktake, + 'notes': $(modal).find('#stocktake-notes').val() + }, + { + success: function(response) { + closeModal(modal); + if (options.success) { + options.success(); + } + }, + error: function(error) { + alert(error); + }, + method: 'post' + } + ); + }); +} + +function adjustStock(options) { + if (options.items) { + updateStock(options.items, options); + } + else { + // Lookup of individual item + if (options.query.pk) { + getStockDetail(options.query.pk, + { + success: function(response) { + updateStock([response], options); + } + }); + } + else { + getStockList(options.query, + { + success: function(response) { + updateStock(response, options); + } + }); + } + } +} function moveStockItems(items, options) { - var modal = '#modal-form'; - - if ('modal' in options) { - modal = options.modal; - } + var modal = options.modal || '#modal-form'; if (items.length == 0) { alert('No stock items selected'); @@ -35,9 +204,11 @@ function moveStockItems(items, options) { getStockLocations({}, { success: function(response) { - openModal(modal); - modalSetTitle(modal, "Move " + items.length + " stock items"); - modalSetButtonText(modal, "Move"); + openModal({ + modal: modal, + title: "Move " + items.length + " stock items", + buttonText: "Move" + }); // Extact part row info var parts = []; @@ -85,83 +256,6 @@ function moveStockItems(items, options) { }); } -function countStockItems(items, options) { - var modal = '#modal-form'; - - if ('modal' in options) { - modal = options.modal; - } - - if (items.length == 0) { - alert('No stock items selected'); - return; - } - - var tbl = "
"; - - openModal(modal); - modalSetTitle(modal, 'Stocktake ' + items.length + ' items'); - - $(modal).find('.modal-form-content').html(tbl); - - $(modal).find('#stocktake-table').bootstrapTable({ - data: items, - columns: [ - { - checkbox: true, - }, - { - field: 'part.name', - title: 'Part', - }, - { - field: 'location.name', - title: 'Location', - }, - { - field: 'quantity', - title: 'Quantity', - } - ] - }); - - $(modal).find('#stocktake-table').bootstrapTable('checkAll'); - - $(modal).on('click', '#modal-form-submit', function() { - var selections = $(modal).find('#stocktake-table').bootstrapTable('getSelections'); - - var stocktake = []; - - console.log('Performing stocktake on ' + selections.length + ' items'); - - for (i = 0; i