Files
documenso/packages/ee/server-only/stripe/transfer-team-subscription.ts
David Nguyen 9d626473c8 feat: wip
2023-12-27 13:04:24 +11:00

97 lines
2.8 KiB
TypeScript

import type Stripe from 'stripe';
import { stripe } from '@documenso/lib/server-only/stripe';
import {
getTeamSeatPriceId,
isSomeSubscriptionsActiveAndCommunityPlan,
} from '@documenso/lib/utils/billing';
import { prisma } from '@documenso/prisma';
import type { Subscription, Team, User } from '@documenso/prisma/client';
import { getStripeCustomerByUser } from './get-customer';
type TransferStripeSubscriptionOptions = {
user: User & { Subscription: Subscription[] };
team: Team;
};
/**
* 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 new subscription, null if no subscription is needed (for community plan).
*/
export const transferTeamSubscription = async ({
user,
team,
}: TransferStripeSubscriptionOptions) => {
const teamSeatPriceId = getTeamSeatPriceId();
const { stripeCustomer } = await getStripeCustomerByUser(user);
const newOwnerHasCommunityPlan = isSomeSubscriptionsActiveAndCommunityPlan(user.Subscription);
const currentTeamSubscriptionId = team.subscriptionId;
let oldSubscription: Stripe.Subscription | null = null;
let newSubscription: Stripe.Subscription | null = null;
if (currentTeamSubscriptionId) {
oldSubscription = await stripe.subscriptions.retrieve(currentTeamSubscriptionId);
}
const numberOfSeats = await prisma.teamMember.count({
where: {
teamId: team.id,
},
});
if (!newOwnerHasCommunityPlan) {
let stripeCreateSubscriptionPayload: Stripe.SubscriptionCreateParams = {
customer: stripeCustomer.id,
items: [
{
price: teamSeatPriceId,
quantity: numberOfSeats,
},
],
metadata: {
teamId: team.id.toString(),
},
};
// If no payment method is attached to the new owner Stripe customer account, send an
// invoice instead.
if (!stripeCustomer.invoice_settings.default_payment_method) {
stripeCreateSubscriptionPayload = {
...stripeCreateSubscriptionPayload,
collection_method: 'send_invoice',
days_until_due: 7,
};
}
newSubscription = await stripe.subscriptions.create(stripeCreateSubscriptionPayload);
}
if (oldSubscription) {
try {
// Set the quantity to 0 so we can refund/charge the old Stripe customer the prorated amount.
await stripe.subscriptions.update(oldSubscription.id, {
items: oldSubscription.items.data.map((item) => ({
id: item.id,
quantity: 0,
})),
});
await stripe.subscriptions.cancel(oldSubscription.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 newSubscription;
};