mirror of
https://github.com/documenso/documenso.git
synced 2025-11-18 18:51:37 +10:00
feat: update recipient expiry handling
This commit is contained in:
@ -101,6 +101,8 @@ export const ResendDocumentActionItem = ({
|
||||
|
||||
setIsOpen(false);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
|
||||
toast({
|
||||
title: _(msg`Something went wrong`),
|
||||
description: _(msg`This document could not be re-sent at this time. Please try again.`),
|
||||
|
||||
@ -41,10 +41,8 @@ export const StackAvatar = ({ first, zIndex, fallbackText = '', type }: StackAva
|
||||
classes = 'bg-documenso-200 text-documenso-800';
|
||||
break;
|
||||
case RecipientStatusType.REJECTED:
|
||||
classes = 'bg-red-200 text-red-800';
|
||||
break;
|
||||
case RecipientStatusType.EXPIRED:
|
||||
classes = 'bg-gray-200 text-gray-700';
|
||||
classes = 'bg-red-200 text-red-800';
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@ -16,6 +16,7 @@ import type { TRecipientActionAuth } from '../../types/document-auth';
|
||||
import { getIsRecipientsTurnToSign } from '../recipient/get-is-recipient-turn';
|
||||
import { triggerWebhook } from '../webhooks/trigger/trigger-webhook';
|
||||
import { sendPendingEmail } from './send-pending-email';
|
||||
import { updateExpiredRecipients } from './update-expired-recipients';
|
||||
|
||||
export type CompleteDocumentWithTokenOptions = {
|
||||
token: string;
|
||||
@ -61,12 +62,22 @@ export const completeDocumentWithToken = async ({
|
||||
throw new Error(`Document ${document.id} has no recipient with token ${token}`);
|
||||
}
|
||||
|
||||
await updateExpiredRecipients(documentId);
|
||||
|
||||
const [recipient] = document.Recipient;
|
||||
|
||||
if (recipient.expired && recipient.expired < new Date()) {
|
||||
throw new Error(`Recipient ${recipient.id} signature period has expired`);
|
||||
}
|
||||
|
||||
if (recipient.signingStatus === SigningStatus.SIGNED) {
|
||||
throw new Error(`Recipient ${recipient.id} has already signed`);
|
||||
}
|
||||
|
||||
if (recipient.signingStatus === SigningStatus.EXPIRED) {
|
||||
throw new Error(`Recipient ${recipient.id} signature period has expired`);
|
||||
}
|
||||
|
||||
if (document.documentMeta?.signingOrder === DocumentSigningOrder.SEQUENTIAL) {
|
||||
const isRecipientsTurn = await getIsRecipientsTurnToSign({ token: recipient.token });
|
||||
|
||||
|
||||
@ -14,8 +14,8 @@ import type { RequestMetadata } from '@documenso/lib/universal/extract-request-m
|
||||
import { createDocumentAuditLogData } from '@documenso/lib/utils/document-audit-logs';
|
||||
import { renderCustomEmailTemplate } from '@documenso/lib/utils/render-custom-email-template';
|
||||
import { prisma } from '@documenso/prisma';
|
||||
import { DocumentStatus, RecipientRole, SigningStatus } from '@documenso/prisma/client';
|
||||
import type { Prisma } from '@documenso/prisma/client';
|
||||
import { DocumentStatus, RecipientRole, SigningStatus } from '@documenso/prisma/client';
|
||||
|
||||
import { getI18nInstance } from '../../client-only/providers/i18n.server';
|
||||
import { NEXT_PUBLIC_WEBAPP_URL } from '../../constants/app';
|
||||
@ -106,6 +106,23 @@ export const resendDocument = async ({
|
||||
return;
|
||||
}
|
||||
|
||||
let newExpiryDate: Date | null = null;
|
||||
if (recipient.expired) {
|
||||
const durationInMs = recipient.expired.getTime() - document.updatedAt.getTime();
|
||||
newExpiryDate = new Date(Date.now() + durationInMs);
|
||||
|
||||
await prisma.recipient.update({
|
||||
where: { id: recipient.id },
|
||||
data: {
|
||||
expired: newExpiryDate,
|
||||
signingStatus:
|
||||
recipient.signingStatus === SigningStatus.EXPIRED
|
||||
? SigningStatus.NOT_SIGNED
|
||||
: recipient.signingStatus,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const i18n = await getI18nInstance(document.documentMeta?.language);
|
||||
|
||||
const recipientEmailType = RECIPIENT_ROLE_TO_EMAIL_TYPE[recipient.role];
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
import { prisma } from '@documenso/prisma';
|
||||
import { SigningStatus } from '@documenso/prisma/client';
|
||||
|
||||
import { DOCUMENT_AUDIT_LOG_TYPE } from '../../types/document-audit-logs';
|
||||
import { createDocumentAuditLogData } from '../../utils/document-audit-logs';
|
||||
|
||||
export const updateExpiredRecipients = async (documentId: number) => {
|
||||
const now = new Date();
|
||||
|
||||
const expiredRecipients = await prisma.recipient.findMany({
|
||||
where: {
|
||||
documentId,
|
||||
expired: {
|
||||
lt: now,
|
||||
},
|
||||
signingStatus: {
|
||||
not: SigningStatus.EXPIRED,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (expiredRecipients.length > 0) {
|
||||
await prisma.recipient.updateMany({
|
||||
where: {
|
||||
id: {
|
||||
in: expiredRecipients.map((recipient) => recipient.id),
|
||||
},
|
||||
},
|
||||
data: {
|
||||
signingStatus: SigningStatus.EXPIRED,
|
||||
},
|
||||
});
|
||||
|
||||
await Promise.all(
|
||||
expiredRecipients.map(async (recipient) =>
|
||||
prisma.documentAuditLog.create({
|
||||
data: createDocumentAuditLogData({
|
||||
type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_RECIPIENT_EXPIRED,
|
||||
documentId,
|
||||
user: {
|
||||
name: recipient.name,
|
||||
email: recipient.email,
|
||||
},
|
||||
data: {
|
||||
recipientEmail: recipient.email,
|
||||
recipientName: recipient.name,
|
||||
recipientId: recipient.id,
|
||||
recipientRole: recipient.role,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return expiredRecipients;
|
||||
};
|
||||
@ -184,7 +184,7 @@ export function DocumentExpiryDialog({
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="sm:max-w-[450px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Set Document Expiry</DialogTitle>
|
||||
<DialogTitle>Set Recipient Expiry</DialogTitle>
|
||||
<DialogDescription>
|
||||
Set the expiry date for the document signing recipient. The recipient will not be able
|
||||
to sign the document after this date.
|
||||
|
||||
Reference in New Issue
Block a user