Merge branch 'v20260203-10-autotask-resolution-field-aliases' into main

This commit is contained in:
Ivo Oskamp 2026-02-06 13:23:31 +01:00
commit 753c14bb4e
3 changed files with 46 additions and 20 deletions

View File

@ -1 +1 @@
v20260203-09-autotask-resolution-from-note
v20260203-10-autotask-resolution-field-aliases

View File

@ -584,22 +584,43 @@ class AutotaskClient:
if not isinstance(t, dict):
raise AutotaskError("Autotask did not return a ticket object.")
stabilising_fields = [
"id",
"companyID",
"queueID",
"title",
"priority",
"status",
"dueDateTime",
"ticketCategory",
"issueType",
"subIssueType",
"source",
# Some Autotask environments return slightly different field names (e.g. *ID vs *Id).
# We always source values from the fresh GET and send the canonical field names in the PUT payload.
field_sources: Dict[str, list[str]] = {
"id": ["id"],
"companyID": ["companyID", "companyId"],
"queueID": ["queueID", "queueId"],
"title": ["title"],
"priority": ["priority"],
"status": ["status"],
"dueDateTime": ["dueDateTime", "dueDate", "dueDateUtc"],
"ticketCategory": ["ticketCategory", "ticketCategoryID", "ticketCategoryId"],
"issueType": ["issueType", "issueTypeID", "issueTypeId"],
"subIssueType": ["subIssueType", "subIssueTypeID", "subIssueTypeId"],
"source": ["source", "sourceID", "sourceId"],
"organizationalLevelAssociationID": [
"organizationalLevelAssociationID",
]
"organizationalLevelAssociationId",
],
}
def _get_first(ticket_obj: Dict[str, Any], keys: list[str]) -> Any:
for k in keys:
if k in ticket_obj:
return ticket_obj.get(k)
return None
stabilising_fields = list(field_sources.keys())
resolved_values: Dict[str, Any] = {}
missing: list[str] = []
for f in stabilising_fields:
v = _get_first(t, field_sources[f])
# Treat None/"" as missing, but allow 0 for picklists.
if v in (None, ""):
missing.append(f)
resolved_values[f] = v
missing = [f for f in stabilising_fields if t.get(f) in (None, "")]
if missing:
raise AutotaskError(
"Cannot safely update ticket resolution because required fields are missing: " + ", ".join(missing)
@ -614,11 +635,10 @@ class AutotaskClient:
else:
new_res = res_txt
payload: Dict[str, Any] = {k: t.get(k) for k in stabilising_fields}
# Ensure numeric ID is an int for PUT.
payload["id"] = int(t.get("id"))
payload: Dict[str, Any] = dict(resolved_values)
payload["id"] = int(resolved_values.get("id"))
# Explicitly keep status unchanged.
payload["status"] = t.get("status")
payload["status"] = resolved_values.get("status")
payload["resolution"] = new_res
self.update_ticket(payload)

View File

@ -512,6 +512,12 @@ Changes:
- Resolution updates follow the validated safe pattern: GET the current Ticket first, then PUT with stabilising fields while keeping the status unchanged.
- Added verification to ensure the resolution text is persisted after the update.
## v20260203-10-autotask-resolution-field-aliases
- Fix: Resolution PUT now always reuses the latest classification/routing fields from GET /Tickets/{id}, including support for common field-name variants (*ID/*Id).
- Prevents failure when issueType/subIssueType/source are not present under the expected keys after ticket creation or later changes.
- Keeps ticket status unchanged while updating resolution, per validated Postman contract.
***
## v0.1.21