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
« 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
3from decimal import Decimal
5from django.db import migrations, models
7from InvenTree.helpers import normalize
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")
14 to_update = []
15 updated_count = 0
17 # Run BulkUpdate in batches to avoid memory issues with large datasets
18 BATCH_SIZE = 100
20 N_BOM_ITEMS = BomItem.objects.count()
22 def add_bom_item(item):
23 nonlocal to_update
24 nonlocal updated_count
26 to_update.append(item)
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 = []
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)
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)
42 assert updated_count == N_BOM_ITEMS, f"Expected to update {N_BOM_ITEMS} BomItem records, but updated {updated_count} records instead."
44 assert BomItem.objects.filter(raw_amount="").count() == 0, "There are BomItem records with an empty 'raw_amount' field after migration."
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.")
50class Migration(migrations.Migration):
51 """Run a set of data and schema migrations to add a new 'raw_amount' field to the BomItem model.
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 """
58 dependencies = [
59 ("part", "0148_auto_20260427_2233"),
60 ]
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 ]