Auto-commit local changes before build (2026-02-03 16:17:17)

This commit is contained in:
Ivo Oskamp 2026-02-03 16:17:17 +01:00
parent 494f792c0d
commit 04f6041fe6
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): if not isinstance(t, dict):
raise AutotaskError("Autotask did not return a ticket object.") raise AutotaskError("Autotask did not return a ticket object.")
stabilising_fields = [ # Some Autotask environments return slightly different field names (e.g. *ID vs *Id).
"id", # We always source values from the fresh GET and send the canonical field names in the PUT payload.
"companyID", field_sources: Dict[str, list[str]] = {
"queueID", "id": ["id"],
"title", "companyID": ["companyID", "companyId"],
"priority", "queueID": ["queueID", "queueId"],
"status", "title": ["title"],
"dueDateTime", "priority": ["priority"],
"ticketCategory", "status": ["status"],
"issueType", "dueDateTime": ["dueDateTime", "dueDate", "dueDateUtc"],
"subIssueType", "ticketCategory": ["ticketCategory", "ticketCategoryID", "ticketCategoryId"],
"source", "issueType": ["issueType", "issueTypeID", "issueTypeId"],
"subIssueType": ["subIssueType", "subIssueTypeID", "subIssueTypeId"],
"source": ["source", "sourceID", "sourceId"],
"organizationalLevelAssociationID": [
"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: if missing:
raise AutotaskError( raise AutotaskError(
"Cannot safely update ticket resolution because required fields are missing: " + ", ".join(missing) "Cannot safely update ticket resolution because required fields are missing: " + ", ".join(missing)
@ -614,11 +635,10 @@ class AutotaskClient:
else: else:
new_res = res_txt new_res = res_txt
payload: Dict[str, Any] = {k: t.get(k) for k in stabilising_fields} payload: Dict[str, Any] = dict(resolved_values)
# Ensure numeric ID is an int for PUT. payload["id"] = int(resolved_values.get("id"))
payload["id"] = int(t.get("id"))
# Explicitly keep status unchanged. # Explicitly keep status unchanged.
payload["status"] = t.get("status") payload["status"] = resolved_values.get("status")
payload["resolution"] = new_res payload["resolution"] = new_res
self.update_ticket(payload) 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. - 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. - 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 ## v0.1.21