mirror of
https://github.com/documenso/documenso.git
synced 2025-11-10 04:22:32 +10:00
196 lines
5.3 KiB
TypeScript
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,
|
|
};
|
|
};
|