chore: wip

This commit is contained in:
Ephraim Atta-Duncan
2025-02-25 09:44:10 +00:00
parent 633274bab1
commit 70a3f7b3e9
2 changed files with 130 additions and 109 deletions

View File

@ -15,10 +15,14 @@ import { Input } from '@documenso/ui/primitives/input';
export type SigningVolume = { export type SigningVolume = {
id: number; id: number;
name: string | null; name: string;
email: string;
signingVolume: number; signingVolume: number;
createdAt: Date; createdAt: Date;
planId: string; planId: string;
userId?: number | null;
teamId?: number | null;
isTeam: boolean;
}; };
type LeaderboardTableProps = { type LeaderboardTableProps = {

View File

@ -1,17 +1,7 @@
import { Prisma } from '@prisma/client';
import { prisma } from '@documenso/prisma'; import { prisma } from '@documenso/prisma';
import { DocumentStatus, SubscriptionStatus } from '@documenso/prisma/client'; import { DocumentStatus, SubscriptionStatus } from '@documenso/prisma/client';
export type SigningVolume = { type GetSigningVolumeOptions = {
id: number;
name: string;
signingVolume: number;
createdAt: Date;
planId: string;
};
export type GetSigningVolumeOptions = {
search?: string; search?: string;
page?: number; page?: number;
perPage?: number; perPage?: number;
@ -19,133 +9,160 @@ export type GetSigningVolumeOptions = {
sortOrder?: 'asc' | 'desc'; sortOrder?: 'asc' | 'desc';
}; };
export async function getSigningVolume({ export const getSigningVolume = async ({
search = '', search = '',
page = 1, page = 1,
perPage = 10, perPage = 10,
sortBy = 'signingVolume', sortBy = 'signingVolume',
sortOrder = 'desc', sortOrder = 'desc',
}: GetSigningVolumeOptions) { }: GetSigningVolumeOptions) => {
const skip = (page - 1) * perPage; const validPage = Math.max(1, page);
const validPerPage = Math.max(1, perPage);
const skip = (validPage - 1) * validPerPage;
// Find all unique customerIds from both personal and team subscriptions const activeSubscriptions = await prisma.subscription.findMany({
const activeCustomerIds = await prisma.$queryRaw<{ customerId: string }[]>` where: {
SELECT DISTINCT "customerId" status: SubscriptionStatus.ACTIVE,
FROM ( },
-- Get customerIds from users with active subscriptions select: {
SELECT u."customerId" id: true,
FROM "User" u planId: true,
JOIN "Subscription" s ON u.id = s."userId" userId: true,
WHERE s.status = 'ACTIVE' AND u."customerId" IS NOT NULL teamId: true,
createdAt: true,
UNION user: {
-- Get customerIds from teams with active subscriptions
SELECT t."customerId"
FROM "Team" t
JOIN "Subscription" s ON t.id = s."teamId"
WHERE s.status = 'ACTIVE' AND t."customerId" IS NOT NULL
) AS active_customers
${search ? Prisma.sql`WHERE "customerId" LIKE ${`%${search}%`}` : Prisma.empty}
`;
const totalCustomerCount = activeCustomerIds.length;
const paginatedCustomerIds = activeCustomerIds.slice(skip, skip + perPage);
const customerData = await Promise.all(
paginatedCustomerIds.map(async ({ customerId }) => {
const users = await prisma.user.findMany({
where: { customerId },
select: { select: {
id: true, id: true,
name: true, name: true,
email: true, email: true,
createdAt: true, createdAt: true,
}, },
}); },
team: {
const teams = await prisma.team.findMany({
where: { customerId },
select: { select: {
id: true, id: true,
name: true, name: true,
teamEmail: {
select: {
email: true,
},
},
createdAt: true, createdAt: true,
}, },
},
},
}); });
const userDocumentCount = await prisma.document.count({ const subscriptionData = activeSubscriptions.map((subscription) => {
const isTeam = !!subscription.teamId;
return {
id: subscription.id,
planId: subscription.planId,
userId: subscription.userId,
teamId: subscription.teamId,
name: isTeam ? subscription.team?.name : subscription.user?.name || '',
email: isTeam
? subscription.team?.teamEmail?.email || `Team ${subscription.team?.id}`
: subscription.user?.email || '',
createdAt: isTeam ? subscription.team?.createdAt : subscription.user?.createdAt,
isTeam,
};
});
const filteredSubscriptions = search
? subscriptionData.filter((sub) => {
const searchLower = search.toLowerCase();
return (
sub.name?.toLowerCase().includes(searchLower) ||
sub.email?.toLowerCase().includes(searchLower)
);
})
: subscriptionData;
const leaderboardWithVolume = await Promise.all(
filteredSubscriptions.map(async (subscription) => {
let signingVolume = 0;
if (subscription.userId) {
const personalCount = await prisma.document.count({
where: { where: {
userId: { in: users.map((user) => user.id) }, userId: subscription.userId,
status: DocumentStatus.COMPLETED, status: DocumentStatus.COMPLETED,
}, },
}); });
const teamDocumentCount = await prisma.document.count({ signingVolume += personalCount;
where: {
teamId: { in: teams.map((team) => team.id) },
status: DocumentStatus.COMPLETED,
},
});
const subscription = await prisma.subscription.findFirst({ const userTeams = await prisma.teamMember.findMany({
where: { where: {
OR: [{ user: { customerId } }, { team: { customerId } }], userId: subscription.userId,
status: SubscriptionStatus.ACTIVE,
}, },
select: { select: {
planId: true, teamId: true,
}, },
}); });
const displayName = users[0]?.name || teams[0]?.name || customerId; if (userTeams.length > 0) {
const teamIds = userTeams.map((team) => team.teamId);
const teamCount = await prisma.document.count({
where: {
teamId: {
in: teamIds,
},
status: DocumentStatus.COMPLETED,
},
});
const creationDates = [ signingVolume += teamCount;
...users.map((user) => user.createdAt), }
...teams.map((team) => team.createdAt), }
].filter(Boolean);
const createdAt = if (subscription.teamId) {
creationDates.length > 0 const teamCount = await prisma.document.count({
? new Date(Math.min(...creationDates.map((date) => date.getTime()))) where: {
: new Date(); teamId: subscription.teamId,
status: DocumentStatus.COMPLETED,
},
});
signingVolume += teamCount;
}
return { return {
id: users[0]?.id || teams[0]?.id || 0, ...subscription,
customerId, signingVolume,
name: displayName,
signingVolume: userDocumentCount + teamDocumentCount,
createdAt,
planId: subscription?.planId || '',
}; };
}), }),
); );
// Sort the results by the requested sort criteria // Sort the results
const sortedResults = [...customerData]; const sortedResults = [...leaderboardWithVolume].sort((a, b) => {
if (sortBy === 'name') { if (sortBy === 'name') {
sortedResults.sort((a, b) => { return sortOrder === 'asc'
return sortOrder === 'desc' ? (a.name || '').localeCompare(b.name || '')
? (b.name || '').localeCompare(a.name || '') : (b.name || '').localeCompare(a.name || '');
: (a.name || '').localeCompare(b.name || '');
});
} else if (sortBy === 'createdAt') {
sortedResults.sort((a, b) => {
return sortOrder === 'desc'
? b.createdAt.getTime() - a.createdAt.getTime()
: a.createdAt.getTime() - b.createdAt.getTime();
});
} else if (sortBy === 'signingVolume') {
sortedResults.sort((a, b) => {
return sortOrder === 'desc'
? b.signingVolume - a.signingVolume
: a.signingVolume - b.signingVolume;
});
} }
if (sortBy === 'createdAt') {
const dateA = a.createdAt ? new Date(a.createdAt).getTime() : 0;
const dateB = b.createdAt ? new Date(b.createdAt).getTime() : 0;
return sortOrder === 'asc' ? dateA - dateB : dateB - dateA;
}
// Default: sort by signingVolume
return sortOrder === 'asc'
? a.signingVolume - b.signingVolume
: b.signingVolume - a.signingVolume;
});
// Apply pagination
const paginatedResults = sortedResults.slice(skip, skip + validPerPage);
// Calculate total pages
const totalPages = Math.ceil(sortedResults.length / validPerPage);
return { return {
leaderboard: sortedResults, leaderboard: paginatedResults,
totalPages: Math.ceil(totalCustomerCount / perPage), totalPages,
};
}; };
}