wbreport 2.2.1__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of wbreport might be problematic. Click here for more details.

Files changed (66) hide show
  1. wbreport/__init__.py +1 -0
  2. wbreport/admin.py +87 -0
  3. wbreport/apps.py +6 -0
  4. wbreport/defaults/__init__.py +0 -0
  5. wbreport/defaults/factsheets/__init__.py +0 -0
  6. wbreport/defaults/factsheets/base.py +990 -0
  7. wbreport/defaults/factsheets/menu.py +93 -0
  8. wbreport/defaults/factsheets/mixins.py +35 -0
  9. wbreport/defaults/factsheets/multitheme.py +947 -0
  10. wbreport/dynamic_preferences_registry.py +15 -0
  11. wbreport/factories/__init__.py +8 -0
  12. wbreport/factories/data_classes.py +48 -0
  13. wbreport/factories/reports.py +79 -0
  14. wbreport/filters.py +37 -0
  15. wbreport/migrations/0001_initial_squashed_squashed_0007_report_key.py +238 -0
  16. wbreport/migrations/0008_alter_report_file_content_type.py +25 -0
  17. wbreport/migrations/0009_alter_report_color_palette.py +27 -0
  18. wbreport/migrations/0010_auto_20240103_0947.py +43 -0
  19. wbreport/migrations/0011_auto_20240207_1629.py +35 -0
  20. wbreport/migrations/0012_reportversion_lock.py +17 -0
  21. wbreport/migrations/0013_alter_reportversion_context.py +18 -0
  22. wbreport/migrations/0014_alter_reportcategory_options_and_more.py +25 -0
  23. wbreport/migrations/__init__.py +0 -0
  24. wbreport/mixins.py +183 -0
  25. wbreport/models.py +781 -0
  26. wbreport/pdf/__init__.py +0 -0
  27. wbreport/pdf/charts/__init__.py +0 -0
  28. wbreport/pdf/charts/legend.py +15 -0
  29. wbreport/pdf/charts/pie.py +169 -0
  30. wbreport/pdf/charts/timeseries.py +77 -0
  31. wbreport/pdf/sandbox/__init__.py +0 -0
  32. wbreport/pdf/sandbox/run.py +17 -0
  33. wbreport/pdf/sandbox/templates/__init__.py +0 -0
  34. wbreport/pdf/sandbox/templates/basic_factsheet.py +908 -0
  35. wbreport/pdf/sandbox/templates/fund_factsheet.py +864 -0
  36. wbreport/pdf/sandbox/templates/long_industry_exposure_factsheet.py +898 -0
  37. wbreport/pdf/sandbox/templates/multistrat_factsheet.py +872 -0
  38. wbreport/pdf/sandbox/templates/testfile.pdf +434 -0
  39. wbreport/pdf/tables/__init__.py +0 -0
  40. wbreport/pdf/tables/aggregated_tables.py +156 -0
  41. wbreport/pdf/tables/data_tables.py +75 -0
  42. wbreport/serializers.py +191 -0
  43. wbreport/tasks.py +60 -0
  44. wbreport/templates/__init__.py +0 -0
  45. wbreport/templatetags/__init__.py +0 -0
  46. wbreport/templatetags/portfolio_tags.py +35 -0
  47. wbreport/tests/__init__.py +0 -0
  48. wbreport/tests/conftest.py +24 -0
  49. wbreport/tests/test_models.py +253 -0
  50. wbreport/tests/test_tasks.py +17 -0
  51. wbreport/tests/test_viewsets.py +0 -0
  52. wbreport/tests/tests.py +12 -0
  53. wbreport/urls.py +29 -0
  54. wbreport/urls_public.py +10 -0
  55. wbreport/viewsets/__init__.py +10 -0
  56. wbreport/viewsets/configs/__init__.py +18 -0
  57. wbreport/viewsets/configs/buttons.py +193 -0
  58. wbreport/viewsets/configs/displays.py +116 -0
  59. wbreport/viewsets/configs/endpoints.py +23 -0
  60. wbreport/viewsets/configs/menus.py +8 -0
  61. wbreport/viewsets/configs/titles.py +30 -0
  62. wbreport/viewsets/viewsets.py +330 -0
  63. wbreport-2.2.1.dist-info/METADATA +6 -0
  64. wbreport-2.2.1.dist-info/RECORD +66 -0
  65. wbreport-2.2.1.dist-info/WHEEL +5 -0
  66. wbreport-2.2.1.dist-info/licenses/LICENSE +4 -0
