From 31f97934d0b1cbb624fb5c4b811aae4385f20084 Mon Sep 17 00:00:00 2001 From: Oliver Date: Mon, 13 Jul 2026 18:48:49 +1000 Subject: [PATCH] [bug] Child fix (#12374) * Remove outdated helper * Fix children prop and add regression test --- src/backend/InvenTree/stock/models.py | 12 ++----- src/backend/InvenTree/stock/tests.py | 45 +++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/backend/InvenTree/stock/models.py b/src/backend/InvenTree/stock/models.py index edbda1142f..0b35e61e98 100644 --- a/src/backend/InvenTree/stock/models.py +++ b/src/backend/InvenTree/stock/models.py @@ -571,12 +571,11 @@ class StockItem( return 'SI' def get_children(self): - """Return a queryset of all StockItem objects which are children of this StockItem. + """Return a queryset of all StockItem objects which are direct children of this StockItem. - As the StockItem model is no longer a MPTT model, - this function is implemented manually + Simply proxies the reverse foreign-key relation for the 'parent' field. """ - return StockItem.objects.filter(parent=self).exclude(pk=self.pk) + return self.children.all() def get_test_keys(self, include_installed=True): """Construct a flattened list of test 'keys' for this StockItem.""" @@ -2058,11 +2057,6 @@ class StockItem( return items - @property - def children(self): - """Return a list of the child items which have been split from this stock item.""" - return self.get_descendants(include_self=False) - @property def child_count(self): """Return the number of 'child' items associated with this StockItem. diff --git a/src/backend/InvenTree/stock/tests.py b/src/backend/InvenTree/stock/tests.py index 255c3b9349..b79d32ba9b 100644 --- a/src/backend/InvenTree/stock/tests.py +++ b/src/backend/InvenTree/stock/tests.py @@ -351,6 +351,51 @@ class StockTest(StockTestBase): stock.splitStock(stock.quantity, None, self.user) self.assertEqual(StockItem.objects.filter(part=3).count(), n + 1) + def test_child_items(self): + """Test the 'children' reverse relation and 'child_count' property. + + Regression test: StockItem previously defined a 'children' property + (shadowed by the reverse FK accessor, and referencing a method which no + longer exists on the model). The property has been removed - 'children' + must resolve to the reverse foreign-key manager for the 'parent' field. + """ + part = Part.objects.create( + name='Child test part', description='A part for child item testing' + ) + + parent = StockItem.objects.create(part=part, quantity=100) + + self.assertEqual(parent.children.count(), 0) + self.assertEqual(parent.child_count, 0) + self.assertEqual(parent.get_children().count(), 0) + + # Split off two child items + child_1 = parent.splitStock(10, None, self.user) + child_2 = parent.splitStock(20, None, self.user) + + parent.refresh_from_db() + self.assertEqual(parent.quantity, 70) + + children = parent.children.all() + + self.assertEqual(children.count(), 2) + self.assertEqual(parent.child_count, 2) + self.assertIn(child_1, children) + self.assertIn(child_2, children) + + # get_children() proxies the same relation + self.assertEqual( + list(parent.get_children().order_by('pk')), list(children.order_by('pk')) + ) + + # Only *direct* children are included + grandchild = child_1.splitStock(5, None, self.user) + + self.assertEqual(parent.child_count, 2) + self.assertEqual(child_1.child_count, 1) + self.assertIn(grandchild, child_1.children.all()) + self.assertNotIn(grandchild, parent.children.all()) + def test_stocktake(self): """Test stocktake function.""" # Perform stocktake