feat(18-02): PATCH and DELETE handlers at /api/templates/[id]
- PATCH accepts name and signatureFields for rename and field save per D-10 - PATCH sets updatedAt: new Date() explicitly per D-05 - PATCH returns 404 for archived or missing templates - DELETE soft-deletes by setting archivedAt: new Date() per D-07 (no hard delete) - DELETE sets updatedAt: new Date() per D-05, returns 204 No Content - Both handlers auth-gated with auth() per D-11
This commit is contained in:
69
teressa-copeland-homes/src/app/api/templates/[id]/route.ts
Normal file
69
teressa-copeland-homes/src/app/api/templates/[id]/route.ts
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import { auth } from '@/lib/auth';
|
||||||
|
import { db } from '@/lib/db';
|
||||||
|
import { documentTemplates } from '@/lib/db/schema';
|
||||||
|
import type { SignatureFieldData } from '@/lib/db/schema';
|
||||||
|
import { and, eq, isNull } from 'drizzle-orm';
|
||||||
|
|
||||||
|
export async function PATCH(
|
||||||
|
req: Request,
|
||||||
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
|
) {
|
||||||
|
const session = await auth();
|
||||||
|
if (!session) return new Response('Unauthorized', { status: 401 });
|
||||||
|
|
||||||
|
const { id } = await params;
|
||||||
|
const body = await req.json() as {
|
||||||
|
name?: string;
|
||||||
|
signatureFields?: SignatureFieldData[];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Only update non-archived templates
|
||||||
|
const existing = await db.query.documentTemplates.findFirst({
|
||||||
|
where: and(eq(documentTemplates.id, id), isNull(documentTemplates.archivedAt)),
|
||||||
|
});
|
||||||
|
if (!existing) {
|
||||||
|
return Response.json({ error: 'Not found' }, { status: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const updates: Partial<typeof documentTemplates.$inferInsert> = {
|
||||||
|
updatedAt: new Date(), // per D-05: explicit updatedAt on every UPDATE
|
||||||
|
};
|
||||||
|
if (body.name !== undefined) updates.name = body.name;
|
||||||
|
if (body.signatureFields !== undefined) updates.signatureFields = body.signatureFields;
|
||||||
|
|
||||||
|
const [updated] = await db
|
||||||
|
.update(documentTemplates)
|
||||||
|
.set(updates)
|
||||||
|
.where(eq(documentTemplates.id, id))
|
||||||
|
.returning();
|
||||||
|
|
||||||
|
return Response.json(updated);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DELETE(
|
||||||
|
_req: Request,
|
||||||
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
|
) {
|
||||||
|
const session = await auth();
|
||||||
|
if (!session) return new Response('Unauthorized', { status: 401 });
|
||||||
|
|
||||||
|
const { id } = await params;
|
||||||
|
|
||||||
|
// Only soft-delete non-archived templates (idempotent)
|
||||||
|
const existing = await db.query.documentTemplates.findFirst({
|
||||||
|
where: and(eq(documentTemplates.id, id), isNull(documentTemplates.archivedAt)),
|
||||||
|
});
|
||||||
|
if (!existing) {
|
||||||
|
return Response.json({ error: 'Not found' }, { status: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
|
await db
|
||||||
|
.update(documentTemplates)
|
||||||
|
.set({
|
||||||
|
archivedAt: new Date(), // per D-07: soft-delete sets archivedAt
|
||||||
|
updatedAt: new Date(), // per D-05: explicit updatedAt
|
||||||
|
})
|
||||||
|
.where(eq(documentTemplates.id, id));
|
||||||
|
|
||||||
|
return new Response(null, { status: 204 });
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user