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.
- wbreport/__init__.py +1 -0
- wbreport/admin.py +87 -0
- wbreport/apps.py +6 -0
- wbreport/defaults/__init__.py +0 -0
- wbreport/defaults/factsheets/__init__.py +0 -0
- wbreport/defaults/factsheets/base.py +990 -0
- wbreport/defaults/factsheets/menu.py +93 -0
- wbreport/defaults/factsheets/mixins.py +35 -0
- wbreport/defaults/factsheets/multitheme.py +947 -0
- wbreport/dynamic_preferences_registry.py +15 -0
- wbreport/factories/__init__.py +8 -0
- wbreport/factories/data_classes.py +48 -0
- wbreport/factories/reports.py +79 -0
- wbreport/filters.py +37 -0
- wbreport/migrations/0001_initial_squashed_squashed_0007_report_key.py +238 -0
- wbreport/migrations/0008_alter_report_file_content_type.py +25 -0
- wbreport/migrations/0009_alter_report_color_palette.py +27 -0
- wbreport/migrations/0010_auto_20240103_0947.py +43 -0
- wbreport/migrations/0011_auto_20240207_1629.py +35 -0
- wbreport/migrations/0012_reportversion_lock.py +17 -0
- wbreport/migrations/0013_alter_reportversion_context.py +18 -0
- wbreport/migrations/0014_alter_reportcategory_options_and_more.py +25 -0
- wbreport/migrations/__init__.py +0 -0
- wbreport/mixins.py +183 -0
- wbreport/models.py +781 -0
- wbreport/pdf/__init__.py +0 -0
- wbreport/pdf/charts/__init__.py +0 -0
- wbreport/pdf/charts/legend.py +15 -0
- wbreport/pdf/charts/pie.py +169 -0
- wbreport/pdf/charts/timeseries.py +77 -0
- wbreport/pdf/sandbox/__init__.py +0 -0
- wbreport/pdf/sandbox/run.py +17 -0
- wbreport/pdf/sandbox/templates/__init__.py +0 -0
- wbreport/pdf/sandbox/templates/basic_factsheet.py +908 -0
- wbreport/pdf/sandbox/templates/fund_factsheet.py +864 -0
- wbreport/pdf/sandbox/templates/long_industry_exposure_factsheet.py +898 -0
- wbreport/pdf/sandbox/templates/multistrat_factsheet.py +872 -0
- wbreport/pdf/sandbox/templates/testfile.pdf +434 -0
- wbreport/pdf/tables/__init__.py +0 -0
- wbreport/pdf/tables/aggregated_tables.py +156 -0
- wbreport/pdf/tables/data_tables.py +75 -0
- wbreport/serializers.py +191 -0
- wbreport/tasks.py +60 -0
- wbreport/templates/__init__.py +0 -0
- wbreport/templatetags/__init__.py +0 -0
- wbreport/templatetags/portfolio_tags.py +35 -0
- wbreport/tests/__init__.py +0 -0
- wbreport/tests/conftest.py +24 -0
- wbreport/tests/test_models.py +253 -0
- wbreport/tests/test_tasks.py +17 -0
- wbreport/tests/test_viewsets.py +0 -0
- wbreport/tests/tests.py +12 -0
- wbreport/urls.py +29 -0
- wbreport/urls_public.py +10 -0
- wbreport/viewsets/__init__.py +10 -0
- wbreport/viewsets/configs/__init__.py +18 -0
- wbreport/viewsets/configs/buttons.py +193 -0
- wbreport/viewsets/configs/displays.py +116 -0
- wbreport/viewsets/configs/endpoints.py +23 -0
- wbreport/viewsets/configs/menus.py +8 -0
- wbreport/viewsets/configs/titles.py +30 -0
- wbreport/viewsets/viewsets.py +330 -0
- wbreport-2.2.1.dist-info/METADATA +6 -0
- wbreport-2.2.1.dist-info/RECORD +66 -0
- wbreport-2.2.1.dist-info/WHEEL +5 -0
- 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
|
wbreport/tests/tests.py
ADDED
|
@@ -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))]
|
wbreport/urls_public.py
ADDED
|
@@ -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
|
+
)
|