340 lines
8.8 KiB
JavaScript
340 lines
8.8 KiB
JavaScript
/* 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 += "<table class='table table-striped table-condensed' id='stocktake-table'>\n";
|
|
|
|
html += '<thead><tr>';
|
|
html += '<th>Item</th>';
|
|
html += '<th>Location</th>';
|
|
html += '<th>Quantity</th>';
|
|
|
|
html += '</thead><tbody>';
|
|
|
|
for (idx=0; idx<items.length; idx++) {
|
|
var item = items[idx];
|
|
|
|
var vMin = 0;
|
|
var vMax = 0;
|
|
var vCur = item.quantity;
|
|
|
|
if (options.action == 'remove') {
|
|
vCur = 0;
|
|
vMax = item.quantity;
|
|
}
|
|
else if (options.action == 'add') {
|
|
vCur = 0;
|
|
vMax = 0;
|
|
}
|
|
|
|
html += '<tr>';
|
|
|
|
html += '<td>' + item.part.name + '</td>';
|
|
html += '<td>' + item.location.name + '</td>';
|
|
html += "<td><input class='form-control' ";
|
|
html += "value='" + vCur + "' ";
|
|
html += "min='" + vMin + "' ";
|
|
|
|
if (vMax > 0) {
|
|
html += "max='" + vMax + "' ";
|
|
}
|
|
|
|
html += "type='number' id='q-" + item.pk + "'/></td>";
|
|
|
|
html += '</tr>';
|
|
}
|
|
|
|
html += '</tbody></table>';
|
|
|
|
html += "<hr><input type='text' id='stocktake-notes' placeholder='Notes'/>";
|
|
|
|
html += "<p class='warning-msg' id='note-warning'><i>Note field must be filled</i></p>";
|
|
|
|
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).find('#note-warning').hide();
|
|
|
|
modalSubmit(modal, function() {
|
|
|
|
var stocktake = [];
|
|
var notes = $(modal).find('#stocktake-notes').val();
|
|
|
|
if (!notes) {
|
|
$(modal).find('#note-warning').show();
|
|
return false;
|
|
}
|
|
|
|
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()
|
|
},
|
|
{
|
|
method: 'post',
|
|
}).then(function(response) {
|
|
closeModal(modal);
|
|
if (options.success) {
|
|
options.success();
|
|
}
|
|
}).fail(function(xhr, status, error) {
|
|
alert(error);
|
|
});
|
|
});
|
|
}
|
|
|
|
function adjustStock(options) {
|
|
if (options.items) {
|
|
updateStock(options.items, options);
|
|
}
|
|
else {
|
|
// Lookup of individual item
|
|
if (options.query.pk) {
|
|
getStockDetail(options.query.pk).then(function(response) {
|
|
updateStock([response], options);
|
|
});
|
|
}
|
|
else {
|
|
getStockList(options.query).then(function(response) {
|
|
updateStock(response, options);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
function moveStockItems(items, options) {
|
|
|
|
var modal = options.modal || '#modal-form';
|
|
|
|
if (items.length == 0) {
|
|
alert('No stock items selected');
|
|
return;
|
|
}
|
|
|
|
function doMove(location, parts) {
|
|
inventreeUpdate("/api/stock/move/",
|
|
{
|
|
location: location,
|
|
'parts[]': parts
|
|
},
|
|
{
|
|
success: function(response) {
|
|
closeModal(modal);
|
|
if (options.success) {
|
|
options.success();
|
|
}
|
|
},
|
|
error: function(error) {
|
|
alert('error!:\n' + error);
|
|
},
|
|
method: 'post'
|
|
});
|
|
}
|
|
|
|
getStockLocations({},
|
|
{
|
|
success: function(response) {
|
|
openModal({
|
|
modal: modal,
|
|
title: "Move " + items.length + " stock items",
|
|
submit_text: "Move"
|
|
});
|
|
|
|
// Extact part row info
|
|
var parts = [];
|
|
|
|
var html = "Select new location:<br>\n";
|
|
|
|
html += "<select class='select' id='stock-location'>";
|
|
|
|
for (i = 0; i < response.length; i++) {
|
|
var loc = response[i];
|
|
|
|
html += makeOption(loc.pk, loc.name + ' - <i>' + loc.description + '</i>');
|
|
}
|
|
|
|
html += "</select><br><hr>";
|
|
|
|
html += "The following stock items will be moved:<br><ul class='list-group'>\n";
|
|
|
|
for (i = 0; i < items.length; i++) {
|
|
parts.push(items[i].pk);
|
|
|
|
html += "<li class='list-group-item'>" + items[i].quantity + " × " + items[i].part.name;
|
|
|
|
if (items[i].location) {
|
|
html += " (" + items[i].location.name + ")";
|
|
}
|
|
|
|
html += "</li>\n";
|
|
}
|
|
|
|
html += "</ul>\n";
|
|
|
|
modalSetContent(modal, html);
|
|
attachSelect(modal);
|
|
|
|
modalSubmit(modal, function() {
|
|
var locId = $(modal).find("#stock-location").val();
|
|
|
|
doMove(locId, parts);
|
|
});
|
|
},
|
|
error: function(error) {
|
|
alert('Error getting stock locations:\n' + error.error);
|
|
}
|
|
});
|
|
}
|
|
|
|
function deleteStockItems(items, options) {
|
|
|
|
var modal = '#modal-delete';
|
|
|
|
if ('modal' in options) {
|
|
modal = options.modal;
|
|
}
|
|
|
|
if (items.length == 0) {
|
|
alert('No stock items selected');
|
|
return;
|
|
}
|
|
|
|
function doDelete(parts) {
|
|
//TODO
|
|
}
|
|
|
|
openModal({
|
|
modal: modal,
|
|
title: 'Delete ' + items.length + ' stock items'
|
|
});
|
|
}
|
|
|
|
|
|
function loadStockTable(modal, options) {
|
|
modal.bootstrapTable({
|
|
sortable: true,
|
|
search: true,
|
|
method: 'get',
|
|
pagination: true,
|
|
rememberOrder: true,
|
|
queryParams: options.params,
|
|
columns: [
|
|
{
|
|
checkbox: true,
|
|
title: 'Select',
|
|
searchable: false,
|
|
},
|
|
{
|
|
field: 'pk',
|
|
title: 'ID',
|
|
visible: false,
|
|
},
|
|
{
|
|
field: 'part.name',
|
|
title: 'Part',
|
|
sortable: true,
|
|
formatter: function(value, row, index, field) {
|
|
return renderLink(value, row.part.url);
|
|
}
|
|
},
|
|
{
|
|
field: 'location',
|
|
title: 'Location',
|
|
sortable: true,
|
|
formatter: function(value, row, index, field) {
|
|
if (row.location) {
|
|
return renderLink(row.location.pathstring, row.location.url);
|
|
}
|
|
else {
|
|
return '';
|
|
}
|
|
}
|
|
},
|
|
{
|
|
field: 'quantity',
|
|
title: 'Quantity',
|
|
sortable: true,
|
|
formatter: function(value, row, index, field) {
|
|
var text = renderLink(value, row.url);
|
|
text = text + "<span class='badge'>" + row.status + "</span>";
|
|
return text;
|
|
}
|
|
},
|
|
{
|
|
field: 'notes',
|
|
title: 'Notes',
|
|
}
|
|
],
|
|
url: options.url,
|
|
});
|
|
}; |