2
0

📈 (billing) Track when workspace subscription is cancelled

This commit is contained in:
Baptiste Arnaud
2023-06-26 11:33:06 +02:00
parent 6430d576ad
commit 6f7ef820e2
4 changed files with 55 additions and 27 deletions

View File

@@ -134,7 +134,6 @@ export const createCheckoutSessionUrl =
(stripe: Stripe) => (stripe: Stripe) =>
async ({ async ({
customerId, customerId,
userId,
workspaceId, workspaceId,
currency, currency,
plan, plan,
@@ -158,7 +157,6 @@ export const createCheckoutSessionUrl =
plan, plan,
additionalChats, additionalChats,
additionalStorage, additionalStorage,
userId,
}, },
currency, currency,
billing_address_collection: 'required', billing_address_collection: 'required',

View File

@@ -84,7 +84,6 @@ export const createCustomCheckoutSession = authenticatedProcedure
mode: 'subscription', mode: 'subscription',
metadata: { metadata: {
claimableCustomPlanId: workspace.claimableCustomPlan.id, claimableCustomPlanId: workspace.claimableCustomPlan.id,
userId: user.id,
}, },
currency: workspace.claimableCustomPlan.currency, currency: workspace.claimableCustomPlan.currency,
billing_address_collection: 'required', billing_address_collection: 'required',

View File

@@ -4,7 +4,7 @@ import Stripe from 'stripe'
import Cors from 'micro-cors' import Cors from 'micro-cors'
import { buffer } from 'micro' import { buffer } from 'micro'
import prisma from '@/lib/prisma' import prisma from '@/lib/prisma'
import { Plan } from '@typebot.io/prisma' import { Plan, WorkspaceRole } from '@typebot.io/prisma'
import { RequestHandler } from 'next/dist/server/next' import { RequestHandler } from 'next/dist/server/next'
import { sendTelemetryEvents } from '@typebot.io/lib/telemetry/sendTelemetryEvent' import { sendTelemetryEvents } from '@typebot.io/lib/telemetry/sendTelemetryEvent'
import { PublicTypebot, Typebot } from '@typebot.io/schemas' import { PublicTypebot, Typebot } from '@typebot.io/schemas'
@@ -52,18 +52,13 @@ const webhookHandler = async (req: NextApiRequest, res: NextApiResponse) => {
} }
| { claimableCustomPlanId: string; userId: string } | { claimableCustomPlanId: string; userId: string }
if ('plan' in metadata) { if ('plan' in metadata) {
const { const { workspaceId, plan, additionalChats, additionalStorage } =
workspaceId, metadata
plan,
additionalChats,
additionalStorage,
userId,
} = metadata
if (!workspaceId || !plan || !additionalChats || !additionalStorage) if (!workspaceId || !plan || !additionalChats || !additionalStorage)
return res return res
.status(500) .status(500)
.send({ message: `Couldn't retrieve valid metadata` }) .send({ message: `Couldn't retrieve valid metadata` })
await prisma.workspace.update({ const workspace = await prisma.workspace.update({
where: { id: workspaceId }, where: { id: workspaceId },
data: { data: {
plan, plan,
@@ -72,20 +67,31 @@ const webhookHandler = async (req: NextApiRequest, res: NextApiResponse) => {
additionalStorageIndex: parseInt(additionalStorage), additionalStorageIndex: parseInt(additionalStorage),
isQuarantined: false, isQuarantined: false,
}, },
}) include: {
members: {
await sendTelemetryEvents([ select: { user: { select: { id: true } } },
{ where: {
name: 'Subscription updated', role: WorkspaceRole.ADMIN,
workspaceId, },
userId,
data: {
plan,
additionalChatsIndex: parseInt(additionalChats),
additionalStorageIndex: parseInt(additionalStorage),
}, },
}, },
]) })
for (const user of workspace.members.map((member) => member.user)) {
if (!user?.id) continue
await sendTelemetryEvents([
{
name: 'Subscription updated',
workspaceId,
userId: user.id,
data: {
plan,
additionalChatsIndex: parseInt(additionalChats),
additionalStorageIndex: parseInt(additionalStorage),
},
},
])
}
} else { } else {
const { claimableCustomPlanId, userId } = metadata const { claimableCustomPlanId, userId } = metadata
if (!claimableCustomPlanId) if (!claimableCustomPlanId)
@@ -139,7 +145,32 @@ const webhookHandler = async (req: NextApiRequest, res: NextApiResponse) => {
customStorageLimit: null, customStorageLimit: null,
customSeatsLimit: null, customSeatsLimit: null,
}, },
include: {
members: {
select: { user: { select: { id: true } } },
where: {
role: WorkspaceRole.ADMIN,
},
},
},
}) })
for (const user of workspace.members.map((member) => member.user)) {
if (!user?.id) continue
await sendTelemetryEvents([
{
name: 'Subscription updated',
workspaceId: workspace.id,
userId: user.id,
data: {
plan: Plan.FREE,
additionalChatsIndex: 0,
additionalStorageIndex: 0,
},
},
])
}
const typebots = (await prisma.typebot.findMany({ const typebots = (await prisma.typebot.findMany({
where: { where: {
workspaceId: workspace.id, workspaceId: workspace.id,

View File

@@ -18,7 +18,7 @@ const checkSubscriptionsStatus = async () => {
apiVersion: '2022-11-15', apiVersion: '2022-11-15',
}) })
let activeSubscriptions = 0 let totalActiveSubscriptions = 0
for (const workspace of workspacesWithPaidPlan) { for (const workspace of workspacesWithPaidPlan) {
if (!workspace.stripeId) { if (!workspace.stripeId) {
console.log('No stripe ID', workspace.id) console.log('No stripe ID', workspace.id)
@@ -35,12 +35,12 @@ const checkSubscriptionsStatus = async () => {
continue continue
} }
if (subscription.status === 'active') { if (subscription.status === 'active') {
activeSubscriptions++ totalActiveSubscriptions++
continue continue
} }
console.log(`${workspace.id} - ${workspace.name} - ${subscription.status}`) console.log(`${workspace.id} - ${workspace.name} - ${subscription.status}`)
} }
console.log('Active subscriptions', activeSubscriptions) console.log('Active subscriptions', totalActiveSubscriptions)
} }
checkSubscriptionsStatus() checkSubscriptionsStatus()