mirror of
https://github.com/documenso/documenso.git
synced 2025-11-13 00:03:33 +10:00
feat: add direct templates links (#1165)
## Description Direct templates links is a feature that provides template owners the ability to allow users to create documents based of their templates. ## General outline This works by allowing the template owner to configure a "direct recipient" in the template. When a user opens the direct link to the template, it will create a flow where they sign the fields configured by the template owner for the direct recipient. After these fields are signed the following will occur: - A document will be created where the owner is the template owner - The direct recipient fields will be signed - The document will be sent to any other recipients configured in the template - If there are none the document will be immediately completed ## Notes There's a custom prisma migration to migrate all documents to have 'DOCUMENT' as the source, then sets the column to required. --------- Co-authored-by: Lucas Smith <me@lucasjamessmith.me>
This commit is contained in:
107
packages/lib/server-only/template/create-template-direct-link.ts
Normal file
107
packages/lib/server-only/template/create-template-direct-link.ts
Normal file
@ -0,0 +1,107 @@
|
||||
'use server';
|
||||
|
||||
import { nanoid } from 'nanoid';
|
||||
|
||||
import { prisma } from '@documenso/prisma';
|
||||
import type { Recipient, TemplateDirectLink } from '@documenso/prisma/client';
|
||||
|
||||
import {
|
||||
DIRECT_TEMPLATE_RECIPIENT_EMAIL,
|
||||
DIRECT_TEMPLATE_RECIPIENT_NAME,
|
||||
} from '../../constants/template';
|
||||
import { AppError, AppErrorCode } from '../../errors/app-error';
|
||||
|
||||
export type CreateTemplateDirectLinkOptions = {
|
||||
templateId: number;
|
||||
userId: number;
|
||||
directRecipientId?: number;
|
||||
};
|
||||
|
||||
export const createTemplateDirectLink = async ({
|
||||
templateId,
|
||||
userId,
|
||||
directRecipientId,
|
||||
}: CreateTemplateDirectLinkOptions): Promise<TemplateDirectLink> => {
|
||||
const template = await prisma.template.findFirst({
|
||||
where: {
|
||||
id: templateId,
|
||||
OR: [
|
||||
{
|
||||
userId,
|
||||
},
|
||||
{
|
||||
team: {
|
||||
members: {
|
||||
some: {
|
||||
userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
include: {
|
||||
Recipient: true,
|
||||
directLink: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!template) {
|
||||
throw new AppError(AppErrorCode.NOT_FOUND, 'Template not found');
|
||||
}
|
||||
|
||||
if (template.directLink) {
|
||||
throw new AppError(AppErrorCode.ALREADY_EXISTS, 'Direct template already exists');
|
||||
}
|
||||
|
||||
if (
|
||||
directRecipientId &&
|
||||
!template.Recipient.find((recipient) => recipient.id === directRecipientId)
|
||||
) {
|
||||
throw new AppError(AppErrorCode.NOT_FOUND, 'Recipient not found');
|
||||
}
|
||||
|
||||
if (
|
||||
!directRecipientId &&
|
||||
template.Recipient.find(
|
||||
(recipient) => recipient.email.toLowerCase() === DIRECT_TEMPLATE_RECIPIENT_EMAIL,
|
||||
)
|
||||
) {
|
||||
throw new AppError(AppErrorCode.INVALID_BODY, 'Cannot generate placeholder direct recipient');
|
||||
}
|
||||
|
||||
return await prisma.$transaction(async (tx) => {
|
||||
let recipient: Recipient | undefined;
|
||||
|
||||
if (directRecipientId) {
|
||||
recipient = await tx.recipient.update({
|
||||
where: {
|
||||
templateId,
|
||||
id: directRecipientId,
|
||||
},
|
||||
data: {
|
||||
name: DIRECT_TEMPLATE_RECIPIENT_NAME,
|
||||
email: DIRECT_TEMPLATE_RECIPIENT_EMAIL,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
recipient = await tx.recipient.create({
|
||||
data: {
|
||||
templateId,
|
||||
name: DIRECT_TEMPLATE_RECIPIENT_NAME,
|
||||
email: DIRECT_TEMPLATE_RECIPIENT_EMAIL,
|
||||
token: nanoid(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return await tx.templateDirectLink.create({
|
||||
data: {
|
||||
templateId,
|
||||
enabled: true,
|
||||
token: nanoid(),
|
||||
directTemplateRecipientId: recipient.id,
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user