mirror of
https://github.com/inventree/InvenTree.git
synced 2026-05-06 09:43:38 +00:00
Prevent delete serialized stock (#11872)
* Add setting to prevent deletion of serialized stock Co-authored-by: Copilot <copilot@github.com> * Add unit test Co-authored-by: Copilot <copilot@github.com> * Update CHANGELOG Co-authored-by: Copilot <copilot@github.com> --------- Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -716,6 +716,12 @@ SYSTEM_SETTINGS: dict[str, InvenTreeSettingsKeyType] = {
|
||||
'default': True,
|
||||
'validator': bool,
|
||||
},
|
||||
'STOCK_ALLOW_DELETE_SERIALIZED': {
|
||||
'name': _('Delete Serialized Stock'),
|
||||
'description': _('Allow deletion of stock items which have a serial number'),
|
||||
'default': True,
|
||||
'validator': bool,
|
||||
},
|
||||
'STOCK_BATCH_CODE_TEMPLATE': {
|
||||
'name': _('Batch Code Template'),
|
||||
'description': _('Template for generating default batch codes for stock items'),
|
||||
|
||||
@@ -449,6 +449,14 @@ class StockItem(
|
||||
|
||||
order_insertion_by = ['part']
|
||||
|
||||
def delete(self, **kwargs):
|
||||
"""Custom delete method for StockItem model."""
|
||||
if not get_global_setting('STOCK_ALLOW_DELETE_SERIALIZED', cache=False):
|
||||
if self.serialized:
|
||||
raise ValidationError(_('Serialized stock items cannot be deleted'))
|
||||
|
||||
super().delete(**kwargs)
|
||||
|
||||
@staticmethod
|
||||
def get_api_url():
|
||||
"""Return API url."""
|
||||
|
||||
@@ -2181,6 +2181,37 @@ class StockItemDeletionTest(StockAPITestCase):
|
||||
|
||||
self.assertEqual(StockItem.objects.count(), n)
|
||||
|
||||
def test_delete_serialized(self):
|
||||
"""Test deletion of serialized stock items."""
|
||||
trackable_part = part.models.Part.objects.create(
|
||||
name='My part',
|
||||
description='A trackable part',
|
||||
trackable=True,
|
||||
default_location=StockLocation.objects.get(pk=1),
|
||||
)
|
||||
|
||||
stock_item = StockItem.objects.create(
|
||||
part=trackable_part, quantity=1, serial='12345'
|
||||
)
|
||||
|
||||
set_global_setting('STOCK_ALLOW_DELETE_SERIALIZED', False)
|
||||
|
||||
response = self.delete(
|
||||
reverse('api-stock-detail', kwargs={'pk': stock_item.pk}), expected_code=400
|
||||
)
|
||||
|
||||
self.assertIn('Serialized stock items cannot be deleted', str(response.data))
|
||||
|
||||
set_global_setting('STOCK_ALLOW_DELETE_SERIALIZED', True)
|
||||
|
||||
response = self.delete(
|
||||
reverse('api-stock-detail', kwargs={'pk': stock_item.pk}), expected_code=204
|
||||
)
|
||||
|
||||
self.get(
|
||||
reverse('api-stock-detail', kwargs={'pk': stock_item.pk}), expected_code=404
|
||||
)
|
||||
|
||||
|
||||
class StockTestResultTest(StockAPITestCase):
|
||||
"""Tests for StockTestResult APIs."""
|
||||
|
||||
@@ -245,6 +245,7 @@ export default function SystemSettings() {
|
||||
<GlobalSettingList
|
||||
keys={[
|
||||
'SERIAL_NUMBER_GLOBALLY_UNIQUE',
|
||||
'STOCK_ALLOW_DELETE_SERIALIZED',
|
||||
'STOCK_DELETE_DEPLETED_DEFAULT',
|
||||
'STOCK_BATCH_CODE_TEMPLATE',
|
||||
'STOCK_OWNERSHIP_CONTROL',
|
||||
|
||||
Reference in New Issue
Block a user