From 62c609f105f0e32b5d1b744fcd10b0faeb80bb91 Mon Sep 17 00:00:00 2001 From: David Nguyen Date: Thu, 12 Feb 2026 15:04:16 +1100 Subject: [PATCH] fix: completed audit logs --- .../internal/seal-document.handler.ts | 32 ++++++++++++------- .../server-only/pdf/generate-audit-log-pdf.ts | 26 +++++++++++++-- .../pdf/generate-certificate-pdf.ts | 12 ++++++- .../lib/server-only/pdf/render-audit-logs.ts | 4 +-- 4 files changed, 56 insertions(+), 18 deletions(-) diff --git a/packages/lib/jobs/definitions/internal/seal-document.handler.ts b/packages/lib/jobs/definitions/internal/seal-document.handler.ts index 242e1db5d..27cd7d796 100644 --- a/packages/lib/jobs/definitions/internal/seal-document.handler.ts +++ b/packages/lib/jobs/definitions/internal/seal-document.handler.ts @@ -169,12 +169,28 @@ export const run = async ({ }); } + const envelopeCompletedAuditLog = createDocumentAuditLogData({ + type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_COMPLETED, + envelopeId: envelope.id, + requestMetadata, + user: null, + data: { + transactionId: nanoid(), + ...(isRejected ? { isRejected: true, rejectionReason: rejectionReason } : {}), + }, + }); + + const finalEnvelopeStatus = isRejected ? DocumentStatus.REJECTED : DocumentStatus.COMPLETED; + let certificateDoc: PDF | null = null; let auditLogDoc: PDF | null = null; if (settings.includeSigningCertificate || settings.includeAuditLog) { const certificatePayload = { - envelope, + envelope: { + ...envelope, + status: finalEnvelopeStatus, + }, recipients: envelope.recipients, // Need to use the recipients from envelope which contains ALL recipients. fields, language: envelope.documentMeta.language, @@ -185,6 +201,7 @@ export const run = async ({ envelopeItems: envelopeItems.map((item) => item.title), pageWidth: PDF_SIZE_A4_72PPI.width, pageHeight: PDF_SIZE_A4_72PPI.height, + envelopeCompletedAuditLog, }; // Use Playwright-based PDF generation if enabled, otherwise use Konva-based generation. @@ -263,22 +280,13 @@ export const run = async ({ id: envelope.id, }, data: { - status: isRejected ? DocumentStatus.REJECTED : DocumentStatus.COMPLETED, + status: finalEnvelopeStatus, completedAt: new Date(), }, }); await tx.documentAuditLog.create({ - data: createDocumentAuditLogData({ - type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_COMPLETED, - envelopeId: envelope.id, - requestMetadata, - user: null, - data: { - transactionId: nanoid(), - ...(isRejected ? { isRejected: true, rejectionReason: rejectionReason } : {}), - }, - }), + data: envelopeCompletedAuditLog, }); }); diff --git a/packages/lib/server-only/pdf/generate-audit-log-pdf.ts b/packages/lib/server-only/pdf/generate-audit-log-pdf.ts index aac8245db..44850ce6c 100644 --- a/packages/lib/server-only/pdf/generate-audit-log-pdf.ts +++ b/packages/lib/server-only/pdf/generate-audit-log-pdf.ts @@ -1,6 +1,7 @@ import { PDF } from '@libpdf/core'; import { i18n } from '@lingui/core'; +import { type TDocumentAuditLog } from '@documenso/lib/types/document-audit-logs'; import { prisma } from '@documenso/prisma'; import { ZSupportedLanguageCodeSchema } from '../../constants/i18n'; @@ -15,12 +16,20 @@ type GenerateAuditLogPdfOptions = GenerateCertificatePdfOptions & { }; export const generateAuditLogPdf = async (options: GenerateAuditLogPdfOptions) => { - const { envelope, envelopeOwner, envelopeItems, recipients, language, pageWidth, pageHeight } = - options; + const { + envelope, + envelopeOwner, + envelopeItems, + recipients, + language, + pageWidth, + pageHeight, + envelopeCompletedAuditLog, + } = options; const documentLanguage = ZSupportedLanguageCodeSchema.parse(language); - const [organisationClaim, auditLogs, messages] = await Promise.all([ + const [organisationClaim, partialAuditLogs, messages] = await Promise.all([ getOrganisationClaimByTeamId({ teamId: envelope.teamId }), getAuditLogs(envelope.id), getTranslations(documentLanguage), @@ -31,6 +40,17 @@ export const generateAuditLogPdf = async (options: GenerateAuditLogPdfOptions) = messages, }); + const auditLogs: TDocumentAuditLog[] = [...partialAuditLogs]; + + if (envelopeCompletedAuditLog) { + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + auditLogs.unshift({ + ...envelopeCompletedAuditLog, + id: '', + createdAt: new Date(), + } satisfies Omit as TDocumentAuditLog); + } + const auditLogPages = await renderAuditLogs({ envelope, envelopeOwner, diff --git a/packages/lib/server-only/pdf/generate-certificate-pdf.ts b/packages/lib/server-only/pdf/generate-certificate-pdf.ts index ff12edc91..70405cbc7 100644 --- a/packages/lib/server-only/pdf/generate-certificate-pdf.ts +++ b/packages/lib/server-only/pdf/generate-certificate-pdf.ts @@ -7,6 +7,8 @@ import { FieldType } from '@prisma/client'; import { prop, sortBy } from 'remeda'; import { match } from 'ts-pattern'; +import type { CreateDocumentAuditLogDataResponse } from '@documenso/lib/utils/document-audit-logs'; + import { ZSupportedLanguageCodeSchema } from '../../constants/i18n'; import type { TDocumentAuditLogBaseSchema } from '../../types/document-audit-logs'; import { extractDocumentAuthMethods } from '../../utils/document-auth'; @@ -16,7 +18,14 @@ import { getOrganisationClaimByTeamId } from '../organisation/get-organisation-c import { renderCertificate } from './render-certificate'; export type GenerateCertificatePdfOptions = { - envelope: Envelope & { + /** + * Note: completedAt is not included since it's not real at this point in time. + * + * If we actually need it here in the future, we will need to preserve the + * completedAt value and pass it to the final `envelope.update` function when + * the document is initially sealed. + */ + envelope: Omit & { documentMeta: DocumentMeta; }; envelopeOwner: { @@ -30,6 +39,7 @@ export type GenerateCertificatePdfOptions = { language?: string; pageWidth: number; pageHeight: number; + envelopeCompletedAuditLog?: CreateDocumentAuditLogDataResponse; }; export const generateCertificatePdf = async (options: GenerateCertificatePdfOptions) => { diff --git a/packages/lib/server-only/pdf/render-audit-logs.ts b/packages/lib/server-only/pdf/render-audit-logs.ts index 2cd5d307c..53874e96e 100644 --- a/packages/lib/server-only/pdf/render-audit-logs.ts +++ b/packages/lib/server-only/pdf/render-audit-logs.ts @@ -30,7 +30,7 @@ export type AuditLogRecipient = { }; type GenerateAuditLogsOptions = { - envelope: Envelope & { + envelope: Omit & { documentMeta: DocumentMeta; }; envelopeItems: string[]; @@ -168,7 +168,7 @@ const renderVerticalLabelAndText = (options: RenderVerticalLabelAndTextOptions) }; type RenderOverviewCardOptions = { - envelope: Envelope & { + envelope: Omit & { documentMeta: DocumentMeta; }; envelopeItems: string[];