--- phase: 18-template-schema-and-crud-api plan: "02" subsystem: api tags: [drizzle, next-app-router, rest-api, soft-delete, postgresql] requires: - phase: 18-01 provides: documentTemplates Drizzle table + 0012 migration provides: - GET /api/templates — list active templates with formName JOIN and computed fieldCount - POST /api/templates — create template with name + formTemplateId FK validation - PATCH /api/templates/[id] — rename and/or update signatureFields with explicit updatedAt - DELETE /api/templates/[id] — soft-delete via archivedAt (no hard delete) affects: [Phase 19 template editor UI, Phase 20 apply-template endpoint] tech-stack: added: [] patterns: [soft-delete filter (isNull archivedAt), LEFT JOIN for computed field, explicit updatedAt on every UPDATE] key-files: created: - teressa-copeland-homes/src/app/api/templates/route.ts - teressa-copeland-homes/src/app/api/templates/[id]/route.ts modified: [] key-decisions: - "fieldCount derived server-side as (signatureFields ?? []).length — not stored in DB per D-12" - "PATCH guards against archived templates via isNull(archivedAt) before update — archived templates return 404" - "DELETE sets archivedAt + updatedAt atomically in a single UPDATE statement, returns 204 No Content" - "POST validates FK existence via db.query.formTemplates.findFirst before INSERT — returns 404 not 500 on bad FK" patterns-established: - "Soft-delete list filter: .where(isNull(documentTemplates.archivedAt)) in GET handler" - "Soft-delete guard in mutating handlers: findFirst with and(eq(id), isNull(archivedAt)) → 404 if missing/archived" - "Explicit updatedAt: new Date() in every UPDATE per D-05 pattern" requirements-completed: [TMPL-01, TMPL-02, TMPL-03, TMPL-04] duration: 3min completed: 2026-04-06 --- # Phase 18 Plan 02: Template CRUD API Summary **Four REST handlers at /api/templates providing full CRUD with soft-delete, auth guard, FK validation, and computed fieldCount via LEFT JOIN on formTemplates.** ## Performance - **Duration:** ~3 min - **Started:** 2026-04-06T18:16:47Z - **Completed:** 2026-04-06T18:19:30Z - **Tasks:** 2 - **Files modified:** 2 ## Accomplishments - GET /api/templates lists active templates only (archivedAt IS NULL) with formName from joined formTemplates and computed fieldCount - POST /api/templates validates name + formTemplateId, checks FK exists in formTemplates, inserts and returns 201 - PATCH /api/templates/[id] handles rename and signatureFields update with explicit updatedAt, guards archived templates - DELETE /api/templates/[id] soft-deletes via archivedAt = new Date() per D-07, returns 204 — never removes the row ## Task Commits 1. **Task 1: Create GET and POST routes at /api/templates** - `28c7773` (feat) 2. **Task 2: Create PATCH and DELETE routes at /api/templates/[id]** - `12a74fc` (feat) ## Files Created/Modified - `teressa-copeland-homes/src/app/api/templates/route.ts` — GET (list active templates with JOIN) and POST (create with FK validation) - `teressa-copeland-homes/src/app/api/templates/[id]/route.ts` — PATCH (rename/update fields, explicit updatedAt) and DELETE (soft-delete via archivedAt) ## Decisions Made - PATCH returns 404 for archived templates (guards via `and(eq(id), isNull(archivedAt))`) — ensures mutating handlers do not resurrect archived templates accidentally - POST verifies `formTemplateId` FK exists before INSERT, returning 404 with a clear error message rather than letting the DB constraint throw a 500 - DELETE returns 204 No Content on success (no body) — matches REST convention for soft-delete confirmation ## Deviations from Plan None - plan executed exactly as written. ## Issues Encountered None. ## User Setup Required None - no external service configuration required. ## Next Phase Readiness - All four CRUD routes are ready for Phase 19 (template editor UI) - Phase 19 will call GET to list templates, POST to create, PATCH with signatureFields to save field layout, and optionally DELETE - Phase 20 (apply template) will call GET to pick a template, then read signatureFields to stamp fresh UUIDs at apply time - No blockers. TypeScript compiles clean. --- *Phase: 18-template-schema-and-crud-api* *Completed: 2026-04-06*