diff --git a/.last-branch b/.last-branch index 19347a4..e4dbd71 100644 --- a/.last-branch +++ b/.last-branch @@ -1 +1 @@ -v20260104-07-reports-html-export-fix-json +v20260104-08-reports-html-total-runs-and-jobs-table-fix 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 b637ab2..7aee060 100644 --- a/containers/backupchecks/src/backend/app/main/routes_reporting_api.py +++ b/containers/backupchecks/src/backend/app/main/routes_reporting_api.py @@ -911,7 +911,6 @@ def _build_report_stats_payload(report_id: int) -> dict: trends = [] for tr in trend_rows or []: - day_total = int(tr.total_runs or 0) day_success = int(tr.success_runs or 0) day_warning = int(tr.warning_runs or 0) day_failed = int(tr.failed_runs or 0) @@ -926,6 +925,7 @@ def _build_report_stats_payload(report_id: int) -> dict: denom += day_failed if "missed_count" in include_keys: denom += day_missed + day_total = int(denom or 0) if denom > 0: day_rate = (day_success / float(denom)) * 100.0 trends.append( @@ -968,12 +968,21 @@ def _build_report_stats_payload(report_id: int) -> dict: "missed_count": 0, } for pr in perf_rows or []: - total_runs = int(pr.total_runs or 0) success_count = int(pr.success_count or 0) warning_count = int(pr.warning_count or 0) 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 + totals["total_runs"] += total_runs totals["success_count"] += success_count totals["warning_count"] += warning_count @@ -1280,6 +1289,12 @@ def _export_html_response(report: ReportDefinition, report_id: int, view: str): # Job table (aggregated per job) for a single-customer report. 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_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) + jobs_rows = [] with db.engine.connect() as conn: rows = conn.execute( @@ -1315,6 +1330,21 @@ def _export_html_response(report: ReportDefinition, report_id: int, view: str): missed=int(r.missed_count or 0), include_keys=include_keys_jobs, ) + + jr_success = int(r.success_count or 0) + jr_warning = int(r.warning_count or 0) + jr_failed = int(r.failed_count or 0) + jr_missed = int(r.missed_count or 0) + jr_total = 0 + if "success_count" in include_keys_jobs: + jr_total += jr_success + if "warning_count" in include_keys_jobs: + jr_total += jr_warning + if "failed_count" in include_keys_jobs: + jr_total += jr_failed + if "missed_count" in include_keys_jobs: + jr_total += jr_missed + jobs_rows.append( { "object_name": r.object_name or "", @@ -1322,19 +1352,24 @@ def _export_html_response(report: ReportDefinition, report_id: int, view: str): "job_name": r.job_name or "", "backup_software": r.backup_software or "", "backup_type": r.backup_type or "", - "total_runs": str(int(r.total_runs or 0)), - "success_count": str(int(r.success_count or 0)), + "total_runs": str(int(jr_total or 0)), + "success_count": str(jr_success), "success_override_count": str(int(r.success_override_count or 0)), - "warning_count": str(int(r.warning_count or 0)), - "failed_count": str(int(r.failed_count or 0)), - "missed_count": str(int(r.missed_count or 0)), + "warning_count": str(jr_warning), + "failed_count": str(jr_failed), + "missed_count": str(jr_missed), "success_rate": f"{round(rate, 2)}%", } ) + def _sort_key_jobs(it: dict) -> tuple: + return tuple(((it.get(k) or "").strip().lower()) for k in jobs_sort_fields) + + jobs_rows.sort(key=_sort_key_jobs) + jobs_th, jobs_tr = _render_table("jobs", jobs_rows) - jobs_table_html = """