From fc275a028572f08b561d763f83e32bcd54f8f9fa Mon Sep 17 00:00:00 2001 From: Ivo Oskamp Date: Sun, 4 Jan 2026 15:50:22 +0100 Subject: [PATCH] Auto-commit local changes before build (2026-01-04 15:50:22) --- .last-branch | 2 +- .../backend/app/main/routes_reporting_api.py | 43 +++++++++++-------- docs/changelog.md | 8 ++++ 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/.last-branch b/.last-branch index e4dbd71..92ac91b 100644 --- a/.last-branch +++ b/.last-branch @@ -1 +1 @@ -v20260104-08-reports-html-total-runs-and-jobs-table-fix +v20260104-09-reports-html-total-runs-selection-and-jobs-text-column-remove diff --git a/containers/backupchecks/src/backend/app/main/routes_reporting_api.py b/containers/backupchecks/src/backend/app/main/routes_reporting_api.py index 7aee060..95df3dc 100644 --- a/containers/backupchecks/src/backend/app/main/routes_reporting_api.py +++ b/containers/backupchecks/src/backend/app/main/routes_reporting_api.py @@ -222,7 +222,6 @@ def build_report_columns_meta(): "reviewed_at", ], "jobs": [ - "object_name", "customer_name", "job_name", "backup_software", @@ -292,7 +291,7 @@ def build_report_columns_meta(): { "name": "Text", "items": [ - {"key": "object_name", "label": "Text", "views": ["snapshot", "summary", "jobs"]}, + {"key": "object_name", "label": "Text", "views": ["snapshot", "summary"]}, ], }, { @@ -624,12 +623,14 @@ def api_reports_data(report_id: int): return err report = ReportDefinition.query.get_or_404(report_id) - include_keys = _get_success_rate_keys_from_report(report) + include_keys = None view = (request.args.get("view") or "summary").strip().lower() if view not in ("summary", "snapshot", "jobs"): view = "summary" + include_keys = _get_success_rate_keys_from_report(report, view_key=view) + limit = _clamp_int(request.args.get("limit"), default=100, min_v=1, max_v=500) offset = _clamp_int(request.args.get("offset"), default=0, min_v=0, max_v=1_000_000) @@ -652,7 +653,7 @@ def api_reports_data(report_id: int): "object_name": r.object_name or "", "customer_id": int(r.customer_id) if getattr(r, "customer_id", None) is not None else "", "customer_name": r.customer_name or "", - "total_runs": int(r.total_runs or 0), + "total_runs": _compute_total_runs(int(r.success_count or 0), int(r.warning_count or 0), int(r.failed_count or 0), int(r.missed_count or 0), include_keys), "success_count": int(r.success_count or 0), "success_override_count": int(r.success_override_count or 0), "warning_count": int(r.warning_count or 0), @@ -734,7 +735,7 @@ def api_reports_data(report_id: int): "job_name": r.job_name or "", "backup_software": r.backup_software or "", "backup_type": r.backup_type or "", - "total_runs": int(r.total_runs or 0), + "total_runs": _compute_total_runs(int(r.success_count or 0), int(r.warning_count or 0), int(r.failed_count or 0), int(r.missed_count or 0), include_keys), "success_count": int(r.success_count or 0), "success_override_count": int(r.success_override_count or 0), "warning_count": int(r.warning_count or 0), @@ -838,6 +839,20 @@ def _get_success_rate_keys_from_report(report: ReportDefinition, view_key: str = return out + +def _compute_total_runs(success: int, warning: int, failed: int, missed: int, include_keys: set[str]) -> int: + total = 0 + if "success_count" in include_keys: + total += int(success or 0) + if "warning_count" in include_keys: + total += int(warning or 0) + if "failed_count" in include_keys: + total += int(failed or 0) + if "missed_count" in include_keys: + total += int(missed or 0) + return int(total) + + def _compute_success_rate(success: int, warning: int, failed: int, missed: int, include_keys: set[str]) -> float: denom = 0 if "success_count" in include_keys: @@ -859,7 +874,7 @@ def _build_report_stats_payload(report_id: int) -> dict: """Compute summary and chart datasets for a generated report.""" report = ReportDefinition.query.get_or_404(report_id) - include_keys = _get_success_rate_keys_from_report(report) + include_keys = _get_success_rate_keys_from_report(report, view_key=view) with db.engine.connect() as conn: status_rows = conn.execute( @@ -973,15 +988,7 @@ def _build_report_stats_payload(report_id: int) -> dict: failed_count = int(pr.failed_count or 0) missed_count = int(pr.missed_count or 0) - total_runs = 0 - if "success_count" in include_keys: - total_runs += success_count - if "warning_count" in include_keys: - total_runs += warning_count - if "failed_count" in include_keys: - total_runs += failed_count - if "missed_count" in include_keys: - total_runs += missed_count + total_runs = _compute_total_runs(success_count, warning_count, failed_count, missed_count, include_keys) totals["total_runs"] += total_runs totals["success_count"] += success_count @@ -1062,7 +1069,7 @@ def _export_csv_response(report: ReportDefinition, report_id: int, view: str): if view not in ("summary", "snapshot", "jobs"): view = "summary" - include_keys = _get_success_rate_keys_from_report(report) + include_keys = _get_success_rate_keys_from_report(report, view_key=view) with db.engine.connect() as conn: if view == "summary": @@ -1097,11 +1104,11 @@ def _export_csv_response(report: ReportDefinition, report_id: int, view: str): "success_rate", ]) for r in rows or []: - total_runs = int(r.total_runs or 0) success_count = int(r.success_count or 0) warning_count = int(r.warning_count or 0) failed_count = int(r.failed_count or 0) missed_count = int(r.missed_count or 0) + total_runs = _compute_total_runs(success_count, warning_count, failed_count, missed_count, include_keys) rate = _compute_success_rate( success=success_count, warning=warning_count, @@ -1290,7 +1297,7 @@ def _export_html_response(report: ReportDefinition, report_id: int, view: str): include_keys_jobs = _get_success_rate_keys_from_report(report, view_key="jobs") jobs_selected_cols = _selected_cols("jobs") - jobs_sort_order = ["customer_name", "backup_software", "backup_type", "job_name", "object_name"] + jobs_sort_order = ["customer_name", "backup_software", "backup_type", "job_name"] jobs_sort_fields = [k for k in jobs_sort_order if k in set(jobs_selected_cols or [])] if not jobs_sort_fields: jobs_sort_fields = list(jobs_sort_order) diff --git a/docs/changelog.md b/docs/changelog.md index d9a9600..03bff03 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -257,6 +257,14 @@ - Fixed **Jobs table column headers** so the correct labels are displayed instead of placeholder keys (e.g. `{jobs_th}`). - Improved **Jobs table sorting** to follow a logical hierarchy: Customer > Backup software > Backup type > Job name > Object, depending on the selected columns. +--- + +## v20260104-09-reports-html-total-runs-selection-and-jobs-text-column-remove + +- Fixed “Total runs” to only sum the selected status counters (e.g. excluding missed when it’s not selected), instead of using the raw total that included missed runs. +- Removed the duplicate “Text” column from the Jobs report view by excluding `object_name` from the Jobs column set and Jobs defaults. + + ================================================================================================================================================ ## v0.1.15