Coverage for src/backend/InvenTree/stock/migrations/0106_auto_20240207_0353.py: 24%

57 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-07 17:47 +0000

1# Generated by Django 4.2.9 on 2024-02-07 03:53 

2 

3from django.db import migrations 

4 

5 

6def set_template(apps, schema_editor): 

7 """Matching existing StockItemTestResult objects to their associated template. 

8 

9 - Use the 'key' value from the associated test object. 

10 - Look at the referenced part first 

11 - If no matches, look at parent part template(s) 

12 - If still no matches, create a new PartTestTemplate object 

13 """ 

14 import time 

15 import InvenTree.helpers 

16 

17 StockItemTestResult = apps.get_model('stock', 'stockitemtestresult') 

18 PartTestTemplate = apps.get_model('part', 'parttesttemplate') 

19 Part = apps.get_model('part', 'part') 

20 

21 # Look at any test results which do not match a template 

22 results = StockItemTestResult.objects.filter(template=None) 

23 

24 parts = results.values_list('stock_item__part', flat=True).distinct() 

25 

26 n_results = results.count() 

27 

28 if n_results == 0: 28 ↛ 31line 28 didn't jump to line 31 because the condition on line 28 was always true

29 return 

30 

31 print(f"\n{n_results} StockItemTestResult objects do not have matching templates!") 

32 print(f"Updating test results for {len(parts)} unique parts...") 

33 

34 # Keep a map of test templates  

35 part_tree_map = {} 

36 

37 t1 = time.time() 

38 

39 new_templates = 0 

40 

41 # For each part with missing templates, work out what templates are missing 

42 for pk in parts: 

43 part = Part.objects.get(pk=pk) 

44 tree_id = part.tree_id 

45 # Find all results matching this part 

46 part_results = results.filter(stock_item__part=part) 

47 test_names = part_results.values_list('test', flat=True).distinct() 

48 

49 key_map = part_tree_map.get(tree_id, None) or {} 

50 

51 for name in test_names: 

52 template = None 

53 

54 key = InvenTree.helpers.generateTestKey(name) 

55 

56 if template := key_map.get(key, None): 

57 # We have a template for this key 

58 pass 

59 

60 elif template := PartTestTemplate.objects.filter(part__tree_id=part.tree_id, key=key).first(): 

61 # We have found an existing template for this test 

62 pass 

63 

64 elif template := PartTestTemplate.objects.filter( 

65 part__tree_id=part.tree_id, 

66 part__lft__lte=part.lft, 

67 part__rght__gte=part.rght, 

68 key=key).first(): 

69 # We have found an existing template for this test 

70 pass 

71 

72 # Create a new template, based on the available test information 

73 else: 

74 

75 # Find the parent part template 

76 top_level_part = part 

77 

78 while top_level_part.variant_of: 

79 top_level_part = top_level_part.variant_of 

80 

81 template = PartTestTemplate.objects.create( 

82 part=top_level_part, 

83 test_name=name, 

84 key=key, 

85 ) 

86 

87 new_templates += 1 

88 

89 # Finally, update all matching results 

90 part_results.filter(test=name).update(template=template) 

91 

92 # Update the key map for this part tree 

93 key_map[key] = template 

94 

95 # Update the part tree map 

96 part_tree_map[tree_id] = key_map 

97 

98 t2 = time.time() 

99 dt = t2 - t1 

100 

101 print(f"Updated {n_results} StockItemTestResult objects in {dt:.3f} seconds.") 

102 

103 if new_templates > 0: 

104 print(f"Created {new_templates} new templates!") 

105 

106 # Check that there are now zero reamining results without templates 

107 results = StockItemTestResult.objects.filter(template=None) 

108 assert(results.count() == 0) 

109 

110 

111def remove_template(apps, schema_editor): 

112 """Remove template links from existing StockItemTestResult objects.""" 

113 

114 StockItemTestResult = apps.get_model('stock', 'stockitemtestresult') 

115 results = StockItemTestResult.objects.all() 

116 results.update(template=None) 

117 

118 if results.count() > 0: 

119 print(f"\nRemoved template links from {results.count()} StockItemTestResult objects") 

120 

121 

122class Migration(migrations.Migration): 

123 

124 atomic = False 

125 

126 dependencies = [ 

127 ('stock', '0105_stockitemtestresult_template'), 

128 ('part', '0121_auto_20240207_0344') 

129 ] 

130 

131 operations = [ 

132 migrations.RunPython(set_template, reverse_code=remove_template), 

133 ]