diff --git a/apps/web/modules/settings/platform/billing/billing-view.tsx b/apps/web/modules/settings/platform/billing/billing-view.tsx index 4d2f2d1a87..5d589f3949 100644 --- a/apps/web/modules/settings/platform/billing/billing-view.tsx +++ b/apps/web/modules/settings/platform/billing/billing-view.tsx @@ -30,16 +30,18 @@ declare global { export default function PlatformBillingUpgrade() { const pathname = usePathname(); const { t } = useLocale(); + const { isUserLoading, isUserBillingDataLoading, isPlatformUser, userBillingData, isPaidUser, userOrgId } = + useGetUserAttributes(); + const returnTo = pathname; - const billingHref = `/api/integrations/stripepayment/portal?returnTo=${WEBAPP_URL}${returnTo}`; + const teamId = `teamId=${userOrgId}`; + const billingHref = `/api/integrations/stripepayment/portal?returnTo=${WEBAPP_URL}${returnTo}&${teamId}`; const onContactSupportClick = async () => { if (window.Support) { window.Support.open(); } }; - const { isUserLoading, isUserBillingDataLoading, isPlatformUser, userBillingData, isPaidUser, userOrgId } = - useGetUserAttributes(); const { mutateAsync: removeTeamSubscription, isPending: isRemoveTeamSubscriptionLoading } = useUnsubscribeTeamToStripe({ diff --git a/packages/app-store/stripepayment/lib/services/team/TeamBillingPortalService.ts b/packages/app-store/stripepayment/lib/services/team/TeamBillingPortalService.ts index 77eb559bcb..2d22babd49 100644 --- a/packages/app-store/stripepayment/lib/services/team/TeamBillingPortalService.ts +++ b/packages/app-store/stripepayment/lib/services/team/TeamBillingPortalService.ts @@ -1,4 +1,5 @@ import logger from "@calcom/lib/logger"; +import type { Prisma } from "@calcom/prisma/client"; import { MembershipRole } from "@calcom/prisma/enums"; import { teamMetadataSchema } from "@calcom/prisma/zod-utils"; @@ -18,25 +19,53 @@ export class TeamBillingPortalService extends BillingPortalService { }); } - async getCustomerId(teamId: number): Promise { - const log = logger.getSubLogger({ prefix: ["TeamBillingPortalService", "getCustomerId"] }); - - const team = await this.teamRepository.findById({ id: teamId }); - if (!team) return null; - - const teamMetadataParsed = teamMetadataSchema.safeParse(team.metadata); + async getValidatedTeamSubscriptionId(metadata: Prisma.JsonValue) { + const teamMetadataParsed = teamMetadataSchema.safeParse(metadata); if (!teamMetadataParsed.success || !teamMetadataParsed.data?.subscriptionId) { return null; } + return teamMetadataParsed.data.subscriptionId; + } + + async getValidatedTeamSubscriptionIdForPlatform(subscriptionId?: string | null) { + if (!subscriptionId) { + return null; + } + + return subscriptionId; + } + + async getCustomerId(teamId: number): Promise { + const log = logger.getSubLogger({ prefix: ["TeamBillingPortalService", "getCustomerId"] }); + + const team = await this.teamRepository.findByIdIncludePlatformBilling({ id: teamId }); + if (!team) return null; + + let teamSubscriptionId = ""; + + if (team.isPlatform) { + const subscriptionId = await this.getValidatedTeamSubscriptionIdForPlatform( + team.platformBilling?.subscriptionId + ); + + if (!subscriptionId) return null; + teamSubscriptionId = subscriptionId; + } else { + const subscriptionId = await this.getValidatedTeamSubscriptionId(team.metadata); + + if (!subscriptionId) return null; + teamSubscriptionId = subscriptionId; + } + try { - const subscription = await getSubscriptionFromId(teamMetadataParsed.data.subscriptionId); + const subscription = await getSubscriptionFromId(teamSubscriptionId); if (!subscription?.customer) { log.warn("Subscription found but no customer ID", { teamId, - subscriptionId: teamMetadataParsed.data.subscriptionId, + teamSubscriptionId, }); return null; } diff --git a/packages/lib/server/repository/team.ts b/packages/lib/server/repository/team.ts index 20f8b12959..67d89bb787 100644 --- a/packages/lib/server/repository/team.ts +++ b/packages/lib/server/repository/team.ts @@ -183,6 +183,19 @@ export class TeamRepository { return getParsedTeam(team); } + async findByIdIncludePlatformBilling({ id }: { id: number }) { + const team = await this.prismaClient.team.findUnique({ + where: { + id, + }, + select: { ...teamSelect, platformBilling: true }, + }); + if (!team) { + return null; + } + return getParsedTeam(team); + } + async findAllByParentId({ parentId, select = teamSelect,