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,23 @@
|
|
|
1
|
+
from rest_framework.reverse import reverse
|
|
2
|
+
from wbcore.metadata.configs.endpoints import EndpointViewConfig
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ReportVersionEndpointConfig(EndpointViewConfig):
|
|
6
|
+
def get_endpoint(self, **kwargs):
|
|
7
|
+
return None
|
|
8
|
+
|
|
9
|
+
def get_list_endpoint(self, **kwargs):
|
|
10
|
+
return reverse("wbreport:reportversion-list", request=self.request)
|
|
11
|
+
|
|
12
|
+
def get_instance_endpoint(self):
|
|
13
|
+
return self.get_list_endpoint()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ReportEndpointConfig(EndpointViewConfig):
|
|
17
|
+
def get_endpoint(self, **kwargs):
|
|
18
|
+
return reverse("wbreport:report-list", request=self.request)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ReportVersionReportEndpointConfig(EndpointViewConfig):
|
|
22
|
+
def get_list_endpoint(self, **kwargs):
|
|
23
|
+
return reverse("wbreport:report-version-list", args=[self.view.kwargs["report_id"]], request=self.request)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from wbcore.metadata.configs.titles import TitleViewConfig
|
|
2
|
+
from wbreport.models import Report
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ReportVersionTitleConfig(TitleViewConfig):
|
|
6
|
+
def get_list_title(self):
|
|
7
|
+
return "Versions"
|
|
8
|
+
|
|
9
|
+
def get_instance_title(self):
|
|
10
|
+
return "Version: {{title}}"
|
|
11
|
+
|
|
12
|
+
def get_create_title(self):
|
|
13
|
+
return "New Version"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ReportTitleConfig(TitleViewConfig):
|
|
17
|
+
def get_list_title(self):
|
|
18
|
+
return "Reports"
|
|
19
|
+
|
|
20
|
+
def get_instance_title(self):
|
|
21
|
+
return "Report: {{title}}"
|
|
22
|
+
|
|
23
|
+
def get_create_title(self):
|
|
24
|
+
return "New Report"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ReportVersionReportTitleConfig(ReportVersionTitleConfig):
|
|
28
|
+
def get_list_title(self):
|
|
29
|
+
report = Report.objects.get(id=self.view.kwargs["report_id"])
|
|
30
|
+
return f"Versions for report {str(report)}"
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from django.db.models import Case, Exists, F, IntegerField, OuterRef, When
|
|
4
|
+
from django.http import FileResponse, HttpResponse
|
|
5
|
+
from django.shortcuts import get_object_or_404, render
|
|
6
|
+
from django.views.decorators.cache import cache_page
|
|
7
|
+
from rest_framework import filters, status
|
|
8
|
+
from rest_framework.authentication import SessionAuthentication
|
|
9
|
+
from rest_framework.decorators import (
|
|
10
|
+
action,
|
|
11
|
+
api_view,
|
|
12
|
+
authentication_classes,
|
|
13
|
+
permission_classes,
|
|
14
|
+
)
|
|
15
|
+
from rest_framework.permissions import AllowAny, IsAuthenticated
|
|
16
|
+
from rest_framework.renderers import StaticHTMLRenderer
|
|
17
|
+
from rest_framework.response import Response
|
|
18
|
+
from wbcore import viewsets
|
|
19
|
+
from wbcore.contrib.authentication.authentication import (
|
|
20
|
+
JWTCookieAuthentication,
|
|
21
|
+
QueryTokenAuthentication,
|
|
22
|
+
)
|
|
23
|
+
from wbcore.contrib.guardian.viewsets.mixins import GuardianFilterMixin
|
|
24
|
+
from wbreport.filters import ReportFilterSet, ReportVersionFilterSet
|
|
25
|
+
from wbreport.models import (
|
|
26
|
+
Report,
|
|
27
|
+
ReportCategory,
|
|
28
|
+
ReportClass,
|
|
29
|
+
ReportVersion,
|
|
30
|
+
bulk_create_child_reports_as_task,
|
|
31
|
+
generate_next_reports_as_task,
|
|
32
|
+
set_primary_report_version_as_task,
|
|
33
|
+
update_context_as_task,
|
|
34
|
+
update_version_context_as_task,
|
|
35
|
+
)
|
|
36
|
+
from wbreport.serializers import (
|
|
37
|
+
ReportCategoryModelSerializer,
|
|
38
|
+
ReportCategoryRepresentationSerializer,
|
|
39
|
+
ReportClassRepresentationSerializer,
|
|
40
|
+
ReportModelSerializer,
|
|
41
|
+
ReportRepresentationSerializer,
|
|
42
|
+
ReportVersionModelSerializer,
|
|
43
|
+
ReportVersionRepresentationSerializer,
|
|
44
|
+
)
|
|
45
|
+
from wbreport.tasks import generate_and_send_current_report_file
|
|
46
|
+
from wbreport.viewsets.configs import (
|
|
47
|
+
ReportButtonConfig,
|
|
48
|
+
ReportCategoryDisplayConfig,
|
|
49
|
+
ReportDisplayConfig,
|
|
50
|
+
ReportEndpointConfig,
|
|
51
|
+
ReportTitleConfig,
|
|
52
|
+
ReportVersionButtonConfig,
|
|
53
|
+
ReportVersionDisplayConfig,
|
|
54
|
+
ReportVersionEndpointConfig,
|
|
55
|
+
ReportVersionReportDisplayConfig,
|
|
56
|
+
ReportVersionReportEndpointConfig,
|
|
57
|
+
ReportVersionReportTitleConfig,
|
|
58
|
+
ReportVersionTitleConfig,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@api_view(["GET"])
|
|
63
|
+
@permission_classes([AllowAny])
|
|
64
|
+
@authentication_classes([SessionAuthentication, JWTCookieAuthentication, QueryTokenAuthentication])
|
|
65
|
+
def report(request, namespace):
|
|
66
|
+
report = get_object_or_404(Report, namespace=namespace, is_active=True)
|
|
67
|
+
if (version := report.primary_version) and not version.disabled:
|
|
68
|
+
# Need the report to be public or the user to have access
|
|
69
|
+
if version.report.is_accessible(request.user):
|
|
70
|
+
return HttpResponse(version.generate_html())
|
|
71
|
+
return render(
|
|
72
|
+
request,
|
|
73
|
+
"errors/custom.html",
|
|
74
|
+
{
|
|
75
|
+
"title": "Report Unavailable",
|
|
76
|
+
"header": "Report Unavailable",
|
|
77
|
+
"description": "If you thing this report should be enabled, please " "contact a system administrator",
|
|
78
|
+
},
|
|
79
|
+
status=status.HTTP_403_FORBIDDEN,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@api_view(["GET"])
|
|
84
|
+
@cache_page(None, key_prefix="report")
|
|
85
|
+
@permission_classes([AllowAny])
|
|
86
|
+
@authentication_classes([SessionAuthentication, JWTCookieAuthentication, QueryTokenAuthentication])
|
|
87
|
+
def download_report_version_file(request, uuid):
|
|
88
|
+
version = get_object_or_404(ReportVersion, uuid=uuid, report__is_active=True, disabled=False)
|
|
89
|
+
if version.report.is_accessible(request.user):
|
|
90
|
+
output = version.generate_file()
|
|
91
|
+
if output:
|
|
92
|
+
return FileResponse(
|
|
93
|
+
output,
|
|
94
|
+
as_attachment=True,
|
|
95
|
+
filename=output.name,
|
|
96
|
+
content_type=Report.FileContentType[version.report.file_content_type].label,
|
|
97
|
+
)
|
|
98
|
+
return HttpResponse(
|
|
99
|
+
"No PDF report for this version, please contact an administrator", status=status.HTTP_403_FORBIDDEN
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@api_view(["GET"])
|
|
104
|
+
@permission_classes([AllowAny])
|
|
105
|
+
@authentication_classes([SessionAuthentication, JWTCookieAuthentication, QueryTokenAuthentication])
|
|
106
|
+
def report_version(request, lookup):
|
|
107
|
+
version = get_object_or_404(ReportVersion, lookup=lookup, report__is_active=True, disabled=False)
|
|
108
|
+
# Need the report to be public or the user to have access
|
|
109
|
+
if version.report.is_accessible(request.user):
|
|
110
|
+
return HttpResponse(version.generate_html())
|
|
111
|
+
return render(
|
|
112
|
+
request,
|
|
113
|
+
"errors/custom.html",
|
|
114
|
+
{
|
|
115
|
+
"title": "Report Unavailable",
|
|
116
|
+
"header": "Report Unavailable",
|
|
117
|
+
"description": "If you thing this report should be enabled, please " "contact a system administrator",
|
|
118
|
+
},
|
|
119
|
+
status=status.HTTP_403_FORBIDDEN,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class ReportCategoryRepresentationViewSet(viewsets.RepresentationViewSet):
|
|
124
|
+
filter_backends = (filters.OrderingFilter, filters.SearchFilter)
|
|
125
|
+
ordering_fields = ordering = ("title",)
|
|
126
|
+
search_fields = ("title",)
|
|
127
|
+
serializer_class = ReportCategoryRepresentationSerializer
|
|
128
|
+
queryset = ReportCategory.objects.all()
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class ReportRepresentationViewSet(viewsets.RepresentationViewSet):
|
|
132
|
+
filter_backends = (filters.OrderingFilter, filters.SearchFilter)
|
|
133
|
+
ordering_fields = ordering = ("title",)
|
|
134
|
+
search_fields = ("title",)
|
|
135
|
+
serializer_class = ReportRepresentationSerializer
|
|
136
|
+
queryset = Report.objects.all()
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class ReportClassRepresentationViewSet(viewsets.RepresentationViewSet):
|
|
140
|
+
ordering_fields = ordering = ("title",)
|
|
141
|
+
search_fields = ("title",)
|
|
142
|
+
serializer_class = ReportClassRepresentationSerializer
|
|
143
|
+
queryset = ReportClass.objects.all()
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class ReportVersionRepresentationViewSet(viewsets.RepresentationViewSet):
|
|
147
|
+
ordering_fields = ordering = ("title",)
|
|
148
|
+
search_fields = ("title",)
|
|
149
|
+
serializer_class = ReportVersionRepresentationSerializer
|
|
150
|
+
queryset = ReportVersion.objects.all()
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class ReportCategoryModelViewSet(viewsets.ModelViewSet):
|
|
154
|
+
serializer_class = ReportCategoryModelSerializer
|
|
155
|
+
ordering_fields = ("title", "order")
|
|
156
|
+
ordering = ("-title",)
|
|
157
|
+
search_fields = ("title",)
|
|
158
|
+
|
|
159
|
+
display_config_class = ReportCategoryDisplayConfig
|
|
160
|
+
|
|
161
|
+
queryset = ReportCategory.objects.all()
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class ReportModelViewSet(GuardianFilterMixin, viewsets.ModelViewSet):
|
|
165
|
+
serializer_class = ReportModelSerializer
|
|
166
|
+
ordering_fields = (
|
|
167
|
+
"title",
|
|
168
|
+
"parent_report__title",
|
|
169
|
+
"category__title",
|
|
170
|
+
"is_active",
|
|
171
|
+
"permission_type",
|
|
172
|
+
"base_color",
|
|
173
|
+
"mailing_list__title",
|
|
174
|
+
)
|
|
175
|
+
ordering = ("title",)
|
|
176
|
+
search_fields = ("title",)
|
|
177
|
+
filterset_class = ReportFilterSet
|
|
178
|
+
display_config_class = ReportDisplayConfig
|
|
179
|
+
endpoint_config_class = ReportEndpointConfig
|
|
180
|
+
title_config_class = ReportTitleConfig
|
|
181
|
+
button_config_class = ReportButtonConfig
|
|
182
|
+
|
|
183
|
+
queryset = Report.objects.annotate(
|
|
184
|
+
has_children=Exists(Report.objects.filter(parent_report=OuterRef("pk"))),
|
|
185
|
+
_group_key=Case(When(has_children=True, then=F("id")), default=None, output_field=IntegerField()),
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
@action(detail=True, methods=["PATCH"], permission_classes=[IsAuthenticated])
|
|
189
|
+
def bundletreport(self, request, pk=None):
|
|
190
|
+
if request.user.is_superuser:
|
|
191
|
+
report = get_object_or_404(Report, pk=pk)
|
|
192
|
+
try:
|
|
193
|
+
parameters = json.loads(request.POST["parameters"])
|
|
194
|
+
except KeyError:
|
|
195
|
+
parameters = report.last_version.parameters if report.versions.exists() else None
|
|
196
|
+
generate_and_send_current_report_file.delay(request.user.id, pk, parameters=parameters)
|
|
197
|
+
return Response({}, status=status.HTTP_200_OK)
|
|
198
|
+
|
|
199
|
+
@action(detail=True, methods=["PATCH"], permission_classes=[IsAuthenticated])
|
|
200
|
+
def switchprimaryversions(self, request, pk=None):
|
|
201
|
+
if request.user.is_superuser:
|
|
202
|
+
report = get_object_or_404(Report, pk=pk)
|
|
203
|
+
try:
|
|
204
|
+
parameters = json.loads(request.POST["parameters"])
|
|
205
|
+
except KeyError:
|
|
206
|
+
parameters = report.last_version.parameters if report.versions.exists() else None
|
|
207
|
+
set_primary_report_version_as_task.delay(report.pk, parameters=parameters)
|
|
208
|
+
return Response({}, status=status.HTTP_200_OK)
|
|
209
|
+
|
|
210
|
+
@action(detail=True, methods=["PATCH"], permission_classes=[IsAuthenticated])
|
|
211
|
+
def generatenextreports(self, request, pk=None):
|
|
212
|
+
if request.user.is_superuser:
|
|
213
|
+
parameters = None
|
|
214
|
+
if (start := request.GET.get("start_date", None)) and (end := request.GET.get("end_date", None)):
|
|
215
|
+
parameters = {"start": start, "end": end}
|
|
216
|
+
generate_next_reports_as_task.delay(
|
|
217
|
+
pk,
|
|
218
|
+
user=request.user,
|
|
219
|
+
parameters=parameters,
|
|
220
|
+
comment=request.GET.get("comment", ""),
|
|
221
|
+
max_depth_only=request.GET.get("max_depth_only", False) == "true",
|
|
222
|
+
)
|
|
223
|
+
return Response({}, status=status.HTTP_200_OK)
|
|
224
|
+
|
|
225
|
+
@action(detail=True, methods=["PATCH"], permission_classes=[IsAuthenticated])
|
|
226
|
+
def bulkcreatereport(self, request, pk=None):
|
|
227
|
+
if request.user.is_superuser:
|
|
228
|
+
start_parameters = end_parameters = None
|
|
229
|
+
if start_parameters_str := request.POST.get("start_parameters", None):
|
|
230
|
+
start_parameters = json.loads(start_parameters_str)
|
|
231
|
+
if end_parameters_str := request.POST.get("end_parameters", None):
|
|
232
|
+
end_parameters = json.loads(end_parameters_str)
|
|
233
|
+
|
|
234
|
+
if start_parameters and end_parameters:
|
|
235
|
+
bulk_create_child_reports_as_task.delay(pk, start_parameters, end_parameters, user=request.user)
|
|
236
|
+
return Response({}, status=status.HTTP_200_OK)
|
|
237
|
+
|
|
238
|
+
@action(detail=True, methods=["PATCH"], permission_classes=[IsAuthenticated])
|
|
239
|
+
def updatecontext(self, request, pk=None):
|
|
240
|
+
if request.user.is_superuser:
|
|
241
|
+
report = get_object_or_404(Report, pk=pk)
|
|
242
|
+
if report.versions.exists():
|
|
243
|
+
try:
|
|
244
|
+
parameters = json.loads(request.POST["parameters"])
|
|
245
|
+
except KeyError:
|
|
246
|
+
parameters = report.last_version.parameters
|
|
247
|
+
update_version_context_as_task.delay(pk, parameters=parameters, user=request.user)
|
|
248
|
+
return Response({}, status=status.HTTP_200_OK)
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
class ReportVersionModelViewSet(viewsets.ModelViewSet):
|
|
252
|
+
serializer_class = ReportVersionModelSerializer
|
|
253
|
+
ordering_fields = (
|
|
254
|
+
"uuid",
|
|
255
|
+
"report",
|
|
256
|
+
"title",
|
|
257
|
+
"version_date",
|
|
258
|
+
"creation_date",
|
|
259
|
+
"update_date",
|
|
260
|
+
"is_primary",
|
|
261
|
+
"disabled",
|
|
262
|
+
)
|
|
263
|
+
ordering = ("-version_date",)
|
|
264
|
+
search_fields = ("title", "report__title")
|
|
265
|
+
filterset_class = ReportVersionFilterSet
|
|
266
|
+
|
|
267
|
+
display_config_class = ReportVersionDisplayConfig
|
|
268
|
+
endpoint_config_class = ReportVersionEndpointConfig
|
|
269
|
+
title_config_class = ReportVersionTitleConfig
|
|
270
|
+
button_config_class = ReportVersionButtonConfig
|
|
271
|
+
|
|
272
|
+
queryset = ReportVersion.objects.all()
|
|
273
|
+
|
|
274
|
+
@action(detail=True, methods=["GET"], permission_classes=[IsAuthenticated])
|
|
275
|
+
def sendemail(self, request, pk=None):
|
|
276
|
+
version = ReportVersion.objects.get(id=pk)
|
|
277
|
+
if version:
|
|
278
|
+
version.send_mail()
|
|
279
|
+
return Response({}, status=status.HTTP_200_OK)
|
|
280
|
+
return Response({}, status=status.HTTP_404_NOT_FOUND)
|
|
281
|
+
|
|
282
|
+
@action(detail=True, methods=["GET"], permission_classes=[IsAuthenticated])
|
|
283
|
+
def updatecontext(self, request, pk=None):
|
|
284
|
+
update_context_as_task.delay(pk, request.user, comment=request.GET.get("comment", ""))
|
|
285
|
+
return Response({}, status=status.HTTP_200_OK)
|
|
286
|
+
|
|
287
|
+
@action(
|
|
288
|
+
detail=True,
|
|
289
|
+
methods=["GET"],
|
|
290
|
+
permission_classes=[IsAuthenticated],
|
|
291
|
+
renderer_classes=[StaticHTMLRenderer],
|
|
292
|
+
authentication_classes=[JWTCookieAuthentication],
|
|
293
|
+
)
|
|
294
|
+
def html(self, request, pk=None):
|
|
295
|
+
version = get_object_or_404(ReportVersion, id=pk, disabled=False, report__is_active=True)
|
|
296
|
+
if version.report.is_accessible(request.user):
|
|
297
|
+
return HttpResponse(version.generate_html())
|
|
298
|
+
return Response({}, status=status.HTTP_401_UNAUTHORIZED)
|
|
299
|
+
|
|
300
|
+
@action(
|
|
301
|
+
detail=True,
|
|
302
|
+
methods=["GET"],
|
|
303
|
+
permission_classes=[IsAuthenticated],
|
|
304
|
+
authentication_classes=[JWTCookieAuthentication],
|
|
305
|
+
)
|
|
306
|
+
def file(self, request, pk=None):
|
|
307
|
+
version = get_object_or_404(ReportVersion, id=pk, disabled=False, report__is_active=True)
|
|
308
|
+
if version.report.is_accessible(request.user):
|
|
309
|
+
output = version.generate_file()
|
|
310
|
+
output.seek(0)
|
|
311
|
+
if output:
|
|
312
|
+
return FileResponse(
|
|
313
|
+
output,
|
|
314
|
+
as_attachment=True,
|
|
315
|
+
filename=output.name,
|
|
316
|
+
content_type=Report.FileContentType[version.report.file_content_type].label,
|
|
317
|
+
)
|
|
318
|
+
return Response({}, status=status.HTTP_401_UNAUTHORIZED)
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
class ReportVersionReportModelViewSet(ReportVersionModelViewSet):
|
|
322
|
+
display_config_class = ReportVersionReportDisplayConfig
|
|
323
|
+
endpoint_config_class = ReportVersionReportEndpointConfig
|
|
324
|
+
title_config_class = ReportVersionReportTitleConfig
|
|
325
|
+
|
|
326
|
+
def get_queryset(self):
|
|
327
|
+
report = Report.objects.get(id=self.kwargs["report_id"])
|
|
328
|
+
if report.is_accessible(self.request.user):
|
|
329
|
+
return super().get_queryset().filter(report=self.kwargs["report_id"])
|
|
330
|
+
return ReportVersion.objects.none()
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
wbreport/__init__.py,sha256=J-j-u0itpEFT6irdmWmixQqYMadNl1X91TxUmoiLHMI,22
|
|
2
|
+
wbreport/admin.py,sha256=tQPq0BKzXZ7I3aOE0FaGyjuKs37TiT56s7OT0mDfOXo,2364
|
|
3
|
+
wbreport/apps.py,sha256=4z2N25hswEAlsJsntASC5iOWUwsqMCL99-gvqBlPGFY,148
|
|
4
|
+
wbreport/dynamic_preferences_registry.py,sha256=nGT-fS5vN-BSVNyGcJ81ORjiXlOngePRN9hipB9olPw,508
|
|
5
|
+
wbreport/filters.py,sha256=2j8osC3fx5mLWilV3rKoSjSph9mWL04TMuVcd-yEf4A,1146
|
|
6
|
+
wbreport/mixins.py,sha256=Hx_LTPVfmygrnyDTOjNi58N_QNfdBURPmriLNV3pbfU,5520
|
|
7
|
+
wbreport/models.py,sha256=cRKgmdbb2cKRr04jkTtwv6kmRc5fd8CcIUENKlGIegQ,29595
|
|
8
|
+
wbreport/serializers.py,sha256=_heMGD75ncR3ygs-OcdpFVPjCZUyEI4F3iVS9yp47Yc,7226
|
|
9
|
+
wbreport/tasks.py,sha256=KLSRyw0aRhLsmT5UGdlalpRbNyRFXBRfejg5k9j8wPo,2270
|
|
10
|
+
wbreport/urls.py,sha256=6VuxcSKi5aMmH8IIqmXlBcIhdam_pGl2T_xemhZh6FI,1205
|
|
11
|
+
wbreport/urls_public.py,sha256=LbzOc79VKmKUntsUb54lm0QoC22ip05ZdyNbSl2j3KQ,369
|
|
12
|
+
wbreport/defaults/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
+
wbreport/defaults/factsheets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
+
wbreport/defaults/factsheets/base.py,sha256=0qmn10S2l6cqcZV_pUS7c-lHlC8ajOmDmUsgJVQ2OJU,41089
|
|
15
|
+
wbreport/defaults/factsheets/menu.py,sha256=G2iX6jZhqddoFsc3-t2uI7ZverUaBzF7EjqAbLrIEYU,4579
|
|
16
|
+
wbreport/defaults/factsheets/mixins.py,sha256=E0RvxmUpvpG7B7YngBPXJ35eD3nwNandJFzLjj1rNRI,1267
|
|
17
|
+
wbreport/defaults/factsheets/multitheme.py,sha256=Kje360mRE8XTIOugCOL7-44fjjIrnbmcx5HrzVqtzbI,38487
|
|
18
|
+
wbreport/factories/__init__.py,sha256=jyD1_R-xc2JPZIaSwtE7zYATdL9NIXIDqTwjLw1MolA,170
|
|
19
|
+
wbreport/factories/data_classes.py,sha256=BwYqbw75lnZSim8LNY9-mhf79GjGqdQdd8XQiPPNyvA,1486
|
|
20
|
+
wbreport/factories/reports.py,sha256=_oJBJp5WmoaZ0BjU8MwqYdBpSJxsQH61b3QQrOmYOOU,2285
|
|
21
|
+
wbreport/migrations/0001_initial_squashed_squashed_0007_report_key.py,sha256=ghAnYJK01-ISld9CUfU18sqdIstuw5UrOgWH2y8gcTs,10061
|
|
22
|
+
wbreport/migrations/0008_alter_report_file_content_type.py,sha256=qPR9kWiZLDvfw9H3-BsUdmdIEwlhm5iHSoSax8hzjNE,715
|
|
23
|
+
wbreport/migrations/0009_alter_report_color_palette.py,sha256=sEIqeMBPYfOg5Onom8H9VCNmlMkpqNI9qT51UVtoBTM,770
|
|
24
|
+
wbreport/migrations/0010_auto_20240103_0947.py,sha256=voHHRETqSZRxrUJBD81ig20MuJMm_ymnZ8cbdANUMLQ,1468
|
|
25
|
+
wbreport/migrations/0011_auto_20240207_1629.py,sha256=7f21bmsb91nEUWtnWnXpNJwJYRUMurnGzWEmQxmU2Wk,1505
|
|
26
|
+
wbreport/migrations/0012_reportversion_lock.py,sha256=eSs6TIJY2YgWPMk3k8ykl2nsnNBc16lFMKtkWCC1btA,445
|
|
27
|
+
wbreport/migrations/0013_alter_reportversion_context.py,sha256=_6hcwvxYzDu3UiBoO6Vq6-pxF_j7hNlQ4VK-dltxUSw,485
|
|
28
|
+
wbreport/migrations/0014_alter_reportcategory_options_and_more.py,sha256=52ot6CkuICQfGCrYU5Zqtz7olqUgSw2Ppp17adnPqh0,723
|
|
29
|
+
wbreport/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
30
|
+
wbreport/pdf/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
31
|
+
wbreport/pdf/charts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
32
|
+
wbreport/pdf/charts/legend.py,sha256=D-_-ZLDF7q7KlYLiNYVXHWLs4I-LgV8Ce8lk1sLfbPU,461
|
|
33
|
+
wbreport/pdf/charts/pie.py,sha256=EcWTDOv1ZD5Az6MnBt_w5pBXusPBB3zTHlpguBPNjfU,4287
|
|
34
|
+
wbreport/pdf/charts/timeseries.py,sha256=dN2N66qg9S3bW9OV8q-Vms3wFxUHhLMnaUnymzTNeWY,2381
|
|
35
|
+
wbreport/pdf/sandbox/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
36
|
+
wbreport/pdf/sandbox/run.py,sha256=Vkzp_xVVJHctToS49Uef2Mnpb_5KUOWPxNdTFHOqri8,584
|
|
37
|
+
wbreport/pdf/sandbox/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
|
+
wbreport/pdf/sandbox/templates/basic_factsheet.py,sha256=w_PpPS8rbirkrodgXs538_xOw6aNKGr4GGuVn_XGPPU,33967
|
|
39
|
+
wbreport/pdf/sandbox/templates/fund_factsheet.py,sha256=aGf5CfUHAp-kGJfU8tZ3TnEO26re4Sny_G2QCFte4gk,31054
|
|
40
|
+
wbreport/pdf/sandbox/templates/long_industry_exposure_factsheet.py,sha256=TnOz_NJLhX7ZT1amnbPkyee719dYug688JGSzVGRaMQ,32684
|
|
41
|
+
wbreport/pdf/sandbox/templates/multistrat_factsheet.py,sha256=8-WU-r7x6Yq5v1ml2mUT7e33SUYk7IzKMNXFWuE7Y2k,31481
|
|
42
|
+
wbreport/pdf/sandbox/templates/testfile.pdf,sha256=eV55RNFdqxqYzre6mg8EWZoL_cbc_lwPjyTGt1pr1AI,144012
|
|
43
|
+
wbreport/pdf/tables/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
44
|
+
wbreport/pdf/tables/aggregated_tables.py,sha256=rYikFswLMcaTpW7Em5B5oE1WSItQjkW_MJJTsumRpq8,4763
|
|
45
|
+
wbreport/pdf/tables/data_tables.py,sha256=snJlyMMRz4YSR4gcXeIdQR38h-IkOQiO0A5jx5lF45o,2241
|
|
46
|
+
wbreport/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
47
|
+
wbreport/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
48
|
+
wbreport/templatetags/portfolio_tags.py,sha256=N2MC_6iFcUAFDH5Wx5rD1-PVK_Ltq4VPIoq7WL4aXGQ,900
|
|
49
|
+
wbreport/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
50
|
+
wbreport/tests/conftest.py,sha256=oMidAuP41_yxMubUDUpqcsW_YslEq_CyPmfD11CUPhY,745
|
|
51
|
+
wbreport/tests/test_models.py,sha256=nCBcCLBylZsFMSgkU6mm4iQdoPVRuS42taCI0pb6Gx4,11292
|
|
52
|
+
wbreport/tests/test_tasks.py,sha256=icRtEyAtKfhxyx_oN6cYtkUA4QMaGwEpdKKhc07OPKc,762
|
|
53
|
+
wbreport/tests/test_viewsets.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
54
|
+
wbreport/tests/tests.py,sha256=j2A1uu5DtGu2w056j0S4O7u2OxylldMPCmr7bbSOvfk,282
|
|
55
|
+
wbreport/viewsets/__init__.py,sha256=EzsLpS7Y7HxrcLXUJ0DPAmtgewOqkKjoLwHmgijT7Hk,287
|
|
56
|
+
wbreport/viewsets/viewsets.py,sha256=MuglJiKtfKWX3uq81ghChEGJVzvXDqJEef9dSEZJ2Ao,13120
|
|
57
|
+
wbreport/viewsets/configs/__init__.py,sha256=Tsw7Ffe_iy63CPRZgtsIXkZjUMvKdsMxSz5xzmyqF5A,494
|
|
58
|
+
wbreport/viewsets/configs/buttons.py,sha256=Hbofe9TtZ5JdoLOb_rlGzC-_Z_lnJpIseXnFoJd9i-g,8914
|
|
59
|
+
wbreport/viewsets/configs/displays.py,sha256=py3Wcut9uKmer7LV-ftIi0xU97PFctJT-yKZmdgc8qk,4897
|
|
60
|
+
wbreport/viewsets/configs/endpoints.py,sha256=wPbB0JnnKSF8hSX07W67rdGkP0VKqLBhTnjBKjZzaL0,799
|
|
61
|
+
wbreport/viewsets/configs/menus.py,sha256=trDZsdjXip8KQ4SY1uIudZWFqwb3rQHIRSU36dzRzy0,269
|
|
62
|
+
wbreport/viewsets/configs/titles.py,sha256=AYY1ekJp9V8iihcuR8Ygl-7_1AYpXoAp8WthpWWD5GE,782
|
|
63
|
+
wbreport-2.2.1.dist-info/METADATA,sha256=QibKFoERBiSBijkT61pOTxBm2HR1_dq88xVRskwPzH4,163
|
|
64
|
+
wbreport-2.2.1.dist-info/WHEEL,sha256=aO3RJuuiFXItVSnAUEmQ0yRBvv9e1sbJh68PtuQkyAE,105
|
|
65
|
+
wbreport-2.2.1.dist-info/licenses/LICENSE,sha256=jvfVH0SY8_YMHlsJHKe_OajiscQDz4lpTlqT6x24sVw,172
|
|
66
|
+
wbreport-2.2.1.dist-info/RECORD,,
|