Files
documenso/packages/trpc/server/billing/create-subscription.ts
David Nguyen e5aaa17545 fix: restrict individual plans to upgrade only (#1900)
Prevent users from creating a separate organisation for individual
plans. Only applies to users who have 1 personal organisation and are
subscribing to the "Individual" plan.

The reason for this change is to keep the layout in the "Personal" mode
which means it doesn't show a bunch of unusable "organisation" related
UI.
2025-07-16 14:35:42 +10:00

93 lines
2.5 KiB
TypeScript

import { createCheckoutSession } from '@documenso/ee/server-only/stripe/create-checkout-session';
import { createCustomer } from '@documenso/ee/server-only/stripe/create-customer';
import { IS_BILLING_ENABLED, NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
import { ORGANISATION_MEMBER_ROLE_PERMISSIONS_MAP } from '@documenso/lib/constants/organisations';
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
import { buildOrganisationWhereQuery } from '@documenso/lib/utils/organisations';
import { prisma } from '@documenso/prisma';
import { authenticatedProcedure } from '../trpc';
import { ZCreateSubscriptionRequestSchema } from './create-subscription.types';
export const createSubscriptionRoute = authenticatedProcedure
.input(ZCreateSubscriptionRequestSchema)
.mutation(async ({ ctx, input }) => {
const { organisationId, priceId, isPersonalLayoutMode } = input;
ctx.logger.info({
input: {
organisationId,
priceId,
},
});
const userId = ctx.user.id;
if (!IS_BILLING_ENABLED()) {
throw new AppError(AppErrorCode.INVALID_REQUEST, {
message: 'Billing is not enabled',
});
}
const organisation = await prisma.organisation.findFirst({
where: buildOrganisationWhereQuery({
organisationId,
userId,
roles: ORGANISATION_MEMBER_ROLE_PERMISSIONS_MAP['MANAGE_BILLING'],
}),
include: {
subscription: true,
owner: {
select: {
email: true,
name: true,
},
},
},
});
if (!organisation) {
throw new AppError(AppErrorCode.UNAUTHORIZED);
}
let customerId = organisation.customerId;
if (!customerId) {
const customer = await createCustomer({
name: organisation.name,
email: organisation.owner.email,
});
customerId = customer.id;
await prisma.organisation.update({
where: {
id: organisationId,
},
data: {
customerId: customer.id,
},
});
}
const returnUrl = isPersonalLayoutMode
? `${NEXT_PUBLIC_WEBAPP_URL()}/settings/billing`
: `${NEXT_PUBLIC_WEBAPP_URL()}/o/${organisation.url}/settings/billing`;
const redirectUrl = await createCheckoutSession({
customerId,
priceId,
returnUrl,
});
if (!redirectUrl) {
throw new AppError(AppErrorCode.UNKNOWN_ERROR, {
message: 'Failed to create checkout session',
});
}
return {
redirectUrl,
};
});