from __future__ import annotations import asyncio import json from sqlalchemy import text from app.models.base import async_session from app.services.credit.utils import utc_now async def amain() -> int: async with async_session() as db: rows = (await db.execute(text(""" SELECT e.id, e.total_call_count, e.successful_call_count, e.failed_call_count, e.total_input_tokens, e.total_output_tokens, e.total_tokens, COUNT(a.id) AS actual_calls, COALESCE(SUM(CASE WHEN a.status = 'succeeded' THEN 1 ELSE 0 END), 0) AS actual_success, COALESCE(SUM(CASE WHEN a.status IN ('failed','timeout','unknown') THEN 1 ELSE 0 END), 0) AS actual_failed, COALESCE(SUM(a.input_tokens), 0) AS actual_input, COALESCE(SUM(a.output_tokens), 0) AS actual_output, COALESCE(SUM(a.total_tokens), 0) AS actual_total FROM llm_billing_executions e LEFT JOIN llm_call_attempts a ON a.billing_execution_id = e.id GROUP BY e.id HAVING e.total_call_count <> COUNT(a.id) OR e.successful_call_count <> COALESCE(SUM(CASE WHEN a.status = 'succeeded' THEN 1 ELSE 0 END), 0) OR e.failed_call_count <> COALESCE(SUM(CASE WHEN a.status IN ('failed','timeout','unknown') THEN 1 ELSE 0 END), 0) OR e.total_tokens <> COALESCE(SUM(a.total_tokens), 0) ORDER BY e.id LIMIT 1000 """))).mappings().all() print(json.dumps({"checked_at": utc_now().isoformat(), "mismatch_count": len(rows), "items": [dict(r) for r in rows]}, ensure_ascii=False, indent=2, default=str)) return 0 if not rows else 2 if __name__ == "__main__": raise SystemExit(asyncio.run(amain()))