fix: platform billing portal (#23975)
* fix: check if team is platform or not when sending billingPortalUrl * update team repository * fix: pass teamId explicitely for platform team * fix: coderabbit feedback * fix: merge conflicts * fix: merge conflicts * fix: make sure we pass in the correct subsciption id * fix: implement PR feedback
This commit is contained in:
@@ -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({
|
||||
|
||||
@@ -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<string | null> {
|
||||
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<string | null> {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user