From 295c4f3e5da45763111f67b6677c1e4b4156159b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 22 Nov 2025 13:44:48 +1100 Subject: [PATCH] [bug] Serialize location (#10882) (#10883) * Properly set location id when serializing stock * Add correct tracking entries * Add unit test (cherry picked from commit a7ff1250ba179cc45427149e8ea82b39f8bddf93) Co-authored-by: Oliver --- src/backend/InvenTree/stock/models.py | 23 ++++++++++++++++++--- src/backend/InvenTree/stock/status_codes.py | 1 + src/backend/InvenTree/stock/tests.py | 7 ++++++- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/backend/InvenTree/stock/models.py b/src/backend/InvenTree/stock/models.py index 326ccb1a47..20b0adf503 100644 --- a/src/backend/InvenTree/stock/models.py +++ b/src/backend/InvenTree/stock/models.py @@ -1908,7 +1908,12 @@ class StockItem( data = dict(StockItem.objects.filter(pk=self.pk).values()[0]) if location: - data['location'] = location + if location.structural: + raise ValidationError({ + 'location': _('Cannot assign stock to structural location') + }) + + data['location_id'] = location.pk # Set the parent ID correctly data['parent'] = self @@ -1921,7 +1926,17 @@ class StockItem( history_items = [] for item in items: - # Construct a tracking entry for the new StockItem + # Construct tracking entries for the new StockItem + if entry := item.add_tracking_entry( + StockHistoryCode.SPLIT_FROM_PARENT, + user, + quantity=1, + notes=notes, + location=location, + commit=False, + ): + history_items.append(entry) + if entry := item.add_tracking_entry( StockHistoryCode.ASSIGNED_SERIAL, user, @@ -1938,7 +1953,9 @@ class StockItem( StockItemTracking.objects.bulk_create(history_items) # Remove the equivalent number of items - self.take_stock(quantity, user, notes=notes) + self.take_stock( + quantity, user, code=StockHistoryCode.STOCK_SERIZALIZED, notes=notes + ) return items diff --git a/src/backend/InvenTree/stock/status_codes.py b/src/backend/InvenTree/stock/status_codes.py index af99974d7e..978bca0b0e 100644 --- a/src/backend/InvenTree/stock/status_codes.py +++ b/src/backend/InvenTree/stock/status_codes.py @@ -53,6 +53,7 @@ class StockHistoryCode(StatusCode): STOCK_COUNT = 10, _('Stock counted') STOCK_ADD = 11, _('Stock manually added') STOCK_REMOVE = 12, _('Stock manually removed') + STOCK_SERIZALIZED = 13, _('Serialized stock items') RETURNED_TO_STOCK = 15, _('Returned to stock') # Stock item returned to stock diff --git a/src/backend/InvenTree/stock/tests.py b/src/backend/InvenTree/stock/tests.py index ef400fb067..514e8f0ec3 100644 --- a/src/backend/InvenTree/stock/tests.py +++ b/src/backend/InvenTree/stock/tests.py @@ -1271,9 +1271,11 @@ class StockTreeTest(StockTestBase): self.assertEqual(item_1.get_children().count(), 1) self.assertEqual(item_2.parent, item_1) + loc = StockLocation.objects.filter(structural=False).first() + # Serialize the secondary item serials = [str(i) for i in range(20)] - items = item_2.serializeStock(20, serials) + items = item_2.serializeStock(20, serials, location=loc) self.assertEqual(len(items), 20) self.assertEqual(StockItem.objects.count(), N + 22) @@ -1290,6 +1292,9 @@ class StockTreeTest(StockTestBase): self.assertEqual(child.parent, item_2) self.assertGreater(child.lft, item_2.lft) self.assertLess(child.rght, item_2.rght) + self.assertEqual(child.location, loc) + self.assertIsNotNone(child.location) + self.assertEqual(child.tracking_info.count(), 2) # Delete item_2 : we expect that all children will be re-parented to item_1 item_2.delete()