diff --git a/packages/features/ee/billing/credit-service.ts b/packages/features/ee/billing/credit-service.ts index 4a62918c6c05fc..b1663cc3b63d96 100644 --- a/packages/features/ee/billing/credit-service.ts +++ b/packages/features/ee/billing/credit-service.ts @@ -792,6 +792,54 @@ export class CreditService { }; } + async moveCreditsFromTeamToUser({teamId , userId} : {teamId : number; userId : number}) { + return await prisma.$transaction(async (tx) => { + const teamCreditBalance = await CreditsRepository.findCreditBalance({teamId}, tx); + + if(!teamCreditBalance || teamCreditBalance.additionalCredits <= 0) { + return ; + } + + let userCreditBalance = await CreditsRepository.findCreditBalance({userId}, tx); + + if(!userCreditBalance) { + userCreditBalance = await CreditsRepository.createCreditBalance( + {userId}, + tx + ); + } + + const creditsToTransfer = teamCreditBalance.additionalCredits; + + logger.info("Moving credits from team to owner" , { + teamId, + userId, + creditsToTransfer, + }) + + await CreditsRepository.updateCreditBalance ( + { + teamId, + data : {additionalCredits : 0}, + }, + tx + ); + + await CreditsRepository.updateCreditBalance( + { + userId , + data : { + additionalCredits : { + increment : creditsToTransfer, + }, + }, + }, + tx + ); + return { creditsTransferred : creditsToTransfer }; + }); + } + async moveCreditsFromTeamToOrg({ teamId, orgId }: { teamId: number; orgId: number }) { return await prisma.$transaction(async (tx) => { // Get team's credit balance diff --git a/packages/features/ee/billing/service/teams/TeamBillingService.ts b/packages/features/ee/billing/service/teams/TeamBillingService.ts index bb6979d459cef6..8a3254403048d6 100644 --- a/packages/features/ee/billing/service/teams/TeamBillingService.ts +++ b/packages/features/ee/billing/service/teams/TeamBillingService.ts @@ -22,6 +22,8 @@ import { type TeamBillingInput, TeamBillingPublishResponseStatus, } from "./ITeamBillingService"; +import { MembershipRole } from "@calcom/prisma/enums"; +import { CreditService } from "../../credit-service" const log = logger.getSubLogger({ prefix: ["TeamBilling"] }); @@ -133,6 +135,25 @@ export class TeamBillingService implements ITeamBillingService { } async downgrade() { try { + const creditService = new CreditService(); + + const owner = await prisma.membership.findFirst({ + where : { + teamId : this.team.id, + role : MembershipRole.OWNER + }, + }); + + if(!owner) { + throw new Error(`No owner found for team ${this.team.id}`); + } + + await creditService.moveCreditsFromTeamToUser({ + teamId : this.team.id, + userId : owner.userId, + }); + + const { mergeMetadata } = getMetadataHelpers(teamPaymentMetadataSchema, this.team.metadata); const metadata = mergeMetadata({ paymentId: undefined,