From 0c9cf21d5db16d0566b36e3e36c4f36e578d77ce Mon Sep 17 00:00:00 2001 From: Ivo Oskamp Date: Thu, 5 Feb 2026 15:56:55 +0100 Subject: [PATCH] Fix Autotask resolution update for tickets with unset classification fields For picklist fields (issueType, subIssueType, source), use 0 as default when fields are null/missing in GET response. Value 0 is valid in Autotask and means "not set". Only id and status are truly required with real values. Co-Authored-By: Claude Opus 4.5 --- .../app/integrations/autotask/client.py | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/containers/backupchecks/src/backend/app/integrations/autotask/client.py b/containers/backupchecks/src/backend/app/integrations/autotask/client.py index 3a02e6b..1146b7d 100644 --- a/containers/backupchecks/src/backend/app/integrations/autotask/client.py +++ b/containers/backupchecks/src/backend/app/integrations/autotask/client.py @@ -597,27 +597,30 @@ class AutotaskClient: if not isinstance(ticket, dict) or not ticket: raise AutotaskError("Autotask did not return a ticket object.") - def _pick(d: Dict[str, Any], keys: List[str]) -> Any: + def _pick(d: Dict[str, Any], keys: List[str], default: Any = None) -> Any: + """Pick first available value from possible field names. + + Note: 0 is a valid Autotask picklist value, so we only skip None and empty string. + Returns default if no value is found. + """ for k in keys: if k in d and d.get(k) not in (None, ""): return d.get(k) - return None + return default - # Required stabilising fields for safe resolution updates (validated via Postman tests) - resolved_issue_type = _pick(ticket, ["issueType", "issueTypeID", "issueTypeId"]) - resolved_sub_issue_type = _pick(ticket, ["subIssueType", "subIssueTypeID", "subIssueTypeId"]) - resolved_source = _pick(ticket, ["source", "sourceID", "sourceId"]) - resolved_status = _pick(ticket, ["status", "statusID", "statusId"]) + # Required stabilising fields for safe resolution updates (validated via Postman tests). + # Field names are camelCase as per API contract (docs/autotask_rest_api.md section 2.1). + # For picklist fields (issueType, subIssueType, source), 0 is valid and means "not set". + # If these fields are null/missing in the GET response, we default to 0 for the PUT payload. + resolved_issue_type = _pick(ticket, ["issueType"], default=0) + resolved_sub_issue_type = _pick(ticket, ["subIssueType"], default=0) + resolved_source = _pick(ticket, ["source"], default=0) + resolved_status = _pick(ticket, ["status"]) + # Only id and status are truly required (must have real values) missing: List[str] = [] if _pick(ticket, ["id"]) in (None, ""): missing.append("id") - if resolved_issue_type in (None, ""): - missing.append("issueType") - if resolved_sub_issue_type in (None, ""): - missing.append("subIssueType") - if resolved_source in (None, ""): - missing.append("source") if resolved_status in (None, ""): missing.append("status")