Auto-commit local changes before build (2026-01-15 16:31:32)

This commit is contained in:
Ivo Oskamp 2026-01-15 16:31:32 +01:00
parent 66f5a57fe0
commit 83a29a7a3c
3 changed files with 72 additions and 2 deletions

View File

@ -1 +1 @@
v20260115-16-autotask-ticket-create-response-fix v20260115-17-autotask-ticket-create-trackingid-lookup

View File

@ -426,6 +426,51 @@ class AutotaskClient:
return data return data
raise AutotaskError("Autotask did not return a ticket object.") raise AutotaskError("Autotask did not return a ticket object.")
def _lookup_created_ticket_id(
self,
tracking_identifier: str,
company_id: Optional[int] = None,
) -> Optional[int]:
"""Lookup the most recently created ticket by tracking identifier.
Some Autotask tenants return an empty body and omit Location headers on
successful POST /Tickets calls. In that case, we must lookup the created
ticket deterministically via query.
We prefer filtering by CompanyID when available to reduce ambiguity.
"""
tid = (tracking_identifier or "").strip()
if not tid:
return None
filters: List[Dict[str, Any]] = [
{"op": "eq", "field": "TrackingIdentifier", "value": tid},
]
if isinstance(company_id, int) and company_id > 0:
filters.append({"op": "eq", "field": "CompanyID", "value": int(company_id)})
# Order by createDate desc when supported; fall back to id desc.
search_payload: Dict[str, Any] = {
"filter": filters,
"maxRecords": 1,
"orderby": [
{"field": "createDate", "direction": "desc"},
{"field": "id", "direction": "desc"},
],
}
params = {"search": json.dumps(search_payload)}
data = self._request("GET", "Tickets/query", params=params)
items = self._as_items_list(data)
if not items:
return None
first = items[0]
if isinstance(first, dict) and str(first.get("id") or "").isdigit():
return int(first["id"])
return None
def create_ticket(self, payload: Dict[str, Any]) -> Dict[str, Any]: def create_ticket(self, payload: Dict[str, Any]) -> Dict[str, Any]:
"""Create a Ticket in Autotask. """Create a Ticket in Autotask.
@ -485,11 +530,30 @@ class AutotaskClient:
if ticket_id is not None: if ticket_id is not None:
return self.get_ticket(ticket_id) return self.get_ticket(ticket_id)
# Deterministic fallback: query by tracking identifier (+ company) if present.
tracking_identifier = (
payload.get("trackingIdentifier")
or payload.get("TrackingIdentifier")
or ""
)
company_id: Optional[int] = None
for ck in ("companyID", "companyId", "CompanyID"):
if str(payload.get(ck) or "").isdigit():
company_id = int(payload[ck])
break
looked_up_id = self._lookup_created_ticket_id(str(tracking_identifier), company_id=company_id)
if looked_up_id is not None:
return self.get_ticket(looked_up_id)
# Last-resort fallback: normalize first item if possible. # Last-resort fallback: normalize first item if possible.
items = self._as_items_list(data) items = self._as_items_list(data)
if items: if items:
return items[0] return items[0]
raise AutotaskError( raise AutotaskError(
f"Autotask did not return a created ticket object (HTTP {resp.status_code})." "Autotask did not return a ticket id. "
"Ticket creation may still have succeeded; configure ticket TrackingIdentifier to be unique per run "
"to allow deterministic lookup. "
f"(HTTP {resp.status_code})."
) )

View File

@ -117,6 +117,12 @@ Changes:
- Added support for extracting the created ticket ID from itemId/id fields and from the Location header. - Added support for extracting the created ticket ID from itemId/id fields and from the Location header.
- Added a follow-up GET /Tickets/{id} to always retrieve the full created ticket object (ensuring ticketNumber/id are available). - Added a follow-up GET /Tickets/{id} to always retrieve the full created ticket object (ensuring ticketNumber/id are available).
## v20260115-17-autotask-ticket-create-trackingid-lookup
- Reworked Autotask ticket creation flow to no longer rely on POST /Tickets response data for returning an ID.
- Added deterministic fallback lookup using Tickets/query filtered by TrackingIdentifier (and CompanyID when available).
- Ensured the created ticket is reliably retrieved via follow-up GET /Tickets/{id} so ticketNumber/id can always be stored.
- Eliminated false-negative ticket creation errors when Autotask returns an empty body and no Location header.
*** ***
## v0.1.21 ## v0.1.21