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

1"""Background tasks for the stock app.""" 

2 

3from datetime import datetime, timedelta 

4 

5import structlog 

6from opentelemetry import trace 

7 

8from common.settings import get_global_setting 

9from InvenTree.tasks import ScheduledTask, offload_task, scheduled_task 

10 

11tracer = trace.get_tracer(__name__) 

12logger = structlog.get_logger('inventree') 

13 

14 

15@tracer.start_as_current_span('rebuild_stock_items') 

16def rebuild_stock_items(): 

17 """Rebuild the entire StockItem tree structure. 

18 

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 

24 

25 logger.info('Rebuilding StockItem tree structure') 

26 

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) 

32 

33 log_error('rebuild_stock_items') 

34 logger.exception('Failed to rebuild StockItem tree: %s', e) 

35 

36 

37def rebuild_stock_item_tree(tree_id: int, rebuild_on_fail: bool = True) -> bool: 

38 """Rebuild the stock tree structure. 

39 

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. 

43 

44 Returns: 

45 bool: True if the partial tree rebuild was successful, False otherwise. 

46 

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 

52 

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) 

61 

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 

72 

73 

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 

79 

80 if not get_global_setting('STOCK_TRACKING_DELETE_OLD_ENTRIES', False): 

81 return 

82 

83 delete_n_days = int(get_global_setting('STOCK_TRACKING_DELETE_DAYS', 365)) 

84 

85 threshold = datetime.now() - timedelta(days=delete_n_days) 

86 

87 old_entries = StockItemTracking.objects.filter(date__lte=threshold) 

88 

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()