mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Fixes for unit tests
This commit is contained in:
parent
758e402a66
commit
95e7cc7a5d
@ -372,7 +372,7 @@
|
|||||||
{
|
{
|
||||||
success: function(items) {
|
success: function(items) {
|
||||||
adjustStock(action, items, {
|
adjustStock(action, items, {
|
||||||
onSuccess: function() {
|
success: function() {
|
||||||
location.reload();
|
location.reload();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -561,7 +561,7 @@ function itemAdjust(action) {
|
|||||||
{
|
{
|
||||||
success: function(item) {
|
success: function(item) {
|
||||||
adjustStock(action, [item], {
|
adjustStock(action, [item], {
|
||||||
onSuccess: function() {
|
success: function() {
|
||||||
location.reload();
|
location.reload();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -287,7 +287,7 @@
|
|||||||
{
|
{
|
||||||
success: function(items) {
|
success: function(items) {
|
||||||
adjustStock(action, items, {
|
adjustStock(action, items, {
|
||||||
onSuccess: function() {
|
success: function() {
|
||||||
location.reload();
|
location.reload();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -513,31 +513,34 @@ class StocktakeTest(StockAPITestCase):
|
|||||||
|
|
||||||
# POST with a valid action
|
# POST with a valid action
|
||||||
response = self.post(url, data)
|
response = self.post(url, data)
|
||||||
self.assertContains(response, "must contain list", status_code=status.HTTP_400_BAD_REQUEST)
|
|
||||||
|
self.assertIn("This field is required", str(response.data["items"]))
|
||||||
|
|
||||||
data['items'] = [{
|
data['items'] = [{
|
||||||
'no': 'aa'
|
'no': 'aa'
|
||||||
}]
|
}]
|
||||||
|
|
||||||
# POST without a PK
|
# POST without a PK
|
||||||
response = self.post(url, data)
|
response = self.post(url, data, expected_code=400)
|
||||||
self.assertContains(response, 'must contain a valid integer primary-key', status_code=status.HTTP_400_BAD_REQUEST)
|
|
||||||
|
self.assertIn('This field is required', str(response.data))
|
||||||
|
|
||||||
# POST with an invalid PK
|
# POST with an invalid PK
|
||||||
data['items'] = [{
|
data['items'] = [{
|
||||||
'pk': 10
|
'pk': 10
|
||||||
}]
|
}]
|
||||||
|
|
||||||
response = self.post(url, data)
|
response = self.post(url, data, expected_code=400)
|
||||||
self.assertContains(response, 'does not match valid stock item', status_code=status.HTTP_400_BAD_REQUEST)
|
|
||||||
|
self.assertContains(response, 'object does not exist', status_code=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
# POST with missing quantity value
|
# POST with missing quantity value
|
||||||
data['items'] = [{
|
data['items'] = [{
|
||||||
'pk': 1234
|
'pk': 1234
|
||||||
}]
|
}]
|
||||||
|
|
||||||
response = self.post(url, data)
|
response = self.post(url, data, expected_code=400)
|
||||||
self.assertContains(response, 'Invalid quantity value', status_code=status.HTTP_400_BAD_REQUEST)
|
self.assertContains(response, 'This field is required', status_code=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
# POST with an invalid quantity value
|
# POST with an invalid quantity value
|
||||||
data['items'] = [{
|
data['items'] = [{
|
||||||
@ -546,7 +549,7 @@ class StocktakeTest(StockAPITestCase):
|
|||||||
}]
|
}]
|
||||||
|
|
||||||
response = self.post(url, data)
|
response = self.post(url, data)
|
||||||
self.assertContains(response, 'Invalid quantity value', status_code=status.HTTP_400_BAD_REQUEST)
|
self.assertContains(response, 'A valid number is required', status_code=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
data['items'] = [{
|
data['items'] = [{
|
||||||
'pk': 1234,
|
'pk': 1234,
|
||||||
@ -554,18 +557,7 @@ class StocktakeTest(StockAPITestCase):
|
|||||||
}]
|
}]
|
||||||
|
|
||||||
response = self.post(url, data)
|
response = self.post(url, data)
|
||||||
self.assertContains(response, 'must not be less than zero', status_code=status.HTTP_400_BAD_REQUEST)
|
self.assertContains(response, 'Ensure this value is greater than or equal to 0', status_code=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
# Test with a single item
|
|
||||||
data = {
|
|
||||||
'item': {
|
|
||||||
'pk': 1234,
|
|
||||||
'quantity': '10',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
response = self.post(url, data)
|
|
||||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
||||||
|
|
||||||
def test_transfer(self):
|
def test_transfer(self):
|
||||||
"""
|
"""
|
||||||
@ -573,24 +565,27 @@ class StocktakeTest(StockAPITestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'item': {
|
'items': [
|
||||||
|
{
|
||||||
'pk': 1234,
|
'pk': 1234,
|
||||||
'quantity': 10,
|
'quantity': 10,
|
||||||
},
|
}
|
||||||
|
],
|
||||||
'location': 1,
|
'location': 1,
|
||||||
'notes': "Moving to a new location"
|
'notes': "Moving to a new location"
|
||||||
}
|
}
|
||||||
|
|
||||||
url = reverse('api-stock-transfer')
|
url = reverse('api-stock-transfer')
|
||||||
|
|
||||||
response = self.post(url, data)
|
# This should succeed
|
||||||
self.assertContains(response, "Moved 1 parts to", status_code=status.HTTP_200_OK)
|
response = self.post(url, data, expected_code=201)
|
||||||
|
|
||||||
# Now try one which will fail due to a bad location
|
# Now try one which will fail due to a bad location
|
||||||
data['location'] = 'not a location'
|
data['location'] = 'not a location'
|
||||||
|
|
||||||
response = self.post(url, data)
|
response = self.post(url, data, expected_code=400)
|
||||||
self.assertContains(response, 'Valid location must be specified', status_code=status.HTTP_400_BAD_REQUEST)
|
|
||||||
|
self.assertContains(response, 'Incorrect type. Expected pk value', status_code=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
class StockItemDeletionTest(StockAPITestCase):
|
class StockItemDeletionTest(StockAPITestCase):
|
||||||
|
@ -247,7 +247,7 @@ function adjustStock(action, items, options={}) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var image = item.part_detail.thumbnail || item.part_detail.image || blankImage();
|
var thumb = thumbnailImage(item.part_detail.thumbnail || item.part_detail.image);
|
||||||
|
|
||||||
var status = stockStatusDisplay(item.status, {
|
var status = stockStatusDisplay(item.status, {
|
||||||
classes: 'float-right'
|
classes: 'float-right'
|
||||||
@ -268,14 +268,18 @@ function adjustStock(action, items, options={}) {
|
|||||||
var actionInput = '';
|
var actionInput = '';
|
||||||
|
|
||||||
if (actionTitle != null) {
|
if (actionTitle != null) {
|
||||||
actionInput = constructNumberInput(
|
actionInput = constructField(
|
||||||
item.pk,
|
`items_quantity_${pk}`,
|
||||||
{
|
{
|
||||||
value: value,
|
type: 'decimal',
|
||||||
min_value: minValue,
|
min_value: minValue,
|
||||||
max_value: maxValue,
|
max_value: maxValue,
|
||||||
read_only: readonly,
|
value: value,
|
||||||
title: readonly ? '{% trans "Quantity cannot be adjusted for serialized stock" %}' : '{% trans "Specify stock quantity" %}',
|
title: readonly ? '{% trans "Quantity cannot be adjusted for serialized stock" %}' : '{% trans "Specify stock quantity" %}',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
hideLabels: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -293,7 +297,7 @@ function adjustStock(action, items, options={}) {
|
|||||||
|
|
||||||
html += `
|
html += `
|
||||||
<tr id='stock_item_${pk}' class='stock-item-row'>
|
<tr id='stock_item_${pk}' class='stock-item-row'>
|
||||||
<td id='part_${pk}'><img src='${image}' class='hover-img-thumb'> ${item.part_detail.full_name}</td>
|
<td id='part_${pk}'>${thumb} ${item.part_detail.full_name}</td>
|
||||||
<td id='stock_${pk}'>${quantity}${status}</td>
|
<td id='stock_${pk}'>${quantity}${status}</td>
|
||||||
<td id='location_${pk}'>${location}</td>
|
<td id='location_${pk}'>${location}</td>
|
||||||
<td id='action_${pk}'>
|
<td id='action_${pk}'>
|
||||||
@ -319,50 +323,89 @@ function adjustStock(action, items, options={}) {
|
|||||||
|
|
||||||
html += `</tbody></table>`;
|
html += `</tbody></table>`;
|
||||||
|
|
||||||
var modal = createNewModal({
|
var extraFields = {};
|
||||||
title: formTitle,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Extra fields
|
if (specifyLocation) {
|
||||||
var extraFields = {
|
extraFields.location = {};
|
||||||
location: {
|
|
||||||
label: '{% trans "Location" %}',
|
|
||||||
help_text: '{% trans "Select destination stock location" %}',
|
|
||||||
type: 'related field',
|
|
||||||
required: true,
|
|
||||||
api_url: `/api/stock/location/`,
|
|
||||||
model: 'stocklocation',
|
|
||||||
name: 'location',
|
|
||||||
},
|
|
||||||
notes: {
|
|
||||||
label: '{% trans "Notes" %}',
|
|
||||||
help_text: '{% trans "Stock transaction notes" %}',
|
|
||||||
type: 'string',
|
|
||||||
name: 'notes',
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!specifyLocation) {
|
|
||||||
delete extraFields.location;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructFormBody({}, {
|
if (action != 'delete') {
|
||||||
preFormContent: html,
|
extraFields.notes = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
constructForm(url, {
|
||||||
|
method: 'POST',
|
||||||
fields: extraFields,
|
fields: extraFields,
|
||||||
|
preFormContent: html,
|
||||||
confirm: true,
|
confirm: true,
|
||||||
confirmMessage: '{% trans "Confirm stock adjustment" %}',
|
confirmMessage: '{% trans "Confirm stock adjustment" %}',
|
||||||
modal: modal,
|
title: formTitle,
|
||||||
onSubmit: function(fields) {
|
afterRender: function(fields, opts) {
|
||||||
|
// Add button callbacks to remove rows
|
||||||
|
$(opts.modal).find('.button-stock-item-remove').click(function() {
|
||||||
|
var pk = $(this).attr('pk');
|
||||||
|
|
||||||
// "Delete" action gets handled differently
|
$(opts.modal).find(`#stock_item_${pk}`).remove();
|
||||||
if (action == 'delete') {
|
});
|
||||||
|
|
||||||
var requests = [];
|
// Initialize "location" field
|
||||||
|
if (specifyLocation) {
|
||||||
|
initializeRelatedField(
|
||||||
|
{
|
||||||
|
name: 'location',
|
||||||
|
type: 'related field',
|
||||||
|
model: 'stocklocation',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
opts
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSubmit: function(fields, opts) {
|
||||||
|
|
||||||
|
// Extract data elements from the form
|
||||||
|
var data = {
|
||||||
|
items: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
if (action != 'delete') {
|
||||||
|
data.notes = getFormFieldValue('notes', {}, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (specifyLocation) {
|
||||||
|
data.location = getFormFieldValue('location', {}, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
var item_pk_values = [];
|
||||||
|
|
||||||
items.forEach(function(item) {
|
items.forEach(function(item) {
|
||||||
|
var pk = item.pk;
|
||||||
|
|
||||||
|
// Does the row exist in the form?
|
||||||
|
var row = $(opts.modal).find(`#stock_item_${pk}`);
|
||||||
|
|
||||||
|
if (row) {
|
||||||
|
|
||||||
|
item_pk_values.push(pk);
|
||||||
|
|
||||||
|
var quantity = getFormFieldValue(`items_quantity_${pk}`, {}, opts);
|
||||||
|
|
||||||
|
data.items.push({
|
||||||
|
pk: pk,
|
||||||
|
quantity: quantity,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Delete action is handled differently
|
||||||
|
if (action == 'delete') {
|
||||||
|
var requests = [];
|
||||||
|
|
||||||
|
item_pk_values.forEach(function(pk) {
|
||||||
requests.push(
|
requests.push(
|
||||||
inventreeDelete(
|
inventreeDelete(
|
||||||
`/api/stock/${item.pk}/`,
|
`/api/stock/${pk}/`,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -370,72 +413,40 @@ function adjustStock(action, items, options={}) {
|
|||||||
// Wait for *all* the requests to complete
|
// Wait for *all* the requests to complete
|
||||||
$.when.apply($, requests).done(function() {
|
$.when.apply($, requests).done(function() {
|
||||||
// Destroy the modal window
|
// Destroy the modal window
|
||||||
$(modal).modal('hide');
|
$(opts.modal).modal('hide');
|
||||||
|
|
||||||
if (options.onSuccess) {
|
if (options.success) {
|
||||||
options.onSuccess();
|
options.success();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Data to transmit
|
opts.nested = {
|
||||||
var data = {
|
'items': item_pk_values,
|
||||||
items: [],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add values for each selected stock item
|
|
||||||
items.forEach(function(item) {
|
|
||||||
|
|
||||||
var q = getFormFieldValue(item.pk, {}, {modal: modal});
|
|
||||||
|
|
||||||
if (q != null) {
|
|
||||||
data.items.push({pk: item.pk, quantity: q});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add in extra field data
|
|
||||||
for (var field_name in extraFields) {
|
|
||||||
data[field_name] = getFormFieldValue(
|
|
||||||
field_name,
|
|
||||||
fields[field_name],
|
|
||||||
{
|
|
||||||
modal: modal,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
inventreePut(
|
inventreePut(
|
||||||
url,
|
url,
|
||||||
data,
|
data,
|
||||||
{
|
{
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
success: function() {
|
success: function(response) {
|
||||||
|
// Hide the modal
|
||||||
|
$(opts.modal).modal('hide');
|
||||||
|
|
||||||
// Destroy the modal window
|
if (options.success) {
|
||||||
$(modal).modal('hide');
|
options.success(response);
|
||||||
|
|
||||||
if (options.onSuccess) {
|
|
||||||
options.onSuccess();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: function(xhr) {
|
error: function(xhr) {
|
||||||
switch (xhr.status) {
|
switch (xhr.status) {
|
||||||
case 400:
|
case 400:
|
||||||
|
handleFormErrors(xhr.responseJSON, fields, opts);
|
||||||
// Handle errors for standard fields
|
|
||||||
handleFormErrors(
|
|
||||||
xhr.responseJSON,
|
|
||||||
extraFields,
|
|
||||||
{
|
|
||||||
modal: modal,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$(modal).modal('hide');
|
$(opts.modal).modal('hide');
|
||||||
showApiError(xhr);
|
showApiError(xhr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -444,18 +455,6 @@ function adjustStock(action, items, options={}) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 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%');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1258,7 +1257,7 @@ function loadStockTable(table, options) {
|
|||||||
var items = $(table).bootstrapTable('getSelections');
|
var items = $(table).bootstrapTable('getSelections');
|
||||||
|
|
||||||
adjustStock(action, items, {
|
adjustStock(action, items, {
|
||||||
onSuccess: function() {
|
success: function() {
|
||||||
$(table).bootstrapTable('refresh');
|
$(table).bootstrapTable('refresh');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user