From f3b1b56b6abc746dcc48bb81ccc4cc95ceb52b01 Mon Sep 17 00:00:00 2001 From: Ivo Oskamp Date: Tue, 10 Feb 2026 09:32:23 +0100 Subject: [PATCH] Fix Autotask ticket propagation to new runs When a new run is created, Autotask tickets were not being propagated if the associated internal ticket was resolved. This caused users to have to manually re-link tickets on each new run. The previous implementation relied on finding an open internal ticket first, then using its ticket code to find a matching Autotask-linked run. If the internal ticket was resolved, the Autotask propagation would fail. This commit implements a two-strategy approach: 1. Strategy 1: Use internal ticket code (existing logic, improved error handling) 2. Strategy 2: Direct Autotask propagation - find most recent non-deleted Autotask ticket for the job, independent of internal ticket status Now Autotask tickets remain linked across runs regardless of internal ticket resolution status, matching the behavior of internal tickets. Co-Authored-By: Claude Sonnet 4.5 --- .../src/backend/app/ticketing_utils.py | 26 ++++++++++++++++--- docs/changelog-claude.md | 5 ++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/containers/backupchecks/src/backend/app/ticketing_utils.py b/containers/backupchecks/src/backend/app/ticketing_utils.py index 23557c6..5d94691 100644 --- a/containers/backupchecks/src/backend/app/ticketing_utils.py +++ b/containers/backupchecks/src/backend/app/ticketing_utils.py @@ -213,16 +213,34 @@ def link_open_internal_tickets_to_run(*, run: JobRun, job: Job) -> None: except Exception: pass + # Strategy 1: Use internal ticket code to find matching Autotask-linked run try: # Use the newest ticket code to find a matching prior Autotask-linked run. - newest_code = (rows[0][1] or "").strip() - if not newest_code: - return + newest_code = (rows[0][1] or "").strip() if rows else "" + if newest_code: + prior = ( + JobRun.query.filter(JobRun.job_id == job.id) + .filter(JobRun.autotask_ticket_id.isnot(None)) + .filter(JobRun.autotask_ticket_number == newest_code) + .order_by(JobRun.id.desc()) + .first() + ) + if prior and getattr(prior, "autotask_ticket_id", None): + run.autotask_ticket_id = prior.autotask_ticket_id + run.autotask_ticket_number = prior.autotask_ticket_number + run.autotask_ticket_created_at = getattr(prior, "autotask_ticket_created_at", None) + run.autotask_ticket_created_by_user_id = getattr(prior, "autotask_ticket_created_by_user_id", None) + return + except Exception: + pass + # Strategy 2: Direct Autotask propagation (independent of internal ticket status) + # Find the most recent non-deleted Autotask ticket for this job and propagate it. + try: prior = ( JobRun.query.filter(JobRun.job_id == job.id) .filter(JobRun.autotask_ticket_id.isnot(None)) - .filter(JobRun.autotask_ticket_number == newest_code) + .filter(JobRun.autotask_ticket_deleted_at.is_(None)) .order_by(JobRun.id.desc()) .first() ) diff --git a/docs/changelog-claude.md b/docs/changelog-claude.md index e2e807c..701402a 100644 --- a/docs/changelog-claude.md +++ b/docs/changelog-claude.md @@ -2,6 +2,11 @@ This file documents all changes made to this project via Claude Code. +## [2026-02-10] + +### 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 Autotask ticket on job regardless of internal ticket status, ensuring PSA ticket reference persists across runs) + ## [2026-02-09] ### Added