2025-01-02 15:33:37 +11:00
import { DocumentDataType , DocumentStatus } from '@prisma/client' ;
2023-06-21 23:49:23 +10:00
import { TRPCError } from '@trpc/server' ;
2024-04-10 15:13:18 +07:00
import { DateTime } from 'luxon' ;
2023-06-21 23:49:23 +10:00
2023-10-15 20:26:32 +11:00
import { getServerLimits } from '@documenso/ee/server-only/limits/server' ;
2024-04-10 15:13:18 +07:00
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app' ;
2024-01-17 17:28:28 +11:00
import { DOCUMENSO_ENCRYPTION_KEY } from '@documenso/lib/constants/crypto' ;
2025-01-19 22:07:02 +11:00
import { AppError , AppErrorCode } from '@documenso/lib/errors/app-error' ;
2024-04-10 15:13:18 +07:00
import { encryptSecondaryData } from '@documenso/lib/server-only/crypto/encrypt' ;
2025-01-16 13:36:00 +11:00
import { createDocumentData } from '@documenso/lib/server-only/document-data/create-document-data' ;
2023-12-02 09:38:24 +11:00
import { upsertDocumentMeta } from '@documenso/lib/server-only/document-meta/upsert-document-meta' ;
2025-01-14 00:43:35 +11:00
import { createDocument } from '@documenso/lib/server-only/document/create-document' ;
2025-01-16 13:36:00 +11:00
import { createDocumentV2 } from '@documenso/lib/server-only/document/create-document-v2' ;
2023-12-06 05:41:51 +05:30
import { deleteDocument } from '@documenso/lib/server-only/document/delete-document' ;
2025-01-14 00:43:35 +11:00
import { duplicateDocument } from '@documenso/lib/server-only/document/duplicate-document-by-id' ;
2024-02-15 18:20:10 +11:00
import { findDocumentAuditLogs } from '@documenso/lib/server-only/document/find-document-audit-logs' ;
2025-01-14 00:43:35 +11:00
import { findDocuments } from '@documenso/lib/server-only/document/find-documents' ;
2023-09-07 19:27:21 +10:00
import { getDocumentById } from '@documenso/lib/server-only/document/get-document-by-id' ;
import { getDocumentAndSenderByToken } from '@documenso/lib/server-only/document/get-document-by-token' ;
2025-01-14 00:43:35 +11:00
import { getDocumentWithDetailsById } from '@documenso/lib/server-only/document/get-document-with-details-by-id' ;
2025-01-02 15:33:37 +11:00
import type { GetStatsInput } from '@documenso/lib/server-only/document/get-stats' ;
import { getStats } from '@documenso/lib/server-only/document/get-stats' ;
2025-01-14 00:43:35 +11:00
import { moveDocumentToTeam } from '@documenso/lib/server-only/document/move-document-to-team' ;
2023-11-16 07:35:45 +05:30
import { resendDocument } from '@documenso/lib/server-only/document/resend-document' ;
2023-12-06 07:18:05 +05:30
import { searchDocumentsWithKeyword } from '@documenso/lib/server-only/document/search-documents-with-keyword' ;
2025-01-14 00:43:35 +11:00
import { sendDocument } from '@documenso/lib/server-only/document/send-document' ;
import { updateDocument } from '@documenso/lib/server-only/document/update-document' ;
2025-01-02 15:33:37 +11:00
import { getTeamById } from '@documenso/lib/server-only/team/get-team' ;
2024-01-17 17:28:28 +11:00
import { symmetricEncrypt } from '@documenso/lib/universal/crypto' ;
2025-01-16 13:36:00 +11:00
import { getPresignPostUrl } from '@documenso/lib/universal/upload/server-actions' ;
2023-06-21 23:49:23 +10:00
2023-09-07 19:27:21 +10:00
import { authenticatedProcedure , procedure , router } from '../trpc' ;
2023-06-21 23:49:23 +10:00
import {
2025-01-14 00:43:35 +11:00
ZCreateDocumentRequestSchema ,
2025-01-16 13:36:00 +11:00
ZCreateDocumentV2RequestSchema ,
ZCreateDocumentV2ResponseSchema ,
2024-12-10 16:11:20 +09:00
ZDeleteDocumentMutationSchema ,
2025-01-14 00:43:35 +11:00
ZDistributeDocumentRequestSchema ,
ZDistributeDocumentResponseSchema ,
2024-04-10 15:13:18 +07:00
ZDownloadAuditLogsMutationSchema ,
2024-08-09 04:19:48 +02:00
ZDownloadCertificateMutationSchema ,
2025-01-14 00:43:35 +11:00
ZDuplicateDocumentRequestSchema ,
ZDuplicateDocumentResponseSchema ,
2024-02-15 18:20:10 +11:00
ZFindDocumentAuditLogsQuerySchema ,
2025-01-02 15:33:37 +11:00
ZFindDocumentsInternalRequestSchema ,
ZFindDocumentsInternalResponseSchema ,
2025-01-14 00:43:35 +11:00
ZFindDocumentsRequestSchema ,
ZFindDocumentsResponseSchema ,
2025-01-20 19:47:39 +11:00
ZGenericSuccessResponse ,
2023-09-07 19:27:21 +10:00
ZGetDocumentByIdQuerySchema ,
ZGetDocumentByTokenQuerySchema ,
2025-01-14 00:43:35 +11:00
ZGetDocumentWithDetailsByIdRequestSchema ,
ZGetDocumentWithDetailsByIdResponseSchema ,
ZMoveDocumentToTeamResponseSchema ,
2024-12-14 01:23:35 +09:00
ZMoveDocumentToTeamSchema ,
2023-11-16 07:35:45 +05:30
ZResendDocumentMutationSchema ,
2023-12-06 07:18:05 +05:30
ZSearchDocumentsMutationSchema ,
2024-01-12 20:54:59 +05:30
ZSetPasswordForDocumentMutationSchema ,
2024-09-16 12:36:45 +00:00
ZSetSigningOrderForDocumentMutationSchema ,
2025-01-20 19:47:39 +11:00
ZSuccessResponseSchema ,
2025-01-11 15:33:20 +11:00
ZUpdateDocumentRequestSchema ,
2025-01-14 00:43:35 +11:00
ZUpdateDocumentResponseSchema ,
2023-06-21 23:49:23 +10:00
} from './schema' ;
export const documentRouter = router ( {
2024-12-14 01:23:35 +09:00
/ * *
* @private
* /
2023-09-07 19:27:21 +10:00
getDocumentById : authenticatedProcedure
. input ( ZGetDocumentByIdQuerySchema )
. query ( async ( { input , ctx } ) = > {
2025-01-11 15:33:20 +11:00
const { teamId } = ctx ;
const { documentId } = input ;
2024-12-06 16:01:24 +09:00
return await getDocumentById ( {
userId : ctx.user.id ,
2025-01-11 15:33:20 +11:00
teamId ,
documentId ,
2024-12-06 16:01:24 +09:00
} ) ;
2023-09-07 19:27:21 +10:00
} ) ,
2024-12-14 01:23:35 +09:00
/ * *
* @private
* /
2024-03-28 13:13:29 +08:00
getDocumentByToken : procedure
. input ( ZGetDocumentByTokenQuerySchema )
. query ( async ( { input , ctx } ) = > {
2024-12-06 16:01:24 +09:00
const { token } = input ;
2023-09-07 19:27:21 +10:00
2024-12-06 16:01:24 +09:00
return await getDocumentAndSenderByToken ( {
token ,
userId : ctx.user?.id ,
} ) ;
2024-03-28 13:13:29 +08:00
} ) ,
2023-09-07 19:27:21 +10:00
2024-12-14 01:23:35 +09:00
/ * *
* @public
* /
2024-12-10 16:11:20 +09:00
findDocuments : authenticatedProcedure
. meta ( {
openapi : {
method : 'GET' ,
2025-01-11 15:33:20 +11:00
path : '/document' ,
2024-12-10 16:11:20 +09:00
summary : 'Find documents' ,
description : 'Find documents based on a search criteria' ,
2025-01-11 15:33:20 +11:00
tags : [ 'Document' ] ,
2024-12-10 16:11:20 +09:00
} ,
} )
2025-01-14 00:43:35 +11:00
. input ( ZFindDocumentsRequestSchema )
2024-12-14 01:23:35 +09:00
. output ( ZFindDocumentsResponseSchema )
2024-12-10 16:11:20 +09:00
. query ( async ( { input , ctx } ) = > {
2025-01-11 15:33:20 +11:00
const { user , teamId } = ctx ;
2024-12-10 16:11:20 +09:00
2025-01-11 15:33:20 +11:00
const { query , templateId , page , perPage , orderByDirection , orderByColumn , source , status } =
input ;
2024-12-10 16:11:20 +09:00
const documents = await findDocuments ( {
userId : user.id ,
teamId ,
templateId ,
2024-12-11 19:39:50 +09:00
query ,
2024-12-10 16:11:20 +09:00
source ,
status ,
page ,
perPage ,
2024-12-14 01:23:35 +09:00
orderBy : orderByColumn ? { column : orderByColumn , direction : orderByDirection } : undefined ,
2024-12-10 16:11:20 +09:00
} ) ;
return documents ;
} ) ,
2025-01-02 15:33:37 +11:00
/ * *
* Internal endpoint for / d o c u m e n t s p a g e t o a d d i t i o n a l l y r e t u r n g e t S t a t s .
*
* @private
* /
findDocumentsInternal : authenticatedProcedure
. input ( ZFindDocumentsInternalRequestSchema )
. output ( ZFindDocumentsInternalResponseSchema )
. query ( async ( { input , ctx } ) = > {
const { user , teamId } = ctx ;
const {
query ,
templateId ,
page ,
perPage ,
orderByDirection ,
orderByColumn ,
source ,
status ,
period ,
senderIds ,
} = input ;
const getStatOptions : GetStatsInput = {
user ,
period ,
search : query ,
} ;
if ( teamId ) {
const team = await getTeamById ( { userId : user.id , teamId } ) ;
getStatOptions . team = {
teamId : team.id ,
teamEmail : team.teamEmail?.email ,
senderIds ,
currentTeamMemberRole : team.currentTeamMember?.role ,
currentUserEmail : user.email ,
userId : user.id ,
} ;
}
const [ stats , documents ] = await Promise . all ( [
getStats ( getStatOptions ) ,
findDocuments ( {
userId : user.id ,
teamId ,
query ,
templateId ,
page ,
perPage ,
source ,
status ,
period ,
senderIds ,
orderBy : orderByColumn
? { column : orderByColumn , direction : orderByDirection }
: undefined ,
} ) ,
] ) ;
return {
. . . documents ,
stats ,
} ;
} ) ,
2024-12-14 01:23:35 +09:00
/ * *
* @public
*
* Todo : Refactor to getDocumentById .
* /
2024-03-26 21:12:41 +08:00
getDocumentWithDetailsById : authenticatedProcedure
2024-12-10 16:11:20 +09:00
. meta ( {
openapi : {
method : 'GET' ,
path : '/document/{documentId}' ,
summary : 'Get document' ,
description : 'Returns a document given an ID' ,
2025-01-11 15:33:20 +11:00
tags : [ 'Document' ] ,
2024-12-10 16:11:20 +09:00
} ,
} )
2025-01-14 00:43:35 +11:00
. input ( ZGetDocumentWithDetailsByIdRequestSchema )
2024-12-14 01:23:35 +09:00
. output ( ZGetDocumentWithDetailsByIdResponseSchema )
2024-03-26 21:12:41 +08:00
. query ( async ( { input , ctx } ) = > {
2025-01-11 15:33:20 +11:00
const { teamId , user } = ctx ;
const { documentId } = input ;
2024-12-06 16:01:24 +09:00
return await getDocumentWithDetailsById ( {
2025-01-11 15:33:20 +11:00
userId : user.id ,
teamId ,
documentId ,
2024-12-06 16:01:24 +09:00
} ) ;
2024-03-26 21:12:41 +08:00
} ) ,
2025-01-16 13:36:00 +11:00
/ * *
* Temporariy endpoint for V2 Beta until we allow passthrough documents on create .
*
* @public
* @deprecated
* /
createDocumentTemporary : authenticatedProcedure
. meta ( {
openapi : {
method : 'POST' ,
path : '/document/create/beta' ,
summary : 'Create document' ,
description :
'You will need to upload the PDF to the provided URL returned. Note: Once V2 API is released, this will be removed since we will allow direct uploads, instead of using an upload URL.' ,
tags : [ 'Document' ] ,
} ,
} )
. input ( ZCreateDocumentV2RequestSchema )
. output ( ZCreateDocumentV2ResponseSchema )
. mutation ( async ( { input , ctx } ) = > {
const { teamId } = ctx ;
const {
title ,
externalId ,
visibility ,
globalAccessAuth ,
globalActionAuth ,
recipients ,
meta ,
} = input ;
const { remaining } = await getServerLimits ( { email : ctx.user.email , teamId } ) ;
if ( remaining . documents <= 0 ) {
2025-01-19 22:07:02 +11:00
throw new AppError ( AppErrorCode . LIMIT_EXCEEDED , {
2025-01-16 13:36:00 +11:00
message : 'You have reached your document limit for this month. Please upgrade your plan.' ,
2025-01-19 22:07:02 +11:00
statusCode : 400 ,
2025-01-16 13:36:00 +11:00
} ) ;
}
const fileName = title . endsWith ( '.pdf' ) ? title : ` ${ title } .pdf ` ;
const { url , key } = await getPresignPostUrl ( fileName , 'application/pdf' ) ;
const documentData = await createDocumentData ( {
data : key ,
type : DocumentDataType . S3_PATH ,
} ) ;
const createdDocument = await createDocumentV2 ( {
userId : ctx.user.id ,
teamId ,
documentDataId : documentData.id ,
normalizePdf : false , // Not normalizing because of presigned URL.
data : {
title ,
externalId ,
visibility ,
globalAccessAuth ,
globalActionAuth ,
recipients ,
} ,
meta ,
requestMetadata : ctx.metadata ,
} ) ;
return {
document : createdDocument ,
uploadUrl : url ,
} ;
} ) ,
2024-12-14 01:23:35 +09:00
/ * *
2025-01-11 15:33:20 +11:00
* Wait until RR7 so we can passthrough documents .
*
* @private
2024-12-14 01:23:35 +09:00
* /
2023-09-14 12:46:36 +10:00
createDocument : authenticatedProcedure
2025-01-11 15:33:20 +11:00
// .meta({
// openapi: {
// method: 'POST',
// path: '/document/create',
// summary: 'Create document',
// tags: ['Document'],
// },
// })
2025-01-14 00:43:35 +11:00
. input ( ZCreateDocumentRequestSchema )
2023-09-14 12:46:36 +10:00
. mutation ( async ( { input , ctx } ) = > {
2025-01-11 15:33:20 +11:00
const { teamId } = ctx ;
const { title , documentDataId , timezone } = input ;
2023-09-14 12:46:36 +10:00
2024-12-06 16:01:24 +09:00
const { remaining } = await getServerLimits ( { email : ctx.user.email , teamId } ) ;
2023-09-14 12:46:36 +10:00
2024-12-06 16:01:24 +09:00
if ( remaining . documents <= 0 ) {
2025-01-19 22:07:02 +11:00
throw new AppError ( AppErrorCode . LIMIT_EXCEEDED , {
2024-12-06 16:01:24 +09:00
message : 'You have reached your document limit for this month. Please upgrade your plan.' ,
2025-01-19 22:07:02 +11:00
statusCode : 400 ,
2023-09-14 12:46:36 +10:00
} ) ;
}
2024-12-06 16:01:24 +09:00
return await createDocument ( {
userId : ctx.user.id ,
teamId ,
title ,
documentDataId ,
2024-12-18 08:14:14 +11:00
normalizePdf : true ,
2024-12-31 01:27:24 +02:00
timezone ,
2025-01-11 15:33:20 +11:00
requestMetadata : ctx.metadata ,
2024-12-06 16:01:24 +09:00
} ) ;
2023-09-14 12:46:36 +10:00
} ) ,
2024-12-14 01:23:35 +09:00
/ * *
* @public
*
* Todo : Refactor to updateDocument .
* /
2024-03-28 13:13:29 +08:00
setSettingsForDocument : authenticatedProcedure
2024-12-10 16:11:20 +09:00
. meta ( {
openapi : {
method : 'POST' ,
2025-01-11 15:33:20 +11:00
path : '/document/update' ,
2024-12-10 16:11:20 +09:00
summary : 'Update document' ,
2025-01-11 15:33:20 +11:00
tags : [ 'Document' ] ,
2024-12-10 16:11:20 +09:00
} ,
} )
2025-01-11 15:33:20 +11:00
. input ( ZUpdateDocumentRequestSchema )
. output ( ZUpdateDocumentResponseSchema )
2024-03-28 13:13:29 +08:00
. mutation ( async ( { input , ctx } ) = > {
2025-01-11 15:33:20 +11:00
const { teamId } = ctx ;
const { documentId , data , meta = { } } = input ;
2024-12-06 16:01:24 +09:00
const userId = ctx . user . id ;
2025-01-11 15:33:20 +11:00
if ( Object . values ( meta ) . length > 0 ) {
2024-12-06 16:01:24 +09:00
await upsertDocumentMeta ( {
2025-01-11 15:33:20 +11:00
userId : ctx.user.id ,
teamId ,
2024-03-28 13:13:29 +08:00
documentId ,
2025-01-11 15:33:20 +11:00
subject : meta.subject ,
message : meta.message ,
2024-12-06 16:01:24 +09:00
timezone : meta.timezone ,
2025-01-11 15:33:20 +11:00
dateFormat : meta.dateFormat ,
2024-12-06 16:01:24 +09:00
language : meta.language ,
2025-01-11 15:33:20 +11:00
typedSignatureEnabled : meta.typedSignatureEnabled ,
redirectUrl : meta.redirectUrl ,
distributionMethod : meta.distributionMethod ,
2025-01-16 13:36:00 +11:00
signingOrder : meta.signingOrder ,
2025-01-11 15:33:20 +11:00
emailSettings : meta.emailSettings ,
requestMetadata : ctx.metadata ,
2024-03-28 13:13:29 +08:00
} ) ;
}
2024-12-06 16:01:24 +09:00
2025-01-11 15:33:20 +11:00
return await updateDocument ( {
2024-12-06 16:01:24 +09:00
userId ,
teamId ,
documentId ,
data ,
2025-01-11 15:33:20 +11:00
requestMetadata : ctx.metadata ,
2024-12-06 16:01:24 +09:00
} ) ;
2024-03-28 13:13:29 +08:00
} ) ,
2024-12-14 01:23:35 +09:00
/ * *
* @public
* /
2024-12-10 16:11:20 +09:00
deleteDocument : authenticatedProcedure
. meta ( {
openapi : {
2025-01-16 13:36:00 +11:00
method : 'POST' ,
path : '/document/delete' ,
2024-12-10 16:11:20 +09:00
summary : 'Delete document' ,
2025-01-11 15:33:20 +11:00
tags : [ 'Document' ] ,
2024-12-10 16:11:20 +09:00
} ,
} )
. input ( ZDeleteDocumentMutationSchema )
2025-01-20 19:47:39 +11:00
. output ( ZSuccessResponseSchema )
2024-12-10 16:11:20 +09:00
. mutation ( async ( { input , ctx } ) = > {
2025-01-11 15:33:20 +11:00
const { teamId } = ctx ;
const { documentId } = input ;
2024-12-10 16:11:20 +09:00
const userId = ctx . user . id ;
2024-12-14 01:23:35 +09:00
await deleteDocument ( {
2024-12-10 16:11:20 +09:00
id : documentId ,
userId ,
teamId ,
2025-01-11 15:33:20 +11:00
requestMetadata : ctx.metadata ,
2024-12-10 16:11:20 +09:00
} ) ;
2025-01-20 19:47:39 +11:00
return ZGenericSuccessResponse ;
2024-12-10 16:11:20 +09:00
} ) ,
2024-12-14 01:23:35 +09:00
/ * *
* @public
* /
2024-12-10 16:11:20 +09:00
moveDocumentToTeam : authenticatedProcedure
. meta ( {
openapi : {
method : 'POST' ,
2025-01-11 15:33:20 +11:00
path : '/document/move' ,
2024-12-10 16:11:20 +09:00
summary : 'Move document' ,
2025-01-11 15:33:20 +11:00
description : 'Move a document from your personal account to a team' ,
tags : [ 'Document' ] ,
2024-12-10 16:11:20 +09:00
} ,
} )
2024-12-14 01:23:35 +09:00
. input ( ZMoveDocumentToTeamSchema )
. output ( ZMoveDocumentToTeamResponseSchema )
2024-12-10 16:11:20 +09:00
. mutation ( async ( { input , ctx } ) = > {
const { documentId , teamId } = input ;
const userId = ctx . user . id ;
return await moveDocumentToTeam ( {
documentId ,
teamId ,
userId ,
2025-01-11 15:33:20 +11:00
requestMetadata : ctx.metadata ,
2024-12-06 16:01:24 +09:00
} ) ;
2023-11-28 09:26:50 +05:30
} ) ,
2024-12-14 01:23:35 +09:00
/ * *
* @private
* /
2024-01-17 17:17:08 +11:00
setPasswordForDocument : authenticatedProcedure
. input ( ZSetPasswordForDocumentMutationSchema )
. mutation ( async ( { input , ctx } ) = > {
2025-01-11 15:33:20 +11:00
const { teamId } = ctx ;
2024-12-06 16:01:24 +09:00
const { documentId , password } = input ;
2024-01-17 17:28:28 +11:00
2024-12-06 16:01:24 +09:00
const key = DOCUMENSO_ENCRYPTION_KEY ;
2024-01-17 17:28:28 +11:00
2024-12-06 16:01:24 +09:00
if ( ! key ) {
throw new Error ( 'Missing encryption key' ) ;
2024-01-17 17:17:08 +11:00
}
2024-12-06 16:01:24 +09:00
const securePassword = symmetricEncrypt ( {
data : password ,
key ,
} ) ;
await upsertDocumentMeta ( {
2025-01-11 15:33:20 +11:00
userId : ctx.user.id ,
teamId ,
2024-12-06 16:01:24 +09:00
documentId ,
password : securePassword ,
2025-01-11 15:33:20 +11:00
requestMetadata : ctx.metadata ,
2024-12-06 16:01:24 +09:00
} ) ;
2024-01-17 17:17:08 +11:00
} ) ,
2023-07-26 18:52:53 +10:00
2024-12-14 01:23:35 +09:00
/ * *
* @private
2025-01-16 13:36:00 +11:00
*
* Todo : Remove and use ` updateDocument ` endpoint instead .
2024-12-14 01:23:35 +09:00
* /
2024-09-16 12:36:45 +00:00
setSigningOrderForDocument : authenticatedProcedure
. input ( ZSetSigningOrderForDocumentMutationSchema )
. mutation ( async ( { input , ctx } ) = > {
2025-01-11 15:33:20 +11:00
const { teamId } = ctx ;
2024-12-06 16:01:24 +09:00
const { documentId , signingOrder } = input ;
return await upsertDocumentMeta ( {
2025-01-11 15:33:20 +11:00
userId : ctx.user.id ,
teamId ,
2024-12-06 16:01:24 +09:00
documentId ,
signingOrder ,
2025-01-11 15:33:20 +11:00
requestMetadata : ctx.metadata ,
2024-12-06 16:01:24 +09:00
} ) ;
2024-09-16 12:36:45 +00:00
} ) ,
2024-12-14 01:23:35 +09:00
/ * *
* @public
*
* Todo : Refactor to distributeDocument .
* Todo : Rework before releasing API .
* /
2023-07-26 18:52:53 +10:00
sendDocument : authenticatedProcedure
2024-12-10 16:11:20 +09:00
. meta ( {
openapi : {
method : 'POST' ,
2025-01-11 15:33:20 +11:00
path : '/document/distribute' ,
2024-12-10 16:11:20 +09:00
summary : 'Distribute document' ,
description : 'Send the document out to recipients based on your distribution method' ,
2025-01-11 15:33:20 +11:00
tags : [ 'Document' ] ,
2024-12-10 16:11:20 +09:00
} ,
} )
2025-01-14 00:43:35 +11:00
. input ( ZDistributeDocumentRequestSchema )
. output ( ZDistributeDocumentResponseSchema )
2023-07-26 18:52:53 +10:00
. mutation ( async ( { input , ctx } ) = > {
2025-01-11 15:33:20 +11:00
const { teamId } = ctx ;
const { documentId , meta = { } } = input ;
if ( Object . values ( meta ) . length > 0 ) {
2024-12-06 16:01:24 +09:00
await upsertDocumentMeta ( {
2025-01-11 15:33:20 +11:00
userId : ctx.user.id ,
teamId ,
2023-07-26 18:52:53 +10:00
documentId ,
2024-12-06 16:01:24 +09:00
subject : meta.subject ,
message : meta.message ,
dateFormat : meta.dateFormat ,
timezone : meta.timezone ,
redirectUrl : meta.redirectUrl ,
distributionMethod : meta.distributionMethod ,
emailSettings : meta.emailSettings ,
2025-01-11 15:33:20 +11:00
language : meta.language ,
requestMetadata : ctx.metadata ,
2023-07-26 18:52:53 +10:00
} ) ;
}
2024-12-06 16:01:24 +09:00
return await sendDocument ( {
userId : ctx.user.id ,
documentId ,
teamId ,
2025-01-11 15:33:20 +11:00
requestMetadata : ctx.metadata ,
2024-12-06 16:01:24 +09:00
} ) ;
2023-07-26 18:52:53 +10:00
} ) ,
2023-11-08 09:25:44 +00:00
2024-12-14 01:23:35 +09:00
/ * *
* @public
2025-01-11 15:33:20 +11:00
*
* Todo : Refactor to redistributeDocument .
2024-12-14 01:23:35 +09:00
* /
2023-11-16 07:35:45 +05:30
resendDocument : authenticatedProcedure
2024-12-10 16:11:20 +09:00
. meta ( {
openapi : {
method : 'POST' ,
2025-01-11 15:33:20 +11:00
path : '/document/redistribute' ,
summary : 'Redistribute document' ,
2024-12-10 16:11:20 +09:00
description :
2025-01-11 15:33:20 +11:00
'Redistribute the document to the provided recipients who have not actioned the document. Will use the distribution method set in the document' ,
tags : [ 'Document' ] ,
2024-12-10 16:11:20 +09:00
} ,
} )
2023-11-16 07:35:45 +05:30
. input ( ZResendDocumentMutationSchema )
2025-01-20 19:47:39 +11:00
. output ( ZSuccessResponseSchema )
2023-11-16 07:35:45 +05:30
. mutation ( async ( { input , ctx } ) = > {
2025-01-11 15:33:20 +11:00
const { teamId } = ctx ;
const { documentId , recipients } = input ;
2025-01-20 19:47:39 +11:00
await resendDocument ( {
2024-12-06 16:01:24 +09:00
userId : ctx.user.id ,
2025-01-11 15:33:20 +11:00
teamId ,
documentId ,
recipients ,
requestMetadata : ctx.metadata ,
2024-12-06 16:01:24 +09:00
} ) ;
2025-01-20 19:47:39 +11:00
return ZGenericSuccessResponse ;
2023-11-16 07:35:45 +05:30
} ) ,
2024-12-14 01:23:35 +09:00
/ * *
* @public
* /
2023-11-08 09:25:44 +00:00
duplicateDocument : authenticatedProcedure
2024-12-10 16:11:20 +09:00
. meta ( {
openapi : {
method : 'POST' ,
2025-01-11 15:33:20 +11:00
path : '/document/duplicate' ,
2024-12-10 16:11:20 +09:00
summary : 'Duplicate document' ,
2025-01-11 15:33:20 +11:00
tags : [ 'Document' ] ,
2024-12-10 16:11:20 +09:00
} ,
} )
2025-01-14 00:43:35 +11:00
. input ( ZDuplicateDocumentRequestSchema )
2024-12-14 01:23:35 +09:00
. output ( ZDuplicateDocumentResponseSchema )
2023-11-08 09:25:44 +00:00
. mutation ( async ( { input , ctx } ) = > {
2025-01-11 15:33:20 +11:00
const { teamId , user } = ctx ;
const { documentId } = input ;
2024-12-14 01:23:35 +09:00
return await duplicateDocument ( {
2025-01-11 15:33:20 +11:00
userId : user.id ,
teamId ,
documentId ,
2024-12-06 16:01:24 +09:00
} ) ;
2023-11-08 09:25:44 +00:00
} ) ,
2023-12-06 07:18:05 +05:30
2024-12-14 01:23:35 +09:00
/ * *
* @private
* /
2023-12-06 07:18:05 +05:30
searchDocuments : authenticatedProcedure
. input ( ZSearchDocumentsMutationSchema )
. query ( async ( { input , ctx } ) = > {
const { query } = input ;
2024-12-06 16:01:24 +09:00
const documents = await searchDocumentsWithKeyword ( {
query ,
userId : ctx.user.id ,
} ) ;
2024-03-30 14:00:34 +08:00
2024-12-06 16:01:24 +09:00
return documents ;
2023-12-06 07:18:05 +05:30
} ) ,
2024-04-10 15:13:18 +07:00
2024-12-14 01:23:35 +09:00
/ * *
* @private
* /
2024-12-10 16:11:20 +09:00
findDocumentAuditLogs : authenticatedProcedure
. input ( ZFindDocumentAuditLogsQuerySchema )
. query ( async ( { input , ctx } ) = > {
2025-01-11 15:33:20 +11:00
const { teamId } = ctx ;
2024-12-14 01:23:35 +09:00
const {
page ,
perPage ,
documentId ,
cursor ,
filterForRecentActivity ,
orderByColumn ,
orderByDirection ,
} = input ;
2024-12-10 16:11:20 +09:00
return await findDocumentAuditLogs ( {
2025-01-11 15:33:20 +11:00
userId : ctx.user.id ,
teamId ,
2024-12-10 16:11:20 +09:00
page ,
perPage ,
documentId ,
cursor ,
filterForRecentActivity ,
2024-12-14 01:23:35 +09:00
orderBy : orderByColumn ? { column : orderByColumn , direction : orderByDirection } : undefined ,
2024-12-10 16:11:20 +09:00
} ) ;
} ) ,
2024-12-14 01:23:35 +09:00
/ * *
* @private
* /
2024-04-10 15:13:18 +07:00
downloadAuditLogs : authenticatedProcedure
. input ( ZDownloadAuditLogsMutationSchema )
. mutation ( async ( { input , ctx } ) = > {
2025-01-11 15:33:20 +11:00
const { teamId } = ctx ;
const { documentId } = input ;
2024-04-10 15:13:18 +07:00
2024-12-06 16:01:24 +09:00
const document = await getDocumentById ( {
2024-12-10 16:11:20 +09:00
documentId ,
2024-12-06 16:01:24 +09:00
userId : ctx.user.id ,
teamId ,
} ) . catch ( ( ) = > null ) ;
2024-04-10 15:13:18 +07:00
2024-12-06 16:01:24 +09:00
if ( ! document || ( teamId && document . teamId !== teamId ) ) {
2024-04-10 15:13:18 +07:00
throw new TRPCError ( {
2024-12-06 16:01:24 +09:00
code : 'FORBIDDEN' ,
message : 'You do not have access to this document.' ,
2024-04-10 15:13:18 +07:00
} ) ;
}
2024-12-06 16:01:24 +09:00
const encrypted = encryptSecondaryData ( {
data : document.id.toString ( ) ,
expiresAt : DateTime.now ( ) . plus ( { minutes : 5 } ) . toJSDate ( ) . valueOf ( ) ,
} ) ;
return {
url : ` ${ NEXT_PUBLIC_WEBAPP_URL ( ) } /__htmltopdf/audit-log?d= ${ encrypted } ` ,
} ;
2024-04-10 15:13:18 +07:00
} ) ,
2024-12-14 01:23:35 +09:00
/ * *
* @private
* /
2024-04-10 15:13:18 +07:00
downloadCertificate : authenticatedProcedure
2024-08-09 04:19:48 +02:00
. input ( ZDownloadCertificateMutationSchema )
2024-04-10 15:13:18 +07:00
. mutation ( async ( { input , ctx } ) = > {
2025-01-11 15:33:20 +11:00
const { teamId } = ctx ;
const { documentId } = input ;
2024-04-10 15:13:18 +07:00
2024-12-06 16:01:24 +09:00
const document = await getDocumentById ( {
2024-12-10 16:11:20 +09:00
documentId ,
2024-12-06 16:01:24 +09:00
userId : ctx.user.id ,
teamId ,
} ) ;
2024-04-24 19:51:18 +07:00
2024-12-06 16:01:24 +09:00
if ( document . status !== DocumentStatus . COMPLETED ) {
throw new AppError ( 'DOCUMENT_NOT_COMPLETE' ) ;
}
2024-04-10 15:13:18 +07:00
2024-12-06 16:01:24 +09:00
const encrypted = encryptSecondaryData ( {
data : document.id.toString ( ) ,
expiresAt : DateTime.now ( ) . plus ( { minutes : 5 } ) . toJSDate ( ) . valueOf ( ) ,
} ) ;
2024-04-10 15:13:18 +07:00
2024-12-06 16:01:24 +09:00
return {
url : ` ${ NEXT_PUBLIC_WEBAPP_URL ( ) } /__htmltopdf/certificate?d= ${ encrypted } ` ,
} ;
2024-04-10 15:13:18 +07:00
} ) ,
2023-06-21 23:49:23 +10:00
} ) ;