Coverage for src/backend/InvenTree/report/migrations/0026_auto_20240422_1301.py: 41%
61 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 4.2.11 on 2024-04-22 13:01
3import os
5from django.core.files.base import ContentFile
6from django.core.files.storage import default_storage
7from django.db import connection, migrations
9import InvenTree.ready
12def label_model_map():
13 """Map legacy label template models to model_type values."""
15 return {
16 "stockitemlabel": "stockitem",
17 "stocklocationlabel": "stocklocation",
18 "partlabel": "part",
19 "buildlinelabel": "buildline",
20 }
23def convert_legacy_labels(table_name, model_name, template_model):
24 """Map labels from an existing table to a new model type
26 Arguments:
27 table_name: The name of the existing table
28 model_name: The name of the new model type
29 template_model: The model class for the new template model
31 Note: We use raw SQL queries here, as the original 'label' app has been removed entirely.
32 """
33 count = 0
35 fields = [
36 'name', 'description', 'label', 'enabled', 'height', 'width', 'filename_pattern', 'filters'
37 ]
39 non_null_fields = ['description', 'filename_pattern', 'filters']
41 fieldnames = ', '.join(fields)
43 query = f"SELECT {fieldnames} FROM {table_name};"
45 with connection.cursor() as cursor:
46 try:
47 cursor.execute(query)
48 except Exception:
49 # Table likely does not exist - database was created more recently
50 return 0
52 rows = cursor.fetchall()
54 for row in rows:
55 data = {
56 fields[idx]: row[idx] for idx in range(len(fields))
57 }
59 for field in non_null_fields:
60 if data.get(field, None) is None:
61 data[field] = ''
63 # Skip any "builtin" labels
64 if 'label/inventree/' in data['label']:
65 continue
67 print(f"Creating new LabelTemplate for {model_name} - {data['name']}")
69 if template_model.objects.filter(name=data['name'], model_type=model_name).exists():
70 print(f"LabelTemplate {data['name']} already exists for {model_name} - skipping")
71 continue
74 if not default_storage.exists(data['label']):
75 print(f"Label template file {data['label']} does not exist - skipping")
76 continue
78 # Create a new template file object
79 filedata = default_storage.open(data['label']).read()
80 filename = os.path.basename(data['label'])
82 # Remove the 'label' key from the data dictionary
83 data.pop('label')
85 data['template'] = ContentFile(filedata, filename)
86 data['model_type'] = model_name
88 template_model.objects.create(**data)
90 count += 1
92 return count
95def forward(apps, schema_editor):
96 """Run forwards migrations.
98 - Create a new LabelTemplate instance for each existing legacy label template.
99 """
101 LabelTemplate = apps.get_model('report', 'labeltemplate')
103 count = 0
105 for template_class, model_type in label_model_map().items():
107 table_name = f'label_{template_class}'
109 count += convert_legacy_labels(table_name, model_type, LabelTemplate) or 0
111 if count > 0: 111 ↛ 112line 111 didn't jump to line 112 because the condition on line 111 was never true
112 print(f"Migrated {count} report templates to new LabelTemplate model.")
114def reverse(apps, schema_editor):
115 """Run reverse migrations.
117 - Delete any LabelTemplate instances in the database
118 """
120 LabelTemplate = apps.get_model('report', 'labeltemplate')
122 n = LabelTemplate.objects.count()
124 if n > 0:
125 for item in LabelTemplate.objects.all():
127 item.template.delete()
128 item.delete()
130 print(f"Deleted {n} LabelTemplate objects and templates")
132class Migration(migrations.Migration):
134 atomic = False
136 dependencies = [
137 ('report', '0025_labeltemplate'),
138 ]
140 operations = [
141 migrations.RunPython(forward, reverse_code=reverse)
142 ]