acra-api / credits.py
Nottybro's picture
deploy: credits.py
cc6f383 verified
from fastapi import HTTPException
from db import supabase
from datetime import datetime, timezone
PLAN_CREDITS = {"free": 100, "hobby": 5_000, "team": 25_000,
"business": 100_000, "enterprise": 999_999_999}
async def check_and_deduct_credits(user_id: str, cost: int) -> int:
res = (supabase.table("users")
.select("credits_remaining,plan,credits_reset_at")
.eq("id", user_id).single().execute())
user = res.data
if not user: raise HTTPException(404, "User not found")
if user["plan"] == "free":
reset = datetime.fromisoformat(user["credits_reset_at"])
now = datetime.now(timezone.utc)
if now > reset:
supabase.table("users").update({
"credits_remaining": PLAN_CREDITS["free"],
"credits_reset_at": now.replace(hour=0,minute=0,second=0).isoformat()
}).eq("id", user_id).execute()
user["credits_remaining"] = PLAN_CREDITS["free"]
if user["credits_remaining"] < cost:
raise HTTPException(429, {
"error": "Out of credits", "plan": user["plan"],
"credits_remaining": user["credits_remaining"],
"upgrade_url": "https://nurricai.com/pricing"})
new_bal = user["credits_remaining"] - cost
supabase.table("users").update({"credits_remaining": new_bal}).eq("id", user_id).execute()
supabase.table("usage_logs").insert({
"user_id": user_id, "credits_used": cost,
"timestamp": datetime.now(timezone.utc).isoformat()
}).execute()
return new_bal