diff --git a/teressa-copeland-homes/src/app/api/documents/[id]/send/route.ts b/teressa-copeland-homes/src/app/api/documents/[id]/send/route.ts index 530ac4e..04806a2 100644 --- a/teressa-copeland-homes/src/app/api/documents/[id]/send/route.ts +++ b/teressa-copeland-homes/src/app/api/documents/[id]/send/route.ts @@ -1,7 +1,7 @@ import { NextResponse } from 'next/server'; import { auth } from '@/lib/auth'; import { db } from '@/lib/db'; -import { documents, clients } from '@/lib/db/schema'; +import { documents, clients, DocumentSigner } from '@/lib/db/schema'; import { eq } from 'drizzle-orm'; import { createSigningToken } from '@/lib/signing/token'; import { sendSigningRequestEmail } from '@/lib/signing/signing-mailer'; @@ -26,24 +26,45 @@ export async function POST( if (doc.status === 'Signed') return NextResponse.json({ error: 'Already signed' }, { status: 409 }); - // Resolve recipient: prefer assignedClientId, fall back to clientId - const clientId = doc.assignedClientId ?? doc.clientId; - const client = await db.query.clients.findFirst({ where: eq(clients.id, clientId) }); - if (!client) return NextResponse.json({ error: 'Client not found' }, { status: 422 }); + const baseUrl = process.env.APP_BASE_URL ?? 'http://localhost:3000'; - const { token, expiresAt } = await createSigningToken(doc.id); - const baseUrl = process.env.NEXT_PUBLIC_BASE_URL ?? 'http://localhost:3000'; - const signingUrl = `${baseUrl}/sign/${token}`; + if (doc.signers && (doc.signers as DocumentSigner[]).length > 0) { + // ── Multi-signer path (D-02) ── + const signers = doc.signers as DocumentSigner[]; + await Promise.all( + signers.map(async (signer) => { + const { token, expiresAt } = await createSigningToken(doc.id, signer.email); + const signingUrl = `${baseUrl}/sign/${token}`; + await sendSigningRequestEmail({ + to: signer.email, + documentName: doc.name, + signingUrl, + expiresAt, + }); + await logAuditEvent({ + documentId: doc.id, + eventType: 'email_sent', + metadata: { signerEmail: signer.email }, + }); + }) + ); + } else { + // ── Legacy single-signer path (D-01) ── + const clientId = doc.assignedClientId ?? doc.clientId; + const client = await db.query.clients.findFirst({ where: eq(clients.id, clientId) }); + if (!client) return NextResponse.json({ error: 'Client not found' }, { status: 422 }); - await sendSigningRequestEmail({ - to: client.email, - clientName: client.name, - documentName: doc.name, - signingUrl, - expiresAt, - }); - - await logAuditEvent({ documentId: doc.id, eventType: 'email_sent' }); + const { token, expiresAt } = await createSigningToken(doc.id); + const signingUrl = `${baseUrl}/sign/${token}`; + await sendSigningRequestEmail({ + to: client.email, + clientName: client.name, + documentName: doc.name, + signingUrl, + expiresAt, + }); + await logAuditEvent({ documentId: doc.id, eventType: 'email_sent' }); + } // Update status to Sent (skip if already Sent or Signed to avoid downgrade) if (doc.status === 'Draft') { @@ -53,7 +74,7 @@ export async function POST( .where(eq(documents.id, id)); } - return NextResponse.json({ ok: true, expiresAt: expiresAt.toISOString() }); + return NextResponse.json({ ok: true }); } catch (err) { console.error('[send] error:', err); return NextResponse.json({ error: 'Failed to send signing email' }, { status: 502 });