wbreport 1.49.5__py2.py3-none-any.whl → 1.60.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.
- wbreport/defaults/factsheets/base.py +5 -5
- wbreport/defaults/factsheets/multitheme.py +5 -5
- wbreport/filters.py +12 -3
- wbreport/mixins.py +1 -3
- wbreport/models.py +30 -24
- wbreport/pdf/charts/legend.py +1 -1
- wbreport/pdf/charts/pie.py +1 -0
- wbreport/pdf/charts/timeseries.py +1 -1
- wbreport/pdf/flowables/risk.py +2 -1
- wbreport/pdf/flowables/textboxes.py +2 -1
- wbreport/pdf/sandbox/templates/basic_factsheet.py +11 -10
- wbreport/pdf/sandbox/templates/fund_factsheet.py +10 -9
- wbreport/pdf/sandbox/templates/long_industry_exposure_factsheet.py +10 -9
- wbreport/pdf/sandbox/templates/multistrat_factsheet.py +7 -6
- wbreport/pdf/tables/aggregated_tables.py +4 -3
- wbreport/pdf/tables/data_tables.py +2 -1
- wbreport/serializers.py +6 -5
- wbreport/tasks.py +2 -1
- wbreport/tests/test_models.py +1 -0
- wbreport/tests/test_tasks.py +1 -0
- wbreport/viewsets/configs/buttons.py +24 -11
- wbreport/viewsets/configs/displays.py +29 -13
- wbreport/viewsets/configs/endpoints.py +3 -10
- wbreport/viewsets/viewsets.py +10 -6
- {wbreport-1.49.5.dist-info → wbreport-1.60.1.dist-info}/METADATA +1 -1
- {wbreport-1.49.5.dist-info → wbreport-1.60.1.dist-info}/RECORD +28 -28
- {wbreport-1.49.5.dist-info → wbreport-1.60.1.dist-info}/WHEEL +1 -1
- {wbreport-1.49.5.dist-info → wbreport-1.60.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -22,7 +22,6 @@ from reportlab.platypus import (
|
|
|
22
22
|
Flowable,
|
|
23
23
|
NextPageTemplate,
|
|
24
24
|
PageTemplate,
|
|
25
|
-
Paragraph,
|
|
26
25
|
Spacer,
|
|
27
26
|
Table,
|
|
28
27
|
TableStyle,
|
|
@@ -33,6 +32,7 @@ from wbcore.utils.figures import (
|
|
|
33
32
|
get_horizontal_barplot,
|
|
34
33
|
get_piechart,
|
|
35
34
|
)
|
|
35
|
+
from wbcore.utils.reportlab import FormattedParagraph as Paragraph
|
|
36
36
|
from wbportfolio.models.products import InvestmentIndex
|
|
37
37
|
|
|
38
38
|
from wbreport.mixins import ReportMixin
|
|
@@ -199,7 +199,7 @@ class ReportClass(FactsheetReportMixin, ReportMixin):
|
|
|
199
199
|
return template.render(context)
|
|
200
200
|
|
|
201
201
|
@classmethod
|
|
202
|
-
def generate_file(cls, context):
|
|
202
|
+
def generate_file(cls, context): # noqa: C901
|
|
203
203
|
debug = False
|
|
204
204
|
# Product Data
|
|
205
205
|
# Main Feature table as dictionary
|
|
@@ -446,7 +446,7 @@ class ReportClass(FactsheetReportMixin, ReportMixin):
|
|
|
446
446
|
# Price Timeseries Chart
|
|
447
447
|
elements.append(
|
|
448
448
|
get_timeseries_chart(
|
|
449
|
-
data=[list(zip(prices.index, prices.net_value))],
|
|
449
|
+
data=[list(zip(prices.index, prices.net_value, strict=False))],
|
|
450
450
|
width=CONTENT_WIDTH_PAGE1_LEFT - CONTENT_OFFSET,
|
|
451
451
|
height=4.34 * cm,
|
|
452
452
|
color=c_product,
|
|
@@ -467,7 +467,7 @@ class ReportClass(FactsheetReportMixin, ReportMixin):
|
|
|
467
467
|
"<strong>Top 3 Contributors</strong>",
|
|
468
468
|
"<strong>Bottom 3 Contributors</strong>",
|
|
469
469
|
],
|
|
470
|
-
data=list(zip(top_3_holdings, top_3_contributors, bottom_3_contributors)),
|
|
470
|
+
data=list(zip(top_3_holdings, top_3_contributors, bottom_3_contributors, strict=False)),
|
|
471
471
|
width=CONTENT_WIDTH_PAGE1_LEFT,
|
|
472
472
|
header_row_height=0.85 * cm,
|
|
473
473
|
data_row_height=0.39 * cm,
|
|
@@ -636,7 +636,7 @@ class ReportClass(FactsheetReportMixin, ReportMixin):
|
|
|
636
636
|
|
|
637
637
|
data = list()
|
|
638
638
|
categories = list()
|
|
639
|
-
for
|
|
639
|
+
for row in df.itertuples():
|
|
640
640
|
data.append(row.weighting * 100)
|
|
641
641
|
categories.append(f"{row.aggregated_title} ({row.weighting * 100:.1f}%)")
|
|
642
642
|
|
|
@@ -21,7 +21,6 @@ from reportlab.platypus import (
|
|
|
21
21
|
BaseDocTemplate,
|
|
22
22
|
NextPageTemplate,
|
|
23
23
|
PageTemplate,
|
|
24
|
-
Paragraph,
|
|
25
24
|
Spacer,
|
|
26
25
|
Table,
|
|
27
26
|
TableStyle,
|
|
@@ -32,6 +31,7 @@ from wbcore.utils.figures import (
|
|
|
32
31
|
get_horizontal_barplot,
|
|
33
32
|
get_piechart,
|
|
34
33
|
)
|
|
34
|
+
from wbcore.utils.reportlab import FormattedParagraph as Paragraph
|
|
35
35
|
from wbportfolio.models.products import InvestmentIndex
|
|
36
36
|
|
|
37
37
|
from wbreport.mixins import ReportMixin
|
|
@@ -199,7 +199,7 @@ class ReportClass(FactsheetReportMixin, ReportMixin):
|
|
|
199
199
|
return template.render(context)
|
|
200
200
|
|
|
201
201
|
@classmethod
|
|
202
|
-
def generate_file(cls, context):
|
|
202
|
+
def generate_file(cls, context): # noqa: C901
|
|
203
203
|
debug = False
|
|
204
204
|
|
|
205
205
|
main_features_dict = context["information_table"]["Main Features"]
|
|
@@ -450,7 +450,7 @@ class ReportClass(FactsheetReportMixin, ReportMixin):
|
|
|
450
450
|
# Price Timeseries Chart
|
|
451
451
|
elements.append(
|
|
452
452
|
get_timeseries_chart(
|
|
453
|
-
data=[list(zip(prices.index, prices.net_value))],
|
|
453
|
+
data=[list(zip(prices.index, prices.net_value, strict=False))],
|
|
454
454
|
width=CONTENT_WIDTH_PAGE1_LEFT - CONTENT_OFFSET,
|
|
455
455
|
height=4.34 * cm,
|
|
456
456
|
color=c_product,
|
|
@@ -471,7 +471,7 @@ class ReportClass(FactsheetReportMixin, ReportMixin):
|
|
|
471
471
|
"<strong>Top 3 Contributors</strong>",
|
|
472
472
|
"<strong>Bottom 3 Contributors</strong>",
|
|
473
473
|
],
|
|
474
|
-
data=list(zip(top_3_holdings, top_3_contributors, bottom_3_contributors)),
|
|
474
|
+
data=list(zip(top_3_holdings, top_3_contributors, bottom_3_contributors, strict=False)),
|
|
475
475
|
width=CONTENT_WIDTH_PAGE1_LEFT,
|
|
476
476
|
header_row_height=0.85 * cm,
|
|
477
477
|
data_row_height=0.39 * cm,
|
|
@@ -639,7 +639,7 @@ class ReportClass(FactsheetReportMixin, ReportMixin):
|
|
|
639
639
|
|
|
640
640
|
data = list()
|
|
641
641
|
categories = list()
|
|
642
|
-
for
|
|
642
|
+
for row in df.itertuples:
|
|
643
643
|
data.append(row.weighting * 100)
|
|
644
644
|
categories.append(f"{row.aggregated_title} ({row.weighting * 100:.1f}%)")
|
|
645
645
|
|
wbreport/filters.py
CHANGED
|
@@ -4,13 +4,22 @@ from wbreport.models import Report, ReportVersion
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class ReportFilterSet(wb_filters.FilterSet):
|
|
7
|
-
is_active = wb_filters.BooleanFilter(
|
|
7
|
+
is_active = wb_filters.BooleanFilter(initial=True)
|
|
8
|
+
|
|
9
|
+
parent_report = wb_filters.ModelChoiceFilter(
|
|
10
|
+
label="Parent",
|
|
11
|
+
queryset=Report.objects.all(),
|
|
12
|
+
endpoint=Report.get_representation_endpoint(),
|
|
13
|
+
value_key=Report.get_representation_value_key(),
|
|
14
|
+
label_key=Report.get_representation_label_key(),
|
|
15
|
+
hidden=True,
|
|
16
|
+
)
|
|
17
|
+
parent_report__isnull = wb_filters.BooleanFilter(field_name="parent_report", lookup_expr="isnull", hidden=True)
|
|
8
18
|
|
|
9
19
|
class Meta:
|
|
10
20
|
model = Report
|
|
11
21
|
fields = {
|
|
12
22
|
"category": ["exact"],
|
|
13
|
-
"parent_report": ["exact", "isnull"],
|
|
14
23
|
"permission_type": ["exact"],
|
|
15
24
|
"base_color": ["exact"],
|
|
16
25
|
"mailing_list": ["exact"],
|
|
@@ -18,7 +27,7 @@ class ReportFilterSet(wb_filters.FilterSet):
|
|
|
18
27
|
|
|
19
28
|
|
|
20
29
|
class ReportVersionFilterSet(wb_filters.FilterSet):
|
|
21
|
-
disabled = wb_filters.BooleanFilter(method="boolean_is_disabled",
|
|
30
|
+
disabled = wb_filters.BooleanFilter(method="boolean_is_disabled", initial=False)
|
|
22
31
|
|
|
23
32
|
def boolean_is_disabled(self, queryset, name, value):
|
|
24
33
|
if value is True:
|
wbreport/mixins.py
CHANGED
|
@@ -2,13 +2,11 @@ from datetime import date
|
|
|
2
2
|
from io import BytesIO
|
|
3
3
|
from typing import Any, Dict
|
|
4
4
|
|
|
5
|
-
from django.contrib.auth import get_user_model
|
|
6
5
|
from django.template.loader import get_template
|
|
6
|
+
from wbcore.contrib.authentication.models.users import User
|
|
7
7
|
|
|
8
8
|
from wbreport.models import Report, ReportVersion
|
|
9
9
|
|
|
10
|
-
User = get_user_model()
|
|
11
|
-
|
|
12
10
|
|
|
13
11
|
class ReportMixin:
|
|
14
12
|
HTML_TEMPLATE_FILE = ""
|
wbreport/models.py
CHANGED
|
@@ -8,7 +8,6 @@ from typing import Any, Dict, List, Optional
|
|
|
8
8
|
from celery import shared_task
|
|
9
9
|
from colorfield.fields import ColorField
|
|
10
10
|
from django.conf import settings
|
|
11
|
-
from django.contrib.auth import get_user_model
|
|
12
11
|
from django.contrib.contenttypes.fields import GenericForeignKey
|
|
13
12
|
from django.contrib.contenttypes.models import ContentType
|
|
14
13
|
from django.core.serializers.json import DjangoJSONEncoder
|
|
@@ -22,14 +21,14 @@ from guardian.shortcuts import get_objects_for_user
|
|
|
22
21
|
from mptt.models import MPTTModel, TreeForeignKey
|
|
23
22
|
from ordered_model.models import OrderedModel
|
|
24
23
|
from rest_framework.reverse import reverse
|
|
24
|
+
from wbcore.contrib.authentication.models.users import User
|
|
25
25
|
from wbcore.contrib.guardian.models.mixins import PermissionObjectModelMixin
|
|
26
26
|
from wbcore.contrib.notifications.dispatch import send_notification
|
|
27
27
|
from wbcore.contrib.notifications.utils import create_notification_type
|
|
28
28
|
from wbcore.models import WBModel
|
|
29
|
+
from wbcore.workers import Queue
|
|
29
30
|
from wbmailing.models import MailTemplate, MassMail
|
|
30
31
|
|
|
31
|
-
User = get_user_model()
|
|
32
|
-
|
|
33
32
|
|
|
34
33
|
class ReportAsset(models.Model):
|
|
35
34
|
"""
|
|
@@ -112,9 +111,9 @@ class ReportClass(WBModel):
|
|
|
112
111
|
"""
|
|
113
112
|
if (len(args) == 3 and (class_path := args[2])) or (class_path := kwargs.get("class_path", None)):
|
|
114
113
|
try:
|
|
115
|
-
if
|
|
114
|
+
if class_module := getattr(importlib.import_module(class_path), "ReportClass", None):
|
|
116
115
|
for method in self.REPORT_CLASS_DEFAULT_METHODS:
|
|
117
|
-
setattr(self, method, getattr(
|
|
116
|
+
setattr(self, method, getattr(class_module, method))
|
|
118
117
|
except ModuleNotFoundError:
|
|
119
118
|
for method in self.REPORT_CLASS_DEFAULT_METHODS:
|
|
120
119
|
setattr(self, method, lambda *a, **k: None)
|
|
@@ -612,16 +611,18 @@ class ReportVersion(models.Model):
|
|
|
612
611
|
**kwargs: Divers keyword arguments to be injected in the get_context function
|
|
613
612
|
"""
|
|
614
613
|
if not self.lock or force_context_update:
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
614
|
+
context = {}
|
|
615
|
+
try:
|
|
616
|
+
context = self.get_context(**kwargs)
|
|
617
|
+
self.disabled = False
|
|
618
|
+
except Exception as e:
|
|
619
|
+
self.comment = f"Error while updating this version context: {e}"
|
|
620
|
+
self.disabled = True
|
|
621
|
+
if not silent:
|
|
622
|
+
raise e
|
|
623
|
+
context = self.report.report_class.serialize_context(context)
|
|
624
|
+
if context:
|
|
625
|
+
self.context = context
|
|
625
626
|
self.save()
|
|
626
627
|
|
|
627
628
|
def generate_file(self) -> BytesIO:
|
|
@@ -674,6 +675,10 @@ class ReportVersion(models.Model):
|
|
|
674
675
|
mass_mail.send()
|
|
675
676
|
mass_mail.save()
|
|
676
677
|
|
|
678
|
+
@classmethod
|
|
679
|
+
def get_endpoint_basename(cls) -> str:
|
|
680
|
+
return "wbreport:reportversion"
|
|
681
|
+
|
|
677
682
|
@classmethod
|
|
678
683
|
def get_representation_endpoint(cls) -> str:
|
|
679
684
|
return "wbreport:reportversionrepresentation-list"
|
|
@@ -696,7 +701,7 @@ def generate_version_context_if_null(sender, instance, created, raw, **kwargs):
|
|
|
696
701
|
update_context_as_task.apply_async((instance.id,), countdown=30)
|
|
697
702
|
|
|
698
703
|
|
|
699
|
-
@shared_task()
|
|
704
|
+
@shared_task(queue=Queue.DEFAULT.value)
|
|
700
705
|
def generate_next_reports_as_task(report_id, parameters=None, user=None, comment=None, max_depth_only=False):
|
|
701
706
|
"""
|
|
702
707
|
Trigger the Report generate_next_reports as a task
|
|
@@ -712,7 +717,7 @@ def generate_next_reports_as_task(report_id, parameters=None, user=None, comment
|
|
|
712
717
|
)
|
|
713
718
|
|
|
714
719
|
|
|
715
|
-
@shared_task()
|
|
720
|
+
@shared_task(queue=Queue.DEFAULT.value)
|
|
716
721
|
def bulk_create_child_reports_as_task(report_id, start_parameters, end_parameters, user=None):
|
|
717
722
|
"""
|
|
718
723
|
Trigger the Report generate_next_reports as a task
|
|
@@ -728,16 +733,17 @@ def bulk_create_child_reports_as_task(report_id, start_parameters, end_parameter
|
|
|
728
733
|
)
|
|
729
734
|
|
|
730
735
|
|
|
731
|
-
@shared_task()
|
|
732
|
-
def update_context_as_task(
|
|
736
|
+
@shared_task(queue=Queue.DEFAULT.value)
|
|
737
|
+
def update_context_as_task(
|
|
738
|
+
report_version_id: int, user: User | None = None, comment: str | None = None, force_context_update: bool = False
|
|
739
|
+
):
|
|
733
740
|
"""
|
|
734
741
|
Trigger the Report Version update_report_context as a task
|
|
735
742
|
"""
|
|
736
743
|
version = ReportVersion.objects.get(id=report_version_id)
|
|
737
744
|
if comment:
|
|
738
745
|
version.comment = comment
|
|
739
|
-
|
|
740
|
-
version.update_context()
|
|
746
|
+
version.update_context(force_context_update=force_context_update)
|
|
741
747
|
if user:
|
|
742
748
|
send_notification(
|
|
743
749
|
code="wbreport.report.background_task",
|
|
@@ -747,7 +753,7 @@ def update_context_as_task(report_version_id, user=None, comment=None):
|
|
|
747
753
|
)
|
|
748
754
|
|
|
749
755
|
|
|
750
|
-
@shared_task()
|
|
756
|
+
@shared_task(queue=Queue.DEFAULT.value)
|
|
751
757
|
def update_version_context_as_task(report_id, parameters=None, user=None):
|
|
752
758
|
"""
|
|
753
759
|
Trigger the Report Version update_report_context as a task
|
|
@@ -756,7 +762,7 @@ def update_version_context_as_task(report_id, parameters=None, user=None):
|
|
|
756
762
|
models.Q(is_active=True) & (models.Q(id=report_id) | models.Q(parent_report=report_id))
|
|
757
763
|
).distinct():
|
|
758
764
|
print( # noqa: T201
|
|
759
|
-
f
|
|
765
|
+
f"Updating context for report {str(report)} and version parameters {parameters if parameters else '{all}'}"
|
|
760
766
|
)
|
|
761
767
|
versions = report.versions.filter(disabled=False)
|
|
762
768
|
if parameters:
|
|
@@ -772,7 +778,7 @@ def update_version_context_as_task(report_id, parameters=None, user=None):
|
|
|
772
778
|
)
|
|
773
779
|
|
|
774
780
|
|
|
775
|
-
@shared_task()
|
|
781
|
+
@shared_task(queue=Queue.HIGH_PRIORITY.value)
|
|
776
782
|
def set_primary_report_version_as_task(report_id, parameters=None, user=None):
|
|
777
783
|
"""
|
|
778
784
|
Trigger the Report set_primary_versions as a task
|
wbreport/pdf/charts/legend.py
CHANGED
|
@@ -4,7 +4,7 @@ from reportlab.lib.colors import transparent
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class CustomLegend(Legend):
|
|
7
|
-
def _defaultSwatch(self, x, thisy, dx, dy, fillColor, strokeWidth, strokeColor):
|
|
7
|
+
def _defaultSwatch(self, x, thisy, dx, dy, fillColor, strokeWidth, strokeColor): # noqa: N803, N802
|
|
8
8
|
return Circle(
|
|
9
9
|
x,
|
|
10
10
|
thisy + dx / 2,
|
wbreport/pdf/charts/pie.py
CHANGED
|
@@ -17,7 +17,7 @@ class LogScaleTimeSeriesPlot(LinePlot):
|
|
|
17
17
|
super().__init__()
|
|
18
18
|
|
|
19
19
|
class CustomYAxis(LogYValueAxis):
|
|
20
|
-
def _calcTickPositions(self):
|
|
20
|
+
def _calcTickPositions(self): # noqa: N802
|
|
21
21
|
return self._calcStepAndTickPositions()[1]
|
|
22
22
|
|
|
23
23
|
self.xValueAxis = NormalDateXValueAxis()
|
wbreport/pdf/flowables/risk.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
from reportlab.lib.colors import HexColor, black, white
|
|
2
2
|
from reportlab.lib.units import cm
|
|
3
3
|
from reportlab.pdfbase.pdfmetrics import stringWidth
|
|
4
|
-
from reportlab.platypus import Flowable
|
|
4
|
+
from reportlab.platypus import Flowable
|
|
5
|
+
from wbcore.utils.reportlab import FormattedParagraph as Paragraph
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
class RiskScale(Flowable):
|
|
@@ -2,8 +2,9 @@ from reportlab.graphics import renderPDF
|
|
|
2
2
|
from reportlab.lib.colors import black
|
|
3
3
|
from reportlab.lib.units import cm
|
|
4
4
|
from reportlab.pdfbase.pdfmetrics import stringWidth
|
|
5
|
-
from reportlab.platypus import Flowable, Image,
|
|
5
|
+
from reportlab.platypus import Flowable, Image, Table, TableStyle
|
|
6
6
|
from svglib.svglib import svg2rlg
|
|
7
|
+
from wbcore.utils.reportlab import FormattedParagraph as Paragraph
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
class TextBox(Flowable):
|
|
@@ -22,7 +22,6 @@ from reportlab.platypus import (
|
|
|
22
22
|
Image,
|
|
23
23
|
NextPageTemplate,
|
|
24
24
|
PageTemplate,
|
|
25
|
-
Paragraph,
|
|
26
25
|
Spacer,
|
|
27
26
|
Table,
|
|
28
27
|
TableStyle,
|
|
@@ -30,6 +29,8 @@ from reportlab.platypus import (
|
|
|
30
29
|
from reportlab.platypus.flowables import KeepTogether, TopPadder
|
|
31
30
|
from reportlab.platypus.frames import Frame
|
|
32
31
|
from svglib.svglib import svg2rlg
|
|
32
|
+
from wbcore.utils.reportlab import FormattedParagraph as Paragraph
|
|
33
|
+
|
|
33
34
|
from wbreport.models import ReportAsset
|
|
34
35
|
from wbreport.pdf.charts.pie import (
|
|
35
36
|
get_pie_chart_horizontal,
|
|
@@ -43,7 +44,7 @@ from wbreport.pdf.tables.aggregated_tables import get_simple_aggregated_table
|
|
|
43
44
|
from wbreport.pdf.tables.data_tables import get_simple_data_table
|
|
44
45
|
|
|
45
46
|
|
|
46
|
-
def generate_report(context):
|
|
47
|
+
def generate_report(context): # noqa: C901
|
|
47
48
|
debug = False
|
|
48
49
|
### Product Data ###
|
|
49
50
|
# Main Feature table as dictionary
|
|
@@ -121,7 +122,7 @@ def generate_report(context):
|
|
|
121
122
|
s_base_small_justified = ParagraphStyle(
|
|
122
123
|
name="s_base_small_justified", parent=s_base, fontSize=6.5, leading=7, alignment=TA_JUSTIFY
|
|
123
124
|
)
|
|
124
|
-
s_base_small_justified_indent = ParagraphStyle(
|
|
125
|
+
s_base_small_justified_indent = ParagraphStyle( # noqa: F841
|
|
125
126
|
name="s_base_small_justified_indent", parent=s_base_small_justified, leftIndent=CONTENT_OFFSET
|
|
126
127
|
)
|
|
127
128
|
s_base_indent = ParagraphStyle(name="s_description", parent=s_base, spaceBefore=8, leftIndent=CONTENT_OFFSET)
|
|
@@ -135,7 +136,7 @@ def generate_report(context):
|
|
|
135
136
|
s_table_medium_leading = ParagraphStyle(name="s_table_medium_leading", parent=s_table_medium, leading=13.9)
|
|
136
137
|
s_table_large = ParagraphStyle(name="s_table_large", parent=s_table_medium, fontSize=11, leading=11)
|
|
137
138
|
s_table_large_center = ParagraphStyle(name="s_table_large", parent=s_table_large, alignment=TA_CENTER)
|
|
138
|
-
s_table_large_center_padding = ParagraphStyle(
|
|
139
|
+
s_table_large_center_padding = ParagraphStyle( # noqa: F841
|
|
139
140
|
name="s_table_large", parent=s_table_large_center, spaceBefore=20, spaceAfter=20
|
|
140
141
|
)
|
|
141
142
|
s_table_center = ParagraphStyle(
|
|
@@ -278,7 +279,7 @@ def generate_report(context):
|
|
|
278
279
|
)
|
|
279
280
|
return title_table
|
|
280
281
|
|
|
281
|
-
def impress(
|
|
282
|
+
def impress(elements):
|
|
282
283
|
style = s_table_headline_2
|
|
283
284
|
table_data = [
|
|
284
285
|
[
|
|
@@ -306,7 +307,7 @@ def generate_report(context):
|
|
|
306
307
|
]
|
|
307
308
|
)
|
|
308
309
|
)
|
|
309
|
-
|
|
310
|
+
elements.append(KeepTogether(TopPadder(t)))
|
|
310
311
|
|
|
311
312
|
# Description
|
|
312
313
|
elements.append(generate_title(general_data["title"]))
|
|
@@ -334,7 +335,7 @@ def generate_report(context):
|
|
|
334
335
|
# Price Timeseries Chart
|
|
335
336
|
elements.append(
|
|
336
337
|
get_timeseries_chart(
|
|
337
|
-
data=[list(zip(prices.index, prices.net_value))],
|
|
338
|
+
data=[list(zip(prices.index, prices.net_value, strict=False))],
|
|
338
339
|
width=CONTENT_WIDTH_PAGE1_LEFT - CONTENT_OFFSET,
|
|
339
340
|
height=4.34 * cm,
|
|
340
341
|
color=c_product,
|
|
@@ -355,7 +356,7 @@ def generate_report(context):
|
|
|
355
356
|
"<strong>Top 3 Contributors</strong>",
|
|
356
357
|
"<strong>Bottom 3 Contributors</strong>",
|
|
357
358
|
],
|
|
358
|
-
data=list(zip(top_3_holdings, top_3_contributors, bottom_3_contributors)),
|
|
359
|
+
data=list(zip(top_3_holdings, top_3_contributors, bottom_3_contributors, strict=False)),
|
|
359
360
|
width=CONTENT_WIDTH_PAGE1_LEFT,
|
|
360
361
|
header_row_height=0.85 * cm,
|
|
361
362
|
data_row_height=0.39 * cm,
|
|
@@ -557,7 +558,7 @@ def generate_report(context):
|
|
|
557
558
|
|
|
558
559
|
data = list()
|
|
559
560
|
categories = list()
|
|
560
|
-
for
|
|
561
|
+
for row in df.itertuples():
|
|
561
562
|
data.append(row.weighting * 100)
|
|
562
563
|
categories.append(f"{row.aggregated_title} ({row.weighting*100:.1f}%)")
|
|
563
564
|
|
|
@@ -834,7 +835,7 @@ def generate_report(context):
|
|
|
834
835
|
|
|
835
836
|
last_row_height = right_height - liquid_height - 0.85 * cm
|
|
836
837
|
|
|
837
|
-
last_height = min(
|
|
838
|
+
last_height = min( # noqa: F841
|
|
838
839
|
max(industry_height - liquid_height + 6, 3.564 * cm), max_available_height - liquid_height
|
|
839
840
|
) # 6 because of the drawn string
|
|
840
841
|
|
|
@@ -21,7 +21,6 @@ from reportlab.platypus import (
|
|
|
21
21
|
BaseDocTemplate,
|
|
22
22
|
Image,
|
|
23
23
|
PageTemplate,
|
|
24
|
-
Paragraph,
|
|
25
24
|
Spacer,
|
|
26
25
|
Table,
|
|
27
26
|
TableStyle,
|
|
@@ -29,6 +28,8 @@ from reportlab.platypus import (
|
|
|
29
28
|
from reportlab.platypus.flowables import KeepTogether, TopPadder
|
|
30
29
|
from reportlab.platypus.frames import Frame
|
|
31
30
|
from svglib.svglib import svg2rlg
|
|
31
|
+
from wbcore.utils.reportlab import FormattedParagraph as Paragraph
|
|
32
|
+
|
|
32
33
|
from wbreport.models import ReportAsset
|
|
33
34
|
from wbreport.pdf.charts.pie import (
|
|
34
35
|
get_pie_chart_horizontal,
|
|
@@ -44,12 +45,12 @@ from wbreport.pdf.tables.aggregated_tables import (
|
|
|
44
45
|
from wbreport.pdf.tables.data_tables import get_simple_data_table
|
|
45
46
|
|
|
46
47
|
|
|
47
|
-
def generate_report(context):
|
|
48
|
+
def generate_report(context): # noqa: C901
|
|
48
49
|
debug = False
|
|
49
50
|
|
|
50
51
|
main_features_dict_tmp = context["information_table"]
|
|
51
52
|
main_features_dict = {}
|
|
52
|
-
for
|
|
53
|
+
for v in main_features_dict_tmp.values():
|
|
53
54
|
main_features_dict.update(v)
|
|
54
55
|
# Monthly returns table as dataframe, None is no value
|
|
55
56
|
monthly_returns = context["monthly_returns"]
|
|
@@ -129,7 +130,7 @@ def generate_report(context):
|
|
|
129
130
|
s_base_small_justified = ParagraphStyle(
|
|
130
131
|
name="s_base_small_justified", parent=s_base, fontSize=6.5, leading=7, alignment=TA_JUSTIFY
|
|
131
132
|
)
|
|
132
|
-
s_base_small_justified_indent = ParagraphStyle(
|
|
133
|
+
s_base_small_justified_indent = ParagraphStyle( # noqa: F841
|
|
133
134
|
name="s_base_small_justified_indent", parent=s_base_small_justified, leftIndent=CONTENT_OFFSET
|
|
134
135
|
)
|
|
135
136
|
s_base_indent = ParagraphStyle(name="s_description", parent=s_base, spaceBefore=8, leftIndent=CONTENT_OFFSET)
|
|
@@ -143,7 +144,7 @@ def generate_report(context):
|
|
|
143
144
|
s_table_medium_leading = ParagraphStyle(name="s_table_medium_leading", parent=s_table_medium, leading=13.9)
|
|
144
145
|
s_table_large = ParagraphStyle(name="s_table_large", parent=s_table_medium, fontSize=11, leading=11)
|
|
145
146
|
s_table_large_center = ParagraphStyle(name="s_table_large", parent=s_table_large, alignment=TA_CENTER)
|
|
146
|
-
s_table_large_center_padding = ParagraphStyle(
|
|
147
|
+
s_table_large_center_padding = ParagraphStyle( # noqa: F841
|
|
147
148
|
name="s_table_large", parent=s_table_large_center, spaceBefore=20, spaceAfter=20
|
|
148
149
|
)
|
|
149
150
|
s_table_center = ParagraphStyle(
|
|
@@ -284,7 +285,7 @@ def generate_report(context):
|
|
|
284
285
|
)
|
|
285
286
|
return title_table
|
|
286
287
|
|
|
287
|
-
def impress(
|
|
288
|
+
def impress(elements):
|
|
288
289
|
style = s_table_headline_2
|
|
289
290
|
table_data = [
|
|
290
291
|
[
|
|
@@ -312,7 +313,7 @@ def generate_report(context):
|
|
|
312
313
|
]
|
|
313
314
|
)
|
|
314
315
|
)
|
|
315
|
-
|
|
316
|
+
elements.append(KeepTogether(TopPadder(t)))
|
|
316
317
|
|
|
317
318
|
# Description
|
|
318
319
|
elements.append(generate_title(general_data["title"]))
|
|
@@ -347,7 +348,7 @@ def generate_report(context):
|
|
|
347
348
|
# Price Timeseries Chart
|
|
348
349
|
elements.append(
|
|
349
350
|
get_timeseries_chart(
|
|
350
|
-
data=[list(zip(prices.index, prices.net_value))],
|
|
351
|
+
data=[list(zip(prices.index, prices.net_value, strict=False))],
|
|
351
352
|
width=CONTENT_WIDTH_PAGE1_LEFT - CONTENT_OFFSET,
|
|
352
353
|
height=4.34 * cm,
|
|
353
354
|
color=c_product,
|
|
@@ -567,7 +568,7 @@ def generate_report(context):
|
|
|
567
568
|
|
|
568
569
|
data = list()
|
|
569
570
|
categories = list()
|
|
570
|
-
for
|
|
571
|
+
for row in df.itertuples():
|
|
571
572
|
data.append(row.weighting * 100)
|
|
572
573
|
categories.append(f"{row.aggregated_title} ({row.weighting*100:.1f}%)")
|
|
573
574
|
|
|
@@ -22,7 +22,6 @@ from reportlab.platypus import (
|
|
|
22
22
|
Image,
|
|
23
23
|
NextPageTemplate,
|
|
24
24
|
PageTemplate,
|
|
25
|
-
Paragraph,
|
|
26
25
|
Spacer,
|
|
27
26
|
Table,
|
|
28
27
|
TableStyle,
|
|
@@ -30,6 +29,8 @@ from reportlab.platypus import (
|
|
|
30
29
|
from reportlab.platypus.flowables import KeepTogether, TopPadder
|
|
31
30
|
from reportlab.platypus.frames import Frame
|
|
32
31
|
from svglib.svglib import svg2rlg
|
|
32
|
+
from wbcore.utils.reportlab import FormattedParagraph as Paragraph
|
|
33
|
+
|
|
33
34
|
from wbreport.models import ReportAsset
|
|
34
35
|
from wbreport.pdf.charts.pie import (
|
|
35
36
|
get_pie_chart_horizontal,
|
|
@@ -42,7 +43,7 @@ from wbreport.pdf.tables.aggregated_tables import get_simple_aggregated_table
|
|
|
42
43
|
from wbreport.pdf.tables.data_tables import get_simple_data_table
|
|
43
44
|
|
|
44
45
|
|
|
45
|
-
def generate_report(context):
|
|
46
|
+
def generate_report(context): # noqa: C901
|
|
46
47
|
debug = False
|
|
47
48
|
### Product Data ###
|
|
48
49
|
# Main Feature table as dictionary
|
|
@@ -120,7 +121,7 @@ def generate_report(context):
|
|
|
120
121
|
s_base_small_justified = ParagraphStyle(
|
|
121
122
|
name="s_base_small_justified", parent=s_base, fontSize=6.5, leading=7, alignment=TA_JUSTIFY
|
|
122
123
|
)
|
|
123
|
-
s_base_small_justified_indent = ParagraphStyle(
|
|
124
|
+
s_base_small_justified_indent = ParagraphStyle( # noqa: F841
|
|
124
125
|
name="s_base_small_justified_indent", parent=s_base_small_justified, leftIndent=CONTENT_OFFSET
|
|
125
126
|
)
|
|
126
127
|
s_base_indent = ParagraphStyle(name="s_description", parent=s_base, spaceBefore=8, leftIndent=CONTENT_OFFSET)
|
|
@@ -134,7 +135,7 @@ def generate_report(context):
|
|
|
134
135
|
s_table_medium_leading = ParagraphStyle(name="s_table_medium_leading", parent=s_table_medium, leading=13.9)
|
|
135
136
|
s_table_large = ParagraphStyle(name="s_table_large", parent=s_table_medium, fontSize=11, leading=11)
|
|
136
137
|
s_table_large_center = ParagraphStyle(name="s_table_large", parent=s_table_large, alignment=TA_CENTER)
|
|
137
|
-
s_table_large_center_padding = ParagraphStyle(
|
|
138
|
+
s_table_large_center_padding = ParagraphStyle( # noqa: F841
|
|
138
139
|
name="s_table_large", parent=s_table_large_center, spaceBefore=20, spaceAfter=20
|
|
139
140
|
)
|
|
140
141
|
s_table_center = ParagraphStyle(
|
|
@@ -277,7 +278,7 @@ def generate_report(context):
|
|
|
277
278
|
)
|
|
278
279
|
return title_table
|
|
279
280
|
|
|
280
|
-
def impress(
|
|
281
|
+
def impress(elements):
|
|
281
282
|
style = s_table_headline_2
|
|
282
283
|
table_data = [
|
|
283
284
|
[
|
|
@@ -305,7 +306,7 @@ def generate_report(context):
|
|
|
305
306
|
]
|
|
306
307
|
)
|
|
307
308
|
)
|
|
308
|
-
|
|
309
|
+
elements.append(KeepTogether(TopPadder(t)))
|
|
309
310
|
|
|
310
311
|
############################
|
|
311
312
|
## Page 1: BEGINING
|
|
@@ -337,7 +338,7 @@ def generate_report(context):
|
|
|
337
338
|
# Price Timeseries Chart
|
|
338
339
|
elements.append(
|
|
339
340
|
get_timeseries_chart(
|
|
340
|
-
data=[list(zip(prices.index, prices.net_value))],
|
|
341
|
+
data=[list(zip(prices.index, prices.net_value, strict=False))],
|
|
341
342
|
width=CONTENT_WIDTH_PAGE1_LEFT - CONTENT_OFFSET,
|
|
342
343
|
height=4.34 * cm,
|
|
343
344
|
color=c_product,
|
|
@@ -358,7 +359,7 @@ def generate_report(context):
|
|
|
358
359
|
"<strong>Top 3 Contributors</strong>",
|
|
359
360
|
"<strong>Bottom 3 Contributors</strong>",
|
|
360
361
|
],
|
|
361
|
-
data=list(zip(top_3_holdings, top_3_contributors, bottom_3_contributors)),
|
|
362
|
+
data=list(zip(top_3_holdings, top_3_contributors, bottom_3_contributors, strict=False)),
|
|
362
363
|
width=CONTENT_WIDTH_PAGE1_LEFT,
|
|
363
364
|
header_row_height=0.85 * cm,
|
|
364
365
|
data_row_height=0.39 * cm,
|
|
@@ -559,7 +560,7 @@ def generate_report(context):
|
|
|
559
560
|
|
|
560
561
|
data = list()
|
|
561
562
|
categories = list()
|
|
562
|
-
for
|
|
563
|
+
for row in df.itertuples():
|
|
563
564
|
data.append(row.weighting * 100)
|
|
564
565
|
categories.append(f"{row.aggregated_title} ({row.weighting*100:.1f}%)")
|
|
565
566
|
|
|
@@ -21,7 +21,6 @@ from reportlab.platypus import (
|
|
|
21
21
|
Image,
|
|
22
22
|
NextPageTemplate,
|
|
23
23
|
PageTemplate,
|
|
24
|
-
Paragraph,
|
|
25
24
|
Spacer,
|
|
26
25
|
Table,
|
|
27
26
|
TableStyle,
|
|
@@ -29,6 +28,8 @@ from reportlab.platypus import (
|
|
|
29
28
|
from reportlab.platypus.flowables import KeepTogether, TopPadder
|
|
30
29
|
from reportlab.platypus.frames import Frame
|
|
31
30
|
from svglib.svglib import svg2rlg
|
|
31
|
+
from wbcore.utils.reportlab import FormattedParagraph as Paragraph
|
|
32
|
+
|
|
32
33
|
from wbreport.models import ReportAsset
|
|
33
34
|
from wbreport.pdf.charts.pie import (
|
|
34
35
|
get_pie_chart_horizontal,
|
|
@@ -42,7 +43,7 @@ from wbreport.pdf.tables.aggregated_tables import get_simple_aggregated_table
|
|
|
42
43
|
from wbreport.pdf.tables.data_tables import get_simple_data_table
|
|
43
44
|
|
|
44
45
|
|
|
45
|
-
def generate_report(context):
|
|
46
|
+
def generate_report(context): # noqa: C901
|
|
46
47
|
debug = False
|
|
47
48
|
|
|
48
49
|
main_features_dict = context["information_table"]["Main Features"]
|
|
@@ -133,7 +134,7 @@ def generate_report(context):
|
|
|
133
134
|
s_table_medium = ParagraphStyle(name="s_table_medium", parent=s_table_base, fontSize=9, leading=8)
|
|
134
135
|
s_table_medium_leading = ParagraphStyle(name="s_table_medium_leading", parent=s_table_medium, leading=13.9)
|
|
135
136
|
s_table_large = ParagraphStyle(name="s_table_large", parent=s_table_medium, fontSize=11, leading=11)
|
|
136
|
-
s_table_large_center = ParagraphStyle(name="s_table_large", parent=s_table_large, alignment=TA_CENTER)
|
|
137
|
+
s_table_large_center = ParagraphStyle(name="s_table_large", parent=s_table_large, alignment=TA_CENTER) # noqa: F841
|
|
137
138
|
s_table_center = ParagraphStyle(
|
|
138
139
|
name="s_table_center",
|
|
139
140
|
parent=s_table_base,
|
|
@@ -330,7 +331,7 @@ def generate_report(context):
|
|
|
330
331
|
# Price Timeseries Chart
|
|
331
332
|
elements.append(
|
|
332
333
|
get_timeseries_chart(
|
|
333
|
-
data=[list(zip(prices.index, prices.net_value))],
|
|
334
|
+
data=[list(zip(prices.index, prices.net_value, strict=False))],
|
|
334
335
|
width=CONTENT_WIDTH_PAGE1_LEFT - CONTENT_OFFSET,
|
|
335
336
|
height=4.34 * cm,
|
|
336
337
|
color=c_product,
|
|
@@ -351,7 +352,7 @@ def generate_report(context):
|
|
|
351
352
|
"<strong>Top 3 Contributors</strong>",
|
|
352
353
|
"<strong>Bottom 3 Contributors</strong>",
|
|
353
354
|
],
|
|
354
|
-
data=list(zip(top_3_holdings, top_3_contributors, bottom_3_contributors)),
|
|
355
|
+
data=list(zip(top_3_holdings, top_3_contributors, bottom_3_contributors, strict=False)),
|
|
355
356
|
width=CONTENT_WIDTH_PAGE1_LEFT,
|
|
356
357
|
header_row_height=0.85 * cm,
|
|
357
358
|
data_row_height=0.39 * cm,
|
|
@@ -553,7 +554,7 @@ def generate_report(context):
|
|
|
553
554
|
|
|
554
555
|
data = list()
|
|
555
556
|
categories = list()
|
|
556
|
-
for
|
|
557
|
+
for row in df.itertuples():
|
|
557
558
|
data.append(row.weighting * 100)
|
|
558
559
|
categories.append(f"{row.aggregated_title} ({row.weighting*100:.1f}%)")
|
|
559
560
|
|
|
@@ -2,7 +2,8 @@ import numpy as np
|
|
|
2
2
|
from reportlab.lib.colors import grey
|
|
3
3
|
from reportlab.lib.enums import TA_CENTER
|
|
4
4
|
from reportlab.lib.styles import ParagraphStyle
|
|
5
|
-
from reportlab.platypus import
|
|
5
|
+
from reportlab.platypus import Spacer, Table, TableStyle
|
|
6
|
+
from wbcore.utils.reportlab import FormattedParagraph as Paragraph
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
def get_simple_aggregated_table(
|
|
@@ -37,7 +38,7 @@ def get_simple_aggregated_table(
|
|
|
37
38
|
|
|
38
39
|
table_row.append(Paragraph(str(year), style=row_style))
|
|
39
40
|
|
|
40
|
-
for
|
|
41
|
+
for _, element in row.items():
|
|
41
42
|
if element.get("performance", None) is None:
|
|
42
43
|
table_row.append(Spacer(width=0, height=0))
|
|
43
44
|
else:
|
|
@@ -110,7 +111,7 @@ def get_fund_table(
|
|
|
110
111
|
table_data.append(table_row)
|
|
111
112
|
|
|
112
113
|
# Generate table
|
|
113
|
-
for
|
|
114
|
+
for _, row in df.iterrows():
|
|
114
115
|
table_row = list()
|
|
115
116
|
|
|
116
117
|
for value in row:
|
wbreport/serializers.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
from rest_framework.reverse import reverse
|
|
2
2
|
from wbcore import serializers as wb_serializers
|
|
3
|
-
from wbcore.
|
|
3
|
+
from wbcore.contrib.authentication.authentication import inject_short_lived_token
|
|
4
|
+
from wbcore.contrib.content_type.serializers import (
|
|
4
5
|
ContentTypeRepresentationSerializer,
|
|
5
6
|
DynamicObjectIDRepresentationSerializer,
|
|
6
7
|
)
|
|
7
|
-
from wbcore.contrib.authentication.authentication import inject_short_lived_token
|
|
8
8
|
from wbmailing.serializers import MailingListRepresentationSerializer
|
|
9
9
|
|
|
10
10
|
from .models import Report, ReportCategory, ReportClass, ReportVersion
|
|
@@ -48,6 +48,7 @@ class ReportCategoryModelSerializer(wb_serializers.ModelSerializer):
|
|
|
48
48
|
class ReportVersionModelSerializer(wb_serializers.ModelSerializer):
|
|
49
49
|
_report = ReportRepresentationSerializer(source="report")
|
|
50
50
|
parameters = wb_serializers.JSONTableField()
|
|
51
|
+
parameters_repr = wb_serializers.CharField(read_only=True)
|
|
51
52
|
|
|
52
53
|
@wb_serializers.register_resource()
|
|
53
54
|
def version_resources(self, instance, request, user):
|
|
@@ -65,8 +66,6 @@ class ReportVersionModelSerializer(wb_serializers.ModelSerializer):
|
|
|
65
66
|
res["send_email"] = reverse("report:reportversion-sendemail", args=[instance.id], request=request)
|
|
66
67
|
return res
|
|
67
68
|
|
|
68
|
-
from wbcore.contrib.authentication.authentication import TokenAuthentication
|
|
69
|
-
|
|
70
69
|
@wb_serializers.register_resource()
|
|
71
70
|
@inject_short_lived_token(view_name="public_report:report_version")
|
|
72
71
|
def public_html_resources(self, instance, request, user):
|
|
@@ -86,8 +85,10 @@ class ReportVersionModelSerializer(wb_serializers.ModelSerializer):
|
|
|
86
85
|
"update_date",
|
|
87
86
|
"is_primary",
|
|
88
87
|
"disabled",
|
|
88
|
+
"lock",
|
|
89
89
|
"lookup",
|
|
90
90
|
"parameters",
|
|
91
|
+
"parameters_repr",
|
|
91
92
|
"comment",
|
|
92
93
|
"report",
|
|
93
94
|
"_report",
|
|
@@ -114,7 +115,7 @@ class ReportModelSerializer(wb_serializers.ModelSerializer):
|
|
|
114
115
|
res = {}
|
|
115
116
|
if instance.is_accessible(user):
|
|
116
117
|
res["versions"] = reverse("wbreport:report-version-list", args=[instance.id], request=request)
|
|
117
|
-
res["reports"] = f
|
|
118
|
+
res["reports"] = f"{reverse('wbreport:report-list', args=[], request=request)}?parent_report={instance.id}"
|
|
118
119
|
if instance.child_reports.exists():
|
|
119
120
|
res["bundle_versions"] = reverse("wbreport:report-bundletreport", args=[instance.id], request=request)
|
|
120
121
|
|
wbreport/tasks.py
CHANGED
|
@@ -8,11 +8,12 @@ from django.template.loader import get_template
|
|
|
8
8
|
from slugify import slugify
|
|
9
9
|
from wbcore.contrib.authentication.models import User
|
|
10
10
|
from wbcore.utils.html import convert_html2text
|
|
11
|
+
from wbcore.workers import Queue
|
|
11
12
|
|
|
12
13
|
from wbreport.models import Report, ReportVersion
|
|
13
14
|
|
|
14
15
|
|
|
15
|
-
@shared_task()
|
|
16
|
+
@shared_task(queue=Queue.BACKGROUND.value)
|
|
16
17
|
def generate_and_send_current_report_file(user_id, parent_report_id, parameters=None):
|
|
17
18
|
zip_buffer = BytesIO()
|
|
18
19
|
parent_report = Report.objects.get(id=parent_report_id)
|
wbreport/tests/test_models.py
CHANGED
wbreport/tests/test_tasks.py
CHANGED
|
@@ -14,6 +14,19 @@ class CommentSerializer(wb_serializers.Serializer):
|
|
|
14
14
|
comment = wb_serializers.TextField(default="")
|
|
15
15
|
|
|
16
16
|
|
|
17
|
+
class GenerateNextReportSerializer(CommentSerializer):
|
|
18
|
+
max_depth_only = wb_serializers.BooleanField(default=False)
|
|
19
|
+
start_date = wb_serializers.DateField()
|
|
20
|
+
end_date = wb_serializers.DateField()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class UpdateContextSerializer(CommentSerializer):
|
|
24
|
+
override_lock = wb_serializers.BooleanField(
|
|
25
|
+
default=False,
|
|
26
|
+
help_text="Enable this option to force context updates even when the report version is locked. (Warning: this operation may overwrite existing data.)",
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
17
30
|
class ReportButtonConfig(ButtonViewConfig):
|
|
18
31
|
def get_custom_list_instance_buttons(self):
|
|
19
32
|
return {
|
|
@@ -46,6 +59,9 @@ class ReportButtonConfig(ButtonViewConfig):
|
|
|
46
59
|
class ParametersSerializer(wb_serializers.Serializer):
|
|
47
60
|
parameters = wb_serializers.JSONTableField(default=default_parameters, label="Version Parameters")
|
|
48
61
|
|
|
62
|
+
class ContextUpdateSerializer(UpdateContextSerializer, ParametersSerializer):
|
|
63
|
+
pass
|
|
64
|
+
|
|
49
65
|
class StartEndParametersSerializer(wb_serializers.Serializer):
|
|
50
66
|
start_parameters = wb_serializers.JSONTableField(
|
|
51
67
|
default=earliest_parent_parameters, label="Start Parameters"
|
|
@@ -53,11 +69,6 @@ class ReportButtonConfig(ButtonViewConfig):
|
|
|
53
69
|
end_parameters = wb_serializers.JSONTableField(default=latest_parent_paremeters, label="End Parameters")
|
|
54
70
|
comment = wb_serializers.TextField(default="")
|
|
55
71
|
|
|
56
|
-
class GenerateNextReportSerializer(CommentSerializer):
|
|
57
|
-
max_depth_only = wb_serializers.BooleanField(default=False)
|
|
58
|
-
start_date = wb_serializers.DateField()
|
|
59
|
-
end_date = wb_serializers.DateField()
|
|
60
|
-
|
|
61
72
|
return self.get_custom_list_instance_buttons() | {
|
|
62
73
|
bt.DropDownButton(
|
|
63
74
|
label="Utility",
|
|
@@ -76,7 +87,9 @@ class ReportButtonConfig(ButtonViewConfig):
|
|
|
76
87
|
serializer=GenerateNextReportSerializer,
|
|
77
88
|
action_label="Generate Next Report",
|
|
78
89
|
title="Generate Report to Next Iteration",
|
|
79
|
-
instance_display=create_simple_display(
|
|
90
|
+
instance_display=create_simple_display(
|
|
91
|
+
[["start_date", "end_date"], ["max_depth_only", "max_depth_only"]]
|
|
92
|
+
),
|
|
80
93
|
),
|
|
81
94
|
bt.ActionButton(
|
|
82
95
|
method=RequestType.PATCH,
|
|
@@ -84,15 +97,14 @@ class ReportButtonConfig(ButtonViewConfig):
|
|
|
84
97
|
key="update_versions_context",
|
|
85
98
|
label="Regenerate context",
|
|
86
99
|
icon=WBIcon.REGENERATE.icon,
|
|
87
|
-
serializer=
|
|
100
|
+
serializer=ContextUpdateSerializer,
|
|
88
101
|
description_fields="""
|
|
89
102
|
<p> Do you want to regenerate this report's versions?</p>
|
|
90
|
-
<p> If parameters is unset, it will recompute all report's versions</p>
|
|
91
103
|
<p> Note: This action takes few minute?</p>
|
|
92
104
|
""",
|
|
93
105
|
action_label="Regenerate versions context",
|
|
94
106
|
title="Regenerate versions context",
|
|
95
|
-
instance_display=create_simple_display([["
|
|
107
|
+
instance_display=create_simple_display([["comment"], ["parameters"], ["override_lock"]]),
|
|
96
108
|
),
|
|
97
109
|
bt.ActionButton(
|
|
98
110
|
method=RequestType.PATCH,
|
|
@@ -164,14 +176,15 @@ class ReportVersionButtonConfig(ButtonViewConfig):
|
|
|
164
176
|
icon=WBIcon.SAVE.icon,
|
|
165
177
|
),
|
|
166
178
|
bt.ActionButton(
|
|
167
|
-
method=RequestType.
|
|
179
|
+
method=RequestType.PATCH,
|
|
168
180
|
identifiers=("wbreport:reportversion",),
|
|
169
181
|
key="update_context",
|
|
170
182
|
label="Update Context",
|
|
171
183
|
description_fields="""
|
|
172
184
|
<p>Update and actualize context</p>
|
|
173
185
|
""",
|
|
174
|
-
|
|
186
|
+
instance_display=create_simple_display([["comment"], ["override_lock"]]),
|
|
187
|
+
serializer=UpdateContextSerializer,
|
|
175
188
|
icon=WBIcon.REGENERATE.icon,
|
|
176
189
|
action_label="Update Context",
|
|
177
190
|
title="Update Context",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from typing import Optional
|
|
2
2
|
|
|
3
3
|
from rest_framework.reverse import reverse
|
|
4
|
+
from wbcore.enums import Unit
|
|
4
5
|
from wbcore.metadata.configs import display as dp
|
|
5
6
|
from wbcore.metadata.configs.display.instance_display import Display
|
|
6
7
|
from wbcore.metadata.configs.display.instance_display.shortcuts import (
|
|
@@ -39,13 +40,12 @@ class ReportDisplayConfig(DisplayViewConfig):
|
|
|
39
40
|
],
|
|
40
41
|
tree=True,
|
|
41
42
|
# tree_group_lookup="id_repr",
|
|
42
|
-
tree_group_pinned="left",
|
|
43
43
|
tree_group_field="title",
|
|
44
|
-
tree_group_label="Title",
|
|
45
44
|
tree_group_level_options=[
|
|
46
45
|
dp.TreeGroupLevelOption(
|
|
47
46
|
filter_key="parent_report",
|
|
48
47
|
filter_depth=1,
|
|
48
|
+
filter_blacklist=["parent_report__isnull"],
|
|
49
49
|
list_endpoint=reverse(
|
|
50
50
|
"wbreport:report-list",
|
|
51
51
|
args=[],
|
|
@@ -76,16 +76,25 @@ class ReportDisplayConfig(DisplayViewConfig):
|
|
|
76
76
|
class ReportVersionDisplayConfig(DisplayViewConfig):
|
|
77
77
|
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
78
78
|
return dp.ListDisplay(
|
|
79
|
-
fields=
|
|
79
|
+
fields=[
|
|
80
80
|
dp.Field(key="uuid", label="UUID"),
|
|
81
81
|
dp.Field(key="lookup", label="Lookup"),
|
|
82
82
|
dp.Field(key="title", label="Title"),
|
|
83
83
|
dp.Field(key="version_date", label="Date"),
|
|
84
84
|
dp.Field(key="report", label="Report"),
|
|
85
|
-
dp.Field(key="
|
|
86
|
-
dp.Field(
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
dp.Field(key="comment", label="Comment"),
|
|
86
|
+
dp.Field(
|
|
87
|
+
key=None,
|
|
88
|
+
label="Information",
|
|
89
|
+
open_by_default=False,
|
|
90
|
+
children=[
|
|
91
|
+
dp.Field(key="is_primary", label="Primary", width=Unit.PIXEL(100)),
|
|
92
|
+
dp.Field(key="disabled", label="Disabled", width=Unit.PIXEL(100)),
|
|
93
|
+
dp.Field(key="lock", label="Lock", width=Unit.PIXEL(100), show="open"),
|
|
94
|
+
dp.Field(key="parameters_repr", label="Parameters", show="open"),
|
|
95
|
+
],
|
|
96
|
+
),
|
|
97
|
+
]
|
|
89
98
|
)
|
|
90
99
|
|
|
91
100
|
def get_instance_display(self) -> Display:
|
|
@@ -102,15 +111,22 @@ class ReportVersionDisplayConfig(DisplayViewConfig):
|
|
|
102
111
|
class ReportVersionReportDisplayConfig(ReportVersionDisplayConfig):
|
|
103
112
|
def get_list_display(self) -> Optional[dp.ListDisplay]:
|
|
104
113
|
return dp.ListDisplay(
|
|
105
|
-
fields=
|
|
114
|
+
fields=[
|
|
106
115
|
dp.Field(key="uuid", label="UUID"),
|
|
107
116
|
dp.Field(key="lookup", label="Lookup"),
|
|
108
117
|
dp.Field(key="title", label="Title"),
|
|
109
118
|
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
119
|
dp.Field(key="comment", label="Comment"),
|
|
115
|
-
|
|
120
|
+
dp.Field(
|
|
121
|
+
key=None,
|
|
122
|
+
label="Information",
|
|
123
|
+
open_by_default=False,
|
|
124
|
+
children=[
|
|
125
|
+
dp.Field(key="is_primary", label="Primary", width=Unit.PIXEL(100)),
|
|
126
|
+
dp.Field(key="disabled", label="Disabled", width=Unit.PIXEL(100)),
|
|
127
|
+
dp.Field(key="lock", label="Lock", width=Unit.PIXEL(100), show="open"),
|
|
128
|
+
dp.Field(key="parameters_repr", label="Parameters", show="open"),
|
|
129
|
+
],
|
|
130
|
+
),
|
|
131
|
+
]
|
|
116
132
|
)
|
|
@@ -6,12 +6,9 @@ class ReportVersionEndpointConfig(EndpointViewConfig):
|
|
|
6
6
|
def get_endpoint(self, **kwargs):
|
|
7
7
|
return None
|
|
8
8
|
|
|
9
|
-
def
|
|
9
|
+
def get_instance_endpoint(self, **kwargs):
|
|
10
10
|
return reverse("wbreport:reportversion-list", request=self.request)
|
|
11
11
|
|
|
12
|
-
def get_instance_endpoint(self):
|
|
13
|
-
return self.get_list_endpoint()
|
|
14
|
-
|
|
15
12
|
|
|
16
13
|
class ReportEndpointConfig(EndpointViewConfig):
|
|
17
14
|
def get_endpoint(self, **kwargs):
|
|
@@ -19,12 +16,8 @@ class ReportEndpointConfig(EndpointViewConfig):
|
|
|
19
16
|
|
|
20
17
|
|
|
21
18
|
class ReportVersionReportEndpointConfig(EndpointViewConfig):
|
|
22
|
-
|
|
23
|
-
return reverse("wbreport:report-version-list", args=[self.view.kwargs["report_id"]], request=self.request)
|
|
19
|
+
pass
|
|
24
20
|
|
|
25
21
|
|
|
26
22
|
class ReportVersionReportHTMEndpointConfig(EndpointViewConfig):
|
|
27
|
-
|
|
28
|
-
return reverse(
|
|
29
|
-
"wbreport:reportversion-rawhtml-list", args=[self.view.kwargs["report_version_id"]], request=self.request
|
|
30
|
-
)
|
|
23
|
+
pass
|
wbreport/viewsets/viewsets.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import json
|
|
2
2
|
|
|
3
|
-
from django.db.models import Case, Exists, F, IntegerField, OuterRef, When
|
|
3
|
+
from django.db.models import Case, Exists, F, IntegerField, OuterRef, TextField, When
|
|
4
|
+
from django.db.models.functions import Cast
|
|
4
5
|
from django.http import FileResponse, HttpResponse
|
|
5
6
|
from django.shortcuts import get_object_or_404, render
|
|
6
7
|
from django.views.decorators.cache import cache_page
|
|
@@ -76,7 +77,7 @@ def report(request, namespace):
|
|
|
76
77
|
{
|
|
77
78
|
"title": "Report Unavailable",
|
|
78
79
|
"header": "Report Unavailable",
|
|
79
|
-
"description": "If you thing this report should be enabled, please
|
|
80
|
+
"description": "If you thing this report should be enabled, please contact a system administrator",
|
|
80
81
|
},
|
|
81
82
|
status=status.HTTP_403_FORBIDDEN,
|
|
82
83
|
)
|
|
@@ -116,7 +117,7 @@ def report_version(request, lookup):
|
|
|
116
117
|
{
|
|
117
118
|
"title": "Report Unavailable",
|
|
118
119
|
"header": "Report Unavailable",
|
|
119
|
-
"description": "If you thing this report should be enabled, please
|
|
120
|
+
"description": "If you thing this report should be enabled, please contact a system administrator",
|
|
120
121
|
},
|
|
121
122
|
status=status.HTTP_403_FORBIDDEN,
|
|
122
123
|
)
|
|
@@ -271,7 +272,7 @@ class ReportVersionModelViewSet(viewsets.ModelViewSet):
|
|
|
271
272
|
title_config_class = ReportVersionTitleConfig
|
|
272
273
|
button_config_class = ReportVersionButtonConfig
|
|
273
274
|
|
|
274
|
-
queryset = ReportVersion.objects.
|
|
275
|
+
queryset = ReportVersion.objects.annotate(parameters_repr=Cast("parameters", TextField()))
|
|
275
276
|
|
|
276
277
|
@action(detail=True, methods=["GET"], permission_classes=[IsAuthenticated])
|
|
277
278
|
def sendemail(self, request, pk=None):
|
|
@@ -281,9 +282,12 @@ class ReportVersionModelViewSet(viewsets.ModelViewSet):
|
|
|
281
282
|
return Response({}, status=status.HTTP_200_OK)
|
|
282
283
|
return Response({}, status=status.HTTP_404_NOT_FOUND)
|
|
283
284
|
|
|
284
|
-
@action(detail=True, methods=["
|
|
285
|
+
@action(detail=True, methods=["PATCH"], permission_classes=[IsAuthenticated])
|
|
285
286
|
def updatecontext(self, request, pk=None):
|
|
286
|
-
|
|
287
|
+
comment = request.data.get("comment", "")
|
|
288
|
+
override_lock = request.data.get("override_lock", "false").lower() == "true"
|
|
289
|
+
|
|
290
|
+
update_context_as_task.delay(pk, request.user, comment=comment, force_context_update=override_lock)
|
|
287
291
|
return Response({}, status=status.HTTP_200_OK)
|
|
288
292
|
|
|
289
293
|
@action(
|
|
@@ -2,19 +2,19 @@ wbreport/__init__.py,sha256=J-j-u0itpEFT6irdmWmixQqYMadNl1X91TxUmoiLHMI,22
|
|
|
2
2
|
wbreport/admin.py,sha256=tQPq0BKzXZ7I3aOE0FaGyjuKs37TiT56s7OT0mDfOXo,2364
|
|
3
3
|
wbreport/apps.py,sha256=4z2N25hswEAlsJsntASC5iOWUwsqMCL99-gvqBlPGFY,148
|
|
4
4
|
wbreport/dynamic_preferences_registry.py,sha256=nGT-fS5vN-BSVNyGcJ81ORjiXlOngePRN9hipB9olPw,508
|
|
5
|
-
wbreport/filters.py,sha256=
|
|
6
|
-
wbreport/mixins.py,sha256=
|
|
7
|
-
wbreport/models.py,sha256=
|
|
8
|
-
wbreport/serializers.py,sha256=
|
|
9
|
-
wbreport/tasks.py,sha256=
|
|
5
|
+
wbreport/filters.py,sha256=Q92qUs0_4NvpqWqbs8_D9OLD81herHLuWcZ1sdneZgw,1523
|
|
6
|
+
wbreport/mixins.py,sha256=fXVwHAi6OSsOZcrrvSmQAdOHh3V_bzk0FJehBTB0xFw,5509
|
|
7
|
+
wbreport/models.py,sha256=XVr4NZtSRqkk7vA_WaPloUBMA8JvyB5u2wUm5MrxzNg,29930
|
|
8
|
+
wbreport/serializers.py,sha256=SpQW-Y-63x71DupbUONcRD4ufgm99KZ4qJqijutM2_M,7276
|
|
9
|
+
wbreport/tasks.py,sha256=8Cwb-eKHMmW520fW5m4Xf2t3TSnG_crlB-4MBaLCqlI,2332
|
|
10
10
|
wbreport/urls.py,sha256=yoIFuuwPCRRjOM0VzMznyMmMQXbSVfdk1l12xZJ7Ecs,1463
|
|
11
11
|
wbreport/urls_public.py,sha256=oc_gBiKvLqWkSDAm_0yitWgpfEnlh3_hGUugkLrLCLs,370
|
|
12
12
|
wbreport/defaults/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
13
|
wbreport/defaults/factsheets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
-
wbreport/defaults/factsheets/base.py,sha256=
|
|
14
|
+
wbreport/defaults/factsheets/base.py,sha256=CliFS0MpfweN8a7GpWcxeerzICgpiDym9G_doPmB3GE,41166
|
|
15
15
|
wbreport/defaults/factsheets/menu.py,sha256=NTcUuViV4Q-qkffoA7wMSyxnE4mWPysu3KTKWxFmMCM,4580
|
|
16
16
|
wbreport/defaults/factsheets/mixins.py,sha256=E0RvxmUpvpG7B7YngBPXJ35eD3nwNandJFzLjj1rNRI,1267
|
|
17
|
-
wbreport/defaults/factsheets/multitheme.py,sha256=
|
|
17
|
+
wbreport/defaults/factsheets/multitheme.py,sha256=OrJEmgcS8vACAk9l0cM_L9D_uOTbZClezGWfM-WLF7Y,38562
|
|
18
18
|
wbreport/factories/__init__.py,sha256=jyD1_R-xc2JPZIaSwtE7zYATdL9NIXIDqTwjLw1MolA,170
|
|
19
19
|
wbreport/factories/data_classes.py,sha256=Ms9bqG370OQTmE3Kxvt9xay-6lfTnqEA3Sx7zCQKWXw,1487
|
|
20
20
|
wbreport/factories/reports.py,sha256=nGWa_fS78XGUbS8E35rGl3IJySHLB81ggq-3JllPOx4,2286
|
|
@@ -30,41 +30,41 @@ wbreport/migrations/0014_alter_reportcategory_options_and_more.py,sha256=52ot6Ck
|
|
|
30
30
|
wbreport/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
31
31
|
wbreport/pdf/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
32
32
|
wbreport/pdf/charts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
|
-
wbreport/pdf/charts/legend.py,sha256=
|
|
34
|
-
wbreport/pdf/charts/pie.py,sha256=
|
|
35
|
-
wbreport/pdf/charts/timeseries.py,sha256=
|
|
36
|
-
wbreport/pdf/flowables/risk.py,sha256=
|
|
37
|
-
wbreport/pdf/flowables/textboxes.py,sha256=
|
|
33
|
+
wbreport/pdf/charts/legend.py,sha256=g_yAnI6zuMn11pXOphReWiKA1PPIEJ6NzKeeKLHx4t0,481
|
|
34
|
+
wbreport/pdf/charts/pie.py,sha256=QzsP18-s1IKXyiUT8sHi-wjivqEUKkxy42qMVaJP-fk,4288
|
|
35
|
+
wbreport/pdf/charts/timeseries.py,sha256=O1MCneh6hPJD6jVyJfytGL3WdYx9WaQ-vfO66lCjgUI,2395
|
|
36
|
+
wbreport/pdf/flowables/risk.py,sha256=jmqdqDjk21Ob5qQA0GxSv_DPrUTCyGaAmJuGq0PIYcA,3499
|
|
37
|
+
wbreport/pdf/flowables/textboxes.py,sha256=WIdqFyGG_kb_rO1OvB88QISPB36Zi3rTxjqBkGKeINY,4425
|
|
38
38
|
wbreport/pdf/flowables/themes.py,sha256=Y5LcgSTJDhIZM3uIWAPY68HVMhTY9aY9PDwWsG5_IVk,6548
|
|
39
39
|
wbreport/pdf/sandbox/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
40
40
|
wbreport/pdf/sandbox/run.py,sha256=Vkzp_xVVJHctToS49Uef2Mnpb_5KUOWPxNdTFHOqri8,584
|
|
41
41
|
wbreport/pdf/sandbox/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
42
|
-
wbreport/pdf/sandbox/templates/basic_factsheet.py,sha256=
|
|
43
|
-
wbreport/pdf/sandbox/templates/fund_factsheet.py,sha256=
|
|
44
|
-
wbreport/pdf/sandbox/templates/long_industry_exposure_factsheet.py,sha256=
|
|
45
|
-
wbreport/pdf/sandbox/templates/multistrat_factsheet.py,sha256=
|
|
42
|
+
wbreport/pdf/sandbox/templates/basic_factsheet.py,sha256=1bU6nPg8TI6QTtqmCn7FO9cio2vrsQ32OtViDa-Okqw,34100
|
|
43
|
+
wbreport/pdf/sandbox/templates/fund_factsheet.py,sha256=WHYMKnTaUW1UtLW4-QeWlRhdHfgP0FasRZWJKB9Riyk,31157
|
|
44
|
+
wbreport/pdf/sandbox/templates/long_industry_exposure_factsheet.py,sha256=nZgy_NUR7JT22jFyBzZnr800T4EkHzErcgLAr9C6_-s,32803
|
|
45
|
+
wbreport/pdf/sandbox/templates/multistrat_factsheet.py,sha256=WR_zlgfNQom257U2b12GIeKY6dM17Or6k1H9Jupeo1Q,31572
|
|
46
46
|
wbreport/pdf/sandbox/templates/testfile.pdf,sha256=eV55RNFdqxqYzre6mg8EWZoL_cbc_lwPjyTGt1pr1AI,144012
|
|
47
47
|
wbreport/pdf/tables/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
48
|
-
wbreport/pdf/tables/aggregated_tables.py,sha256=
|
|
49
|
-
wbreport/pdf/tables/data_tables.py,sha256=
|
|
48
|
+
wbreport/pdf/tables/aggregated_tables.py,sha256=ARQD3i2hbclx-IdUUNytePbIWQVMHEb0qRPYlZBjG-E,4811
|
|
49
|
+
wbreport/pdf/tables/data_tables.py,sha256=c3YZsTgOlcupNAPBpZQIxR89bgyk5PgZvyJCucy7KAw,2297
|
|
50
50
|
wbreport/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
51
51
|
wbreport/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
52
52
|
wbreport/templatetags/portfolio_tags.py,sha256=N2MC_6iFcUAFDH5Wx5rD1-PVK_Ltq4VPIoq7WL4aXGQ,900
|
|
53
53
|
wbreport/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
54
54
|
wbreport/tests/conftest.py,sha256=oMidAuP41_yxMubUDUpqcsW_YslEq_CyPmfD11CUPhY,745
|
|
55
|
-
wbreport/tests/test_models.py,sha256=
|
|
56
|
-
wbreport/tests/test_tasks.py,sha256=
|
|
55
|
+
wbreport/tests/test_models.py,sha256=jJ_Am79tf8gX7lUpheV9dhe-rZu7UlOSG5dE3RGcqU8,11293
|
|
56
|
+
wbreport/tests/test_tasks.py,sha256=_u2Ns4w8aHTXrMscodv4lOPhrgV2EkVwMhnEttkwcLM,763
|
|
57
57
|
wbreport/tests/test_viewsets.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
58
58
|
wbreport/tests/tests.py,sha256=j2A1uu5DtGu2w056j0S4O7u2OxylldMPCmr7bbSOvfk,282
|
|
59
59
|
wbreport/viewsets/__init__.py,sha256=iEgYvZsLxQ3Hhf1hwHVdSD7Dm1OZK1Z6qhvTADqs-oc,322
|
|
60
|
-
wbreport/viewsets/viewsets.py,sha256=
|
|
60
|
+
wbreport/viewsets/viewsets.py,sha256=NAk5rdBn8NYPEx94AH8hGthDN1HtjmpG2w7OskSWlNg,13998
|
|
61
61
|
wbreport/viewsets/configs/__init__.py,sha256=WDvXbmGKD6_DP3nongBzL6lOHYwz5JC0gWtS1C2N4FY,535
|
|
62
|
-
wbreport/viewsets/configs/buttons.py,sha256=
|
|
63
|
-
wbreport/viewsets/configs/displays.py,sha256=
|
|
64
|
-
wbreport/viewsets/configs/endpoints.py,sha256=
|
|
62
|
+
wbreport/viewsets/configs/buttons.py,sha256=e2B3UNMysLWwS4k5HiHrnVVAdABstzAwc0R9oR8mTNk,9364
|
|
63
|
+
wbreport/viewsets/configs/displays.py,sha256=No-JZ9JC-wtFGqsrNk7_NX5I3RaHWZkG2hJuuwlPkGs,5705
|
|
64
|
+
wbreport/viewsets/configs/endpoints.py,sha256=2k2aPoAo4Nq8czbYWLqz2hBbdgPAOk91GSUCt7twA_E,651
|
|
65
65
|
wbreport/viewsets/configs/menus.py,sha256=trDZsdjXip8KQ4SY1uIudZWFqwb3rQHIRSU36dzRzy0,269
|
|
66
66
|
wbreport/viewsets/configs/titles.py,sha256=bAfruj40yHrSUPzuJ7WGlfJDl7NXXKSaTqITPNn4eJA,783
|
|
67
|
-
wbreport-1.
|
|
68
|
-
wbreport-1.
|
|
69
|
-
wbreport-1.
|
|
70
|
-
wbreport-1.
|
|
67
|
+
wbreport-1.60.1.dist-info/METADATA,sha256=o8ekY77q4ZL5VKh8XZkxywjHnj3Rk0gC-EKXqq6xidk,186
|
|
68
|
+
wbreport-1.60.1.dist-info/WHEEL,sha256=aha0VrrYvgDJ3Xxl3db_g_MDIW-ZexDdrc_m-Hk8YY4,105
|
|
69
|
+
wbreport-1.60.1.dist-info/licenses/LICENSE,sha256=jvfVH0SY8_YMHlsJHKe_OajiscQDz4lpTlqT6x24sVw,172
|
|
70
|
+
wbreport-1.60.1.dist-info/RECORD,,
|
|
File without changes
|