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,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,8 @@
1
+ from wbcore.menus import ItemPermission, MenuItem
2
+
3
+ REPORT_MENUITEM = MenuItem(
4
+ label="Reports",
5
+ endpoint="wbreport:report-list",
6
+ permission=ItemPermission(permissions=["wbreport.view_report"]),
7
+ endpoint_get_parameters={"parent_report__isnull": True},
8
+ )
@@ -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,6 @@
1
+ Metadata-Version: 2.3
2
+ Name: wbreport
3
+ Version: 2.2.1
4
+ Author-email: Christopher Wittlinger <c.wittlinger@stainly.com>
5
+ Requires-Dist: wbcore
6
+ Requires-Dist: wbmailing
@@ -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,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.26.3
3
+ Root-Is-Purelib: true
4
+ Tag: py2-none-any
5
+ Tag: py3-none-any
@@ -0,0 +1,4 @@
1
+ This repository is not allowed to be used without written consent from either:
2
+
3
+ - Stainly SarL (Geneva, Switzerland)
4
+ - Intellineers GmbH & Co.KG (Hamburg, Germany)