Files
video-gen/video-gen-api/app/cmd/reconcile_user_credits.py
2026-08-11 09:24:18 +08:00

40 lines
1.6 KiB
Python

from __future__ import annotations
import asyncio
import json
from decimal import Decimal
from sqlalchemy import text
from app.models.base import async_session
from app.services.credit.utils import utc_now
async def amain() -> int:
checked_at = utc_now()
async with async_session() as db:
row = (await db.execute(text("""
SELECT
COALESCE(SUM(CASE WHEN credits > 0 THEN credits ELSE 0 END), 0) AS legacy_positive,
COALESCE((SELECT SUM(grant_amount) FROM user_credit_balances WHERE source_type = 'legacy_migration'), 0) AS migrated_grant,
COALESCE((SELECT SUM(unspent_amount) FROM user_credit_balances WHERE source_type = 'legacy_migration'), 0) AS migrated_unspent,
COALESCE((SELECT COUNT(*) FROM users WHERE credits < 0), 0) AS legacy_negative_users
FROM users
"""))).mappings().one()
legacy = Decimal(str(row["legacy_positive"] or 0)).quantize(Decimal("0.01"))
migrated = Decimal(str(row["migrated_grant"] or 0)).quantize(Decimal("0.01"))
output = {
"checked_at": checked_at.isoformat(),
"legacy_positive": str(legacy),
"migrated_grant": str(migrated),
"migrated_unspent": str(Decimal(str(row["migrated_unspent"] or 0)).quantize(Decimal("0.01"))),
"legacy_negative_users_reset_to_zero": int(row["legacy_negative_users"] or 0),
"matched": legacy == migrated,
}
print(json.dumps(output, ensure_ascii=False, indent=2))
return 0 if output["matched"] else 2
if __name__ == "__main__":
raise SystemExit(asyncio.run(amain()))