👷 Add convenient script for migrating Stripe prices
This commit is contained in:
@ -17,7 +17,11 @@ const createChatsPrices = async () => {
|
||||
await stripe.prices.create({
|
||||
currency: 'usd',
|
||||
billing_scheme: 'tiered',
|
||||
recurring: { interval: 'month', usage_type: 'metered' },
|
||||
recurring: {
|
||||
interval: 'month',
|
||||
usage_type: 'metered',
|
||||
aggregate_usage: 'last_during_period',
|
||||
},
|
||||
tiers: starterChatTiers,
|
||||
tiers_mode: 'volume',
|
||||
tax_behavior: 'exclusive',
|
||||
@ -33,7 +37,11 @@ const createChatsPrices = async () => {
|
||||
await stripe.prices.create({
|
||||
currency: 'usd',
|
||||
billing_scheme: 'tiered',
|
||||
recurring: { interval: 'month', usage_type: 'metered' },
|
||||
recurring: {
|
||||
interval: 'month',
|
||||
usage_type: 'metered',
|
||||
aggregate_usage: 'last_during_period',
|
||||
},
|
||||
tiers: proChatTiers,
|
||||
tiers_mode: 'volume',
|
||||
tax_behavior: 'exclusive',
|
||||
|
29
packages/scripts/getUsage.ts
Normal file
29
packages/scripts/getUsage.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { PrismaClient } from '@typebot.io/prisma'
|
||||
import { promptAndSetEnvironment } from './utils'
|
||||
|
||||
const getUsage = async () => {
|
||||
await promptAndSetEnvironment()
|
||||
const prisma = new PrismaClient({
|
||||
log: [{ emit: 'event', level: 'query' }, 'info', 'warn', 'error'],
|
||||
})
|
||||
|
||||
prisma.$on('query', (e) => {
|
||||
console.log(e.query)
|
||||
console.log(e.params)
|
||||
console.log(e.duration, 'ms')
|
||||
})
|
||||
|
||||
const count = await prisma.result.count({
|
||||
where: {
|
||||
typebot: { workspaceId: '' },
|
||||
hasStarted: true,
|
||||
createdAt: {
|
||||
gte: '2023-09-18T00:00:00.000Z',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
console.log(count)
|
||||
}
|
||||
|
||||
getUsage()
|
109
packages/scripts/migrateSubscriptionItemPriceId.ts
Normal file
109
packages/scripts/migrateSubscriptionItemPriceId.ts
Normal file
@ -0,0 +1,109 @@
|
||||
import { PrismaClient } from '@typebot.io/prisma'
|
||||
import { promptAndSetEnvironment } from './utils'
|
||||
import { writeFileSync } from 'fs'
|
||||
import Stripe from 'stripe'
|
||||
|
||||
const migrateSubscriptionItemPriceId = async () => {
|
||||
await promptAndSetEnvironment()
|
||||
const prisma = new PrismaClient({
|
||||
log: [{ emit: 'event', level: 'query' }, 'info', 'warn', 'error'],
|
||||
})
|
||||
|
||||
prisma.$on('query', (e) => {
|
||||
console.log(e.query)
|
||||
console.log(e.params)
|
||||
console.log(e.duration, 'ms')
|
||||
})
|
||||
|
||||
if (
|
||||
!process.env.STRIPE_STARTER_CHATS_PRICE_ID_OLD ||
|
||||
!process.env.STRIPE_STARTER_CHATS_PRICE_ID ||
|
||||
!process.env.STRIPE_PRO_CHATS_PRICE_ID_OLD ||
|
||||
!process.env.STRIPE_PRO_CHATS_PRICE_ID ||
|
||||
!process.env.STRIPE_SECRET_KEY
|
||||
)
|
||||
throw new Error('Missing some env variables')
|
||||
|
||||
const workspacesWithPaidPlan = await prisma.workspace.findMany({
|
||||
where: {
|
||||
plan: {
|
||||
in: ['PRO', 'STARTER'],
|
||||
},
|
||||
isSuspended: false,
|
||||
},
|
||||
select: {
|
||||
plan: true,
|
||||
name: true,
|
||||
id: true,
|
||||
stripeId: true,
|
||||
isQuarantined: true,
|
||||
members: {
|
||||
select: {
|
||||
user: {
|
||||
select: { email: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
writeFileSync(
|
||||
'./workspacesWithPaidPlan.json',
|
||||
JSON.stringify(workspacesWithPaidPlan, null, 2)
|
||||
)
|
||||
|
||||
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {
|
||||
apiVersion: '2022-11-15',
|
||||
})
|
||||
|
||||
let i = 0
|
||||
for (const workspace of workspacesWithPaidPlan) {
|
||||
i += 1
|
||||
console.log(
|
||||
`(${i} / ${workspacesWithPaidPlan.length})`,
|
||||
'Migrating workspace:',
|
||||
workspace.id,
|
||||
workspace.name,
|
||||
workspace.stripeId,
|
||||
JSON.stringify(workspace.members.map((member) => member.user.email))
|
||||
)
|
||||
if (!workspace.stripeId) {
|
||||
console.log('No stripe ID, skipping...')
|
||||
continue
|
||||
}
|
||||
|
||||
const subscriptions = await stripe.subscriptions.list({
|
||||
customer: workspace.stripeId,
|
||||
})
|
||||
|
||||
const currentSubscription = subscriptions.data
|
||||
.filter((sub) => ['past_due', 'active'].includes(sub.status))
|
||||
.sort((a, b) => a.created - b.created)
|
||||
.shift()
|
||||
|
||||
if (!currentSubscription) {
|
||||
console.log('No current subscription in workspace:', workspace.id)
|
||||
continue
|
||||
}
|
||||
|
||||
const subscriptionItem = currentSubscription.items.data.find(
|
||||
(item) =>
|
||||
item.price.id === process.env.STRIPE_STARTER_CHATS_PRICE_ID_OLD ||
|
||||
item.price.id === process.env.STRIPE_PRO_CHATS_PRICE_ID_OLD
|
||||
)
|
||||
|
||||
if (!subscriptionItem) {
|
||||
console.log('Could not find subscriptio item. Skipping...')
|
||||
continue
|
||||
}
|
||||
|
||||
await stripe.subscriptionItems.update(subscriptionItem.id, {
|
||||
price:
|
||||
workspace.plan === 'STARTER'
|
||||
? process.env.STRIPE_STARTER_CHATS_PRICE_ID
|
||||
: process.env.STRIPE_PRO_CHATS_PRICE_ID,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
migrateSubscriptionItemPriceId()
|
@ -17,7 +17,8 @@
|
||||
"checkSubscriptionsStatus": "tsx checkSubscriptionsStatus.ts",
|
||||
"createChatsPrices": "tsx createChatsPrices.ts",
|
||||
"migrateSubscriptionsToUsageBased": "tsx migrateSubscriptionsToUsageBased.ts",
|
||||
"importContactToBrevo": "tsx importContactToBrevo.ts"
|
||||
"importContactToBrevo": "tsx importContactToBrevo.ts",
|
||||
"getUsage": "tsx getUsage.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typebot.io/emails": "workspace:*",
|
||||
|
Reference in New Issue
Block a user