mirror of
https://github.com/inventree/InvenTree.git
synced 2025-05-03 05:48:47 +00:00
Refactorin'
This commit is contained in:
parent
14ab1bef14
commit
c045a3b6f6
@ -143,7 +143,7 @@ class StockAdjust(APIView):
|
|||||||
elif 'items' in request.data:
|
elif 'items' in request.data:
|
||||||
_items = request.data['items']
|
_items = request.data['items']
|
||||||
else:
|
else:
|
||||||
raise ValidationError({'items': 'Request must contain list of stock items'})
|
raise ValidationError({'items': _('Request must contain list of stock items')})
|
||||||
|
|
||||||
# List of validated items
|
# List of validated items
|
||||||
self.items = []
|
self.items = []
|
||||||
@ -151,13 +151,14 @@ class StockAdjust(APIView):
|
|||||||
for entry in _items:
|
for entry in _items:
|
||||||
|
|
||||||
if not type(entry) == dict:
|
if not type(entry) == dict:
|
||||||
raise ValidationError({'error': 'Improperly formatted data'})
|
raise ValidationError({'error': _('Improperly formatted data')})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
pk = entry.get('pk', None)
|
# Look for 'pk' value first, with 'id' as a backup
|
||||||
|
pk = entry.get('pk', entry.get('id', None))
|
||||||
item = StockItem.objects.get(pk=pk)
|
item = StockItem.objects.get(pk=pk)
|
||||||
except (ValueError, StockItem.DoesNotExist):
|
except (ValueError, StockItem.DoesNotExist):
|
||||||
raise ValidationError({'pk': 'Each entry must contain a valid pk field'})
|
raise ValidationError({'pk': _('Each entry must contain a valid pk field')})
|
||||||
|
|
||||||
if self.allow_missing_quantity and 'quantity' not in entry:
|
if self.allow_missing_quantity and 'quantity' not in entry:
|
||||||
entry['quantity'] = item.quantity
|
entry['quantity'] = item.quantity
|
||||||
@ -165,10 +166,10 @@ class StockAdjust(APIView):
|
|||||||
try:
|
try:
|
||||||
quantity = Decimal(str(entry.get('quantity', None)))
|
quantity = Decimal(str(entry.get('quantity', None)))
|
||||||
except (ValueError, TypeError, InvalidOperation):
|
except (ValueError, TypeError, InvalidOperation):
|
||||||
raise ValidationError({'quantity': "Each entry must contain a valid quantity value"})
|
raise ValidationError({'quantity': _("Each entry must contain a valid quantity value")})
|
||||||
|
|
||||||
if quantity < 0:
|
if quantity < 0:
|
||||||
raise ValidationError({'quantity': 'Quantity field must not be less than zero'})
|
raise ValidationError({'quantity': _('Quantity field must not be less than zero')})
|
||||||
|
|
||||||
self.items.append({
|
self.items.append({
|
||||||
'item': item,
|
'item': item,
|
||||||
|
@ -441,7 +441,17 @@ function constructFormBody(fields, options) {
|
|||||||
modalEnable(modal, true);
|
modalEnable(modal, true);
|
||||||
|
|
||||||
// Insert generated form content
|
// Insert generated form content
|
||||||
$(modal).find('.modal-form-content').html(html);
|
$(modal).find('#form-content').html(html);
|
||||||
|
|
||||||
|
if (options.preFormContent) {
|
||||||
|
console.log('pre form content', options.preFormContent);
|
||||||
|
$(modal).find('#pre-form-content').html(options.preFormContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.postFormContent) {
|
||||||
|
console.log('post form content', options.postFormContent);
|
||||||
|
$(modal).find('#post-form-content').html(options.postFormContent);
|
||||||
|
}
|
||||||
|
|
||||||
// Clear any existing buttons from the modal
|
// Clear any existing buttons from the modal
|
||||||
$(modal).find('#modal-footer-buttons').html('');
|
$(modal).find('#modal-footer-buttons').html('');
|
||||||
|
@ -20,6 +20,138 @@ function stockStatusCodes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform stock adjustments
|
||||||
|
*/
|
||||||
|
function adjustStock(items, options={}) {
|
||||||
|
|
||||||
|
var formTitle = 'Form Title Here';
|
||||||
|
var actionTitle = null;
|
||||||
|
|
||||||
|
switch (options.action) {
|
||||||
|
case 'move':
|
||||||
|
formTitle = '{% trans "Transfer Stock" %}';
|
||||||
|
actionTitle = '{% trans "Move" %}';
|
||||||
|
break;
|
||||||
|
case 'count':
|
||||||
|
formTitle = '{% trans "Count Stock" %}';
|
||||||
|
actionTitle = '{% trans "Count" %}';
|
||||||
|
break;
|
||||||
|
case 'take':
|
||||||
|
formTitle = '{% trans "Remove Stock" %}';
|
||||||
|
actionTitle = '{% trans "Take" %}';
|
||||||
|
break;
|
||||||
|
case 'add':
|
||||||
|
formTitle = '{% trans "Add Stock" %}';
|
||||||
|
actionTitle = '{% trans "Add" %}';
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
formTitle = '{% trans "Delete Stock" %}';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate modal HTML content
|
||||||
|
var html = `
|
||||||
|
<table class='table table-striped table-condensed' id='stock-adjust-table'>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans "Part" %}</th>
|
||||||
|
<th>{% trans "Stock" %}</th>
|
||||||
|
<th>{% trans "Location" %}</th>
|
||||||
|
<th>${actionTitle || ''}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
`;
|
||||||
|
|
||||||
|
items.forEach(function(item) {
|
||||||
|
|
||||||
|
var pk = item.pk;
|
||||||
|
|
||||||
|
var image = item.part_detail.thumbnail || item.part_detail.image || blankImage();
|
||||||
|
|
||||||
|
var status = stockStatusDisplay(item.status, {
|
||||||
|
classes: 'float-right'
|
||||||
|
});
|
||||||
|
|
||||||
|
var quantity = item.quantity;
|
||||||
|
|
||||||
|
var location = locationDetail(item, false);
|
||||||
|
|
||||||
|
if (item.location_detail) {
|
||||||
|
location = item.location_detail.pathstring;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.serial != null) {
|
||||||
|
quantity = `#${item.serial}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
var actionInput = '';
|
||||||
|
|
||||||
|
if (actionTitle != null) {
|
||||||
|
actionInput = constructNumberInput(
|
||||||
|
item.pk,
|
||||||
|
{
|
||||||
|
value: item.quantity,
|
||||||
|
min_value: 0,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
var buttons = `<div class='btn-group float-right' role='group'>`;
|
||||||
|
|
||||||
|
buttons += makeIconButton(
|
||||||
|
'fa-trash-alt icon-red',
|
||||||
|
'button-stock-item-remove',
|
||||||
|
pk,
|
||||||
|
'{% trans "Remove stock item" %}',
|
||||||
|
);
|
||||||
|
|
||||||
|
buttons += `</div>`;
|
||||||
|
|
||||||
|
html += `
|
||||||
|
<tr id='stock_item_${pk}'>
|
||||||
|
<td id='part_${pk}'><img src='${image}' class='hover-img-thumb'> ${item.part_detail.full_name}</td>
|
||||||
|
<td id='stock_${pk}'>${quantity}${status}</td>
|
||||||
|
<td id='location_${pk}'>${location}</td>
|
||||||
|
<td id='action_${pk}'>
|
||||||
|
<div>
|
||||||
|
${actionInput}
|
||||||
|
${buttons}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>`;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
html += `</tbody></table>`;
|
||||||
|
|
||||||
|
var modal = createNewModal({
|
||||||
|
title: formTitle,
|
||||||
|
});
|
||||||
|
|
||||||
|
constructFormBody({}, {
|
||||||
|
preFormContent: html,
|
||||||
|
confirm: true,
|
||||||
|
modal: modal,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Attach callbacks for the action buttons
|
||||||
|
$(modal).find('.button-stock-item-remove').click(function() {
|
||||||
|
var pk = $(this).attr('pk');
|
||||||
|
|
||||||
|
$(modal).find(`#stock_item_${pk}`).remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
attachToggle(modal);
|
||||||
|
|
||||||
|
$(modal + ' .select2-container').addClass('select-full-width');
|
||||||
|
$(modal + ' .select2-container').css('width', '100%');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function removeStockRow(e) {
|
function removeStockRow(e) {
|
||||||
// Remove a selected row from a stock modal form
|
// Remove a selected row from a stock modal form
|
||||||
|
|
||||||
@ -228,50 +360,8 @@ function loadStockTestResultsTable(table, options) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadStockTable(table, options) {
|
|
||||||
/* Load data into a stock table with adjustable options.
|
|
||||||
* Fetches data (via AJAX) and loads into a bootstrap table.
|
|
||||||
* Also links in default button callbacks.
|
|
||||||
*
|
|
||||||
* Options:
|
|
||||||
* url - URL for the stock query
|
|
||||||
* params - query params for augmenting stock data request
|
|
||||||
* groupByField - Column for grouping stock items
|
|
||||||
* buttons - Which buttons to link to stock selection callbacks
|
|
||||||
* filterList - <ul> element where filters are displayed
|
|
||||||
* disableFilters: If true, disable custom filters
|
|
||||||
*/
|
|
||||||
|
|
||||||
// List of user-params which override the default filters
|
function locationDetail(row, showLink=true) {
|
||||||
|
|
||||||
options.params['location_detail'] = true;
|
|
||||||
|
|
||||||
var params = options.params || {};
|
|
||||||
|
|
||||||
var filterListElement = options.filterList || "#filter-list-stock";
|
|
||||||
|
|
||||||
var filters = {};
|
|
||||||
|
|
||||||
var filterKey = options.filterKey || options.name || "stock";
|
|
||||||
|
|
||||||
if (!options.disableFilters) {
|
|
||||||
filters = loadTableFilters(filterKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
var original = {};
|
|
||||||
|
|
||||||
for (var key in params) {
|
|
||||||
original[key] = params[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
setupFilterList(filterKey, table, filterListElement);
|
|
||||||
|
|
||||||
// Override the default values, or add new ones
|
|
||||||
for (var key in params) {
|
|
||||||
filters[key] = params[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
function locationDetail(row) {
|
|
||||||
/*
|
/*
|
||||||
* Function to display a "location" of a StockItem.
|
* Function to display a "location" of a StockItem.
|
||||||
*
|
*
|
||||||
@ -314,11 +404,55 @@ function loadStockTable(table, options) {
|
|||||||
url = '';
|
url = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url) {
|
if (showLink && url) {
|
||||||
return renderLink(text, url);
|
return renderLink(text, url);
|
||||||
} else {
|
} else {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function loadStockTable(table, options) {
|
||||||
|
/* Load data into a stock table with adjustable options.
|
||||||
|
* Fetches data (via AJAX) and loads into a bootstrap table.
|
||||||
|
* Also links in default button callbacks.
|
||||||
|
*
|
||||||
|
* Options:
|
||||||
|
* url - URL for the stock query
|
||||||
|
* params - query params for augmenting stock data request
|
||||||
|
* groupByField - Column for grouping stock items
|
||||||
|
* buttons - Which buttons to link to stock selection callbacks
|
||||||
|
* filterList - <ul> element where filters are displayed
|
||||||
|
* disableFilters: If true, disable custom filters
|
||||||
|
*/
|
||||||
|
|
||||||
|
// List of user-params which override the default filters
|
||||||
|
|
||||||
|
options.params['location_detail'] = true;
|
||||||
|
|
||||||
|
var params = options.params || {};
|
||||||
|
|
||||||
|
var filterListElement = options.filterList || "#filter-list-stock";
|
||||||
|
|
||||||
|
var filters = {};
|
||||||
|
|
||||||
|
var filterKey = options.filterKey || options.name || "stock";
|
||||||
|
|
||||||
|
if (!options.disableFilters) {
|
||||||
|
filters = loadTableFilters(filterKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
var original = {};
|
||||||
|
|
||||||
|
for (var key in params) {
|
||||||
|
original[key] = params[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
setupFilterList(filterKey, table, filterListElement);
|
||||||
|
|
||||||
|
// Override the default values, or add new ones
|
||||||
|
for (var key in params) {
|
||||||
|
filters[key] = params[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
var grouping = true;
|
var grouping = true;
|
||||||
@ -741,114 +875,14 @@ function loadStockTable(table, options) {
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
function stockAdjustment(action) {
|
function stockAdjustment(action) {
|
||||||
var items = $("#stock-table").bootstrapTable("getSelections");
|
var items = $("#stock-table").bootstrapTable("getSelections");
|
||||||
|
|
||||||
var stock = [];
|
adjustStock(items, {
|
||||||
|
action: action,
|
||||||
items.forEach(function(item) {
|
|
||||||
stock.push(item.pk);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var title = 'Form title';
|
|
||||||
|
|
||||||
switch (action) {
|
|
||||||
case 'move':
|
|
||||||
title = '{% trans "Transfer Stock" %}';
|
|
||||||
break;
|
|
||||||
case 'count':
|
|
||||||
title = '{% trans "Count Stock" %}';
|
|
||||||
break;
|
|
||||||
case 'take':
|
|
||||||
title = '{% trans "Remove Stock" %}';
|
|
||||||
break;
|
|
||||||
case 'add':
|
|
||||||
title = '{% trans "Add Stock" %}';
|
|
||||||
break;
|
|
||||||
case 'delete':
|
|
||||||
title = '{% trans "Delete Stock" %}';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var modal = createNewModal({
|
|
||||||
title: title,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Generate content for the modal
|
|
||||||
|
|
||||||
var html = `
|
|
||||||
<table class='table table-striped table-condensed' id='stock-adjust-table'>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>{% trans "Part" %}</th>
|
|
||||||
<th>{% trans "Stock" %}</th>
|
|
||||||
<th>{% trans "Location" %}</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
`;
|
|
||||||
|
|
||||||
items.forEach(function(item) {
|
|
||||||
|
|
||||||
var pk = item.pk;
|
|
||||||
|
|
||||||
var image = item.part_detail.thumbnail || item.part_detail.image || blankImage();
|
|
||||||
|
|
||||||
var status = stockStatusDisplay(item.status, {
|
|
||||||
classes: 'float-right'
|
|
||||||
});
|
|
||||||
|
|
||||||
var quantity = item.quantity;
|
|
||||||
|
|
||||||
if (item.serial != null) {
|
|
||||||
quantity = `#${item.serial}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
var buttons = `<div class='btn-group float-right' role='group'>`;
|
|
||||||
|
|
||||||
buttons += makeIconButton(
|
|
||||||
'fa-trash-alt icon-red',
|
|
||||||
'button-stock-item-remove',
|
|
||||||
pk,
|
|
||||||
'{% trans "Remove stock item" %}',
|
|
||||||
);
|
|
||||||
|
|
||||||
buttons += `</div>`;
|
|
||||||
|
|
||||||
html += `
|
|
||||||
<tr id='stock_item_${pk}'>
|
|
||||||
<td id='part_${pk}'><img src='${image}' class='hover-img-thumb'> ${item.part_detail.full_name}${status}</td>
|
|
||||||
<td id='stock_${pk}'>${quantity}</td>
|
|
||||||
<td id='location_${pk}'>${item.location_detail.pathstring}</td>
|
|
||||||
<td id='action_${pk}'>${buttons}</td>
|
|
||||||
</tr>`;
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
html += `</tbody></table>`;
|
|
||||||
|
|
||||||
$(modal).find('.modal-form-content').html(html);
|
|
||||||
|
|
||||||
// Attach callbacks for the action buttons
|
|
||||||
$(modal).find('.button-stock-item-remove').click(function() {
|
|
||||||
var pk = $(this).attr('pk');
|
|
||||||
|
|
||||||
$(modal).find(`#stock_item_${pk}`).remove();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add a "confirm" button
|
|
||||||
insertConfirmButton({
|
|
||||||
modal: modal,
|
|
||||||
});
|
|
||||||
|
|
||||||
attachToggle(modal);
|
|
||||||
|
|
||||||
$(modal + ' .select2-container').addClass('select-full-width');
|
|
||||||
$(modal + ' .select2-container').css('width', '100%');
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Buttons for launching secondary modals
|
// Buttons for launching secondary modals
|
||||||
|
Loading…
x
Reference in New Issue
Block a user