feat: create document in a specific folder (#1965)

This commit is contained in:
Catalin Pit
2025-08-22 17:12:17 +03:00
committed by GitHub
parent 17b36ac8e4
commit 67501b45cf
8 changed files with 77 additions and 3 deletions
+2
View File
@@ -330,6 +330,7 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, {
userId: user.id, userId: user.id,
teamId: team?.id, teamId: team?.id,
formValues: body.formValues, formValues: body.formValues,
folderId: body.folderId,
documentDataId: documentData.id, documentDataId: documentData.id,
requestMetadata: metadata, requestMetadata: metadata,
}); });
@@ -736,6 +737,7 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, {
teamId: team?.id, teamId: team?.id,
recipients: body.recipients, recipients: body.recipients,
prefillFields: body.prefillFields, prefillFields: body.prefillFields,
folderId: body.folderId,
override: { override: {
title: body.title, title: body.title,
...body.meta, ...body.meta,
+12
View File
@@ -136,6 +136,12 @@ export type TUploadDocumentSuccessfulSchema = z.infer<typeof ZUploadDocumentSucc
export const ZCreateDocumentMutationSchema = z.object({ export const ZCreateDocumentMutationSchema = z.object({
title: z.string().min(1), title: z.string().min(1),
externalId: z.string().nullish(), externalId: z.string().nullish(),
folderId: z
.string()
.describe(
'The ID of the folder to create the document in. If not provided, the document will be created in the root folder.',
)
.optional(),
recipients: z.array( recipients: z.array(
z.object({ z.object({
name: z.string().min(1), name: z.string().min(1),
@@ -287,6 +293,12 @@ export type TCreateDocumentFromTemplateMutationResponseSchema = z.infer<
export const ZGenerateDocumentFromTemplateMutationSchema = z.object({ export const ZGenerateDocumentFromTemplateMutationSchema = z.object({
title: z.string().optional(), title: z.string().optional(),
externalId: z.string().optional(), externalId: z.string().optional(),
folderId: z
.string()
.describe(
'The ID of the folder to create the document in. If not provided, the document will be created in the root folder.',
)
.optional(),
recipients: z recipients: z
.array( .array(
z.object({ z.object({
@@ -1,6 +1,7 @@
import type { DocumentVisibility, TemplateMeta } from '@prisma/client'; import type { DocumentVisibility, TemplateMeta } from '@prisma/client';
import { import {
DocumentSource, DocumentSource,
FolderType,
RecipientRole, RecipientRole,
SendStatus, SendStatus,
SigningStatus, SigningStatus,
@@ -45,6 +46,7 @@ export type CreateDocumentOptions = {
globalActionAuth?: TDocumentActionAuthTypes[]; globalActionAuth?: TDocumentActionAuthTypes[];
formValues?: TDocumentFormValues; formValues?: TDocumentFormValues;
recipients: TCreateDocumentV2Request['recipients']; recipients: TCreateDocumentV2Request['recipients'];
folderId?: string;
}; };
meta?: Partial<Omit<TemplateMeta, 'id' | 'templateId'>>; meta?: Partial<Omit<TemplateMeta, 'id' | 'templateId'>>;
requestMetadata: ApiRequestMetadata; requestMetadata: ApiRequestMetadata;
@@ -59,7 +61,7 @@ export const createDocumentV2 = async ({
meta, meta,
requestMetadata, requestMetadata,
}: CreateDocumentOptions) => { }: CreateDocumentOptions) => {
const { title, formValues } = data; const { title, formValues, folderId } = data;
const team = await prisma.team.findFirst({ const team = await prisma.team.findFirst({
where: buildTeamWhereQuery({ teamId, userId }), where: buildTeamWhereQuery({ teamId, userId }),
@@ -78,6 +80,22 @@ export const createDocumentV2 = async ({
}); });
} }
if (folderId) {
const folder = await prisma.folder.findUnique({
where: {
id: folderId,
type: FolderType.DOCUMENT,
team: buildTeamWhereQuery({ teamId, userId }),
},
});
if (!folder) {
throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Folder not found',
});
}
}
const settings = await getTeamSettings({ const settings = await getTeamSettings({
userId, userId,
teamId, teamId,
@@ -164,6 +182,7 @@ export const createDocumentV2 = async ({
teamId, teamId,
authOptions, authOptions,
visibility, visibility,
folderId,
formValues, formValues,
source: DocumentSource.DOCUMENT, source: DocumentSource.DOCUMENT,
documentMeta: { documentMeta: {
@@ -2,6 +2,7 @@ import type { DocumentDistributionMethod, DocumentSigningOrder } from '@prisma/c
import { import {
DocumentSource, DocumentSource,
type Field, type Field,
FolderType,
type Recipient, type Recipient,
RecipientRole, RecipientRole,
SendStatus, SendStatus,
@@ -69,6 +70,7 @@ export type CreateDocumentFromTemplateOptions = {
email: string; email: string;
signingOrder?: number | null; signingOrder?: number | null;
}[]; }[];
folderId?: string;
prefillFields?: TFieldMetaPrefillFieldsSchema[]; prefillFields?: TFieldMetaPrefillFieldsSchema[];
customDocumentDataId?: string; customDocumentDataId?: string;
@@ -274,6 +276,7 @@ export const createDocumentFromTemplate = async ({
customDocumentDataId, customDocumentDataId,
override, override,
requestMetadata, requestMetadata,
folderId,
prefillFields, prefillFields,
}: CreateDocumentFromTemplateOptions) => { }: CreateDocumentFromTemplateOptions) => {
const template = await prisma.template.findUnique({ const template = await prisma.template.findUnique({
@@ -298,6 +301,22 @@ export const createDocumentFromTemplate = async ({
}); });
} }
if (folderId) {
const folder = await prisma.folder.findUnique({
where: {
id: folderId,
type: FolderType.DOCUMENT,
team: buildTeamWhereQuery({ teamId, userId }),
},
});
if (!folder) {
throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Folder not found',
});
}
}
const settings = await getTeamSettings({ const settings = await getTeamSettings({
userId, userId,
teamId, teamId,
@@ -368,6 +387,7 @@ export const createDocumentFromTemplate = async ({
externalId: externalId || template.externalId, externalId: externalId || template.externalId,
templateId: template.id, templateId: template.id,
userId, userId,
folderId,
teamId: template.teamId, teamId: template.teamId,
title: override?.title || template.title, title: override?.title || template.title,
documentDataId: documentData.id, documentDataId: documentData.id,
@@ -284,6 +284,7 @@ export const documentRouter = router({
globalActionAuth, globalActionAuth,
recipients, recipients,
meta, meta,
folderId,
} = input; } = input;
const { remaining } = await getServerLimits({ userId: user.id, teamId }); const { remaining } = await getServerLimits({ userId: user.id, teamId });
@@ -316,6 +317,7 @@ export const documentRouter = router({
globalAccessAuth, globalAccessAuth,
globalActionAuth, globalActionAuth,
recipients, recipients,
folderId,
}, },
meta, meta,
requestMetadata: ctx.metadata, requestMetadata: ctx.metadata,
@@ -209,6 +209,12 @@ export const ZCreateDocumentV2RequestSchema = z.object({
globalAccessAuth: z.array(ZDocumentAccessAuthTypesSchema).optional(), globalAccessAuth: z.array(ZDocumentAccessAuthTypesSchema).optional(),
globalActionAuth: z.array(ZDocumentActionAuthTypesSchema).optional(), globalActionAuth: z.array(ZDocumentActionAuthTypesSchema).optional(),
formValues: ZDocumentFormValuesSchema.optional(), formValues: ZDocumentFormValuesSchema.optional(),
folderId: z
.string()
.describe(
'The ID of the folder to create the document in. If not provided, the document will be created in the root folder.',
)
.optional(),
recipients: z recipients: z
.array( .array(
ZCreateRecipientSchema.extend({ ZCreateRecipientSchema.extend({
@@ -339,8 +339,14 @@ export const templateRouter = router({
.output(ZCreateDocumentFromTemplateResponseSchema) .output(ZCreateDocumentFromTemplateResponseSchema)
.mutation(async ({ ctx, input }) => { .mutation(async ({ ctx, input }) => {
const { teamId } = ctx; const { teamId } = ctx;
const { templateId, recipients, distributeDocument, customDocumentDataId, prefillFields } = const {
input; templateId,
recipients,
distributeDocument,
customDocumentDataId,
prefillFields,
folderId,
} = input;
ctx.logger.info({ ctx.logger.info({
input: { input: {
@@ -361,6 +367,7 @@ export const templateRouter = router({
recipients, recipients,
customDocumentDataId, customDocumentDataId,
requestMetadata: ctx.metadata, requestMetadata: ctx.metadata,
folderId,
prefillFields, prefillFields,
}); });
@@ -117,6 +117,12 @@ export const ZCreateDocumentFromTemplateRequestSchema = z.object({
'The data ID of an alternative PDF to use when creating the document. If not provided, the PDF attached to the template will be used.', 'The data ID of an alternative PDF to use when creating the document. If not provided, the PDF attached to the template will be used.',
) )
.optional(), .optional(),
folderId: z
.string()
.describe(
'The ID of the folder to create the document in. If not provided, the document will be created in the root folder.',
)
.optional(),
prefillFields: z prefillFields: z
.array(ZFieldMetaPrefillFieldsSchema) .array(ZFieldMetaPrefillFieldsSchema)
.describe( .describe(