Files
documenso/packages/lib/server-only/admin/get-signing-volume.ts
Ephraim Duncan f0dcf7e9bf fix: signing volume query (#1753)
This pull request updates the implementation of the admin leaderboard,
enhancing data handling and improving type safety. It introduces clearer
differentiation between users and teams, adds additional fields to track
more relevant information, and refactors the querying logic to optimize
performance and maintainability.
2025-04-24 16:14:38 +10:00

196 lines
5.3 KiB
TypeScript

import { prisma } from '@documenso/prisma';
import { DocumentStatus, SubscriptionStatus } from '@documenso/prisma/client';
type GetSigningVolumeOptions = {
search?: string;
page?: number;
perPage?: number;
sortBy?: 'name' | 'createdAt' | 'signingVolume';
sortOrder?: 'asc' | 'desc';
};
export const getSigningVolume = async ({
search = '',
page = 1,
perPage = 10,
sortBy = 'signingVolume',
sortOrder = 'desc',
}: GetSigningVolumeOptions) => {
const validPage = Math.max(1, page);
const validPerPage = Math.max(1, perPage);
const skip = (validPage - 1) * validPerPage;
const activeSubscriptions = await prisma.subscription.findMany({
where: {
status: SubscriptionStatus.ACTIVE,
},
select: {
id: true,
planId: true,
userId: true,
teamId: true,
createdAt: true,
user: {
select: {
id: true,
name: true,
email: true,
createdAt: true,
},
},
team: {
select: {
id: true,
name: true,
teamEmail: {
select: {
email: true,
},
},
createdAt: true,
},
},
},
});
const userSubscriptionsMap = new Map();
const teamSubscriptionsMap = new Map();
activeSubscriptions.forEach((subscription) => {
const isTeam = !!subscription.teamId;
if (isTeam && subscription.teamId) {
if (!teamSubscriptionsMap.has(subscription.teamId)) {
teamSubscriptionsMap.set(subscription.teamId, {
id: subscription.id,
planId: subscription.planId,
teamId: subscription.teamId,
name: subscription.team?.name || '',
email: subscription.team?.teamEmail?.email || `Team ${subscription.team?.id}`,
createdAt: subscription.team?.createdAt,
isTeam: true,
subscriptionIds: [subscription.id],
});
} else {
const existingTeam = teamSubscriptionsMap.get(subscription.teamId);
existingTeam.subscriptionIds.push(subscription.id);
}
} else if (subscription.userId) {
if (!userSubscriptionsMap.has(subscription.userId)) {
userSubscriptionsMap.set(subscription.userId, {
id: subscription.id,
planId: subscription.planId,
userId: subscription.userId,
name: subscription.user?.name || '',
email: subscription.user?.email || '',
createdAt: subscription.user?.createdAt,
isTeam: false,
subscriptionIds: [subscription.id],
});
} else {
const existingUser = userSubscriptionsMap.get(subscription.userId);
existingUser.subscriptionIds.push(subscription.id);
}
}
});
const subscriptions = [
...Array.from(userSubscriptionsMap.values()),
...Array.from(teamSubscriptionsMap.values()),
];
const filteredSubscriptions = search
? subscriptions.filter((sub) => {
const searchLower = search.toLowerCase();
return (
sub.name?.toLowerCase().includes(searchLower) ||
sub.email?.toLowerCase().includes(searchLower)
);
})
: subscriptions;
const signingVolume = await Promise.all(
filteredSubscriptions.map(async (subscription) => {
let signingVolume = 0;
if (subscription.userId && !subscription.isTeam) {
const personalCount = await prisma.document.count({
where: {
userId: subscription.userId,
status: DocumentStatus.COMPLETED,
teamId: null,
},
});
signingVolume += personalCount;
const userTeams = await prisma.teamMember.findMany({
where: {
userId: subscription.userId,
},
select: {
teamId: true,
},
});
if (userTeams.length > 0) {
const teamIds = userTeams.map((team) => team.teamId);
const teamCount = await prisma.document.count({
where: {
teamId: {
in: teamIds,
},
status: DocumentStatus.COMPLETED,
},
});
signingVolume += teamCount;
}
}
if (subscription.teamId) {
const teamCount = await prisma.document.count({
where: {
teamId: subscription.teamId,
status: DocumentStatus.COMPLETED,
},
});
signingVolume += teamCount;
}
return {
...subscription,
signingVolume,
};
}),
);
const sortedResults = [...signingVolume].sort((a, b) => {
if (sortBy === 'name') {
return sortOrder === 'asc'
? (a.name || '').localeCompare(b.name || '')
: (b.name || '').localeCompare(a.name || '');
}
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;
}
return sortOrder === 'asc'
? a.signingVolume - b.signingVolume
: b.signingVolume - a.signingVolume;
});
const paginatedResults = sortedResults.slice(skip, skip + validPerPage);
const totalPages = Math.ceil(sortedResults.length / validPerPage);
return {
leaderboard: paginatedResults,
totalPages,
};
};