| 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 |
|
|