From 38f0f8954e773313f830b25cf7f34628479f91b7 Mon Sep 17 00:00:00 2001 From: Ivo Oskamp Date: Thu, 19 Feb 2026 14:14:44 +0100 Subject: [PATCH] Fix remark visibility in run alerts --- .../src/backend/app/main/routes_api.py | 72 +++++++++++++++++-- docs/changelog-claude.md | 1 + 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/containers/backupchecks/src/backend/app/main/routes_api.py b/containers/backupchecks/src/backend/app/main/routes_api.py index a98873f..e168134 100644 --- a/containers/backupchecks/src/backend/app/main/routes_api.py +++ b/containers/backupchecks/src/backend/app/main/routes_api.py @@ -126,9 +126,13 @@ def api_job_run_alerts(run_id: int): except Exception as exc: return jsonify({"status": "error", "message": str(exc) or "Failed to load tickets."}), 500 - # Remarks linked to this specific run - # Only show remarks that were explicitly linked via remark_job_runs + # Remarks linked to this run: + # 1. Explicitly linked via remark_job_runs (audit trail when resolved) + # 2. Linked to the job via remark_scopes (active on run date) try: + remark_ids_seen = set() + + # First, remarks explicitly linked to this run. rows = ( db.session.execute( text( @@ -149,6 +153,9 @@ def api_job_run_alerts(run_id: int): ) for rr in rows: + remark_id = int(rr.get("id")) + remark_ids_seen.add(remark_id) + body = (rr.get("body") or "").strip() if len(body) > 180: body = body[:177] + "..." @@ -162,7 +169,64 @@ def api_job_run_alerts(run_id: int): remarks.append( { - "id": int(rr.get("id")), + "id": remark_id, + "body": body, + "start_date": _format_datetime(rr.get("start_date")) if rr.get("start_date") else "-", + "active_from_date": str(rr.get("active_from_date")) if rr.get("active_from_date") else "", + "resolved_at": _format_datetime(rr.get("resolved_at")) if rr.get("resolved_at") else "", + "active": bool(active_now), + "resolved_same_day": bool(resolved_same_day), + } + ) + + # Second, active job-level remarks from scope (not yet explicitly linked to this run). + ui_tz = _get_ui_timezone_name() + rows = ( + db.session.execute( + text( + """ + SELECT DISTINCT r.id, r.body, r.start_date, r.resolved_at, r.active_from_date + FROM remarks r + JOIN remark_scopes rs ON rs.remark_id = r.id + WHERE rs.job_id = :job_id + AND COALESCE( + r.active_from_date, + ((r.start_date AT TIME ZONE 'UTC' AT TIME ZONE :ui_tz)::date) + ) <= :run_date + AND r.resolved_at IS NULL + ORDER BY r.start_date DESC + """ + ), + { + "job_id": job.id if job else 0, + "run_date": run_date, + "ui_tz": ui_tz, + }, + ) + .mappings() + .all() + ) + + for rr in rows: + remark_id = int(rr.get("id")) + if remark_id in remark_ids_seen: + continue + remark_ids_seen.add(remark_id) + + body = (rr.get("body") or "").strip() + if len(body) > 180: + body = body[:177] + "..." + + resolved_at = rr.get("resolved_at") + resolved_same_day = False + if resolved_at and run_date: + resolved_same_day = _to_amsterdam_date(resolved_at) == run_date + + active_now = resolved_at is None or (not resolved_same_day) + + remarks.append( + { + "id": remark_id, "body": body, "start_date": _format_datetime(rr.get("start_date")) if rr.get("start_date") else "-", "active_from_date": str(rr.get("active_from_date")) if rr.get("active_from_date") else "", @@ -608,4 +672,4 @@ def api_remark_link_run(remark_id: int): db.session.rollback() return jsonify({"status": "error", "message": str(exc) or "Failed to link run."}), 500 - return jsonify({"status": "ok"}) \ No newline at end of file + return jsonify({"status": "ok"}) diff --git a/docs/changelog-claude.md b/docs/changelog-claude.md index 0ee482e..646e133 100644 --- a/docs/changelog-claude.md +++ b/docs/changelog-claude.md @@ -14,6 +14,7 @@ This file documents all changes made to this project via Claude Code. - Import success and audit output now includes whether Autotask IDs were imported - 3CX parser now recognizes `3CX Notification: Update Successful - ` as an informational run with `backup_software: 3CX`, `backup_type: Update`, and `overall_status: Success`, and excludes this type from schedule inference (no Expected/Missed generation) - Run Checks now hides only non-backup 3CX informational types (`Update`, `SSL Certificate`), while other backup software/types remain visible +- Restored remark visibility in Run Checks and Job Details alerts by loading remarks from both sources: explicit run links (`remark_job_runs`) and active job scopes (`remark_scopes`) with duplicate prevention ## [2026-02-16]