2
0
Files
bot/apps/builder/src/features/billing/api/procedures/getUsage.ts

95 lines
2.3 KiB
TypeScript
Raw Normal View History

import prisma from '@/lib/prisma'
import { authenticatedProcedure } from '@/utils/server/trpc'
import { TRPCError } from '@trpc/server'
import { z } from 'zod'
export const getUsage = authenticatedProcedure
.meta({
openapi: {
method: 'GET',
path: '/billing/usage',
protect: true,
summary: 'Get current plan usage',
tags: ['Billing'],
},
})
.input(
z.object({
workspaceId: z.string(),
})
)
.output(
z.object({ totalChatsUsed: z.number(), totalStorageUsed: z.number() })
)
.query(async ({ input: { workspaceId }, ctx: { user } }) => {
if (
!process.env.STRIPE_SECRET_KEY ||
!process.env.STRIPE_ADDITIONAL_CHATS_PRICE_ID ||
!process.env.STRIPE_ADDITIONAL_STORAGE_PRICE_ID
)
throw new TRPCError({
code: 'INTERNAL_SERVER_ERROR',
message: 'Stripe environment variables are missing',
})
const workspace = await prisma.workspace.findFirst({
where: {
id: workspaceId,
members: { some: { userId: user.id } },
},
})
if (!workspace)
throw new TRPCError({
code: 'NOT_FOUND',
message: 'Workspace not found',
})
const now = new Date()
const firstDayOfMonth = new Date(now.getFullYear(), now.getMonth(), 1)
const firstDayOfNextMonth = new Date(
now.getFullYear(),
now.getMonth() + 1,
1
)
const [
totalChatsUsed,
{
_sum: { storageUsed: totalStorageUsed },
},
] = await prisma.$transaction(async (tx) => {
const typebots = await tx.typebot.findMany({
where: {
workspace: {
id: workspaceId,
},
},
})
return Promise.all([
prisma.result.count({
where: {
typebotId: { in: typebots.map((typebot) => typebot.id) },
hasStarted: true,
createdAt: {
gte: firstDayOfMonth,
lt: firstDayOfNextMonth,
},
},
}),
prisma.answer.aggregate({
where: {
storageUsed: { gt: 0 },
result: {
typebotId: { in: typebots.map((typebot) => typebot.id) },
},
},
_sum: { storageUsed: true },
}),
])
})
return {
totalChatsUsed,
totalStorageUsed: totalStorageUsed ?? 0,
}
})