From fa676a9e4e84dfda07275fedb82e6bf67f4935b1 Mon Sep 17 00:00:00 2001 From: Ivo Oskamp Date: Sat, 3 Jan 2026 21:42:36 +0100 Subject: [PATCH] Auto-commit local changes before build (2026-01-03 21:42:36) --- .last-branch | 2 +- .../backend/app/main/routes_reporting_api.py | 20 ++++++++++++++----- .../src/backend/app/migrations.py | 4 ++++ .../backupchecks/src/backend/app/models.py | 3 +++ docs/changelog.md | 8 ++++++++ 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/.last-branch b/.last-branch index 2fa57f9..d8398cf 100644 --- a/.last-branch +++ b/.last-branch @@ -1 +1 @@ -v20260103-14-reports-percentage-2-decimals +v20260103-15-reports-customer-column 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 ef86bb9..0a1a6e1 100644 --- a/containers/backupchecks/src/backend/app/main/routes_reporting_api.py +++ b/containers/backupchecks/src/backend/app/main/routes_reporting_api.py @@ -193,6 +193,7 @@ def build_report_columns_meta(): "defaults": { "summary": [ "object_name", + "customer_name", "total_runs", "success_count", "warning_count", @@ -238,7 +239,7 @@ def build_report_columns_meta(): {"key": "job_id", "label": "Job ID", "views": ["snapshot"]}, {"key": "backup_software", "label": "Job type", "views": ["snapshot"]}, {"key": "backup_type", "label": "Repository / Target", "views": ["snapshot"]}, - {"key": "customer_name", "label": "Customer", "views": ["snapshot"]}, + {"key": "customer_name", "label": "Customer", "views": ["snapshot", "summary"]}, ], }, { @@ -446,11 +447,14 @@ def api_reports_generate(report_id: int): text( ''' INSERT INTO report_object_summaries - (report_id, object_name, total_runs, success_count, success_override_count, + (report_id, object_name, customer_id, customer_name, + total_runs, success_count, success_override_count, warning_count, failed_count, missed_count, success_rate, created_at) SELECT :rid AS report_id, COALESCE(s.job_name, '(unknown job)') AS object_name, + s.customer_id AS customer_id, + s.customer_name AS customer_name, COUNT(*)::INTEGER AS total_runs, SUM(CASE WHEN (COALESCE(s.status,'') ILIKE 'success%' AND s.override_applied = FALSE) THEN 1 ELSE 0 END)::INTEGER AS success_count, SUM(CASE WHEN (s.override_applied = TRUE) THEN 1 ELSE 0 END)::INTEGER AS success_override_count, @@ -469,7 +473,7 @@ def api_reports_generate(report_id: int): NOW() AS created_at FROM report_object_snapshots s WHERE s.report_id = :rid - GROUP BY s.job_id, s.job_name + GROUP BY s.customer_id, s.customer_name, s.job_id, s.job_name ''' ), {"rid": report_id}, @@ -513,7 +517,7 @@ def api_reports_data(report_id: int): q = db.session.query(ReportObjectSummary).filter(ReportObjectSummary.report_id == report_id) total = q.count() rows = ( - q.order_by(ReportObjectSummary.object_name.asc()) + q.order_by(db.func.coalesce(ReportObjectSummary.customer_name, '').asc(), ReportObjectSummary.object_name.asc()) .offset(offset) .limit(limit) .all() @@ -526,6 +530,8 @@ def api_reports_data(report_id: int): "items": [ { "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), "success_count": int(r.success_count or 0), "success_override_count": int(r.success_override_count or 0), @@ -732,6 +738,8 @@ def api_reports_export_csv(report_id: int): if view == "summary": writer.writerow([ "object_name", + "customer_id", + "customer_name", "total_runs", "success_count", "success_override_count", @@ -743,12 +751,14 @@ def api_reports_export_csv(report_id: int): rows = ( db.session.query(ReportObjectSummary) .filter(ReportObjectSummary.report_id == report_id) - .order_by(ReportObjectSummary.object_name.asc()) + .order_by(db.func.coalesce(ReportObjectSummary.customer_name, '').asc(), ReportObjectSummary.object_name.asc()) .all() ) for r in rows: writer.writerow([ r.object_name or "", + r.customer_id or "", + r.customer_name or "", int(r.total_runs or 0), int(r.success_count or 0), int(r.success_override_count or 0), diff --git a/containers/backupchecks/src/backend/app/migrations.py b/containers/backupchecks/src/backend/app/migrations.py index 2da1bc4..49e304d 100644 --- a/containers/backupchecks/src/backend/app/migrations.py +++ b/containers/backupchecks/src/backend/app/migrations.py @@ -1371,6 +1371,8 @@ def migrate_reporting_tables() -> None: id SERIAL PRIMARY KEY, report_id INTEGER NOT NULL REFERENCES report_definitions(id) ON DELETE CASCADE, object_name TEXT NOT NULL, + customer_id INTEGER NULL, + customer_name TEXT NULL, total_runs INTEGER NOT NULL DEFAULT 0, success_count INTEGER NOT NULL DEFAULT 0, success_override_count INTEGER NOT NULL DEFAULT 0, @@ -1395,5 +1397,7 @@ def migrate_reporting_tables() -> None: conn.execute(text("ALTER TABLE report_definitions ADD COLUMN IF NOT EXISTS customer_scope VARCHAR(16) NOT NULL DEFAULT 'all'")) conn.execute(text("ALTER TABLE report_definitions ADD COLUMN IF NOT EXISTS customer_ids TEXT NULL")) conn.execute(text("ALTER TABLE report_object_snapshots ADD COLUMN IF NOT EXISTS customer_id INTEGER NULL")) + conn.execute(text("ALTER TABLE report_object_summaries ADD COLUMN IF NOT EXISTS customer_id INTEGER NULL")) + conn.execute(text("ALTER TABLE report_object_summaries ADD COLUMN IF NOT EXISTS customer_name TEXT NULL")) print("[migrations] reporting tables created/verified.") diff --git a/containers/backupchecks/src/backend/app/models.py b/containers/backupchecks/src/backend/app/models.py index 350fddf..04a4627 100644 --- a/containers/backupchecks/src/backend/app/models.py +++ b/containers/backupchecks/src/backend/app/models.py @@ -612,6 +612,9 @@ class ReportObjectSummary(db.Model): report_id = db.Column(db.Integer, db.ForeignKey("report_definitions.id"), nullable=False) object_name = db.Column(db.Text, nullable=False) + customer_id = db.Column(db.Integer, nullable=True) + customer_name = db.Column(db.Text, nullable=True) + total_runs = db.Column(db.Integer, nullable=False, default=0) success_count = db.Column(db.Integer, nullable=False, default=0) success_override_count = db.Column(db.Integer, nullable=False, default=0) diff --git a/docs/changelog.md b/docs/changelog.md index e85b50a..8da7d8c 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -128,6 +128,14 @@ - CSV export generation - Improved readability and consistency of reported percentage values. +--- + +## v20260103-15-reports-customer-column + +- Added **Customer** as a selectable column in report configuration. +- Ensured customer name is included and visible when multiple customers are selected. +- Updated summary and raw data views to correctly display customer information across multi-customer reports. + ================================================================================================================================================ ## v0.1.15