136 lines
4.0 KiB
Markdown
136 lines
4.0 KiB
Markdown
# Task H - PDF Generation and Approved Document Persistence
|
|
|
|
## Files Added
|
|
|
|
- `src/features/foundation/pdf-generator/server/service.ts`
|
|
- `src/app/api/crm/quotations/[id]/pdf-preview/route.ts`
|
|
- `src/app/api/crm/quotations/[id]/pdf-download/route.ts`
|
|
- `src/app/api/crm/quotations/[id]/approved-pdf/route.ts`
|
|
- `drizzle/0007_luxuriant_malice.sql`
|
|
|
|
## Files Modified
|
|
|
|
- `package.json`
|
|
- `package-lock.json`
|
|
- `src/components/icons.tsx`
|
|
- `src/db/schema.ts`
|
|
- `src/lib/auth/rbac.ts`
|
|
- `src/features/crm/quotations/api/types.ts`
|
|
- `src/features/crm/quotations/server/service.ts`
|
|
- `src/features/crm/quotations/document/types.ts`
|
|
- `src/features/crm/quotations/document/server/service.ts`
|
|
- `src/features/foundation/approval/server/service.ts`
|
|
- `src/app/dashboard/crm/quotations/[id]/page.tsx`
|
|
- `src/features/crm/quotations/components/quotation-detail.tsx`
|
|
- `src/features/crm/enquiries/components/enquiry-form-sheet.tsx`
|
|
- `src/features/crm/enquiries/schemas/enquiry.schema.ts`
|
|
- `src/features/crm/quotations/schemas/quotation.schema.ts`
|
|
- `docs/implementation/technical-debt.md`
|
|
|
|
## PDF Generator Added
|
|
|
|
- Added production server-side `pdfme` generation in `src/features/foundation/pdf-generator/server/service.ts`.
|
|
- Installed:
|
|
- `@pdfme/common`
|
|
- `@pdfme/generator`
|
|
- `@pdfme/schemas`
|
|
- Implemented:
|
|
- `generatePdfFromTemplate()`
|
|
- `generateQuotationPdf()`
|
|
- `generateQuotationPreviewPdf()`
|
|
- `generateApprovedQuotationPdf()`
|
|
- `getStoredApprovedQuotationPdf()`
|
|
|
|
## API Routes Added
|
|
|
|
- `GET /api/crm/quotations/[id]/pdf-preview`
|
|
- `GET /api/crm/quotations/[id]/pdf-download`
|
|
- `GET /api/crm/quotations/[id]/approved-pdf`
|
|
- `POST /api/crm/quotations/[id]/approved-pdf`
|
|
|
|
Behavior:
|
|
|
|
- preview returns inline PDF from current quotation state
|
|
- download returns attachment PDF from current quotation state
|
|
- approved-pdf POST generates, persists, audits, and returns the approved PDF
|
|
- approved-pdf GET streams the already stored approved artifact
|
|
|
|
## UI Actions Added
|
|
|
|
Quotation detail now supports:
|
|
|
|
- `Preview PDF`
|
|
- `Download PDF`
|
|
- `Generate Approved PDF`
|
|
- `View Approved PDF`
|
|
|
|
The detail page also now displays:
|
|
|
|
- `Approved At`
|
|
- `Approved Template Version`
|
|
|
|
## Approved Snapshot Persistence
|
|
|
|
Added quotation persistence fields:
|
|
|
|
- `approvedAt`
|
|
- `approvedPdfUrl`
|
|
- `approvedSnapshot`
|
|
- `approvedTemplateVersionId`
|
|
|
|
Approved snapshot now stores:
|
|
|
|
- quotation id
|
|
- approved timestamp
|
|
- normalized document data
|
|
- template version id
|
|
- mapped template input
|
|
- generated timestamp
|
|
- generated by user id
|
|
|
|
## Attachment Metadata Integration
|
|
|
|
After generating an approved PDF:
|
|
|
|
- a local file is written under `public/generated/quotations/<organizationId>/`
|
|
- quotation attachment metadata is created or updated with:
|
|
- `fileName`
|
|
- `originalFileName`
|
|
- `filePath`
|
|
- `fileSize`
|
|
- `fileType = application/pdf`
|
|
- `description = Approved quotation PDF`
|
|
- `uploadedBy`
|
|
- `uploadedAt`
|
|
|
|
## Permission Added
|
|
|
|
- `crm.quotation.pdf.preview`
|
|
- `crm.quotation.pdf.download`
|
|
- `crm.quotation.pdf.generate_approved`
|
|
|
|
## Audit Integration
|
|
|
|
Required audit was added for approved PDF generation with:
|
|
|
|
- `entityType = crm_quotation_pdf_generate_approved`
|
|
- `action = generate_approved`
|
|
|
|
Preview and download remain unaudited by design.
|
|
|
|
## Remaining Risks
|
|
|
|
- Current `pdfme` generation uses a font fallback normalization step because the provided templates reference `cordia/cordiaBold`, while direct TTC-based rendering did not behave reliably with table layout generation.
|
|
- Approved PDF storage uses local filesystem placeholder output under `public/generated/...`, not external object storage.
|
|
- The environment used during implementation had no quotation rows available in the database, so full quotation-specific end-to-end smoke testing through a live record could not be completed here.
|
|
|
|
## Task I Readiness
|
|
|
|
Task H leaves the repo ready for:
|
|
|
|
- auto-generate approved PDF after final approval
|
|
- object-storage abstraction
|
|
- signed download / retention policy
|
|
- immutable approved artifact lifecycle rules
|
|
- richer template version publish controls
|