From c41002313afeff13a0cef32b77590742d481ca27 Mon Sep 17 00:00:00 2001 From: Catalin Pit <25515812+catalinpit@users.noreply.github.com> Date: Thu, 6 Feb 2025 14:27:37 +0200 Subject: [PATCH] chore: allow same signer docs --- .../field/set-fields-for-document.ts | 22 +++++++++---------- .../field/set-fields-for-template.ts | 1 + .../recipient/set-document-recipients.ts | 8 ++----- .../migration.sql | 2 ++ .../migration.sql | 5 +++++ packages/prisma/schema.prisma | 3 +-- packages/trpc/server/field-router/router.ts | 1 + packages/trpc/server/field-router/schema.ts | 15 +++++++------ .../primitives/document-flow/add-fields.tsx | 21 +++++++++--------- .../document-flow/add-fields.types.ts | 2 +- 10 files changed, 42 insertions(+), 38 deletions(-) create mode 100644 packages/prisma/migrations/20250205122523_remove_unique_email_recipient/migration.sql create mode 100644 packages/prisma/migrations/20250206120241_add_email_index_recipient_model/migration.sql diff --git a/packages/lib/server-only/field/set-fields-for-document.ts b/packages/lib/server-only/field/set-fields-for-document.ts index b35deca02..4cbf6027f 100644 --- a/packages/lib/server-only/field/set-fields-for-document.ts +++ b/packages/lib/server-only/field/set-fields-for-document.ts @@ -94,9 +94,7 @@ export const setFieldsForDocument = async ({ const linkedFields = fields.map((field) => { const existing = existingFields.find((existingField) => existingField.id === field.id); - const recipient = document.recipients.find( - (recipient) => recipient.email.toLowerCase() === field.signerEmail.toLowerCase(), - ); + const recipient = document.recipients.find((recipient) => recipient.id === field.recipientId); // Each field MUST have a recipient associated with it. if (!recipient) { @@ -127,8 +125,6 @@ export const setFieldsForDocument = async ({ const persistedFields = await prisma.$transaction(async (tx) => { return await Promise.all( linkedFields.map(async (field) => { - const fieldSignerEmail = field.signerEmail.toLowerCase(); - const parsedFieldMeta = field.fieldMeta ? ZFieldMetaSchema.parse(field.fieldMeta) : undefined; @@ -211,6 +207,13 @@ export const setFieldsForDocument = async ({ id: field._persisted?.id ?? -1, documentId, }, + include: { + recipient: { + select: { + email: true, + }, + }, + }, update: { page: field.pageNumber, positionX: field.pageX, @@ -236,10 +239,7 @@ export const setFieldsForDocument = async ({ }, recipient: { connect: { - documentId_email: { - documentId, - email: fieldSignerEmail, - }, + id: field.recipientId, }, }, }, @@ -251,7 +251,7 @@ export const setFieldsForDocument = async ({ const baseAuditLog = { fieldId: upsertedField.secondaryId, - fieldRecipientEmail: fieldSignerEmail, + fieldRecipientEmail: upsertedField.recipient?.email ?? '', fieldRecipientId: upsertedField.recipientId, fieldType: upsertedField.type, }; @@ -339,7 +339,7 @@ export const setFieldsForDocument = async ({ type FieldData = { id?: number | null; type: FieldType; - signerEmail: string; + recipientId: number; pageNumber: number; pageX: number; pageY: number; diff --git a/packages/lib/server-only/field/set-fields-for-template.ts b/packages/lib/server-only/field/set-fields-for-template.ts index 156f0b359..9669fbe82 100644 --- a/packages/lib/server-only/field/set-fields-for-template.ts +++ b/packages/lib/server-only/field/set-fields-for-template.ts @@ -23,6 +23,7 @@ export type SetFieldsForTemplateOptions = { id?: number | null; type: FieldType; signerEmail: string; + recipientId: number; pageNumber: number; pageX: number; pageY: number; diff --git a/packages/lib/server-only/recipient/set-document-recipients.ts b/packages/lib/server-only/recipient/set-document-recipients.ts index 78ca3f176..a8d2ee66c 100644 --- a/packages/lib/server-only/recipient/set-document-recipients.ts +++ b/packages/lib/server-only/recipient/set-document-recipients.ts @@ -125,16 +125,12 @@ export const setDocumentRecipients = async ({ const removedRecipients = existingRecipients.filter( (existingRecipient) => - !normalizedRecipients.find( - (recipient) => - recipient.id === existingRecipient.id || recipient.email === existingRecipient.email, - ), + !normalizedRecipients.find((recipient) => recipient.id === existingRecipient.id), ); const linkedRecipients = normalizedRecipients.map((recipient) => { const existing = existingRecipients.find( - (existingRecipient) => - existingRecipient.id === recipient.id || existingRecipient.email === recipient.email, + (existingRecipient) => existingRecipient.id === recipient.id, ); if ( diff --git a/packages/prisma/migrations/20250205122523_remove_unique_email_recipient/migration.sql b/packages/prisma/migrations/20250205122523_remove_unique_email_recipient/migration.sql new file mode 100644 index 000000000..bb9d710e1 --- /dev/null +++ b/packages/prisma/migrations/20250205122523_remove_unique_email_recipient/migration.sql @@ -0,0 +1,2 @@ +-- DropIndex +DROP INDEX "Recipient_documentId_email_key"; diff --git a/packages/prisma/migrations/20250206120241_add_email_index_recipient_model/migration.sql b/packages/prisma/migrations/20250206120241_add_email_index_recipient_model/migration.sql new file mode 100644 index 000000000..e9ce4b119 --- /dev/null +++ b/packages/prisma/migrations/20250206120241_add_email_index_recipient_model/migration.sql @@ -0,0 +1,5 @@ +-- DropIndex +DROP INDEX "Recipient_templateId_email_key"; + +-- CreateIndex +CREATE INDEX "Recipient_email_idx" ON "Recipient"("email"); diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index 0cdb1521e..7de38ffaa 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -443,11 +443,10 @@ model Recipient { fields Field[] signatures Signature[] - @@unique([documentId, email]) - @@unique([templateId, email]) @@index([documentId]) @@index([templateId]) @@index([token]) + @@index([email]) } enum FieldType { diff --git a/packages/trpc/server/field-router/router.ts b/packages/trpc/server/field-router/router.ts index df17aef88..eedd68613 100644 --- a/packages/trpc/server/field-router/router.ts +++ b/packages/trpc/server/field-router/router.ts @@ -429,6 +429,7 @@ export const fieldRouter = router({ teamId, fields: fields.map((field) => ({ id: field.nativeId, + recipientId: field.recipientId, signerEmail: field.signerEmail, type: field.type, pageNumber: field.pageNumber, diff --git a/packages/trpc/server/field-router/schema.ts b/packages/trpc/server/field-router/schema.ts index 373d4a693..76a6e8436 100644 --- a/packages/trpc/server/field-router/schema.ts +++ b/packages/trpc/server/field-router/schema.ts @@ -112,14 +112,15 @@ export const ZSetDocumentFieldsRequestSchema = z.object({ z.object({ formId: z.string().min(1), nativeId: z.number().optional(), + id: z.number().optional(), type: z.nativeEnum(FieldType), - signerEmail: z.string().min(1), - pageNumber: z.number().min(1), - pageX: z.number().min(0), - pageY: z.number().min(0), - pageWidth: z.number().min(0), - pageHeight: z.number().min(0), - fieldMeta: ZFieldMetaSchema, + recipientId: z.number(), + pageNumber: ZFieldPageNumberSchema, + pageX: ZFieldPageXSchema, + pageY: ZFieldPageYSchema, + pageWidth: ZFieldWidthSchema, + pageHeight: ZFieldHeightSchema, + fieldMeta: ZFieldMetaSchema.optional(), }), ), }); diff --git a/packages/ui/primitives/document-flow/add-fields.tsx b/packages/ui/primitives/document-flow/add-fields.tsx index f6b1572d8..71cc4afb4 100644 --- a/packages/ui/primitives/document-flow/add-fields.tsx +++ b/packages/ui/primitives/document-flow/add-fields.tsx @@ -92,7 +92,7 @@ export type FieldFormType = { pageY: number; pageWidth: number; pageHeight: number; - signerEmail: string; + recipientId: number; fieldMeta?: FieldMeta; }; @@ -143,8 +143,7 @@ export const AddFieldsFormPartial = ({ pageY: Number(field.positionY), pageWidth: Number(field.width), pageHeight: Number(field.height), - signerEmail: - recipients.find((recipient) => recipient.id === field.recipientId)?.email ?? '', + recipientId: field.recipientId, fieldMeta: field.fieldMeta ? ZFieldMetaSchema.parse(field.fieldMeta) : undefined, })), typedSignatureEnabled: typedSignatureEnabled ?? false, @@ -348,7 +347,7 @@ export const AddFieldsFormPartial = ({ pageY, pageWidth: fieldPageWidth, pageHeight: fieldPageHeight, - signerEmail: selectedSigner.email, + recipientId: selectedSigner.id, fieldMeta: undefined, }; @@ -441,7 +440,7 @@ export const AddFieldsFormPartial = ({ const newField: TAddFieldsFormSchema['fields'][0] = { ...structuredClone(lastActiveField), formId: nanoid(12), - signerEmail: selectedSigner?.email ?? lastActiveField.signerEmail, + recipientId: selectedSigner?.id ?? lastActiveField.recipientId, pageX: lastActiveField.pageX + 3, pageY: lastActiveField.pageY + 3, }; @@ -449,7 +448,7 @@ export const AddFieldsFormPartial = ({ append(newField); } }, - [append, lastActiveField, selectedSigner?.email, toast], + [append, lastActiveField, selectedSigner?.id, toast], ); const onFieldPaste = useCallback( @@ -462,13 +461,13 @@ export const AddFieldsFormPartial = ({ append({ ...copiedField, formId: nanoid(12), - signerEmail: selectedSigner?.email ?? copiedField.signerEmail, + recipientId: selectedSigner?.id ?? copiedField.recipientId, pageX: copiedField.pageX + 3, pageY: copiedField.pageY + 3, }); } }, - [append, fieldClipboard, selectedSigner?.email], + [append, fieldClipboard, selectedSigner?.id], ); useEffect(() => { @@ -567,7 +566,7 @@ export const AddFieldsFormPartial = ({ localFields.some( (field) => (field.type === FieldType.SIGNATURE || field.type === FieldType.FREE_SIGNATURE) && - field.signerEmail === signer.email, + field.recipientId === signer.id, ), ); @@ -637,7 +636,7 @@ export const AddFieldsFormPartial = ({ {isDocumentPdfLoaded && localFields.map((field, index) => { - const recipientIndex = recipients.findIndex((r) => r.email === field.signerEmail); + const recipientIndex = recipients.findIndex((r) => r.id === field.recipientId); const hasFieldError = emptyCheckboxFields.find((f) => f.formId === field.formId) || emptyRadioFields.find((f) => f.formId === field.formId) || @@ -649,7 +648,7 @@ export const AddFieldsFormPartial = ({ recipientIndex={recipientIndex === -1 ? 0 : recipientIndex} field={field} disabled={ - selectedSigner?.email !== field.signerEmail || + selectedSigner?.id !== field.recipientId || !canRecipientBeModified(selectedSigner, fields) } minHeight={MIN_HEIGHT_PX} diff --git a/packages/ui/primitives/document-flow/add-fields.types.ts b/packages/ui/primitives/document-flow/add-fields.types.ts index 4d9c89e73..e86dcd108 100644 --- a/packages/ui/primitives/document-flow/add-fields.types.ts +++ b/packages/ui/primitives/document-flow/add-fields.types.ts @@ -9,7 +9,7 @@ export const ZAddFieldsFormSchema = z.object({ formId: z.string().min(1), nativeId: z.number().optional(), type: z.nativeEnum(FieldType), - signerEmail: z.string().min(1), + recipientId: z.number(), pageNumber: z.number().min(1), pageX: z.number().min(0), pageY: z.number().min(0),