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,253 @@
1
+ import datetime as dt
2
+
3
+ import pytest
4
+ from django.test import override_settings
5
+ from faker import Faker
6
+ from wbmailing.models import MassMail
7
+ from wbreport.models import ReportVersion
8
+
9
+ fake = Faker()
10
+
11
+
12
+ @pytest.mark.django_db
13
+ class TestReportAssetModel:
14
+ def test_init(self, report_asset):
15
+ assert report_asset.id is not None
16
+
17
+ def test_str(self, report_asset):
18
+ assert str(report_asset) == report_asset.key
19
+
20
+
21
+ @pytest.mark.django_db
22
+ class TestReportCategoryModel:
23
+ def test_init(self, report_category):
24
+ assert report_category.id is not None
25
+
26
+ def test_str(self, report_category):
27
+ assert str(report_category) == report_category.title
28
+
29
+
30
+ @pytest.mark.django_db
31
+ class TestReportClassModel:
32
+ def test_init(self, report_class):
33
+ assert report_class.id is not None
34
+
35
+ def test_get_context(self, report_class, report_version_factory):
36
+ report_version = report_version_factory.create(parameters={"a": "b"})
37
+ context = report_class.get_context(report_version)
38
+ assert context == {"title": report_version.title}
39
+
40
+ @pytest.mark.parametrize("report_title", [fake.word()])
41
+ def test_get_version_title(self, report_class, report_title):
42
+ title = report_class.get_version_title(report_title, dict(iteration=0))
43
+ assert title == f"{report_title}-{0}"
44
+ assert title
45
+
46
+ def test_get_version_date(self, report_class):
47
+ assert report_class.get_version_date({"a": "b"}) is None
48
+
49
+ @pytest.mark.parametrize("title", [fake.word()])
50
+ def test_generate_file(self, title, report_class):
51
+ output = report_class.generate_file({"title": title})
52
+ assert output.getvalue().decode("utf_8") == title
53
+
54
+ @pytest.mark.parametrize("title", [fake.word()])
55
+ def test_generate_html(self, title, report_class):
56
+ output = report_class.generate_html({"title": title})
57
+ assert output == f"<p>{title}</p>"
58
+
59
+
60
+ @pytest.mark.django_db
61
+ class TestReportModel:
62
+ @staticmethod
63
+ def convert_date(date: dt.date) -> str:
64
+ return dt.datetime.strftime(date, "%Y-%m-%d")
65
+
66
+ def test_init(self, report_factory):
67
+ report = report_factory.create()
68
+ assert report.id is not None
69
+
70
+ def test_str(self, report_factory):
71
+ parent_parent_report = report_factory.create(parent_report=None)
72
+ parent_report = report_factory.create(parent_report=parent_parent_report)
73
+ report = report_factory.create(parent_report=parent_report)
74
+ assert parent_parent_report.__str__() == parent_parent_report.title
75
+ assert parent_report.__str__() == parent_report.title + f" [{parent_parent_report.title}]"
76
+ assert report.__str__() == report.title + f" [{parent_report.title} - {parent_parent_report.title}]"
77
+
78
+ def test_version(self, report_factory, report_version_factory):
79
+ report = report_factory.create()
80
+ report2 = report_factory.create()
81
+ version_date = fake.date_object()
82
+ version = report_version_factory.create(
83
+ report=report, parameters={"a": "b"}, is_primary=True, version_date=version_date
84
+ )
85
+ version2 = report_version_factory.create(
86
+ report=report, parameters={"a": "b"}, is_primary=False, version_date=version_date + dt.timedelta(days=1)
87
+ )
88
+ assert report.primary_version == version
89
+ assert report.earliest_version == version
90
+ assert report.last_version == version2
91
+ assert report2.earliest_version is None
92
+ assert report2.primary_version is None
93
+ assert report2.last_version is None
94
+
95
+ def test_get_gradient(self, report_factory):
96
+ report = report_factory.create()
97
+ palette = report.get_gradient()
98
+ assert len(list(palette)) == len(report.color_palette.colors)
99
+
100
+ def test_get_context(self, report_factory):
101
+ report = report_factory.create()
102
+ base_context = report.get_context()
103
+ assert list(base_context.keys()) == [
104
+ "report_title",
105
+ "slugify_report_title",
106
+ "report_base_color",
107
+ "colors_palette",
108
+ "report_logo_file_id",
109
+ ]
110
+
111
+ def test_set_primary_version(self, report_factory, report_version_factory):
112
+ report = report_factory.create()
113
+ report_version_factory.create(report=report, is_primary=True, parameters={"iteration": 0})
114
+ assert ReportVersion.objects.filter(is_primary=True).count() == 1
115
+ report_version_factory.create(report=report, is_primary=False, parameters={"iteration": 1})
116
+ assert ReportVersion.objects.filter(is_primary=True, parameters={"iteration": 1}).count() == 0
117
+ report.set_primary_versions({"iteration": 1})
118
+ assert ReportVersion.objects.filter(is_primary=True, parameters={"iteration": 1}).count() == 1
119
+
120
+ def test_get_or_create_version(self, report_factory):
121
+ report = report_factory.create()
122
+ assert ReportVersion.objects.count() == 0
123
+ report.get_or_create_version({"iteration": 0}, update_context=True)
124
+ assert ReportVersion.objects.count() == 1
125
+
126
+ def test_get_next_parameters(self, report_factory, report_version_factory):
127
+ report = report_factory.create()
128
+
129
+ # No Report Version, no explicit parameters, therefore no next parameters.
130
+ next_parameters = report.get_next_parameters()
131
+ assert next_parameters is None
132
+
133
+ # Explicit parameters.
134
+ next_parameters = report.get_next_parameters(next_parameters={"a": "b"})
135
+ assert next_parameters is not None
136
+
137
+ end_date = fake.date_object()
138
+ report_version_factory.create(report=report, parameters={"iteration": 0, "end": self.convert_date(end_date)})
139
+ next_parameters = report.get_next_parameters()
140
+ assert next_parameters == {"iteration": 1, "end": self.convert_date(end_date + dt.timedelta(days=1))}
141
+
142
+ def test_generate_next_reports(self, report_factory, report_version_factory):
143
+ end_date = fake.date_object()
144
+ # The parent report.
145
+ parent_report = report_factory.create(parent_report=None, is_active=True)
146
+
147
+ # Report 1 (parent_report child) has one version.
148
+ report1 = report_factory.create(parent_report=parent_report, is_active=True)
149
+ report_version_factory.create(report=report1, parameters={"iteration": 0, "end": self.convert_date(end_date)})
150
+
151
+ # Report 2 (parent_report child) has one version but the report is not active.
152
+ report2 = report_factory.create(parent_report=parent_report, is_active=False)
153
+ report_version_factory.create(report=report2, parameters={"iteration": 0, "end": self.convert_date(end_date)})
154
+
155
+ # A third report (parent_report child), but no version.
156
+ report_factory.create(parent_report=parent_report, is_active=True)
157
+
158
+ parent_report.generate_next_reports(next_parameters=None)
159
+ assert ReportVersion.objects.count() == 2 + 1 # report1 make a new version.
160
+
161
+ # Same function but with "next_parameters" not None: it will make first new version for no existing versions
162
+ # of report (Parent report + report3) and generate next report version for already existing version report.
163
+ parent_report.generate_next_reports(
164
+ next_parameters={"iteration": 2, "end": self.convert_date(end_date + dt.timedelta(days=2))}
165
+ )
166
+ assert ReportVersion.objects.count() == 3 + 3
167
+
168
+ # Same function but for only leaves node.
169
+ parent_report.generate_next_reports(max_depth_only=True)
170
+ assert ReportVersion.objects.count() == 6 + 2
171
+
172
+ def test_bulk_create(self, report_factory):
173
+ parent_report = report_factory.create(is_active=True)
174
+ report_factory.create_batch(5, parent_report=parent_report, is_active=True)
175
+ end_date = fake.date_object()
176
+ parent_report.bulk_create_child_reports(
177
+ start_parameters={"iteration": 0, "end": self.convert_date(end_date)},
178
+ end_parameters={"iteration": 2, "end": self.convert_date(end_date + dt.timedelta(days=2))},
179
+ )
180
+ assert ReportVersion.objects.count() == 5 * 3 + 3
181
+
182
+ def test_set_primary_report_version(self, report_factory):
183
+ parent_report = report_factory.create(parent_report=None, is_active=True)
184
+ report_factory.create_batch(5, parent_report=parent_report, is_active=True)
185
+ end_date = fake.date_object()
186
+ parent_report.generate_next_reports({"iteration": 0, "end": self.convert_date(end_date)})
187
+ parent_report.generate_next_reports()
188
+ parent_report.set_primary_report_version(
189
+ {"iteration": 1, "end": self.convert_date(end_date + dt.timedelta(days=1))}
190
+ )
191
+ parent_report.set_primary_report_version() # will set primary to the same parameters.
192
+ assert (
193
+ ReportVersion.objects.filter(
194
+ parameters={"iteration": 1, "end": self.convert_date(end_date + dt.timedelta(days=1))}, is_primary=True
195
+ ).count()
196
+ == 6
197
+ )
198
+
199
+
200
+ @pytest.mark.django_db
201
+ class TestReportVersionModel:
202
+ def test_init(self, report_version_factory):
203
+ report_version = report_version_factory.create(parameters={"a": "b"})
204
+ assert report_version.id is not None
205
+
206
+ def test_generate_file(self, report_version_factory, report_factory):
207
+ report_version = report_version_factory.create(parameters={"a": "b"})
208
+ report_version.update_context()
209
+ output = report_version.generate_file()
210
+ assert output.getvalue().decode("utf_8") == report_version.title
211
+
212
+ def test_generate_html(self, report_version_factory):
213
+ report_version = report_version_factory.create(parameters={"a": "b"})
214
+ report_version.update_context()
215
+ output = report_version.generate_html()
216
+ assert output == f"<p>{report_version.title}</p>"
217
+
218
+ @override_settings(EMAIL_BACKEND="anymail.backends.test.EmailBackend")
219
+ def test_send_mail(self, report_version_factory, mail_template):
220
+ report_version = report_version_factory.create(parameters={"a": "b"})
221
+ report_version.send_mail(mail_template)
222
+ assert MassMail.objects.count() == 1
223
+
224
+ def test_get_context(self, report_version_factory):
225
+ report_version = report_version_factory.create(parameters={"a": "b"})
226
+ context = report_version.get_context()
227
+ assert set(context.keys()) == {
228
+ "uuid",
229
+ "download_url",
230
+ "version_title",
231
+ "slugify_version_title",
232
+ "title",
233
+ "report_title",
234
+ "slugify_report_title",
235
+ "comment",
236
+ "report_base_color",
237
+ "colors_palette",
238
+ "report_logo_file_id",
239
+ }
240
+
241
+ def test_update_context(self, report_version_factory):
242
+ report_version = report_version_factory.create(parameters={"a": "b"})
243
+ assert report_version.context == dict()
244
+ report_version.update_context()
245
+ assert report_version.context["title"] == report_version.title
246
+
247
+ def test_update_context_with_error(self, report_version_factory):
248
+ report_version = report_version_factory.create(parameters=dict())
249
+ assert report_version.context == dict()
250
+ assert report_version.disabled is False
251
+ report_version.update_context()
252
+ assert report_version.context == dict()
253
+ assert report_version.disabled is True
@@ -0,0 +1,17 @@
1
+ import pytest
2
+ from django.core import mail
3
+ from django.test import override_settings
4
+ from wbcore.contrib.authentication.factories import SuperUserFactory
5
+ from wbreport.tasks import generate_and_send_current_report_file
6
+
7
+
8
+ @pytest.mark.django_db
9
+ class TestTasks:
10
+ @override_settings(EMAIL_BACKEND="anymail.backends.test.EmailBackend")
11
+ def test_generate_and_send_current_report_file(self, report_factory):
12
+ parent_report = report_factory.create(is_active=True)
13
+ report_factory.create_batch(5, is_active=True, parent_report=parent_report)
14
+ parent_report.generate_next_reports({"iteration": 0})
15
+ user = SuperUserFactory()
16
+ generate_and_send_current_report_file(user.id, parent_report.id)
17
+ assert len(mail.outbox) == 1
File without changes
@@ -0,0 +1,12 @@
1
+ import pytest
2
+ from wbcore.test import GenerateTest, default_config
3
+
4
+ config = {}
5
+ for key, value in default_config.items():
6
+ config[key] = list(filter(lambda x: x.__module__.startswith("wbreport"), value))
7
+
8
+
9
+ @pytest.mark.django_db
10
+ @GenerateTest(config)
11
+ class TestProject:
12
+ pass
wbreport/urls.py ADDED
@@ -0,0 +1,29 @@
1
+ from django.urls import include, path
2
+ from wbcore.routers import WBCoreRouter
3
+ from wbreport.viewsets import viewsets
4
+
5
+ router = WBCoreRouter()
6
+
7
+ router.register(
8
+ r"reportcategoryrepresentation",
9
+ viewsets.ReportCategoryRepresentationViewSet,
10
+ basename="reportcategoryrepresentation",
11
+ )
12
+ router.register(
13
+ r"reportversionerepresentation",
14
+ viewsets.ReportVersionRepresentationViewSet,
15
+ basename="reportversionrepresentation",
16
+ )
17
+ router.register(
18
+ r"reportclassrepresentation", viewsets.ReportClassRepresentationViewSet, basename="reportclassrepresentation"
19
+ )
20
+ router.register(r"reportrepresentation", viewsets.ReportRepresentationViewSet, basename="reportrepresentation")
21
+ router.register(r"report", viewsets.ReportModelViewSet, basename="report")
22
+ router.register(r"reportversion", viewsets.ReportVersionModelViewSet, basename="reportversion")
23
+ router.register(r"reportcategory", viewsets.ReportCategoryModelViewSet, basename="reportcategory")
24
+
25
+ report_router = WBCoreRouter()
26
+ report_router.register(r"version", viewsets.ReportVersionReportModelViewSet, basename="report-version")
27
+
28
+
29
+ urlpatterns = [path("", include(router.urls)), path("report/<int:report_id>/", include(report_router.urls))]
@@ -0,0 +1,10 @@
1
+ from django.urls import path
2
+ from wbreport.viewsets import viewsets
3
+
4
+ urlpatterns = [
5
+ path("<str:namespace>/", viewsets.report, name="report"),
6
+ path("version/<str:lookup>/", viewsets.report_version, name="report_version"),
7
+ path(
8
+ "download_version_file/<str:uuid>/", viewsets.download_report_version_file, name="report_download_version_file"
9
+ ),
10
+ ]
@@ -0,0 +1,10 @@
1
+ from .viewsets import (
2
+ ReportCategoryRepresentationViewSet,
3
+ ReportClassRepresentationViewSet,
4
+ ReportModelViewSet,
5
+ ReportRepresentationViewSet,
6
+ ReportVersionModelViewSet,
7
+ ReportVersionRepresentationViewSet,
8
+ download_report_version_file,
9
+ report_version,
10
+ )
@@ -0,0 +1,18 @@
1
+ from .buttons import ReportButtonConfig, ReportVersionButtonConfig
2
+ from .displays import (
3
+ ReportCategoryDisplayConfig,
4
+ ReportDisplayConfig,
5
+ ReportVersionDisplayConfig,
6
+ ReportVersionReportDisplayConfig,
7
+ )
8
+ from .endpoints import (
9
+ ReportEndpointConfig,
10
+ ReportVersionEndpointConfig,
11
+ ReportVersionReportEndpointConfig,
12
+ )
13
+ from .titles import (
14
+ ReportTitleConfig,
15
+ ReportVersionReportTitleConfig,
16
+ ReportVersionTitleConfig,
17
+ )
18
+ from .menus import REPORT_MENUITEM
@@ -0,0 +1,193 @@
1
+ from wbcore import serializers as wb_serializers
2
+ from wbcore.contrib.icons import WBIcon
3
+ from wbcore.enums import RequestType
4
+ from wbcore.metadata.configs import buttons as bt
5
+ from wbcore.metadata.configs.buttons.view_config import ButtonViewConfig
6
+ from wbcore.metadata.configs.display.instance_display.shortcuts import (
7
+ create_simple_display,
8
+ )
9
+ from wbreport.models import Report
10
+
11
+
12
+ class CommentSerializer(wb_serializers.Serializer):
13
+ comment = wb_serializers.TextField(default="")
14
+
15
+
16
+ class ReportButtonConfig(ButtonViewConfig):
17
+ def get_custom_list_instance_buttons(self):
18
+ return {
19
+ bt.HyperlinkButton(
20
+ key="last_version",
21
+ label="Last Version (unreleased)",
22
+ icon=WBIcon.DOCUMENT_IN_PROGRESS.icon,
23
+ ),
24
+ bt.HyperlinkButton(
25
+ key="primary_version",
26
+ label="Primary Version",
27
+ icon=WBIcon.DOCUMENT_PRIVATE.icon,
28
+ ),
29
+ }
30
+
31
+ def get_custom_instance_buttons(self):
32
+ default_parameters = earliest_parent_parameters = latest_parent_paremeters = dict()
33
+ if report_id := self.view.kwargs.get("pk", None):
34
+ report = Report.objects.get(id=report_id)
35
+ if version := report.last_version:
36
+ default_parameters = version.parameters
37
+ if default_parameters:
38
+ report.report_class.get_next_parameters(default_parameters)
39
+ if parent_report := report.parent_report:
40
+ if version := parent_report.earliest_version:
41
+ earliest_parent_parameters = version.parameters
42
+ if version := parent_report.last_version:
43
+ latest_parent_paremeters = version.parameters
44
+
45
+ class ParametersSerializer(wb_serializers.Serializer):
46
+ parameters = wb_serializers.JSONTableField(default=default_parameters, label="Version Parameters")
47
+
48
+ class StartEndParametersSerializer(wb_serializers.Serializer):
49
+ start_parameters = wb_serializers.JSONTableField(
50
+ default=earliest_parent_parameters, label="Start Parameters"
51
+ )
52
+ end_parameters = wb_serializers.JSONTableField(default=latest_parent_paremeters, label="End Parameters")
53
+ comment = wb_serializers.TextField(default="")
54
+
55
+ class GenerateNextReportSerializer(CommentSerializer):
56
+ max_depth_only = wb_serializers.BooleanField(default=False)
57
+ start_date = wb_serializers.DateField()
58
+ end_date = wb_serializers.DateField()
59
+
60
+ return self.get_custom_list_instance_buttons() | {
61
+ bt.DropDownButton(
62
+ label="Utility",
63
+ icon=WBIcon.UNFOLD.icon,
64
+ buttons=(
65
+ bt.ActionButton(
66
+ method=RequestType.PATCH,
67
+ identifiers=("wbreport:report",),
68
+ key="generate_next_reports",
69
+ label="Generate Next Report",
70
+ icon=WBIcon.GENERATE_NEXT.icon,
71
+ description_fields="""
72
+ <p> Generate reports based on current report parameters to next iteration?</p>
73
+ <p> Note: This action takes a minute</p>
74
+ """,
75
+ serializer=GenerateNextReportSerializer,
76
+ action_label="Generate Next Report",
77
+ title="Generate Report to Next Iteration",
78
+ instance_display=create_simple_display([["start_date"], ["end_date"], ["max_depth_only"]]),
79
+ ),
80
+ bt.ActionButton(
81
+ method=RequestType.PATCH,
82
+ identifiers=("wbreport:report",),
83
+ key="update_versions_context",
84
+ label="Regenerate context",
85
+ icon=WBIcon.REGENERATE.icon,
86
+ serializer=ParametersSerializer,
87
+ description_fields="""
88
+ <p> Do you want to regenerate this report's versions?</p>
89
+ <p> If parameters is unset, it will recompute all report's versions</p>
90
+ <p> Note: This action takes few minute?</p>
91
+ """,
92
+ action_label="Regenerate versions context",
93
+ title="Regenerate versions context",
94
+ instance_display=create_simple_display([["all_versions"], ["parameters"]]),
95
+ ),
96
+ bt.ActionButton(
97
+ method=RequestType.PATCH,
98
+ identifiers=("wbreport:report",),
99
+ key="bundle_versions",
100
+ label="Bundle Versions",
101
+ icon=WBIcon.FOLDERS_OPEN.icon,
102
+ description_fields="""
103
+ <p>Generate a reports bundle for the specified parameters.
104
+ If left empty, will use the latest parameters state.</p>
105
+ <p> Note: This action takes around 10 minutes</p>
106
+ """,
107
+ serializer=ParametersSerializer,
108
+ action_label="Bundle Versions",
109
+ title="Bundle Versions",
110
+ instance_display=create_simple_display([["parameters"]]),
111
+ ),
112
+ bt.ActionButton(
113
+ method=RequestType.PATCH,
114
+ identifiers=("wbreport:report",),
115
+ key="bulk_create_reports",
116
+ label="Bulk Reports Creations",
117
+ icon=WBIcon.FOLDERS_ADD.icon,
118
+ description_fields="""
119
+ <p>Create all the report version between the two specified parameters set.
120
+ <p> Note: This action takes around 10 minutes</p>
121
+ """,
122
+ serializer=StartEndParametersSerializer,
123
+ action_label="Bulk Reports Creations",
124
+ title="Bulk Reports Creations",
125
+ instance_display=create_simple_display([["start_parameters"], ["end_parameters"]]),
126
+ ),
127
+ bt.ActionButton(
128
+ method=RequestType.PATCH,
129
+ identifiers=("wbreport:report",),
130
+ key="switch_primary_versions",
131
+ label="Switch Primary Versions",
132
+ description_fields="""
133
+ <p>Switch the Primary Versions of all the child reports to the given parameters. </p>
134
+ <p> The primary version is the one display by default</p>
135
+ """,
136
+ icon=WBIcon.SYNCHRONIZE.icon,
137
+ serializer=ParametersSerializer,
138
+ action_label="Switch Primary Versions",
139
+ title="Switch Primary Versions",
140
+ instance_display=create_simple_display([["parameters"]]),
141
+ ),
142
+ ),
143
+ )
144
+ }
145
+
146
+
147
+ class ReportVersionButtonConfig(ButtonViewConfig):
148
+ def get_custom_list_instance_buttons(self):
149
+ return {
150
+ bt.HyperlinkButton(
151
+ key="html",
152
+ label="Report (HTML)",
153
+ icon=WBIcon.LINK.icon,
154
+ ),
155
+ bt.HyperlinkButton(
156
+ key="file",
157
+ label="Report (File)",
158
+ icon=WBIcon.SAVE.icon,
159
+ ),
160
+ bt.HyperlinkButton(
161
+ key="public_html",
162
+ label="Public Report",
163
+ icon=WBIcon.SAVE.icon,
164
+ ),
165
+ bt.ActionButton(
166
+ method=RequestType.GET,
167
+ identifiers=("wbreport:reportversion",),
168
+ key="update_context",
169
+ label="Update Context",
170
+ description_fields="""
171
+ <p>Update and actualize context</p>
172
+ """,
173
+ serializer=CommentSerializer,
174
+ icon=WBIcon.REGENERATE.icon,
175
+ action_label="Update Context",
176
+ title="Update Context",
177
+ ),
178
+ bt.ActionButton(
179
+ method=RequestType.GET,
180
+ identifiers=("wbreport:reportversion",),
181
+ key="send_email",
182
+ label="Send to Mailing List",
183
+ description_fields="""
184
+ <p>Send this version as email to the specified report mailing list</p>
185
+ """,
186
+ icon=WBIcon.MAIL.icon,
187
+ action_label="Send Email",
188
+ title="Send Email",
189
+ ),
190
+ }
191
+
192
+ def get_custom_instance_buttons(self):
193
+ return self.get_custom_list_instance_buttons()
@@ -0,0 +1,116 @@
1
+ from typing import Optional
2
+
3
+ from rest_framework.reverse import reverse
4
+ from wbcore.metadata.configs import display as dp
5
+ from wbcore.metadata.configs.display.instance_display import Display
6
+ from wbcore.metadata.configs.display.instance_display.shortcuts import (
7
+ create_simple_display,
8
+ create_simple_section,
9
+ )
10
+ from wbcore.metadata.configs.display.view_config import DisplayViewConfig
11
+
12
+
13
+ class ReportCategoryDisplayConfig(DisplayViewConfig):
14
+ def get_list_display(self) -> Optional[dp.ListDisplay]:
15
+ return dp.ListDisplay(
16
+ fields=(
17
+ dp.Field(key="title", label="Title"),
18
+ dp.Field(key="order", label="Order"),
19
+ )
20
+ )
21
+
22
+ def get_instance_display(self) -> Display:
23
+ return create_simple_display([["title"], ["order"]])
24
+
25
+
26
+ class ReportDisplayConfig(DisplayViewConfig):
27
+ def get_list_display(self) -> Optional[dp.ListDisplay]:
28
+ return dp.ListDisplay(
29
+ fields=[
30
+ dp.Field(key="title", label="Title"),
31
+ dp.Field(key="namespace", label="Namespace"),
32
+ dp.Field(key="parent_report", label="Parent Report"),
33
+ dp.Field(key="category", label="Category"),
34
+ dp.Field(key="is_active", label="Active"),
35
+ dp.Field(key="permission_type", label="Permission Type"),
36
+ dp.Field(key="file_disabled", label="PDF Disabled"),
37
+ dp.Field(key="base_color", label="Color"),
38
+ dp.Field(key="mailing_list", label="Mailing List"),
39
+ ],
40
+ tree=True,
41
+ # tree_group_lookup="id_repr",
42
+ tree_group_pinned="left",
43
+ tree_group_field="title",
44
+ tree_group_label="Title",
45
+ tree_group_level_options=[
46
+ dp.TreeGroupLevelOption(
47
+ filter_key="parent_report",
48
+ filter_depth=1,
49
+ list_endpoint=reverse(
50
+ "wbreport:report-list",
51
+ args=[],
52
+ request=self.request,
53
+ ),
54
+ )
55
+ ],
56
+ )
57
+
58
+ def get_instance_display(self) -> Display:
59
+ version_section = create_simple_section("version_section", "Versions", [["content_type"], ["object_id"]])
60
+ version_table_section = create_simple_section("version_table_section", "Versions", [["versions"]], "versions")
61
+ child_report_section = create_simple_section("child_report_section", "Child Reports", [["reports"]], "reports")
62
+ return create_simple_display(
63
+ [
64
+ ["title", "namespace", "."],
65
+ ["base_color", "category", "file_content_type"],
66
+ ["is_active", "permission_type", "file_disabled"],
67
+ ["mailing_list", "report_class", "."],
68
+ ["version_section", "version_section", "version_section"],
69
+ ["version_table_section", "version_table_section", "version_table_section"],
70
+ ["child_report_section", "child_report_section", "child_report_section"],
71
+ ],
72
+ [child_report_section, version_table_section, version_section],
73
+ )
74
+
75
+
76
+ class ReportVersionDisplayConfig(DisplayViewConfig):
77
+ def get_list_display(self) -> Optional[dp.ListDisplay]:
78
+ return dp.ListDisplay(
79
+ fields=(
80
+ dp.Field(key="uuid", label="UUID"),
81
+ dp.Field(key="lookup", label="Lookup"),
82
+ dp.Field(key="title", label="Title"),
83
+ dp.Field(key="version_date", label="Date"),
84
+ dp.Field(key="report", label="Report"),
85
+ dp.Field(key="is_primary", label="Is Primary"),
86
+ dp.Field(key="disabled", label="Disabled"),
87
+ dp.Field(key="parameters", label="Parameters"),
88
+ )
89
+ )
90
+
91
+ def get_instance_display(self) -> Display:
92
+ return create_simple_display(
93
+ [
94
+ ["title", "lookup", "uuid"],
95
+ ["version_date", "creation_date", "update_date"],
96
+ ["is_primary", "disabled", "disabled"],
97
+ ["parameters", ".", "."],
98
+ ]
99
+ )
100
+
101
+
102
+ class ReportVersionReportDisplayConfig(ReportVersionDisplayConfig):
103
+ def get_list_display(self) -> Optional[dp.ListDisplay]:
104
+ return dp.ListDisplay(
105
+ fields=(
106
+ dp.Field(key="uuid", label="UUID"),
107
+ dp.Field(key="lookup", label="Lookup"),
108
+ dp.Field(key="title", label="Title"),
109
+ dp.Field(key="version_date", label="Date"),
110
+ dp.Field(key="report", label="Report"),
111
+ dp.Field(key="is_primary", label="Is Primary"),
112
+ dp.Field(key="disabled", label="Disabled"),
113
+ dp.Field(key="parameters", label="Parameters"),
114
+ dp.Field(key="comment", label="Comment"),
115
+ )
116
+ )