@@ -0,0 +1,15 @@
1
+ from dynamic_preferences.preferences import Section
2
+ from dynamic_preferences.registries import global_preferences_registry
3
+ from dynamic_preferences.types import IntegerPreference
4
+
5
+ report_section = Section("report")
6
+
7
+
8
+ @global_preferences_registry.register
9
+ class ReportMailTemplateIdPreference(IntegerPreference):
10
+ section = report_section
11
+ name = "report_mail_template_id"
12
+ default = -1
13
+
14
+ verbose_name = "Report Mail Template ID"
15
+ help_text = "The Template ID used to send the report by email"
@@ -0,0 +1,8 @@
1
+ from .reports import (
2
+ ParentReportFactory,
3
+ ReportAssetFactory,
4
+ ReportCategoryFactory,
5
+ ReportClassFactory,
6
+ ReportFactory,
7
+ ReportVersionFactory,
8
+ )
@@ -0,0 +1,48 @@
1
+ import datetime as dt
2
+ from io import BytesIO
3
+
4
+ from django.template import Context, Template
5
+ from wbreport.mixins import ReportMixin
6
+
7
+
8
+ class ReportClass(ReportMixin):
9
+ HTML_TEMPLATE_CONTENT = "<p>{{ title }}</p>"
10
+
11
+ @classmethod
12
+ def parse_parameters(cls, parameters):
13
+ return {
14
+ "iteration": parameters["iteration"],
15
+ "end": dt.datetime.strptime(parameters["end"], "%Y-%m-%d"),
16
+ }
17
+
18
+ @classmethod
19
+ def get_next_parameters(cls, parameters):
20
+ parameters = cls.parse_parameters(parameters=parameters)
21
+ return {
22
+ "iteration": parameters["iteration"] + 1,
23
+ "end": dt.datetime.strftime(parameters["end"] + dt.timedelta(days=1), "%Y-%m-%d"),
24
+ }
25
+
26
+ @classmethod
27
+ def get_version_title(cls, report_title, parameters=None):
28
+ return f'{report_title}-{parameters.get("iteration", "")}'
29
+
30
+ @classmethod
31
+ def get_version_date(cls, parameters):
32
+ return parameters.get("end", None)
33
+
34
+ @classmethod
35
+ def get_context(cls, version):
36
+ if not version.parameters:
37
+ raise ValueError("Parameters needs to be defined")
38
+ return {"title": version.title}
39
+
40
+ @classmethod
41
+ def generate_html(cls, context) -> str:
42
+ template = Template(cls.HTML_TEMPLATE_CONTENT)
43
+ return template.render(Context(context))
44
+
45
+ @classmethod
46
+ def generate_file(cls, context) -> BytesIO:
47
+ output = BytesIO(context["title"].encode("utf_8"))
48
+ return output
@@ -0,0 +1,79 @@
1
+ from io import BytesIO
2
+
3
+ import factory
4
+ from PIL import Image
5
+ from wbcore.contrib.color.factories import ColorGradientFactory
6
+ from wbreport.models import (
7
+ Report,
8
+ ReportAsset,
9
+ ReportCategory,
10
+ ReportClass,
11
+ ReportVersion,
12
+ )
13
+
14
+
15
+ def create_test_image():
16
+ file = BytesIO()
17
+ image = Image.new("RGBA", size=(50, 50), color=(155, 0, 0))
18
+ image.save(file, "png")
19
+ file.name = "test.png"
20
+ file.seek(0)
21
+ return file
22
+
23
+
24
+ class ReportAssetFactory(factory.django.DjangoModelFactory):
25
+ class Meta:
26
+ model = ReportAsset
27
+
28
+ key = factory.Sequence(lambda n: f"Report Asset {n}")
29
+ description = factory.Faker("paragraph")
30
+ text = factory.Faker("paragraph")
31
+ asset = factory.django.ImageField()
32
+
33
+
34
+ class ReportCategoryFactory(factory.django.DjangoModelFactory):
35
+ class Meta:
36
+ model = ReportCategory
37
+
38
+ title = factory.Sequence(lambda n: f"Report Category {n}")
39
+
40
+
41
+ class ReportClassFactory(factory.django.DjangoModelFactory):
42
+ class Meta:
43
+ model = ReportClass
44
+
45
+ title = factory.Sequence(lambda n: f"Report Class {n}")
46
+ class_path = "wbreport.factories.data_classes"
47
+
48
+
49
+ class ReportFactory(factory.django.DjangoModelFactory):
50
+ class Meta:
51
+ model = Report
52
+
53
+ category = factory.SubFactory(ReportCategoryFactory)
54
+ report_class = factory.SubFactory(ReportClassFactory)
55
+ is_active = factory.Faker("boolean")
56
+ base_color = factory.Faker("color")
57
+ title = factory.Sequence(lambda n: f"Report {n}")
58
+ logo_file = factory.django.ImageField()
59
+ color_palette = factory.SubFactory(ColorGradientFactory)
60
+ mailing_list = factory.SubFactory("wbmailing.factories.MailingListFactory")
61
+ parent_report = factory.SubFactory("wbreport.factories.ParentReportFactory")
62
+
63
+
64
+ class ParentReportFactory(ReportFactory):
65
+ parent_report = None
66
+ key = factory.Sequence(lambda n: f"key-{n}")
67
+
68
+
69
+ class ReportVersionFactory(factory.django.DjangoModelFactory):
70
+ class Meta:
71
+ model = ReportVersion
72
+
73
+ title = factory.Sequence(lambda n: f"Report Version {n}")
74
+ lookup = factory.Sequence(lambda n: f"lookup-{n}")
75
+ is_primary = True
76
+ disabled = False
77
+ report = factory.SubFactory(ReportFactory)
78
+ comment = factory.Faker("paragraph")
79
+ parameters = factory.Sequence(lambda n: {"type": f"type{n}"})
wbreport/filters.py ADDED
@@ -0,0 +1,37 @@
1
+ from wbcore import filters as wb_filters
2
+ from wbreport.models import Report, ReportVersion
3
+
4
+
5
+ class ReportFilterSet(wb_filters.FilterSet):
6
+ is_active = wb_filters.BooleanFilter(default=True)
7
+
8
+ class Meta:
9
+ model = Report
10
+ fields = {
11
+ "category": ["exact"],
12
+ "parent_report": ["exact", "isnull"],
13
+ "permission_type": ["exact"],
14
+ "base_color": ["exact"],
15
+ "mailing_list": ["exact"],
16
+ }
17
+
18
+
19
+ class ReportVersionFilterSet(wb_filters.FilterSet):
20
+ disabled = wb_filters.BooleanFilter(method="boolean_is_disabled", default=False)
21
+
22
+ def boolean_is_disabled(self, queryset, name, value):
23
+ if value is True:
24
+ return queryset.filter(disabled=True)
25
+ if value is False:
26
+ return queryset.filter(disabled=False)
27
+ return queryset
28
+
29
+ class Meta:
30
+ model = ReportVersion
31
+ fields = {
32
+ "report": ["exact"],
33
+ "version_date": ["gte", "exact", "lte"],
34
+ "creation_date": ["gte", "exact", "lte"],
35
+ "update_date": ["gte", "exact", "lte"],
36
+ "is_primary": ["exact"],
37
+ }
@@ -0,0 +1,238 @@
1
+ # Generated by Django 4.1.7 on 2023-04-19 05:30
2
+
3
+ import uuid
4
+
5
+ import colorfield.fields
6
+ import django.core.serializers.json
7
+ import django.db.models.deletion
8
+ import mptt.fields
9
+ import picklefield.fields
10
+ from django.conf import settings
11
+ from django.db import migrations, models
12
+
13
+
14
+ class Migration(migrations.Migration):
15
+ initial = True
16
+
17
+ dependencies = [
18
+ ("wbcore", "0001_initial_squashed_squashed_0010_preset_appliedpreset"),
19
+ ("wbmailing", "0001_initial_squashed_squashed_0008_alter_mail_bcc_email_alter_mail_cc_email_and_more"),
20
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
21
+ ("contenttypes", "0002_remove_content_type_name"),
22
+ ]
23
+
24
+ operations = [
25
+ migrations.CreateModel(
26
+ name="Report",
27
+ fields=[
28
+ ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
29
+ (
30
+ "permission_type",
31
+ models.CharField(
32
+ choices=[("INTERNAL", "Internal"), ("PUBLIC", "Public"), ("PRIVATE", "Private")],
33
+ default="PRIVATE",
34
+ max_length=8,
35
+ ),
36
+ ),
37
+ ("object_id", models.PositiveIntegerField(blank=True, null=True)),
38
+ (
39
+ "key",
40
+ models.CharField(
41
+ default="",
42
+ help_text="The key is like the family name: it represents the nature of the report.",
43
+ max_length=256,
44
+ ),
45
+ ),
46
+ (
47
+ "file_content_type",
48
+ models.CharField(
49
+ choices=[("PDF", "application/pdf"), ("CSV", "text/csv")], default="PDF", max_length=64
50
+ ),
51
+ ),
52
+ (
53
+ "is_active",
54
+ models.BooleanField(
55
+ default=False, help_text="True if a report needs to be available for this product"
56
+ ),
57
+ ),
58
+ (
59
+ "file_disabled",
60
+ models.BooleanField(default=False, help_text="True if this version file needs to be disabled"),
61
+ ),
62
+ (
63
+ "base_color",
64
+ colorfield.fields.ColorField(default="#FFF000", image_field=None, max_length=64, samples=None),
65
+ ),
66
+ ("title", models.CharField(max_length=256)),
67
+ ("namespace", models.CharField(default="", max_length=256)),
68
+ ("logo_file", models.FileField(blank=True, max_length=256, null=True, upload_to="report/logo")),
69
+ ("parameters", models.JSONField(default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder)),
70
+ ("lft", models.PositiveIntegerField(editable=False)),
71
+ ("rght", models.PositiveIntegerField(editable=False)),
72
+ ("tree_id", models.PositiveIntegerField(db_index=True, editable=False)),
73
+ ("level", models.PositiveIntegerField(editable=False)),
74
+ ],
75
+ options={
76
+ "verbose_name": "Report",
77
+ "verbose_name_plural": "Reports",
78
+ "abstract": False,
79
+ "default_permissions": ("add", "change", "delete", "view", "administrate"),
80
+ },
81
+ ),
82
+ migrations.CreateModel(
83
+ name="ReportAsset",
84
+ fields=[
85
+ ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
86
+ ("key", models.CharField(max_length=255, unique=True)),
87
+ ("description", models.TextField(blank=True, null=True)),
88
+ ("text", models.TextField(blank=True, null=True)),
89
+ ("asset", models.FileField(blank=True, max_length=256, null=True, upload_to="report/assets")),
90
+ ],
91
+ options={
92
+ "verbose_name": "Report Asset",
93
+ "verbose_name_plural": "Report Assets",
94
+ },
95
+ ),
96
+ migrations.CreateModel(
97
+ name="ReportCategory",
98
+ fields=[
99
+ ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
100
+ ("title", models.CharField(max_length=128)),
101
+ ("order", models.IntegerField(default=0)),
102
+ ],
103
+ options={
104
+ "verbose_name": "Report Category",
105
+ "verbose_name_plural": "Report Categories",
106
+ },
107
+ ),
108
+ migrations.CreateModel(
109
+ name="ReportClass",
110
+ fields=[
111
+ ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
112
+ ("title", models.CharField(max_length=256)),
113
+ ("class_path", models.CharField(max_length=256)),
114
+ ],
115
+ options={
116
+ "verbose_name": "Report Class",
117
+ "verbose_name_plural": "Report Classes",
118
+ },
119
+ ),
120
+ migrations.CreateModel(
121
+ name="ReportVersion",
122
+ fields=[
123
+ ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
124
+ ("uuid", models.UUIDField(default=uuid.uuid4, editable=False, unique=True)),
125
+ ("lookup", models.CharField(default="", max_length=256, unique=True)),
126
+ ("title", models.CharField(max_length=256)),
127
+ ("parameters", models.JSONField(default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder)),
128
+ ("context", picklefield.fields.PickledObjectField(default=dict, editable=False)),
129
+ ("version_date", models.DateField(blank=True, null=True)),
130
+ ("creation_date", models.DateTimeField(auto_now_add=True)),
131
+ ("update_date", models.DateTimeField(auto_now=True)),
132
+ ("comment", models.TextField(default="")),
133
+ (
134
+ "is_primary",
135
+ models.BooleanField(
136
+ default=False,
137
+ help_text="Only one Version from a report can be considered primary and is usually the last created one",
138
+ ),
139
+ ),
140
+ ("disabled", models.BooleanField(default=False, help_text="True if version needs to be disabled")),
141
+ (
142
+ "report",
143
+ models.ForeignKey(
144
+ on_delete=django.db.models.deletion.CASCADE,
145
+ related_name="versions",
146
+ to="wbreport.report",
147
+ verbose_name="Report",
148
+ ),
149
+ ),
150
+ ],
151
+ options={
152
+ "verbose_name": "Report Version",
153
+ "verbose_name_plural": "Report Versions",
154
+ },
155
+ ),
156
+ migrations.AddField(
157
+ model_name="report",
158
+ name="category",
159
+ field=models.ForeignKey(
160
+ blank=True,
161
+ help_text="The Visual Report category",
162
+ null=True,
163
+ on_delete=django.db.models.deletion.SET_NULL,
164
+ related_name="reports",
165
+ to="wbreport.reportcategory",
166
+ verbose_name="Report Category",
167
+ ),
168
+ ),
169
+ migrations.AddField(
170
+ model_name="report",
171
+ name="content_type",
172
+ field=models.ForeignKey(
173
+ blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to="contenttypes.contenttype"
174
+ ),
175
+ ),
176
+ migrations.AddField(
177
+ model_name="report",
178
+ name="creator",
179
+ field=models.ForeignKey(
180
+ blank=True,
181
+ null=True,
182
+ on_delete=django.db.models.deletion.SET_NULL,
183
+ related_name="created_%(app_label)s_%(class)s",
184
+ to=settings.AUTH_USER_MODEL,
185
+ ),
186
+ ),
187
+ migrations.AddField(
188
+ model_name="report",
189
+ name="mailing_list",
190
+ field=models.ForeignKey(
191
+ blank=True,
192
+ help_text="The Mailing List used to send the updated report link",
193
+ null=True,
194
+ on_delete=django.db.models.deletion.SET_NULL,
195
+ related_name="reports",
196
+ to="wbmailing.mailinglist",
197
+ verbose_name="Report Mailing List",
198
+ ),
199
+ ),
200
+ migrations.AddField(
201
+ model_name="report",
202
+ name="parent_report",
203
+ field=mptt.fields.TreeForeignKey(
204
+ blank=True,
205
+ help_text="The Parent Report attached to this report",
206
+ null=True,
207
+ on_delete=django.db.models.deletion.SET_NULL,
208
+ related_name="child_reports",
209
+ to="wbreport.report",
210
+ verbose_name="Parent Report",
211
+ ),
212
+ ),
213
+ migrations.AddField(
214
+ model_name="report",
215
+ name="report_class",
216
+ field=models.ForeignKey(
217
+ blank=True,
218
+ help_text="The method used to generate reports based on context",
219
+ null=True,
220
+ on_delete=django.db.models.deletion.SET_NULL,
221
+ related_name="reports",
222
+ to="wbreport.reportclass",
223
+ verbose_name="Report Class",
224
+ ),
225
+ ),
226
+ migrations.AddConstraint(
227
+ model_name="report",
228
+ constraint=models.UniqueConstraint(
229
+ fields=("parent_report", "title"), name="unique_parent_report_and_report"
230
+ ),
231
+ ),
232
+ migrations.AddConstraint(
233
+ model_name="report",
234
+ constraint=models.UniqueConstraint(
235
+ fields=("key", "content_type", "object_id"), name="unique_content_object_and_key"
236
+ ),
237
+ ),
238
+ ]
@@ -0,0 +1,25 @@
1
+ # Generated by Django 4.2.7 on 2023-11-06 13:30
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+ dependencies = [
8
+ ("wbreport", "0001_initial_squashed_squashed_0007_report_key"),
9
+ ]
10
+
11
+ operations = [
12
+ migrations.AlterField(
13
+ model_name="report",
14
+ name="file_content_type",
15
+ field=models.CharField(
16
+ choices=[
17
+ ("PDF", "application/pdf"),
18
+ ("CSV", "text/csv"),
19
+ ("XLSX", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
20
+ ],
21
+ default="PDF",
22
+ max_length=64,
23
+ ),
24
+ ),
25
+ ]
@@ -0,0 +1,27 @@
1
+ # Generated by Django 4.2.6 on 2023-11-16 14:03
2
+
3
+ import django.db.models.deletion
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+ dependencies = [
9
+ ("color", "0001_initial"),
10
+ ("wbreport", "0008_alter_report_file_content_type"),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AddField(
15
+ model_name="report",
16
+ name="color_palette",
17
+ field=models.ForeignKey(
18
+ blank=True,
19
+ help_text="The report color palette",
20
+ null=True,
21
+ on_delete=django.db.models.deletion.SET_NULL,
22
+ related_name="reports",
23
+ to="color.colorgradient",
24
+ verbose_name="Color Palette",
25
+ ),
26
+ )
27
+ ]
@@ -0,0 +1,43 @@
1
+ # Generated by Django 4.2.8 on 2024-01-03 08:47
2
+
3
+ from contextlib import suppress
4
+
5
+ from django.apps import apps
6
+ from django.contrib.contenttypes.models import ContentType
7
+ from django.db import migrations
8
+
9
+
10
+ def migrate_content_type(apps, schema_editor):
11
+ Report = apps.get_model("wbreport", "Report")
12
+
13
+ for model_name in [
14
+ "Classification",
15
+ "Instrument",
16
+ "ClassificationGroup",
17
+ "Deal",
18
+ "Exchange",
19
+ "InstrumentClassificationRelatedInstrument",
20
+ "InstrumentClassificationThroughModel",
21
+ "InstrumentFavoriteGroup",
22
+ "InstrumentList",
23
+ "InstrumentListThroughModel",
24
+ "InstrumentRequest",
25
+ "RelatedInstrumentThroughModel",
26
+ "InstrumentPrice",
27
+ ]:
28
+ with suppress(ContentType.DoesNotExist):
29
+ old_ct = ContentType.objects.get(app_label="wbportfolio", model=model_name.lower())
30
+ new_ct = ContentType.objects.get(app_label="wbfdm", model=model_name.lower())
31
+ Report.objects.filter(content_type_id=old_ct.id).update(content_type_id=new_ct.id)
32
+
33
+
34
+ class Migration(migrations.Migration):
35
+ dependencies = (
36
+ [
37
+ ("wbreport", "0009_alter_report_color_palette"),
38
+ ("wbfdm", "0012_instrumentprice_created_instrumentprice_modified"),
39
+ ]
40
+ if apps.is_installed("wbfdm")
41
+ else [("wbreport", "0009_alter_report_color_palette")]
42
+ )
43
+ operations = [migrations.RunPython(migrate_content_type)]
@@ -0,0 +1,35 @@
1
+ # Generated by Django 4.2.9 on 2024-02-07 15:29
2
+
3
+ from contextlib import suppress
4
+
5
+ from django.contrib.contenttypes.models import ContentType
6
+ from django.db import migrations
7
+
8
+
9
+ def migrate_theme_portfolio(apps, schema_editor):
10
+ from wbportfolio.models import Product
11
+ from wbreport.models import Report
12
+
13
+ PortfolioPortfolioThroughModel = apps.get_model("wbportfolio", "PortfolioPortfolioThroughModel")
14
+ InstrumentPortfolioThroughModel = apps.get_model("wbportfolio", "InstrumentPortfolioThroughModel")
15
+ for report in Report.objects.filter(content_type=ContentType.objects.get_for_model(Product)):
16
+ theme_portfolio_id = None
17
+ with suppress(InstrumentPortfolioThroughModel.DoesNotExist):
18
+ asset_portfolio = InstrumentPortfolioThroughModel.objects.get(
19
+ instrument_id=report.object_id, asset_portfolio=True
20
+ ).portfolio
21
+ if through_portfolio := PortfolioPortfolioThroughModel.objects.filter(
22
+ portfolio=asset_portfolio, is_theme=True
23
+ ).first():
24
+ theme_portfolio_id = through_portfolio.dependency_portfolio.id
25
+ report.parameters["theme_portfolio_id"] = theme_portfolio_id
26
+ report.save()
27
+
28
+
29
+ class Migration(migrations.Migration):
30
+ run_before = [("wbportfolio", "0054_portfolioinstrumentpreferredclassificationthroughmodel_and_more")]
31
+ dependencies = [
32
+ ("wbreport", "0010_auto_20240103_0947"),
33
+ ]
34
+
35
+ operations = [migrations.RunPython(migrate_theme_portfolio)]
@@ -0,0 +1,17 @@
1
+ # Generated by Django 5.0.6 on 2024-07-05 09:06
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+ dependencies = [
8
+ ("wbreport", "0011_auto_20240207_1629"),
9
+ ]
10
+
11
+ operations = [
12
+ migrations.AddField(
13
+ model_name="reportversion",
14
+ name="lock",
15
+ field=models.BooleanField(default=False, help_text="True, the context cannot be regenerated"),
16
+ ),
17
+ ]
@@ -0,0 +1,18 @@
1
+ # Generated by Django 5.0.7 on 2024-07-30 12:24
2
+
3
+ import django.core.serializers.json
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+ dependencies = [
9
+ ("wbreport", "0012_reportversion_lock"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AlterField(
14
+ model_name="reportversion",
15
+ name="context",
16
+ field=models.JSONField(default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder),
17
+ ),
18
+ ]
@@ -0,0 +1,25 @@
1
+ # Generated by Django 5.0.9 on 2024-11-11 11:59
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+ dependencies = [
8
+ ("wbreport", "0013_alter_reportversion_context"),
9
+ ]
10
+
11
+ operations = [
12
+ migrations.AlterModelOptions(
13
+ name="reportcategory",
14
+ options={
15
+ "ordering": ("order",),
16
+ "verbose_name": "Report Category",
17
+ "verbose_name_plural": "Report Categories",
18
+ },
19
+ ),
20
+ migrations.AlterField(
21
+ model_name="reportcategory",
22
+ name="order",
23
+ field=models.PositiveIntegerField(db_index=True, editable=False, verbose_name="order"),
24
+ ),
25
+ ]
File without changes