Auto-commit local changes before build (2026-01-15 16:31:32)
This commit is contained in:
parent
66f5a57fe0
commit
83a29a7a3c
@ -1 +1 @@
|
|||||||
v20260115-16-autotask-ticket-create-response-fix
|
v20260115-17-autotask-ticket-create-trackingid-lookup
|
||||||
|
|||||||
@ -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})."
|
||||||
)
|
)
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user