전 저장소 리팩터링과 SSOT 정비
This commit is contained in:
parent
14ecbd4e7d
commit
3dfddcac6f
173 changed files with 19679 additions and 6952 deletions
|
|
@ -51,6 +51,70 @@ TicketPriority = Literal["low", "normal", "high", "urgent"]
|
|||
TicketStatus = Literal["open", "triaged", "in_progress", "resolved", "closed"]
|
||||
NotificationDeliveryStatus = Literal["queued", "sending", "sent", "failed", "skipped"]
|
||||
|
||||
METERED_CLIENT_TURN_FILTER_SQL = """
|
||||
speaker = 'client'
|
||||
AND (
|
||||
llm_provider IS NOT NULL OR model IS NOT NULL
|
||||
OR tokens_in IS NOT NULL OR tokens_out IS NOT NULL
|
||||
OR cost_usd IS NOT NULL
|
||||
)
|
||||
"""
|
||||
|
||||
USAGE_AGGREGATE_COLUMNS_SQL = """
|
||||
COUNT(*) AS turns,
|
||||
COALESCE(SUM(tokens_in), 0)::bigint AS tokens_in,
|
||||
COALESCE(SUM(tokens_out), 0)::bigint AS tokens_out,
|
||||
COALESCE(SUM(cost_usd), 0)::numeric AS cost_usd
|
||||
"""
|
||||
|
||||
SUPPORT_TICKET_DETAIL_FROM_SQL = """
|
||||
SELECT
|
||||
t.id,
|
||||
t.reporter_id,
|
||||
t.reporter_email,
|
||||
t.reporter_name,
|
||||
t.reporter_role,
|
||||
t.category,
|
||||
t.priority,
|
||||
t.status,
|
||||
t.subject,
|
||||
t.body,
|
||||
t.source_path,
|
||||
t.fingerprint,
|
||||
t.parent_ticket_id,
|
||||
t.assigned_group,
|
||||
t.resolution_note,
|
||||
t.created_at,
|
||||
t.updated_at,
|
||||
t.resolved_at,
|
||||
COALESCE(dup.duplicate_count, 0) AS duplicate_count,
|
||||
dup.parent_candidate_id AS duplicate_parent_candidate_id,
|
||||
COALESCE(child.child_ticket_count, 0) AS child_ticket_count,
|
||||
COALESCE(ev.event_count, 0) AS event_count,
|
||||
ev.last_event_at
|
||||
FROM app.support_ticket AS t
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT
|
||||
count(*) FILTER (WHERE id <> t.id)::int AS duplicate_count,
|
||||
(array_agg(id::text ORDER BY created_at ASC, id ASC))[1] AS parent_candidate_id
|
||||
FROM app.support_ticket
|
||||
WHERE fingerprint <> ''
|
||||
AND fingerprint = t.fingerprint
|
||||
) AS dup ON TRUE
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT count(*)::int AS child_ticket_count
|
||||
FROM app.support_ticket
|
||||
WHERE parent_ticket_id = t.id
|
||||
) AS child ON TRUE
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT count(*)::int AS event_count, max(created_at) AS last_event_at
|
||||
FROM audit.audit_log
|
||||
WHERE action = 'support_ticket_update'
|
||||
AND target_kind = 'support_ticket'
|
||||
AND target_id = t.id::text
|
||||
) AS ev ON TRUE
|
||||
"""
|
||||
|
||||
|
||||
class AdminServiceHealth(BaseModel):
|
||||
key: str
|
||||
|
|
@ -450,17 +514,10 @@ async def _runtime_health_metrics(*, db_ok: bool) -> RuntimeHealthMetrics:
|
|||
async def _usage_from_database(window_days: int) -> AdminUsageResponse:
|
||||
async with acquire(role="admin") as conn:
|
||||
total_row = await conn.fetchrow(
|
||||
"""
|
||||
f"""
|
||||
SELECT
|
||||
COUNT(*) FILTER (WHERE speaker = 'client') AS total_turns,
|
||||
COUNT(*) FILTER (
|
||||
WHERE speaker = 'client'
|
||||
AND (
|
||||
llm_provider IS NOT NULL OR model IS NOT NULL
|
||||
OR tokens_in IS NOT NULL OR tokens_out IS NOT NULL
|
||||
OR cost_usd IS NOT NULL
|
||||
)
|
||||
) AS metered_turns,
|
||||
COUNT(*) FILTER (WHERE {METERED_CLIENT_TURN_FILTER_SQL}) AS metered_turns,
|
||||
COALESCE(SUM(tokens_in) FILTER (WHERE speaker = 'client'), 0)::bigint AS tokens_in,
|
||||
COALESCE(SUM(tokens_out) FILTER (WHERE speaker = 'client'), 0)::bigint AS tokens_out,
|
||||
COALESCE(SUM(cost_usd) FILTER (WHERE speaker = 'client'), 0)::numeric AS cost_usd
|
||||
|
|
@ -470,22 +527,14 @@ async def _usage_from_database(window_days: int) -> AdminUsageResponse:
|
|||
window_days,
|
||||
)
|
||||
rows = await conn.fetch(
|
||||
"""
|
||||
f"""
|
||||
SELECT
|
||||
COALESCE(llm_provider, 'unknown') AS provider,
|
||||
COALESCE(model, 'unknown') AS model,
|
||||
COUNT(*) AS turns,
|
||||
COALESCE(SUM(tokens_in), 0)::bigint AS tokens_in,
|
||||
COALESCE(SUM(tokens_out), 0)::bigint AS tokens_out,
|
||||
COALESCE(SUM(cost_usd), 0)::numeric AS cost_usd
|
||||
{USAGE_AGGREGATE_COLUMNS_SQL}
|
||||
FROM app.turns
|
||||
WHERE created_at >= now() - ($1::int * interval '1 day')
|
||||
AND speaker = 'client'
|
||||
AND (
|
||||
llm_provider IS NOT NULL OR model IS NOT NULL
|
||||
OR tokens_in IS NOT NULL OR tokens_out IS NOT NULL
|
||||
OR cost_usd IS NOT NULL
|
||||
)
|
||||
AND {METERED_CLIENT_TURN_FILTER_SQL}
|
||||
GROUP BY 1, 2
|
||||
ORDER BY
|
||||
cost_usd DESC,
|
||||
|
|
@ -496,21 +545,13 @@ async def _usage_from_database(window_days: int) -> AdminUsageResponse:
|
|||
window_days,
|
||||
)
|
||||
daily_rows = await conn.fetch(
|
||||
"""
|
||||
f"""
|
||||
SELECT
|
||||
to_char(date_trunc('day', created_at), 'YYYY-MM-DD') AS day,
|
||||
COUNT(*) AS turns,
|
||||
COALESCE(SUM(tokens_in), 0)::bigint AS tokens_in,
|
||||
COALESCE(SUM(tokens_out), 0)::bigint AS tokens_out,
|
||||
COALESCE(SUM(cost_usd), 0)::numeric AS cost_usd
|
||||
{USAGE_AGGREGATE_COLUMNS_SQL}
|
||||
FROM app.turns
|
||||
WHERE created_at >= now() - ($1::int * interval '1 day')
|
||||
AND speaker = 'client'
|
||||
AND (
|
||||
llm_provider IS NOT NULL OR model IS NOT NULL
|
||||
OR tokens_in IS NOT NULL OR tokens_out IS NOT NULL
|
||||
OR cost_usd IS NOT NULL
|
||||
)
|
||||
AND {METERED_CLIENT_TURN_FILTER_SQL}
|
||||
GROUP BY 1
|
||||
ORDER BY 1
|
||||
""",
|
||||
|
|
@ -761,52 +802,8 @@ async def _tickets_from_database(
|
|||
search_filter = search.strip().lower()
|
||||
async with acquire(role="admin") as conn:
|
||||
rows = await conn.fetch(
|
||||
"""
|
||||
SELECT
|
||||
t.id,
|
||||
t.reporter_id,
|
||||
t.reporter_email,
|
||||
t.reporter_name,
|
||||
t.reporter_role,
|
||||
t.category,
|
||||
t.priority,
|
||||
t.status,
|
||||
t.subject,
|
||||
t.body,
|
||||
t.source_path,
|
||||
t.fingerprint,
|
||||
t.parent_ticket_id,
|
||||
t.assigned_group,
|
||||
t.resolution_note,
|
||||
t.created_at,
|
||||
t.updated_at,
|
||||
t.resolved_at,
|
||||
COALESCE(dup.duplicate_count, 0) AS duplicate_count,
|
||||
dup.parent_candidate_id AS duplicate_parent_candidate_id,
|
||||
COALESCE(child.child_ticket_count, 0) AS child_ticket_count,
|
||||
COALESCE(ev.event_count, 0) AS event_count,
|
||||
ev.last_event_at
|
||||
FROM app.support_ticket AS t
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT
|
||||
count(*) FILTER (WHERE id <> t.id)::int AS duplicate_count,
|
||||
(array_agg(id::text ORDER BY created_at ASC, id ASC))[1] AS parent_candidate_id
|
||||
FROM app.support_ticket
|
||||
WHERE fingerprint <> ''
|
||||
AND fingerprint = t.fingerprint
|
||||
) AS dup ON TRUE
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT count(*)::int AS child_ticket_count
|
||||
FROM app.support_ticket
|
||||
WHERE parent_ticket_id = t.id
|
||||
) AS child ON TRUE
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT count(*)::int AS event_count, max(created_at) AS last_event_at
|
||||
FROM audit.audit_log
|
||||
WHERE action = 'support_ticket_update'
|
||||
AND target_kind = 'support_ticket'
|
||||
AND target_id = t.id::text
|
||||
) AS ev ON TRUE
|
||||
SUPPORT_TICKET_DETAIL_FROM_SQL
|
||||
+ """
|
||||
WHERE ($1::text IS NULL OR status = $1)
|
||||
AND ($2::text IS NULL OR category = $2)
|
||||
AND ($3::text IS NULL OR priority = $3)
|
||||
|
|
@ -1736,54 +1733,7 @@ async def patch_ticket(
|
|||
detail=detail,
|
||||
)
|
||||
row = await conn.fetchrow(
|
||||
"""
|
||||
SELECT
|
||||
t.id,
|
||||
t.reporter_id,
|
||||
t.reporter_email,
|
||||
t.reporter_name,
|
||||
t.reporter_role,
|
||||
t.category,
|
||||
t.priority,
|
||||
t.status,
|
||||
t.subject,
|
||||
t.body,
|
||||
t.source_path,
|
||||
t.fingerprint,
|
||||
t.parent_ticket_id,
|
||||
t.assigned_group,
|
||||
t.resolution_note,
|
||||
t.created_at,
|
||||
t.updated_at,
|
||||
t.resolved_at,
|
||||
COALESCE(dup.duplicate_count, 0) AS duplicate_count,
|
||||
dup.parent_candidate_id AS duplicate_parent_candidate_id,
|
||||
COALESCE(child.child_ticket_count, 0) AS child_ticket_count,
|
||||
COALESCE(ev.event_count, 0) AS event_count,
|
||||
ev.last_event_at
|
||||
FROM app.support_ticket AS t
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT
|
||||
count(*) FILTER (WHERE id <> t.id)::int AS duplicate_count,
|
||||
(array_agg(id::text ORDER BY created_at ASC, id ASC))[1] AS parent_candidate_id
|
||||
FROM app.support_ticket
|
||||
WHERE fingerprint <> ''
|
||||
AND fingerprint = t.fingerprint
|
||||
) AS dup ON TRUE
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT count(*)::int AS child_ticket_count
|
||||
FROM app.support_ticket
|
||||
WHERE parent_ticket_id = t.id
|
||||
) AS child ON TRUE
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT count(*)::int AS event_count, max(created_at) AS last_event_at
|
||||
FROM audit.audit_log
|
||||
WHERE action = 'support_ticket_update'
|
||||
AND target_kind = 'support_ticket'
|
||||
AND target_id = t.id::text
|
||||
) AS ev ON TRUE
|
||||
WHERE t.id = $1::uuid
|
||||
""",
|
||||
SUPPORT_TICKET_DETAIL_FROM_SQL + " WHERE t.id = $1::uuid",
|
||||
ticket_id,
|
||||
)
|
||||
except Exception as exc:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue