Fix: Show resolved tickets only on runs where they were linked
Previous fix removed ALL resolved tickets from display, breaking audit trail. Users need to see which tickets were associated with historical runs, even after resolution. Solution: Two-source ticket display 1. Direct links (ticket_job_runs): Always show, even if resolved - Preserves audit trail - Shows tickets that were explicitly linked to runs 2. Active window (ticket_scopes): Only show unresolved - Prevents resolved tickets from appearing on NEW runs - Uses active_from_date without date-based resolved logic Changes: - Added direct_ticket_links map to fetch linked tickets per run - Query ticket_job_runs for audit trail tickets - Modified ticket_codes building to use both sources - Removed date-based resolved_date comparison (resd >= rd) Result: - Run 1 with ticket → ticket resolved → ticket still visible on Run 1 - Run 2 created → ticket NOT shown on Run 2 (correctly filtered) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
a9cae0f8f5
commit
43502ae6f3
@ -168,23 +168,61 @@ def job_detail(job_id: int):
|
|||||||
.all()
|
.all()
|
||||||
)
|
)
|
||||||
|
|
||||||
# Tickets: mark runs that fall within the ticket active window
|
# Tickets: mark runs that fall within the ticket active window OR have direct links
|
||||||
ticket_rows = []
|
ticket_rows = []
|
||||||
ticket_open_count = 0
|
ticket_open_count = 0
|
||||||
ticket_total_count = 0
|
ticket_total_count = 0
|
||||||
|
|
||||||
|
# Map of run_id -> list of directly linked ticket codes (for audit trail)
|
||||||
|
direct_ticket_links = {}
|
||||||
|
|
||||||
remark_rows = []
|
remark_rows = []
|
||||||
remark_open_count = 0
|
remark_open_count = 0
|
||||||
remark_total_count = 0
|
remark_total_count = 0
|
||||||
|
|
||||||
run_dates = []
|
run_dates = []
|
||||||
run_date_map = {}
|
run_date_map = {}
|
||||||
|
run_ids = []
|
||||||
for r in runs:
|
for r in runs:
|
||||||
rd = _to_amsterdam_date(r.run_at) or _to_amsterdam_date(datetime.utcnow())
|
rd = _to_amsterdam_date(r.run_at) or _to_amsterdam_date(datetime.utcnow())
|
||||||
run_date_map[r.id] = rd
|
run_date_map[r.id] = rd
|
||||||
|
run_ids.append(r.id)
|
||||||
if rd:
|
if rd:
|
||||||
run_dates.append(rd)
|
run_dates.append(rd)
|
||||||
|
|
||||||
|
# Get directly linked tickets for these runs (audit trail - show even if resolved)
|
||||||
|
if run_ids:
|
||||||
|
try:
|
||||||
|
rows = (
|
||||||
|
db.session.execute(
|
||||||
|
text(
|
||||||
|
"""
|
||||||
|
SELECT tjr.job_run_id, t.ticket_code, t.resolved_at
|
||||||
|
FROM ticket_job_runs tjr
|
||||||
|
JOIN tickets t ON t.id = tjr.ticket_id
|
||||||
|
WHERE tjr.job_run_id = ANY(:run_ids)
|
||||||
|
"""
|
||||||
|
),
|
||||||
|
{"run_ids": run_ids},
|
||||||
|
)
|
||||||
|
.mappings()
|
||||||
|
.all()
|
||||||
|
)
|
||||||
|
for rr in rows:
|
||||||
|
run_id = rr.get("job_run_id")
|
||||||
|
code = (rr.get("ticket_code") or "").strip()
|
||||||
|
resolved_at = rr.get("resolved_at")
|
||||||
|
if run_id not in direct_ticket_links:
|
||||||
|
direct_ticket_links[run_id] = []
|
||||||
|
direct_ticket_links[run_id].append({
|
||||||
|
"ticket_code": code,
|
||||||
|
"resolved_at": resolved_at,
|
||||||
|
"is_direct_link": True
|
||||||
|
})
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Get active (unresolved) tickets for future runs
|
||||||
if run_dates:
|
if run_dates:
|
||||||
min_date = min(run_dates)
|
min_date = min(run_dates)
|
||||||
max_date = max(run_dates)
|
max_date = max(run_dates)
|
||||||
@ -210,7 +248,12 @@ def job_detail(job_id: int):
|
|||||||
active_from = rr.get("active_from_date")
|
active_from = rr.get("active_from_date")
|
||||||
resolved_at = rr.get("resolved_at")
|
resolved_at = rr.get("resolved_at")
|
||||||
resolved_date = _to_amsterdam_date(resolved_at) if resolved_at else None
|
resolved_date = _to_amsterdam_date(resolved_at) if resolved_at else None
|
||||||
ticket_rows.append({"active_from_date": active_from, "resolved_date": resolved_date, "ticket_code": rr.get("ticket_code")})
|
ticket_rows.append({
|
||||||
|
"active_from_date": active_from,
|
||||||
|
"resolved_date": resolved_date,
|
||||||
|
"ticket_code": rr.get("ticket_code"),
|
||||||
|
"is_direct_link": False
|
||||||
|
})
|
||||||
except Exception:
|
except Exception:
|
||||||
ticket_rows = []
|
ticket_rows = []
|
||||||
|
|
||||||
@ -333,11 +376,22 @@ def job_detail(job_id: int):
|
|||||||
ticket_codes = []
|
ticket_codes = []
|
||||||
remark_items = []
|
remark_items = []
|
||||||
|
|
||||||
|
# First: add directly linked tickets (audit trail - always show)
|
||||||
|
if r.id in direct_ticket_links:
|
||||||
|
for tlink in direct_ticket_links[r.id]:
|
||||||
|
code = tlink.get("ticket_code", "")
|
||||||
|
if code and code not in ticket_codes:
|
||||||
|
ticket_codes.append(code)
|
||||||
|
has_ticket = True
|
||||||
|
|
||||||
|
# Second: add active window tickets (only unresolved)
|
||||||
if rd and ticket_rows:
|
if rd and ticket_rows:
|
||||||
for tr in ticket_rows:
|
for tr in ticket_rows:
|
||||||
|
if tr.get("is_direct_link"):
|
||||||
|
continue # Skip, already added above
|
||||||
af = tr.get("active_from_date")
|
af = tr.get("active_from_date")
|
||||||
resd = tr.get("resolved_date")
|
# Only check active_from, resolved tickets already filtered by query
|
||||||
if af and af <= rd and (resd is None or resd >= rd):
|
if af and af <= rd:
|
||||||
has_ticket = True
|
has_ticket = True
|
||||||
code = (tr.get("ticket_code") or "").strip()
|
code = (tr.get("ticket_code") or "").strip()
|
||||||
if code and code not in ticket_codes:
|
if code and code not in ticket_codes:
|
||||||
|
|||||||
@ -7,7 +7,7 @@ This file documents all changes made to this project via Claude Code.
|
|||||||
### Fixed
|
### Fixed
|
||||||
- Fixed Autotask ticket not being automatically linked to new runs when internal ticket is resolved by implementing independent Autotask propagation strategy (now checks for most recent non-deleted and non-resolved Autotask ticket on job regardless of internal ticket status, ensuring PSA ticket reference persists across runs until explicitly resolved or deleted)
|
- Fixed Autotask ticket not being automatically linked to new runs when internal ticket is resolved by implementing independent Autotask propagation strategy (now checks for most recent non-deleted and non-resolved Autotask ticket on job regardless of internal ticket status, ensuring PSA ticket reference persists across runs until explicitly resolved or deleted)
|
||||||
- Fixed internal and Autotask tickets being linked to new runs even after being resolved by removing date-based "open" logic from ticket query (tickets now only link to new runs if they are genuinely unresolved, not based on run date comparisons)
|
- Fixed internal and Autotask tickets being linked to new runs even after being resolved by removing date-based "open" logic from ticket query (tickets now only link to new runs if they are genuinely unresolved, not based on run date comparisons)
|
||||||
- Fixed Job Details page showing resolved tickets in the Tickets column by removing date-based logic from display query (tickets and remarks now only show if genuinely unresolved, matching the linking behavior)
|
- Fixed Job Details page showing resolved tickets for ALL runs by implementing two-source ticket display: directly linked tickets (via ticket_job_runs) are always shown for audit trail, while active window tickets (via scope query) are only shown if unresolved, preserving historical ticket links while preventing resolved tickets from appearing on new runs
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Added debug logging to ticket linking function to troubleshoot resolved ticket propagation issues (writes to AuditLog table with event_type "ticket_link_debug", visible on Logging page, logs EVERY run import to show whether tickets were found and their resolved_at status, uses commit instead of flush to ensure persistence)
|
- Added debug logging to ticket linking function to troubleshoot resolved ticket propagation issues (writes to AuditLog table with event_type "ticket_link_debug", visible on Logging page, logs EVERY run import to show whether tickets were found and their resolved_at status, uses commit instead of flush to ensure persistence)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user