Source code for ferrosoft.apps.reporting.tasks
# Copyright (c) 2025 Ferrosoft GmbH. All rights reserved.
import logging
from urllib.parse import urljoin
from asgiref.sync import sync_to_async
from django.template.loader import render_to_string
from django.utils.translation import gettext as _
from ferrosoft.apps.ferrobase.models import StoredFile
from ferrosoft.apps.ferrobase.services.taskqueue import tenant_task
from ferrosoft.apps.ferrobase.views import FORCE_DOWNLOAD_PARAM
from ferrosoft.apps.reporting.models import Report
from ferrosoft.apps.reporting.websockets.updater import ReportGeneratorUpdater
def _send_update(
updater: ReportGeneratorUpdater,
message: str,
error: bool = False,
):
updater.send_update(
render_to_string(
"reporting/generator/updated.html",
context={
"message": message,
"error": error,
},
),
)
def _send_result(
updater: ReportGeneratorUpdater,
file: StoredFile,
return_url: str,
):
url = file.content.url
download_url = urljoin(url, f"?{FORCE_DOWNLOAD_PARAM}=1")
updater.send_result(
render_to_string(
"reporting/generator/finished.html",
context={
"return_url": return_url,
"url": url,
"download_url": download_url,
"embed": file.media_type == "application/pdf",
},
),
)
def _send_failed(updater: ReportGeneratorUpdater, error: str):
updater.send_result(
render_to_string("reporting/generator/failed.html", {"error": error})
)
[docs]
@sync_to_async
@tenant_task()
def generate_document(report_id: str):
updater = ReportGeneratorUpdater(report_id)
report = Report.objects.filter(pk=report_id).select_related("document").first()
if report is None:
_send_failed(updater, _("Report not found"))
return
# noinspection PyBroadException
try:
pdf_blob = report.generate_document()
with report.document.content.open("wb") as f:
f.write(pdf_blob)
_send_update(updater, _("Report created successfully."))
_send_result(updater, report.document, report.return_url)
except Exception:
logging.exception("Error generating report")
_send_failed(updater, _("Error generating report"))