From f7b91f55e0a6f678af156286d2fe98c7c0296ec6 Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 22 Apr 2022 15:11:33 +1000 Subject: [PATCH] Chery pick changes from https://github.com/inventree/InvenTree/pull/2859 --- InvenTree/InvenTree/settings.py | 10 +++++++++- InvenTree/part/models.py | 7 ++++++- InvenTree/part/test_part.py | 20 ++++++++++++++++++++ InvenTree/stock/models.py | 8 ++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index 4fb3dc61bb..33f17a3f7f 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -535,11 +535,19 @@ if "sqlite" in db_engine: # Provide OPTIONS dict back to the database configuration dict db_config['OPTIONS'] = db_options +# Set testing options for the database +db_config['TEST'] = { + 'CHARSET': 'utf8', +} + +# Set collation option for mysql test database +if 'mysql' in db_engine: + db_config['TEST']['COLLATION'] = 'utf8_general_ci' + DATABASES = { 'default': db_config } - _cache_config = CONFIG.get("cache", {}) _cache_host = _cache_config.get("host", os.getenv("INVENTREE_CACHE_HOST")) _cache_port = _cache_config.get( diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index b3d975513f..25b159c7ec 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -777,7 +777,8 @@ class Part(MPTTModel): # User can decide whether duplicate IPN (Internal Part Number) values are allowed allow_duplicate_ipn = common.models.InvenTreeSetting.get_setting('PART_ALLOW_DUPLICATE_IPN') - if self.IPN is not None and not allow_duplicate_ipn: + # Raise an error if an IPN is set, and it is a duplicate + if self.IPN and not allow_duplicate_ipn: parts = Part.objects.filter(IPN__iexact=self.IPN) parts = parts.exclude(pk=self.pk) @@ -798,6 +799,10 @@ class Part(MPTTModel): super().clean() + # Strip IPN field + if type(self.IPN) is str: + self.IPN = self.IPN.strip() + if self.trackable: for part in self.get_used_in().all(): diff --git a/InvenTree/part/test_part.py b/InvenTree/part/test_part.py index b61affcafd..d557c0717d 100644 --- a/InvenTree/part/test_part.py +++ b/InvenTree/part/test_part.py @@ -348,6 +348,26 @@ class PartSettingsTest(TestCase): part = Part(name='Hello', description='A thing', IPN='IPN123', revision='C') part.full_clean() + # Any duplicate IPN should raise an error + Part.objects.create(name='xyz', revision='1', description='A part', IPN='UNIQUE') + + # Case insensitive, so variations on spelling should throw an error + for ipn in ['UNiquE', 'uniQuE', 'unique']: + with self.assertRaises(ValidationError): + Part.objects.create(name='xyz', revision='2', description='A part', IPN=ipn) + + with self.assertRaises(ValidationError): + Part.objects.create(name='zyx', description='A part', IPN='UNIQUE') + + # However, *blank* / empty IPN values should be allowed, even if duplicates are not + # Note that leading / trailling whitespace characters are trimmed, too + Part.objects.create(name='abc', revision='1', description='A part', IPN=None) + Part.objects.create(name='abc', revision='2', description='A part', IPN='') + Part.objects.create(name='abc', revision='3', description='A part', IPN=None) + Part.objects.create(name='abc', revision='4', description='A part', IPN=' ') + Part.objects.create(name='abc', revision='5', description='A part', IPN=' ') + Part.objects.create(name='abc', revision='6', description='A part', IPN=' ') + class PartSubscriptionTests(TestCase): diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 171ee7e0a3..9b590838b3 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -453,6 +453,14 @@ class StockItem(MPTTModel): super().clean() + # Strip serial number field + if type(self.serial) is str: + self.serial = self.serial.strip() + + # Strip batch code field + if type(self.batch) is str: + self.batch = self.batch.strip() + try: if self.part.trackable: # Trackable parts must have integer values for quantity field!