fix history when merging

This commit is contained in:
Neil Beukes 2026-05-26 17:30:17 +00:00
parent 1007913a93
commit 9f01acaa66
3 changed files with 25 additions and 17 deletions

View File

@ -2185,7 +2185,8 @@ class StockItem(
return None
candidates = list(
StockItem.objects.filter(part=self.part, location=location)
StockItem.objects
.filter(part=self.part, location=location)
.exclude(pk=self.pk)
.order_by('pk')
)
@ -2214,8 +2215,11 @@ class StockItem(
*This* stock item subsumes the other, which is essentially deleted:
- The quantity of this StockItem is increased
- Tracking history for the *other* item is copied to this item
- Tracking history for the *other* item is copied to this item (unless copy_history=False)
- Any allocations (build order, sales order) are moved to this StockItem
kwargs:
copy_history: If True (default), copy tracking from merged items. Set False for merge-on-transfer.
"""
if isinstance(other_items, StockItem):
other_items = [other_items]
@ -2229,6 +2233,7 @@ class StockItem(
user = kwargs.get('user')
location = kwargs.get('location', self.location)
notes = kwargs.get('notes') or ''
copy_history = kwargs.pop('copy_history', True)
parent_id = self.parent.pk if self.parent else None
@ -2270,17 +2275,15 @@ class StockItem(
self.parent = None
self.save()
self.copyHistoryFrom(other)
if copy_history:
self.copyHistoryFrom(other)
if other.location:
location_note = _('Transferred from %(location)s') % {
'location': other.location.pathstring
}
if notes:
notes = f'{notes}\n{location_note}'
else:
notes = location_note
notes = f'{notes}\n{location_note}' if notes else location_note
other.delete()

View File

@ -1883,6 +1883,7 @@ class StockTransferSerializer(StockAdjustmentSerializer):
'location': location,
'notes': notes,
'user': request.user,
'copy_history': False,
**kwargs,
}
@ -1897,9 +1898,7 @@ class StockTransferSerializer(StockAdjustmentSerializer):
)
target.merge_stock_items([piece], **merge_kwargs)
else:
target.merge_stock_items(
[stock_item], **merge_kwargs
)
target.merge_stock_items([stock_item], **merge_kwargs)
continue

View File

@ -2166,6 +2166,9 @@ class StockTransferMergeTest(StockAPITestCase):
self.source_loc = StockLocation.objects.get(pk=5)
self.url = reverse('api-stock-transfer')
# Remove fixture stock at the destination so merge targets are deterministic
StockItem.objects.filter(part=self.part, location=self.dest).delete()
def test_transfer_without_merge_creates_separate_lot(self):
"""Transfer without merge leaves multiple stock rows at destination."""
existing = StockItem.objects.create(
@ -2219,8 +2222,8 @@ class StockTransferMergeTest(StockAPITestCase):
self.assertEqual(existing.quantity, 150)
self.assertFalse(StockItem.objects.filter(pk=incoming.pk).exists())
def test_transfer_merge_preserves_tracking(self):
"""Transfer merge copies tracking history onto the surviving stock item."""
def test_transfer_merge_does_not_copy_source_tracking(self):
"""Transfer merge keeps destination history and adds a single merge entry."""
existing = StockItem.objects.create(
part=self.part, location=self.dest, quantity=100
)
@ -2229,9 +2232,7 @@ class StockTransferMergeTest(StockAPITestCase):
)
incoming.add_tracking_entry(
StockHistoryCode.STOCK_UPDATE,
self.user,
notes='Source tracking entry',
StockHistoryCode.STOCK_UPDATE, self.user, notes='Source tracking entry'
)
tracking_count = existing.tracking_info.count()
@ -2248,10 +2249,15 @@ class StockTransferMergeTest(StockAPITestCase):
existing.refresh_from_db()
self.assertTrue(
self.assertFalse(
existing.tracking_info.filter(notes='Source tracking entry').exists()
)
self.assertGreater(existing.tracking_info.count(), tracking_count)
self.assertEqual(existing.tracking_info.count(), tracking_count + 1)
self.assertTrue(
existing.tracking_info.filter(
tracking_type=StockHistoryCode.MERGED_STOCK_ITEMS
).exists()
)
class StockItemDeletionTest(StockAPITestCase):