mirror of
https://github.com/documenso/documenso.git
synced 2025-11-19 03:01:59 +10:00
fix: wip
This commit is contained in:
@ -6,7 +6,7 @@ import { ZLimitsResponseSchema } from './schema';
|
||||
|
||||
export type GetLimitsOptions = {
|
||||
headers?: Record<string, string>;
|
||||
teamId?: number | null;
|
||||
teamId: number | null;
|
||||
};
|
||||
|
||||
export const getLimits = async ({ headers, teamId }: GetLimitsOptions = {}) => {
|
||||
|
||||
@ -22,7 +22,7 @@ export const useLimits = () => {
|
||||
|
||||
export type LimitsProviderProps = {
|
||||
initialValue?: TLimitsResponseSchema;
|
||||
teamId?: number;
|
||||
teamId: number;
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ import { ZLimitsSchema } from './schema';
|
||||
|
||||
export type GetServerLimitsOptions = {
|
||||
email: string;
|
||||
teamId?: number | null;
|
||||
teamId: number | null;
|
||||
};
|
||||
|
||||
export const getServerLimits = async ({
|
||||
|
||||
@ -1,20 +1,23 @@
|
||||
import { STRIPE_CUSTOMER_TYPE } from '@documenso/lib/constants/billing';
|
||||
import { stripe } from '@documenso/lib/server-only/stripe';
|
||||
|
||||
type CreateTeamCustomerOptions = {
|
||||
type CreateOrganisationCustomerOptions = {
|
||||
name: string;
|
||||
email: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a Stripe customer for a given team.
|
||||
* Create a Stripe customer for a given Organisation.
|
||||
*/
|
||||
export const createTeamCustomer = async ({ name, email }: CreateTeamCustomerOptions) => {
|
||||
export const createOrganisationCustomer = async ({
|
||||
name,
|
||||
email,
|
||||
}: CreateOrganisationCustomerOptions) => {
|
||||
return await stripe.customers.create({
|
||||
name,
|
||||
email,
|
||||
metadata: {
|
||||
type: STRIPE_CUSTOMER_TYPE.TEAM,
|
||||
type: STRIPE_CUSTOMER_TYPE.ORGANISATION,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@ -27,6 +27,7 @@ export const getStripeCustomerById = async (stripeCustomerId: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
// Todo: (orgs)
|
||||
/**
|
||||
* Get a stripe customer by user.
|
||||
*
|
||||
|
||||
@ -1,128 +0,0 @@
|
||||
import { type Subscription, type Team, type User } from '@prisma/client';
|
||||
import type Stripe from 'stripe';
|
||||
|
||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||
import { stripe } from '@documenso/lib/server-only/stripe';
|
||||
import { subscriptionsContainsActivePlan } from '@documenso/lib/utils/billing';
|
||||
import { prisma } from '@documenso/prisma';
|
||||
|
||||
import { deleteCustomerPaymentMethods } from './delete-customer-payment-methods';
|
||||
import { getTeamPrices } from './get-team-prices';
|
||||
import { getTeamRelatedPriceIds } from './get-team-related-prices';
|
||||
|
||||
type TransferStripeSubscriptionOptions = {
|
||||
/**
|
||||
* The user to transfer the subscription to.
|
||||
*/
|
||||
user: User & { subscriptions: Subscription[] };
|
||||
|
||||
/**
|
||||
* The team the subscription is associated with.
|
||||
*/
|
||||
team: Team & { subscription?: Subscription | null };
|
||||
|
||||
/**
|
||||
* Whether to clear any current payment methods attached to the team.
|
||||
*/
|
||||
clearPaymentMethods: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transfer the Stripe Team seats subscription from one user to another.
|
||||
*
|
||||
* Will create a new subscription for the new owner and cancel the old one.
|
||||
*
|
||||
* Returns the subscription that should be associated with the team, null if
|
||||
* no subscription is needed (for early adopter plan).
|
||||
*/
|
||||
export const transferTeamSubscription = async ({
|
||||
user,
|
||||
team,
|
||||
clearPaymentMethods,
|
||||
}: TransferStripeSubscriptionOptions) => {
|
||||
const teamCustomerId = team.customerId;
|
||||
|
||||
if (!teamCustomerId) {
|
||||
throw new AppError(AppErrorCode.NOT_FOUND, {
|
||||
message: 'Missing customer ID.',
|
||||
});
|
||||
}
|
||||
|
||||
const [teamRelatedPlanPriceIds, teamSeatPrices] = await Promise.all([
|
||||
getTeamRelatedPriceIds(),
|
||||
getTeamPrices(),
|
||||
]);
|
||||
|
||||
const teamSubscriptionRequired = !subscriptionsContainsActivePlan(
|
||||
user.subscriptions,
|
||||
teamRelatedPlanPriceIds,
|
||||
);
|
||||
|
||||
let teamSubscription: Stripe.Subscription | null = null;
|
||||
|
||||
if (team.subscription) {
|
||||
teamSubscription = await stripe.subscriptions.retrieve(team.subscription.planId);
|
||||
|
||||
if (!teamSubscription) {
|
||||
throw new Error('Could not find the current subscription.');
|
||||
}
|
||||
|
||||
if (clearPaymentMethods) {
|
||||
await deleteCustomerPaymentMethods({ customerId: teamCustomerId });
|
||||
}
|
||||
}
|
||||
|
||||
await stripe.customers.update(teamCustomerId, {
|
||||
name: user.name ?? team.name,
|
||||
email: user.email,
|
||||
});
|
||||
|
||||
// If team subscription is required and the team does not have a subscription, create one.
|
||||
if (teamSubscriptionRequired && !teamSubscription) {
|
||||
const numberOfSeats = await prisma.teamMember.count({
|
||||
where: {
|
||||
teamId: team.id,
|
||||
},
|
||||
});
|
||||
|
||||
const teamSeatPriceId = teamSeatPrices.monthly.priceId;
|
||||
|
||||
teamSubscription = await stripe.subscriptions.create({
|
||||
customer: teamCustomerId,
|
||||
items: [
|
||||
{
|
||||
price: teamSeatPriceId,
|
||||
quantity: numberOfSeats,
|
||||
},
|
||||
],
|
||||
metadata: {
|
||||
teamId: team.id.toString(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// If no team subscription is required, cancel the current team subscription if it exists.
|
||||
if (!teamSubscriptionRequired && teamSubscription) {
|
||||
try {
|
||||
// Set the quantity to 0 so we can refund/charge the old Stripe customer the prorated amount.
|
||||
await stripe.subscriptions.update(teamSubscription.id, {
|
||||
items: teamSubscription.items.data.map((item) => ({
|
||||
id: item.id,
|
||||
quantity: 0,
|
||||
})),
|
||||
});
|
||||
|
||||
await stripe.subscriptions.cancel(teamSubscription.id, {
|
||||
invoice_now: true,
|
||||
prorate: false,
|
||||
});
|
||||
} catch (e) {
|
||||
// Do not error out since we can't easily undo the transfer.
|
||||
// Todo: Teams - Alert us.
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return teamSubscription;
|
||||
};
|
||||
@ -7,7 +7,7 @@ import { prisma } from '@documenso/prisma';
|
||||
|
||||
export type OnSubscriptionUpdatedOptions = {
|
||||
userId?: number;
|
||||
teamId?: number;
|
||||
teamId: number;
|
||||
subscription: Stripe.Subscription;
|
||||
};
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ import { getCommunityPlanPriceIds } from '../stripe/get-community-plan-prices';
|
||||
|
||||
export type IsCommunityPlanOptions = {
|
||||
userId: number;
|
||||
teamId?: number;
|
||||
teamId: number;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -8,7 +8,7 @@ import { getEnterprisePlanPriceIds } from '../stripe/get-enterprise-plan-prices'
|
||||
|
||||
export type IsUserEnterpriseOptions = {
|
||||
userId: number;
|
||||
teamId?: number;
|
||||
teamId: number;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user