import { getApproximateQuotaBucket, type QuotaBucket } from "@nproxy/domain"; import type { PrismaClient, SubscriptionStatus } from "@prisma/client"; import { Prisma } from "@prisma/client"; import { prisma as defaultPrisma } from "./prisma-client.js"; import { reconcileElapsedSubscription } from "./subscription-lifecycle.js"; export interface UserAccountOverview { user: { id: string; email: string; isAdmin: boolean; createdAt: Date; }; subscription: { id: string; status: SubscriptionStatus; renewsManually: boolean; activatedAt?: Date; currentPeriodStart?: Date; currentPeriodEnd?: Date; canceledAt?: Date; plan: { id: string; code: string; displayName: string; monthlyPriceUsd: number; billingCurrency: string; isActive: boolean; }; } | null; quota: { approximateBucket: QuotaBucket; } | null; } export function createPrismaAccountStore(database: PrismaClient = defaultPrisma) { return { async getUserAccountOverview(userId: string): Promise { const user = await database.user.findUnique({ where: { id: userId, }, }); if (!user) { return null; } const subscription = await database.subscription.findFirst({ where: { userId, }, include: { plan: true, }, orderBy: [ { currentPeriodEnd: "desc" }, { createdAt: "desc" }, ], }); const currentSubscription = await reconcileElapsedSubscription(database, subscription, { reload: async () => database.subscription.findFirst({ where: { userId, }, include: { plan: true, }, orderBy: [{ currentPeriodEnd: "desc" }, { createdAt: "desc" }], }), }); const quota = currentSubscription?.status === "active" ? await buildQuotaSnapshot(database, userId, { monthlyRequestLimit: currentSubscription.plan.monthlyRequestLimit, cycleStart: currentSubscription.currentPeriodStart ?? currentSubscription.activatedAt ?? currentSubscription.createdAt, }) : null; return { user: { id: user.id, email: user.email, isAdmin: user.isAdmin, createdAt: user.createdAt, }, subscription: currentSubscription ? { id: currentSubscription.id, status: currentSubscription.status, renewsManually: currentSubscription.renewsManually, ...(currentSubscription.activatedAt ? { activatedAt: currentSubscription.activatedAt } : {}), ...(currentSubscription.currentPeriodStart ? { currentPeriodStart: currentSubscription.currentPeriodStart } : {}), ...(currentSubscription.currentPeriodEnd ? { currentPeriodEnd: currentSubscription.currentPeriodEnd } : {}), ...(currentSubscription.canceledAt ? { canceledAt: currentSubscription.canceledAt } : {}), plan: { id: currentSubscription.plan.id, code: currentSubscription.plan.code, displayName: currentSubscription.plan.displayName, monthlyPriceUsd: decimalToNumber(currentSubscription.plan.monthlyPriceUsd), billingCurrency: currentSubscription.plan.billingCurrency, isActive: currentSubscription.plan.isActive, }, } : null, quota, }; }, }; } function decimalToNumber(value: Prisma.Decimal | { toNumber(): number }): number { return value.toNumber(); } async function buildQuotaSnapshot( database: PrismaClient, userId: string, input: { monthlyRequestLimit: number; cycleStart: Date; }, ): Promise { const usageAggregation = await database.usageLedgerEntry.aggregate({ where: { userId, entryType: "generation_success", createdAt: { gte: input.cycleStart, }, }, _sum: { deltaRequests: true, }, }); const usedSuccessfulRequests = usageAggregation._sum.deltaRequests ?? 0; return { approximateBucket: getApproximateQuotaBucket({ used: usedSuccessfulRequests, limit: input.monthlyRequestLimit, }), }; }