removed the tracking item overwrite, Use existing tracking event from transfer
This commit is contained in:
parent
ce0d3c8ae3
commit
f608f33641
|
|
@ -9,7 +9,7 @@ INVENTREE_API_TEXT = """
|
|||
v498 -> 2026-06-01 : https://github.com/inventree/InvenTree/pull/12022
|
||||
- Adds optional "merge" field to each item in the Stock Transfer API endpoint
|
||||
- When merge is enabled, transferred stock is combined into compatible existing stock at the destination
|
||||
- Stock merge tracking entries now include an "added" delta field;
|
||||
- Stock merge tracking entries now include an "added" delta field
|
||||
|
||||
v497 -> 2026-05-27 : https://github.com/inventree/InvenTree/pull/12019
|
||||
- Adds "location" field to StockCount API endpoint
|
||||
|
|
|
|||
|
|
@ -2307,25 +2307,27 @@ class StockItem(
|
|||
self.parent = None
|
||||
self.save()
|
||||
|
||||
if other.location:
|
||||
location_note = _('Transferred from %(location)s') % {
|
||||
'location': other.location.pathstring
|
||||
}
|
||||
|
||||
notes = f'{notes}\n{location_note}' if notes else location_note
|
||||
|
||||
other.delete()
|
||||
|
||||
transfer_deltas = kwargs.pop('transfer_deltas', None)
|
||||
|
||||
tracking_deltas = {
|
||||
'quantity': float(self.quantity),
|
||||
'added': float(merged_quantity),
|
||||
}
|
||||
|
||||
if location:
|
||||
tracking_deltas['location'] = location.pk
|
||||
|
||||
if transfer_deltas:
|
||||
tracking_deltas = {**transfer_deltas, **tracking_deltas}
|
||||
|
||||
self.add_tracking_entry(
|
||||
StockHistoryCode.MERGED_STOCK_ITEMS,
|
||||
user,
|
||||
quantity=self.quantity,
|
||||
notes=notes,
|
||||
deltas={
|
||||
'location': location.pk if location else None,
|
||||
'quantity': float(self.quantity),
|
||||
'added': float(merged_quantity),
|
||||
},
|
||||
deltas=tracking_deltas,
|
||||
)
|
||||
|
||||
# Update the location of the item
|
||||
|
|
@ -2386,6 +2388,8 @@ class StockItem(
|
|||
status: If provided, override the status (default = existing status)
|
||||
packaging: If provided, override the packaging (default = existing packaging)
|
||||
allow_production: If True, allow splitting of stock which is in production (default = False)
|
||||
record_tracking: If False, skip tracking entries (for merge-on-transfer)
|
||||
split_transfer_deltas: Optional dict to receive split tracking deltas
|
||||
|
||||
Returns:
|
||||
The new StockItem object
|
||||
|
|
@ -2398,6 +2402,8 @@ class StockItem(
|
|||
"""
|
||||
# Run initial checks to test if the stock item can actually be "split"
|
||||
allow_production = kwargs.get('allow_production', False)
|
||||
record_tracking = kwargs.pop('record_tracking', True)
|
||||
split_transfer_deltas = kwargs.pop('split_transfer_deltas', None)
|
||||
|
||||
# Cannot split a stock item which is in production
|
||||
if self.is_building and not allow_production:
|
||||
|
|
@ -2470,15 +2476,23 @@ class StockItem(
|
|||
|
||||
new_stock.save(add_note=False)
|
||||
|
||||
# Add a stock tracking entry for the newly created item
|
||||
new_stock.add_tracking_entry(
|
||||
StockHistoryCode.SPLIT_FROM_PARENT,
|
||||
user,
|
||||
quantity=quantity,
|
||||
notes=notes,
|
||||
location=location,
|
||||
deltas=deltas,
|
||||
)
|
||||
if split_transfer_deltas is not None:
|
||||
split_transfer_deltas.clear()
|
||||
split_transfer_deltas.update(deltas)
|
||||
|
||||
if location:
|
||||
split_transfer_deltas['location'] = location.pk
|
||||
|
||||
if record_tracking:
|
||||
# Add a stock tracking entry for the newly created item
|
||||
new_stock.add_tracking_entry(
|
||||
StockHistoryCode.SPLIT_FROM_PARENT,
|
||||
user,
|
||||
quantity=quantity,
|
||||
notes=notes,
|
||||
location=location,
|
||||
deltas=deltas,
|
||||
)
|
||||
|
||||
# Copy the test results of this part to the new one
|
||||
new_stock.copyTestResultsFrom(self)
|
||||
|
|
@ -2491,6 +2505,7 @@ class StockItem(
|
|||
notes=notes,
|
||||
location=location,
|
||||
stockitem=new_stock,
|
||||
record_tracking=record_tracking,
|
||||
)
|
||||
|
||||
# Rebuild the tree for this parent item
|
||||
|
|
@ -2800,7 +2815,10 @@ class StockItem(
|
|||
code: The stock history code to use
|
||||
notes: Optional notes for the stock removal
|
||||
status: Optionally adjust the stock status
|
||||
record_tracking: If False, skip creating a tracking entry
|
||||
"""
|
||||
record_tracking = kwargs.pop('record_tracking', True)
|
||||
|
||||
# Cannot remove items from a serialized part
|
||||
if self.serialized:
|
||||
return False
|
||||
|
|
@ -2850,9 +2868,10 @@ class StockItem(
|
|||
|
||||
self.save(add_note=False)
|
||||
|
||||
self.add_tracking_entry(
|
||||
code, user, notes=kwargs.get('notes', ''), deltas=deltas
|
||||
)
|
||||
if record_tracking:
|
||||
self.add_tracking_entry(
|
||||
code, user, notes=kwargs.get('notes', ''), deltas=deltas
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
|
|
|||
|
|
@ -1907,16 +1907,31 @@ class StockTransferSerializer(StockAdjustmentSerializer):
|
|||
}
|
||||
|
||||
if quantity < stock_item.quantity:
|
||||
transfer_deltas = {}
|
||||
|
||||
piece = stock_item.splitStock(
|
||||
quantity,
|
||||
location,
|
||||
request.user,
|
||||
notes=notes,
|
||||
allow_production=True,
|
||||
record_tracking=False,
|
||||
split_transfer_deltas=transfer_deltas,
|
||||
**kwargs,
|
||||
)
|
||||
merge_kwargs['transfer_deltas'] = transfer_deltas
|
||||
target.merge_stock_items([piece], **merge_kwargs)
|
||||
else:
|
||||
transfer_deltas = {'stockitem': stock_item.pk}
|
||||
|
||||
if location:
|
||||
transfer_deltas['location'] = location.pk
|
||||
|
||||
for field_name in StockItem.optional_transfer_fields():
|
||||
if field_name in kwargs:
|
||||
transfer_deltas[field_name] = kwargs[field_name]
|
||||
|
||||
merge_kwargs['transfer_deltas'] = transfer_deltas
|
||||
target.merge_stock_items([stock_item], **merge_kwargs)
|
||||
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -2448,6 +2448,7 @@ class StockTransferMergeTest(StockAPITestCase):
|
|||
StockHistoryCode.STOCK_UPDATE, self.user, notes='Source tracking entry'
|
||||
)
|
||||
|
||||
incoming_pk = incoming.pk
|
||||
tracking_count = existing.tracking_info.count()
|
||||
|
||||
self.post(
|
||||
|
|
@ -2471,6 +2472,40 @@ class StockTransferMergeTest(StockAPITestCase):
|
|||
self.assertIsNotNone(merge_entry)
|
||||
self.assertEqual(merge_entry.deltas['added'], 50.0)
|
||||
self.assertEqual(merge_entry.deltas['quantity'], 150.0)
|
||||
self.assertEqual(merge_entry.deltas['stockitem'], incoming_pk)
|
||||
self.assertEqual(merge_entry.deltas['location'], self.dest.pk)
|
||||
|
||||
def test_transfer_merge_partial_reuses_split_transfer_deltas(self):
|
||||
"""Partial merge reuses split transfer deltas on the merge tracking entry."""
|
||||
existing = StockItem.objects.create(
|
||||
part=self.part, location=self.dest, quantity=100
|
||||
)
|
||||
incoming = StockItem.objects.create(
|
||||
part=self.part, location=self.source_loc, quantity=100
|
||||
)
|
||||
|
||||
self.post(
|
||||
self.url,
|
||||
{
|
||||
'items': [{'pk': incoming.pk, 'quantity': 30, 'merge': True}],
|
||||
'location': self.dest.pk,
|
||||
},
|
||||
expected_code=201,
|
||||
)
|
||||
|
||||
incoming.refresh_from_db()
|
||||
self.assertEqual(incoming.quantity, 70)
|
||||
|
||||
merge_entry = existing.tracking_info.filter(
|
||||
tracking_type=StockHistoryCode.MERGED_STOCK_ITEMS
|
||||
).first()
|
||||
self.assertEqual(merge_entry.deltas['stockitem'], incoming.pk)
|
||||
self.assertEqual(merge_entry.deltas['location'], self.dest.pk)
|
||||
self.assertFalse(
|
||||
incoming.tracking_info.filter(
|
||||
tracking_type=StockHistoryCode.SPLIT_CHILD_ITEM
|
||||
).exists()
|
||||
)
|
||||
|
||||
|
||||
class StockItemDeletionTest(StockAPITestCase):
|
||||
|
|
|
|||
Loading…
Reference in New Issue