From 26e5b9343db234e0a226d134d26d7e0e8b6ad89a Mon Sep 17 00:00:00 2001 From: Adriano Date: Sat, 7 Feb 2026 15:24:32 +0100 Subject: [PATCH] feat: FASE 6.5 - Report PDF (WeasyPrint + Kaleido) Add PDF report generation for Metrologist dashboard with SPC and measurement reports including SVG charts, capability indices, and company logo embedding. New files: - server/services/report_service.py (Jinja2 + Plotly/Kaleido + WeasyPrint) - server/routers/reports.py (2 GET endpoints with auth) - server/templates/reports/ (base, spc, measurement HTML templates) Modified: - server/main.py (register reports router) - client dashboard (download buttons + proxy routes) - i18n strings IT/EN Co-Authored-By: Claude Opus 4.6 --- client/blueprints/statistics.py | 73 ++- client/templates/statistics/dashboard.html | 75 ++- .../translations/en/LC_MESSAGES/messages.po | 10 + .../translations/it/LC_MESSAGES/messages.po | 10 + server/main.py | 2 + server/routers/reports.py | 81 ++++ server/services/report_service.py | 429 ++++++++++++++++++ server/templates/reports/base_report.html | 190 ++++++++ .../templates/reports/measurement_report.html | 75 +++ server/templates/reports/spc_report.html | 114 +++++ 10 files changed, 1056 insertions(+), 3 deletions(-) create mode 100644 server/routers/reports.py create mode 100644 server/services/report_service.py create mode 100644 server/templates/reports/base_report.html create mode 100644 server/templates/reports/measurement_report.html create mode 100644 server/templates/reports/spc_report.html diff --git a/client/blueprints/statistics.py b/client/blueprints/statistics.py index 4e639e0..7715c32 100644 --- a/client/blueprints/statistics.py +++ b/client/blueprints/statistics.py @@ -1,8 +1,11 @@ """Metrologist blueprint - SPC statistics dashboard and API proxies.""" -from flask import Blueprint, jsonify, render_template, request +import requests as http_requests + +from flask import Blueprint, jsonify, render_template, request, session from flask_babel import gettext as _ from blueprints.auth import login_required, role_required +from config import Config from services.api_client import api_client statistics_bp = Blueprint("statistics", __name__) @@ -105,3 +108,71 @@ def api_subtasks(): return jsonify(resp) return jsonify(resp) + + +# ============================================================================ +# PROXY REPORT PDF → FastAPI +# ============================================================================ + +def _proxy_report(endpoint: str): + """Forward query params to a FastAPI reports endpoint and return PDF.""" + params = {} + for key in [ + "recipe_id", "version_id", "subtask_id", + "date_from", "date_to", "operator_id", + "lot_number", "serial_number", + ]: + val = request.args.get(key) + if val is not None and val != "": + params[key] = val + + base_url = Config.API_SERVER_URL.rstrip("/") + headers = {} + api_key = session.get("api_key") + if api_key: + headers["X-API-Key"] = api_key + + try: + resp = http_requests.get( + f"{base_url}/api/reports/{endpoint}", + headers=headers, + params=params, + timeout=120, + ) + except (http_requests.ConnectionError, http_requests.Timeout) as e: + return jsonify({"error": True, "detail": str(e)}), 502 + + if not resp.ok: + try: + err = resp.json() + detail = err.get("detail", f"HTTP {resp.status_code}") + except Exception: + detail = f"HTTP {resp.status_code}" + return jsonify({"error": True, "detail": detail}), resp.status_code + + from flask import Response as FlaskResponse + return FlaskResponse( + resp.content, + mimetype="application/pdf", + headers={ + "Content-Disposition": resp.headers.get( + "Content-Disposition", f'attachment; filename="report.pdf"' + ) + }, + ) + + +@statistics_bp.route("/api/report-spc") +@login_required +@role_required("Metrologist") +def api_report_spc(): + """Proxy: download SPC PDF report.""" + return _proxy_report("spc") + + +@statistics_bp.route("/api/report-measurements") +@login_required +@role_required("Metrologist") +def api_report_measurements(): + """Proxy: download measurements PDF report.""" + return _proxy_report("measurements") diff --git a/client/templates/statistics/dashboard.html b/client/templates/statistics/dashboard.html index 3a9d7d2..685b2fe 100644 --- a/client/templates/statistics/dashboard.html +++ b/client/templates/statistics/dashboard.html @@ -61,8 +61,41 @@ - -
+ +
+ +
+ + +
+
+