From 1c08cdeb4c30b0850a4cbf3cd4c2af744733b45f Mon Sep 17 00:00:00 2001 From: Madelon Dohmen <99282220+madelondohmen@users.noreply.github.com> Date: Wed, 30 Oct 2024 11:00:54 +0100 Subject: [PATCH] Fix report names for scheduled reports (#3726) Co-authored-by: stephanie0x00 <9821756+stephanie0x00@users.noreply.github.com> Co-authored-by: Jan Klopper --- rocky/reports/forms.py | 4 +-- rocky/reports/runner/report_runner.py | 27 +++++++++++++------ .../partials/report_names_header.html | 6 ++--- rocky/reports/views/mixins.py | 6 ++--- rocky/tests/integration/test_report_runner.py | 6 ++--- 5 files changed, 30 insertions(+), 19 deletions(-) diff --git a/rocky/reports/forms.py b/rocky/reports/forms.py index 58ec6a06956..265d0d15e27 100644 --- a/rocky/reports/forms.py +++ b/rocky/reports/forms.py @@ -107,13 +107,13 @@ class CustomReportScheduleForm(BaseRockyForm): class ParentReportNameForm(BaseRockyForm): parent_report_name = forms.CharField( - label=_("Report name format"), required=False, initial="{report type} for {oois_count} objects" + label=_("Report name format"), required=False, initial="${report_type} for ${oois_count} objects" ) class ChildReportNameForm(BaseRockyForm): child_report_name = forms.CharField( - label=_("Subreports name format"), required=True, initial="{report type} for {ooi}" + label=_("Subreports name format"), required=True, initial="${report_type} for ${ooi}" ) diff --git a/rocky/reports/runner/report_runner.py b/rocky/reports/runner/report_runner.py index f8a742e500e..aaaf3992e6a 100644 --- a/rocky/reports/runner/report_runner.py +++ b/rocky/reports/runner/report_runner.py @@ -1,4 +1,5 @@ from datetime import datetime, timezone +from string import Template from django.conf import settings from tools.models import Organization @@ -30,18 +31,28 @@ def run(self, report_task: ReportTask) -> None: ) self.bytes_client.organization = report_task.organisation_id - report_names = [] - oois_count = 0 + subreport_names = [] + oois_count = len(recipe.input_recipe["input_oois"]) for report_type_id, data in report_data.items(): - oois_count += len(data) report_type = get_report_by_id(report_type_id) for ooi in data: - report_name = recipe.subreport_name_format.replace("{ooi}", ooi).replace( - "{report type}", str(report_type.name) + ooi_human_readable = Reference.from_str(ooi).human_readable + subreport_name = Template(recipe.subreport_name_format).safe_substitute( + ooi=ooi_human_readable, report_type=str(report_type.name) ) - report_names.append((report_name, report_name)) + subreport_names.append((subreport_name, subreport_name)) + + parent_report_name = Template(recipe.report_name_format).safe_substitute(oois_count=str(oois_count)) + + if "${ooi}" in parent_report_name and oois_count == 1: + ooi = recipe.input_recipe["input_oois"][0] + ooi_human_readable = Reference.from_str(ooi).human_readable + parent_report_name = Template(parent_report_name).safe_substitute(ooi=ooi_human_readable) + if "${report_type}" in parent_report_name and len(report_types) == 1: + report_type = get_report_by_id(recipe.report_types[0]) + parent_report_name = Template(parent_report_name).safe_substitute(report_type=str(report_type.name)) save_report_data( self.bytes_client, @@ -56,8 +67,8 @@ def run(self, report_task: ReportTask) -> None: } }, report_data, - report_names, - recipe.report_name_format.replace("{oois_count}", str(oois_count)), + subreport_names, + parent_report_name, ) self.bytes_client.organization = None diff --git a/rocky/reports/templates/partials/report_names_header.html b/rocky/reports/templates/partials/report_names_header.html index 6e3a11906fd..1616fc02f25 100644 --- a/rocky/reports/templates/partials/report_names_header.html +++ b/rocky/reports/templates/partials/report_names_header.html @@ -13,14 +13,14 @@

{% translate "Report name" %}

{% blocktranslate trimmed %} To make the report names more descriptive, you can include placeholders for the object name, the report type and/or the reference date. For subreports and reports over a single object, - use the placeholder "{ooi}" for the object name, "{report type}" for the report type and use a + use the placeholder "${ooi}" for the object name, "${report_type}" for the report type and use a Python strftime code for the reference - date. For reports over multiple objects, use "{oois_count}" for the number of objects in the report. + date. For reports over multiple objects, use "${oois_count}" for the number of objects in the report. {% endblocktranslate %}

{% blocktranslate trimmed %} - For example, the format "{report type} for {ooi} at %x" could generate: + For example, the format "${report_type} for ${ooi} at %x" could generate: "DNS Report for example.com at 01/01/25". {% endblocktranslate %}

diff --git a/rocky/reports/views/mixins.py b/rocky/reports/views/mixins.py index 14ac15cbccd..b8a14ffcf66 100644 --- a/rocky/reports/views/mixins.py +++ b/rocky/reports/views/mixins.py @@ -75,7 +75,7 @@ def save_report_data( raw_id = bytes_client.upload_raw( raw=ReportDataDict(input_data).model_dump_json().encode(), manual_mime_types={"openkat/report"} ) - name = now.strftime(parent_report_name.replace("{report type}", str(ConcatenatedReport.name))) + name = now.strftime(parent_report_name.replace("${report_type}", str(ConcatenatedReport.name))) if not name or name.isspace(): name = ConcatenatedReport.name @@ -163,7 +163,7 @@ def save_report_data( manual_mime_types={"openkat/report"}, ) report_type = get_report_by_id(report_type_id) - name = now.strftime(parent_report_name.replace("{report type}", str(report_type.name))) + name = now.strftime(parent_report_name.replace("${report_type}", str(report_type.name))) if not name or name.isspace(): name = ConcatenatedReport.name @@ -205,7 +205,7 @@ def save_report(self, report_names: list) -> Report | None: self.get_input_data(), report_data, report_names, - report_names[0][0], + report_names[0][1], ) # If OOI could not be found or the date is incorrect, it will be shown to the user as a message error diff --git a/rocky/tests/integration/test_report_runner.py b/rocky/tests/integration/test_report_runner.py index 75f60a3a7b7..dcbd380e68a 100644 --- a/rocky/tests/integration/test_report_runner.py +++ b/rocky/tests/integration/test_report_runner.py @@ -17,8 +17,8 @@ def test_run_report_task(octopoes_api_connector: OctopoesAPIConnector, report_ru recipe = ReportRecipe( recipe_id="abc4e52b-812c-4cc2-8196-35fb8efc63ca", - report_name_format="Concatenated report for {oois_count} objects", - subreport_name_format="{report type} for {ooi} in %Y", + report_name_format="Concatenated report for ${oois_count} objects", + subreport_name_format="${report_type} for ${ooi} in %Y", input_recipe={"input_oois": [oois["hostnames"][0].reference, oois["hostnames"][1].reference]}, report_types=["dns-report"], cron_expression="* * * * *", @@ -92,7 +92,7 @@ def test_run_report_task(octopoes_api_connector: OctopoesAPIConnector, report_ru assert len(subreports) == 2 assert report.name == "Concatenated report for 2 objects" - assert "DNS Report for Hostname|test|a.example.com in 2024" in {x.name for x in subreports} + assert "DNS Report for a.example.com in 2024" in {x.name for x in subreports} # FIXME: the naming logic in reports/views/mixins.py 107-112 is not right. We expect to find example.com in this # set, but instead only find a.example.com because when ooi_name is 'example.com', the check: