mirror of
https://github.com/documenso/documenso
synced 2026-04-21 13:27:18 +00:00
106 lines
3.2 KiB
TypeScript
106 lines
3.2 KiB
TypeScript
import { DocumentStatus, EnvelopeType, RecipientRole, SigningStatus } from '@prisma/client';
|
|
|
|
import { kyselyPrisma, sql } from '@documenso/prisma';
|
|
|
|
import type { FindResultResponse } from '../../types/search-params';
|
|
|
|
export type AdminUnsealedDocument = {
|
|
id: string;
|
|
secondaryId: string;
|
|
title: string;
|
|
status: string;
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
userId: number;
|
|
teamId: number;
|
|
ownerName: string | null;
|
|
ownerEmail: string;
|
|
lastSignedAt: Date | null;
|
|
};
|
|
|
|
export type AdminFindUnsealedDocumentsOptions = {
|
|
page?: number;
|
|
perPage?: number;
|
|
};
|
|
|
|
export const adminFindUnsealedDocuments = async ({
|
|
page = 1,
|
|
perPage = 20,
|
|
}: AdminFindUnsealedDocumentsOptions): Promise<FindResultResponse<AdminUnsealedDocument[]>> => {
|
|
const offset = Math.max(page - 1, 0) * perPage;
|
|
|
|
const baseQuery = kyselyPrisma.$kysely
|
|
.selectFrom('Envelope')
|
|
.where('Envelope.status', '=', sql.lit(DocumentStatus.PENDING))
|
|
.where('Envelope.type', '=', sql.lit(EnvelopeType.DOCUMENT))
|
|
.where('Envelope.deletedAt', 'is', null)
|
|
// Must have at least one recipient.
|
|
.where((eb) =>
|
|
eb.exists(eb.selectFrom('Recipient').whereRef('Recipient.envelopeId', '=', 'Envelope.id')),
|
|
)
|
|
// Document is ready to seal: all recipients are SIGNED/CC, or any recipient REJECTED.
|
|
.where((eb) =>
|
|
eb.or([
|
|
// Case 1: All recipients are either SIGNED or CC.
|
|
eb.not(
|
|
eb.exists(
|
|
eb
|
|
.selectFrom('Recipient')
|
|
.whereRef('Recipient.envelopeId', '=', 'Envelope.id')
|
|
.where('Recipient.signingStatus', '!=', sql.lit(SigningStatus.SIGNED))
|
|
.where('Recipient.role', '!=', sql.lit(RecipientRole.CC)),
|
|
),
|
|
),
|
|
// Case 2: Any recipient has rejected.
|
|
eb.exists(
|
|
eb
|
|
.selectFrom('Recipient')
|
|
.whereRef('Recipient.envelopeId', '=', 'Envelope.id')
|
|
.where('Recipient.signingStatus', '=', sql.lit(SigningStatus.REJECTED)),
|
|
),
|
|
]),
|
|
);
|
|
|
|
const [data, countResult] = await Promise.all([
|
|
baseQuery
|
|
.innerJoin('User', 'User.id', 'Envelope.userId')
|
|
.select([
|
|
'Envelope.id',
|
|
'Envelope.secondaryId',
|
|
'Envelope.title',
|
|
'Envelope.status',
|
|
'Envelope.createdAt',
|
|
'Envelope.updatedAt',
|
|
'Envelope.userId',
|
|
'Envelope.teamId',
|
|
'User.name as ownerName',
|
|
'User.email as ownerEmail',
|
|
])
|
|
.select((eb) =>
|
|
eb
|
|
.selectFrom('Recipient')
|
|
.whereRef('Recipient.envelopeId', '=', 'Envelope.id')
|
|
.select(sql<Date>`max("Recipient"."signedAt")`.as('lastSignedAt'))
|
|
.as('lastSignedAt'),
|
|
)
|
|
.orderBy('Envelope.createdAt', 'desc')
|
|
.limit(perPage)
|
|
.offset(offset)
|
|
.execute(),
|
|
baseQuery.select(({ fn }) => [fn.countAll().as('count')]).execute(),
|
|
]);
|
|
|
|
const count = Number(countResult[0]?.count ?? 0);
|
|
const formattedData: AdminUnsealedDocument[] = data.map((document) => ({
|
|
...document,
|
|
id: String(document.id),
|
|
}));
|
|
|
|
return {
|
|
data: formattedData,
|
|
count,
|
|
currentPage: Math.max(page, 1),
|
|
perPage,
|
|
totalPages: Math.ceil(count / perPage),
|
|
};
|
|
};
|