Files
socaichat/backend/app/api/tickets.py
T
gongzhiyongandClaude Opus 4.6 efb3c53623 feat: add backend service and Azure deployment workflow
- Add complete Python backend (Litestar + LangGraph) with chat, conversations, tickets APIs
- Add GitHub Actions workflow for auto-deploying backend to Azure Web App (soc-backend)
- Add gunicorn to requirements.txt for production serving
- Update CLAUDE.md and EXTERNAL_SERVICES.md with latest config
- Remove obsolete claudehd.md (merged into gpthd.md)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 13:31:00 +08:00

81 lines
2.4 KiB
Python

"""Ticket API endpoints — proxy to Gongdan system.
Returns data in a format aligned with the frontend TicketData interface:
{ id, title, status, priority, createdAt }
"""
from __future__ import annotations
import httpx
from litestar import get
from litestar.exceptions import NotFoundException
from app.config import settings
def _gongdan_headers() -> dict[str, str]:
return {"X-Api-Key": settings.gongdan_api_key}
def _map_status(raw: str) -> str:
mapping = {
"OPEN": "pending",
"ASSIGNED": "processing",
"IN_PROGRESS": "processing",
"PENDING_CUSTOMER": "processing",
"RESOLVED": "resolved",
"CLOSED": "resolved",
}
return mapping.get(raw, "pending")
def _map_priority(raw: str) -> str:
mapping = {
"URGENT": "P0",
"PRIORITY": "P1",
"NORMAL": "P2",
"LOW": "P3",
}
return mapping.get(raw, "P2")
def _transform_ticket(t: dict) -> dict:
"""Transform a Gongdan ticket to the frontend TicketData shape."""
return {
"id": t.get("ticketNumber", t.get("id", "")),
"title": t.get("description", "")[:120] or "No description",
"status": _map_status(t.get("status", "")),
"priority": _map_priority(t.get("priority", "")),
"createdAt": t.get("createdAt", ""),
}
@get("/api/tickets")
async def list_tickets(page: int = 1, page_size: int = 20) -> list[dict]:
"""GET /api/tickets — List tickets from Gongdan, formatted for frontend."""
url = f"{settings.gongdan_api_base}/api/tickets"
params = {"page": page, "pageSize": page_size}
async with httpx.AsyncClient(timeout=15) as client:
resp = await client.get(url, params=params, headers=_gongdan_headers())
resp.raise_for_status()
data = resp.json()
tickets = data.get("tickets", [])
return [_transform_ticket(t) for t in tickets]
@get("/api/tickets/{ticket_id:str}")
async def get_ticket(ticket_id: str) -> dict:
"""GET /api/tickets/:id — Get a single ticket detail."""
url = f"{settings.gongdan_api_base}/api/tickets/{ticket_id}"
async with httpx.AsyncClient(timeout=15) as client:
resp = await client.get(url, headers=_gongdan_headers())
if resp.status_code == 404:
raise NotFoundException(detail=f"Ticket {ticket_id} not found")
resp.raise_for_status()
t = resp.json()
return _transform_ticket(t)