mirror of
https://github.com/inventree/InvenTree.git
synced 2025-05-02 05:26:45 +00:00
Stock history fix (#4541)
* Fix bug in allocateToCustomer method * Data migration to alter stock tracking history with new codes and data * Prevent note duplication
This commit is contained in:
parent
47f52478e0
commit
d0bf4cb81a
70
InvenTree/stock/migrations/0096_auto_20230330_1121.py
Normal file
70
InvenTree/stock/migrations/0096_auto_20230330_1121.py
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
# Generated by Django 3.2.18 on 2023-03-30 11:21
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
def update_stock_history(apps, schema_editor):
|
||||||
|
"""Data migration to fix a 'shortcoming' in the implementation of StockTracking history
|
||||||
|
|
||||||
|
Prior to https://github.com/inventree/InvenTree/pull/4488,
|
||||||
|
shipping items via a SalesOrder did not record the SalesOrder in the tracking history.
|
||||||
|
This PR looks to add in SalesOrder history where it does not already exist:
|
||||||
|
|
||||||
|
- Look for StockItems which are currently assigned to a SalesOrder
|
||||||
|
- Check that it does *not* have any appropriate history
|
||||||
|
- Add the appropriate history!
|
||||||
|
"""
|
||||||
|
|
||||||
|
from InvenTree.status_codes import StockHistoryCode
|
||||||
|
|
||||||
|
StockItem = apps.get_model('stock', 'stockitem')
|
||||||
|
StockItemTracking = apps.get_model('stock', 'stockitemtracking')
|
||||||
|
|
||||||
|
# Find StockItems which are marked as against a SalesOrder
|
||||||
|
items = StockItem.objects.exclude(sales_order=None)
|
||||||
|
|
||||||
|
n = 0
|
||||||
|
|
||||||
|
for item in items:
|
||||||
|
# Find newest relevent history
|
||||||
|
history = StockItemTracking.objects.filter(
|
||||||
|
item=item,
|
||||||
|
tracking_type__in=[StockHistoryCode.SENT_TO_CUSTOMER, StockHistoryCode.SHIPPED_AGAINST_SALES_ORDER]
|
||||||
|
).order_by('-date').first()
|
||||||
|
|
||||||
|
if not history:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# We've already updated this one, it appears
|
||||||
|
if history.tracking_type != StockHistoryCode.SENT_TO_CUSTOMER:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Update the 'deltas' of this history to include SalesOrder information
|
||||||
|
history.deltas['salesorder'] = item.sales_order.pk
|
||||||
|
|
||||||
|
# Change the history type
|
||||||
|
history.tracking_type = StockHistoryCode.SHIPPED_AGAINST_SALES_ORDER
|
||||||
|
|
||||||
|
history.save()
|
||||||
|
n += 1
|
||||||
|
|
||||||
|
if n > 0:
|
||||||
|
print(f"Updated {n} StockItemTracking entries with SalesOrder data")
|
||||||
|
|
||||||
|
|
||||||
|
def nope(apps, schema_editor):
|
||||||
|
"""Provided for reverse migration compatibility"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('stock', '0095_stocklocation_external'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(
|
||||||
|
update_stock_history, reverse_code=nope,
|
||||||
|
)
|
||||||
|
]
|
@ -961,11 +961,13 @@ class StockItem(InvenTreeBarcodeMixin, MetadataMixin, common.models.MetaMixin, M
|
|||||||
item.save(add_note=False)
|
item.save(add_note=False)
|
||||||
|
|
||||||
code = StockHistoryCode.SENT_TO_CUSTOMER
|
code = StockHistoryCode.SENT_TO_CUSTOMER
|
||||||
deltas = {
|
deltas = {}
|
||||||
'customer': customer.pk,
|
|
||||||
'customer_name': customer.pk,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if customer is not None:
|
||||||
|
deltas['customer'] = customer.pk
|
||||||
|
deltas['customer_name'] = customer.name
|
||||||
|
|
||||||
|
# If an order is provided, we are shipping against a SalesOrder, not manually!
|
||||||
if order:
|
if order:
|
||||||
code = StockHistoryCode.SHIPPED_AGAINST_SALES_ORDER
|
code = StockHistoryCode.SHIPPED_AGAINST_SALES_ORDER
|
||||||
deltas['salesorder'] = order.pk
|
deltas['salesorder'] = order.pk
|
||||||
@ -1031,7 +1033,7 @@ class StockItem(InvenTreeBarcodeMixin, MetadataMixin, common.models.MetaMixin, M
|
|||||||
notes=notes
|
notes=notes
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.save()
|
self.save(add_note=False)
|
||||||
|
|
||||||
def is_allocated(self):
|
def is_allocated(self):
|
||||||
"""Return True if this StockItem is allocated to a SalesOrder or a Build."""
|
"""Return True if this StockItem is allocated to a SalesOrder or a Build."""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user