From 233446c2bb520e7ef08a1664f7ec6451b93cef29 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 14 Jul 2022 20:10:56 +1000 Subject: [PATCH] Add fix for stock migration - Ensure the serial number is not too large when performing migration - Add unit test for data migration (cherry picked from commit 661fbf0e3dbdf6444d3d25b02d68ad229925d87c) --- .../migrations/0069_auto_20211109_2347.py | 3 + InvenTree/stock/test_migrations.py | 69 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 InvenTree/stock/test_migrations.py diff --git a/InvenTree/stock/migrations/0069_auto_20211109_2347.py b/InvenTree/stock/migrations/0069_auto_20211109_2347.py index e4e8128f1c..2691b6305e 100644 --- a/InvenTree/stock/migrations/0069_auto_20211109_2347.py +++ b/InvenTree/stock/migrations/0069_auto_20211109_2347.py @@ -28,6 +28,9 @@ def update_serials(apps, schema_editor): except Exception: serial = 0 + # Ensure the integer value is not too large for the database field + if serial > 0x7fffffff: + serial = 0x7fffffff item.serial_int = serial item.save() diff --git a/InvenTree/stock/test_migrations.py b/InvenTree/stock/test_migrations.py new file mode 100644 index 0000000000..07fa9f2fc7 --- /dev/null +++ b/InvenTree/stock/test_migrations.py @@ -0,0 +1,69 @@ +"""Unit tests for data migrations in the 'stock' app""" + +from django_test_migrations.contrib.unittest_case import MigratorTestCase + +from InvenTree import helpers + + +class TestSerialNumberMigration(MigratorTestCase): + """Test data migration which updates serial numbers""" + + migrate_from = ('stock', '0067_alter_stockitem_part') + migrate_to = ('stock', helpers.getNewestMigrationFile('stock')) + + def prepare(self): + """Create initial data for this migration""" + + Part = self.old_state.apps.get_model('part', 'part') + StockItem = self.old_state.apps.get_model('stock', 'stockitem') + + # Create a base part + my_part = Part.objects.create( + name='PART-123', + description='Some part', + active=True, + trackable=True, + level=0, + tree_id=0, + lft=0, rght=0 + ) + + # Create some serialized stock items + for sn in range(10, 20): + StockItem.objects.create( + part=my_part, + quantity=1, + serial=sn, + level=0, + tree_id=0, + lft=0, rght=0 + ) + + # Create a stock item with a very large serial number + item = StockItem.objects.create( + part=my_part, + quantity=1, + serial='9999999999999999999999999999999999999999999999999999999999999', + level=0, + tree_id=0, + lft=0, rght=0 + ) + + self.big_ref_pk = item.pk + + def test_migrations(self): + """Test that the migrations have been applied correctly""" + + StockItem = self.new_state.apps.get_model('stock', 'stockitem') + + # Check that the serial number integer conversion has been applied correctly + for sn in range(10, 20): + item = StockItem.objects.get(serial_int=sn) + + self.assertEqual(item.serial, str(sn)) + + big_ref_item = StockItem.objects.get(pk=self.big_ref_pk) + + # Check that the StockItem maximum serial number + self.assertEqual(big_ref_item.serial, '9999999999999999999999999999999999999999999999999999999999999') + self.assertEqual(big_ref_item.serial_int, 0x7fffffff)