Coverage for src/backend/InvenTree/part/migrations/0149_bomitem_raw_amount.py: 58%

28 statements  

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

1# Generated by Django 5.2.12 on 2026-03-30 10:01 

2 

3from decimal import Decimal 

4 

5from django.db import migrations, models 

6 

7from InvenTree.helpers import normalize 

8 

9 

10def set_default_raw_amount(apps, schema_editor): 

11 """Initialize the 'raw_amount' field for existing BomItem records.""" 

12 BomItem = apps.get_model("part", "BomItem") 

13 

14 to_update = [] 

15 updated_count = 0 

16 

17 # Run BulkUpdate in batches to avoid memory issues with large datasets 

18 BATCH_SIZE = 100 

19 

20 N_BOM_ITEMS = BomItem.objects.count() 

21 

22 def add_bom_item(item): 

23 nonlocal to_update 

24 nonlocal updated_count 

25 

26 to_update.append(item) 

27 

28 if len(to_update) >= BATCH_SIZE: 

29 BomItem.objects.bulk_update(to_update, ["raw_amount"]) 

30 updated_count += len(to_update) 

31 to_update = [] 

32 

33 for item in BomItem.objects.all(): 33 ↛ 34line 33 didn't jump to line 34 because the loop on line 33 never started

34 item.raw_amount = str(normalize(Decimal(item.quantity))) 

35 add_bom_item(item) 

36 

37 # Handle any remaining items that were not updated in the loop 

38 if len(to_update) > 0: 38 ↛ 39line 38 didn't jump to line 39 because the condition on line 38 was never true

39 BomItem.objects.bulk_update(to_update, ["raw_amount"]) 

40 updated_count += len(to_update) 

41 

42 assert updated_count == N_BOM_ITEMS, f"Expected to update {N_BOM_ITEMS} BomItem records, but updated {updated_count} records instead." 

43 

44 assert BomItem.objects.filter(raw_amount="").count() == 0, "There are BomItem records with an empty 'raw_amount' field after migration." 

45 

46 if updated_count > 0: 46 ↛ 47line 46 didn't jump to line 47 because the condition on line 46 was never true

47 print(f"Initialized 'raw_amount' field for {updated_count} BomItem records.") 

48 

49 

50class Migration(migrations.Migration): 

51 """Run a set of data and schema migrations to add a new 'raw_amount' field to the BomItem model. 

52 

53 1. Add a new 'raw_amount' field to the BomItem model, which is a CharField that can store a raw amount of sub-part consumed to produce one part. This field can be used to store fractional amounts or amounts with associated units (e.g. '10 hours', '5 kg', etc.). 

54 2. Run a data migration to initialize the 'raw_amount' field for existing BomItem records, by copying the value from the existing 'quantity' field and converting it to a string. 

55 3. Mark the 'raw_amount' field as blank=False, now that the quantity values have been copied across 

56 """ 

57 

58 dependencies = [ 

59 ("part", "0148_auto_20260427_2233"), 

60 ] 

61 

62 operations = [ 

63 migrations.AddField( 

64 model_name="bomitem", 

65 name="raw_amount", 

66 field=models.CharField( 

67 blank=True, 

68 null=False, 

69 help_text="Amount of sub-part consumed to produce one part", 

70 max_length=25, 

71 verbose_name="Amount", 

72 ), 

73 ), 

74 migrations.RunPython(set_default_raw_amount, reverse_code=migrations.RunPython.noop), 

75 migrations.AlterField( 

76 model_name="bomitem", 

77 name="raw_amount", 

78 field=models.CharField( 

79 blank=False, 

80 null=False, 

81 help_text="Amount of sub-part consumed to produce one part", 

82 max_length=25, 

83 verbose_name="Amount", 

84 ), 

85 ), 

86 ]