diff --git a/packages/features/ee/billing/api/webhook/_checkout.session.completed.ts b/packages/features/ee/billing/api/webhook/_checkout.session.completed.ts index 33a1030580..3c5c3baca5 100644 --- a/packages/features/ee/billing/api/webhook/_checkout.session.completed.ts +++ b/packages/features/ee/billing/api/webhook/_checkout.session.completed.ts @@ -1,5 +1,5 @@ import stripe from "@calcom/features/ee/payments/server/stripe"; -import prisma from "@calcom/prisma"; +import { CreditsRepository } from "@calcom/lib/server/repository/credits"; import type { SWHMap } from "./__handler"; import { HttpCode } from "./__handler"; @@ -39,31 +39,29 @@ async function saveToCreditBalance({ teamId?: number; nrOfCredits: number; }) { - const creditBalance = await prisma.creditBalance.findUnique({ - where: { - teamId, - userId: !teamId ? userId : undefined, - }, - select: { - id: true, - }, - }); + const creditBalance = await CreditsRepository.findCreditBalance({ teamId, userId }); + + let creditBalanceId = creditBalance?.id; if (creditBalance) { - await prisma.creditBalance.update({ - where: { - id: creditBalance.id, - }, + await CreditsRepository.updateCreditBalance({ + id: creditBalance.id, data: { additionalCredits: { increment: nrOfCredits }, limitReachedAt: null, warningSentAt: null }, }); - return; - } - await prisma.creditBalance.create({ - data: { + } else { + const newCreditBalance = await CreditsRepository.createCreditBalance({ teamId: teamId, userId: !teamId ? userId : undefined, additionalCredits: nrOfCredits, - }, - }); + }); + creditBalanceId = newCreditBalance.id; + } + + if (creditBalanceId) { + await CreditsRepository.createCreditPurchaseLog({ + credits: nrOfCredits, + creditBalanceId, + }); + } } export default handler; diff --git a/packages/lib/server/repository/credits.ts b/packages/lib/server/repository/credits.ts index 102dbafed6..87df1a6517 100644 --- a/packages/lib/server/repository/credits.ts +++ b/packages/lib/server/repository/credits.ts @@ -174,4 +174,15 @@ export class CreditsRepository { data, }); } + + static async createCreditPurchaseLog(data: { credits: number; creditBalanceId: string }) { + const { credits, creditBalanceId } = data; + + return prisma.creditPurchaseLog.create({ + data: { + credits, + creditBalanceId, + }, + }); + } } diff --git a/packages/prisma/migrations/20250611112835_add_credit_purchase_log/migration.sql b/packages/prisma/migrations/20250611112835_add_credit_purchase_log/migration.sql new file mode 100644 index 0000000000..b688507563 --- /dev/null +++ b/packages/prisma/migrations/20250611112835_add_credit_purchase_log/migration.sql @@ -0,0 +1,12 @@ +-- CreateTable +CREATE TABLE "CreditPurchaseLog" ( + "id" TEXT NOT NULL, + "creditBalanceId" TEXT NOT NULL, + "credits" INTEGER NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "CreditPurchaseLog_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "CreditPurchaseLog" ADD CONSTRAINT "CreditPurchaseLog_creditBalanceId_fkey" FOREIGN KEY ("creditBalanceId") REFERENCES "CreditBalance"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index 2ca3583cc5..1006b7c6d8 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -539,16 +539,25 @@ model Team { } model CreditBalance { - id String @id @default(uuid()) - team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade) - teamId Int? @unique + id String @id @default(uuid()) + team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade) + teamId Int? @unique // user credit balances will be supported in the future - user User? @relation(fields: [userId], references: [id], onDelete: Cascade) - userId Int? @unique - additionalCredits Int @default(0) + user User? @relation(fields: [userId], references: [id], onDelete: Cascade) + userId Int? @unique + additionalCredits Int @default(0) limitReachedAt DateTime? warningSentAt DateTime? expenseLogs CreditExpenseLog[] + purchaseLogs CreditPurchaseLog[] +} + +model CreditPurchaseLog { + id String @id @default(uuid()) + creditBalanceId String + creditBalance CreditBalance @relation(fields: [creditBalanceId], references: [id], onDelete: Cascade) + credits Int + createdAt DateTime @default(now()) } model CreditExpenseLog {