diff --git a/dashboard_api_rev.py b/dashboard_api_rev.py index c9d5d57..b21dd1e 100644 --- a/dashboard_api_rev.py +++ b/dashboard_api_rev.py @@ -368,6 +368,63 @@ def inc_dashboard( ) +# ── INC ticket explorer (search) ────────────────────────────────────────────── +# Thin passthrough over reporting.fn_inc_search (fleettickets migration 13): ad-hoc +# ticket lookup by id / engineer / cluster / status / state / time, for historical + +# current tracking. Returns { count, truncated, limit, state, rows }. +_INC_STATES = {"open", "closed", "all"} + + +@app.get("/webhook/inc-search") +def inc_search( + ticket_id: str | None = None, # substring match on ticket_id + owner: str | None = None, # engineer — case-insensitive substring on owner + cluster: str | None = None, # exact tickets.inc.cluster + status: str | None = None, # exact normalized_status + state: str = "closed", # closed | open | all + from_: str | None = Query(None, alias="from"), # closed-at range start (ISO-8601) + to: str | None = None, # closed-at range end (exclusive, ISO-8601) +): + state = (state or "closed").lower() + if state not in _INC_STATES: + return _bad_request("state must be one of open|closed|all") + f, t = _clean(from_), _clean(to) + + def _parse(v): + if not v: + return None + try: + return datetime.fromisoformat(v) + except ValueError: + return False + + pf, pt = _parse(f), _parse(t) + if pf is False or pt is False: + return _bad_request("from/to must be ISO-8601 timestamps with an offset/Z") + if pf and pt and pf >= pt: + return _bad_request("from must be earlier than to") + + try: + with get_conn() as conn: + with conn.cursor() as cur: + cur.execute( + "SELECT reporting.fn_inc_search(%s, %s, %s, %s, %s, %s, %s)", + (_clean(ticket_id), _clean(owner), _clean(cluster), _clean(status), state, f, t), + ) + payload = cur.fetchone()[0] or {} + return JSONResponse(payload) # jsonb body returned unchanged + except Exception: + log.exception("inc-search failed") + return JSONResponse( + { + "error": { + "type": "unknown", + "message": "Ticket search is unavailable. Try again in a few seconds.", + } + } + ) + + # ── Fleet trips (#002) ─────────────────────────────────────────────────────── _FILTER_OPTIONS_SQL = """