Coverage for src/backend/InvenTree/stock/tasks.py: 23%
49 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 17:47 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 17:47 +0000
1"""Background tasks for the stock app."""
3from datetime import datetime, timedelta
5import structlog
6from opentelemetry import trace
8from common.settings import get_global_setting
9from InvenTree.tasks import ScheduledTask, offload_task, scheduled_task
11tracer = trace.get_tracer(__name__)
12logger = structlog.get_logger('inventree')
15@tracer.start_as_current_span('rebuild_stock_items')
16def rebuild_stock_items():
17 """Rebuild the entire StockItem tree structure.
19 This may be necessary if the tree structure has become corrupted or inconsistent.
20 """
21 from InvenTree.exceptions import log_error
22 from InvenTree.sentry import report_exception
23 from stock.models import StockItem
25 logger.info('Rebuilding StockItem tree structure')
27 try:
28 StockItem.objects.rebuild()
29 except Exception as e:
30 # This is a critical error, explicitly report to sentry
31 report_exception(e)
33 log_error('rebuild_stock_items')
34 logger.exception('Failed to rebuild StockItem tree: %s', e)
37def rebuild_stock_item_tree(tree_id: int, rebuild_on_fail: bool = True) -> bool:
38 """Rebuild the stock tree structure.
40 Arguments:
41 tree_id (int): The ID of the StockItem tree to rebuild.
42 rebuild_on_fail (bool): If True, will attempt to rebuild the entire StockItem tree if the partial rebuild fails.
44 Returns:
45 bool: True if the partial tree rebuild was successful, False otherwise.
47 - If the rebuild fails, schedule a rebuild of the entire StockItem tree.
48 """
49 from InvenTree.exceptions import log_error
50 from InvenTree.sentry import report_exception
51 from stock.models import StockItem
53 if tree_id:
54 try:
55 StockItem.objects.partial_rebuild(tree_id)
56 logger.info('Rebuilt StockItem tree for tree_id: %s', tree_id)
57 return True
58 except Exception as e:
59 # This is a critical error, explicitly report to sentry
60 report_exception(e)
62 log_error('rebuild_stock_item_tree')
63 logger.warning('Failed to rebuild StockItem tree for tree_id: %s', tree_id)
64 # If the partial rebuild fails, rebuild the entire tree
65 if rebuild_on_fail:
66 offload_task(rebuild_stock_items, group='stock')
67 return False
68 else:
69 # No tree_id provided, so rebuild the entire tree
70 StockItem.objects.rebuild()
71 return True
74@tracer.start_as_current_span('delete_old_stock_tracking')
75@scheduled_task(ScheduledTask.DAILY)
76def delete_old_stock_tracking():
77 """Remove old stock tracking entries before a certain date."""
78 from stock.models import StockItemTracking
80 if not get_global_setting('STOCK_TRACKING_DELETE_OLD_ENTRIES', False):
81 return
83 delete_n_days = int(get_global_setting('STOCK_TRACKING_DELETE_DAYS', 365))
85 threshold = datetime.now() - timedelta(days=delete_n_days)
87 old_entries = StockItemTracking.objects.filter(date__lte=threshold)
89 if old_entries.exists():
90 logger.info(
91 'Deleting old stock tracking entries',
92 count=old_entries.count(),
93 threshold=threshold,
94 )
95 old_entries.delete()