Fix stripe type errors

This commit is contained in:
Joe Au-Yeung 2022-11-03 20:19:29 -04:00
parent a1c9afdf46
commit 7a4c1fbedf
2 changed files with 82 additions and 24 deletions

View File

@ -18,6 +18,15 @@ export const getTeamPricing = async () => {
};
};
export const searchForTeamCustomer = async (teamName: string, ownerEmail: string) => {
// Search to see if the customer is already in Stripe
const customer = await stripe.customers.search({
query: `name: \'${teamName}\' AND email: \'${ownerEmail}\'`,
});
return customer.data[0];
};
export const createTeamCustomer = async (teamName: string, ownerEmail: string) => {
return await stripe.customers.create({
name: teamName,
@ -27,7 +36,8 @@ export const createTeamCustomer = async (teamName: string, ownerEmail: string) =
export const retrieveTeamCustomer = async (customerId: string) => {
const customer = await stripe.customers.retrieve(customerId);
return customer.deleted ? null : (customer as Stripe.Customer);
if (customer.deleted) throw new Error("Customer has been deleted off Stripe");
return customer as Stripe.Customer;
};
export const updateTeamCustomerName = async (customerId: string, teamName: string) => {
@ -35,7 +45,7 @@ export const updateTeamCustomerName = async (customerId: string, teamName: strin
};
export const createTeamSubscription = async (customerId: string, billingFrequency: string, seats: number) => {
return await stripe.subscriptions.create({
const subscription = await stripe.subscriptions.create({
customer: customerId,
items: [
{
@ -49,14 +59,46 @@ export const createTeamSubscription = async (customerId: string, billingFrequenc
payment_behavior: "default_incomplete",
expand: ["latest_invoice.payment_intent"],
});
return subscription as Stripe.Subscription & {
quantity: number;
latest_invoice: Stripe.Invoice & { payment_intent: Stripe.PaymentIntent };
};
};
export const retrieveTeamSubscription = async (subscriptionId: string) => {
const subscription = await stripe.subscriptions.retrieve(subscriptionId);
return subscription as Stripe.Subscription;
export const retrieveTeamSubscription = async ({
subscriptionId,
customerId,
}: {
subscriptionId?: string;
customerId?: string;
}) => {
if (!subscriptionId && !customerId) throw new Error("No Stripe subscriptions found");
if (subscriptionId) {
const subscription = await stripe.subscriptions.retrieve(subscriptionId, {
expand: ["latest_invoice.payment_intent"],
});
return subscription as unknown as Stripe.Subscription & {
quantity: number;
latest_invoice: Stripe.Invoice & { payment_intent: Stripe.PaymentIntent };
};
}
if (customerId) {
const subscription = await stripe.subscriptions.list({
customer: customerId,
status: "incomplete",
limit: 1,
expand: ["data.latest_invoice.payment_intent"],
});
return subscription.data[0] as Stripe.Subscription & {
quantity: number;
latest_invoice: Stripe.Invoice & { payment_intent: Stripe.PaymentIntent };
};
}
};
export const deleteTeamSubscriptionQuantity = async (subscriptionId: string, seats: number) => {
export const deleteTeamSubscriptionQuantity = async (subscriptionId: string) => {
return await stripe.subscriptions.del(subscriptionId);
};

View File

@ -21,6 +21,7 @@ import {
updateTeamCustomerName,
retrieveTeamSubscription,
deleteTeamSubscriptionQuantity,
searchForTeamCustomer,
} from "@calcom/features/ee/teams/lib/payments";
import { HOSTED_CAL_FEATURES, IS_STRIPE_ENABLED, WEBAPP_URL } from "@calcom/lib/constants";
import { getTranslation } from "@calcom/lib/server/i18n";
@ -703,24 +704,38 @@ export const viewerTeamsRouter = createProtectedRouter()
async resolve({ ctx, input }) {
const { teamName, billingFrequency, seats, customerId, subscriptionId } = input;
// Check to see if team name has changed
// Check to see if customer already exists in DB from another session
let customer = await searchForTeamCustomer(teamName, ctx.user.email);
// Check to see if team name has changed if within same session
if (customerId) {
const customer = await retrieveTeamCustomer(customerId);
customer = await retrieveTeamCustomer(customerId);
if (teamName !== customer?.name) {
await updateTeamCustomerName(customerId, teamName);
}
}
if (subscriptionId) {
const subscription = await retrieveTeamSubscription(subscriptionId);
if (seats !== subscription.quantity) {
// Check to that subscription quantity is the same
if (subscriptionId || customer) {
// Grab current "incomplete" subscription
const subscriptionQuery = await retrieveTeamSubscription({
subscriptionId: subscriptionId,
customerId: customer.id,
});
if (!subscriptionQuery)
throw new TRPCError({ code: "NOT_FOUND", message: "Could not find subscription" });
if (subscriptionQuery && seats !== subscriptionQuery?.quantity) {
/* If the number of seats changed we need to cancel the current
incomplete subscription and create a new one */
await deleteTeamSubscriptionQuantity(subscriptionId, seats);
await deleteTeamSubscriptionQuantity(subscriptionId || subscriptionQuery.id);
const customer = await retrieveTeamCustomer(customerId);
const subscription = await createTeamSubscription(customerId, input.billingFrequency, input.seats);
const subscription = await createTeamSubscription(
customerId || customer.id,
input.billingFrequency,
input.seats
);
return {
clientSecret: subscription?.latest_invoice?.payment_intent?.client_secret,
@ -728,19 +743,22 @@ export const viewerTeamsRouter = createProtectedRouter()
subscriptionId: subscription.id,
};
}
// If customer exists and no changes were made to the subscription
return {
clientSecret: subscriptionQuery?.latest_invoice?.payment_intent?.client_secret,
customerId: customer.id,
subscriptionId: subscriptionQuery.id,
};
}
// Retrieve the Stripe subscription
// Compare the quantity of the subscription vs input.seats
// If different then update the subscription
// If no changes then do not create a new customer & subscription, just return
if (!customerId && !subscriptionId) {
// First create the customer
const customer = await createTeamCustomer(input.teamName, ctx.user.email);
// First create the customer if it does not exist
customer = customer || (await createTeamCustomer(teamName, ctx.user.email));
// Create the subscription for the team
const subscription = await createTeamSubscription(customer.id, input.billingFrequency, input.seats);
const subscription = await createTeamSubscription(customer.id, billingFrequency, seats);
// We just need the client secret for the payment intent
return {
@ -749,8 +767,6 @@ export const viewerTeamsRouter = createProtectedRouter()
subscriptionId: subscription.id,
};
}
return;
},
})
.mutation("createTeam", {