303 lines
5.4 KiB
Markdown
303 lines
5.4 KiB
Markdown
# Task H.1: PDF Generation Stabilization
|
|
|
|
## Goal
|
|
|
|
Stabilize Task H PDF generation before starting Task I.
|
|
|
|
Task H already added:
|
|
|
|
* pdfme server-side generation
|
|
* preview/download PDF APIs
|
|
* approved PDF generation
|
|
* approved snapshot persistence
|
|
* approved PDF attachment metadata
|
|
* quotation detail PDF actions
|
|
|
|
Task H.1 focuses on validation, hardening, and documentation.
|
|
|
|
---
|
|
|
|
## Must Read
|
|
|
|
```txt
|
|
docs/implementation/technical-debt.md
|
|
docs/adr/0008-attachment-storage-strategy.md
|
|
|
|
src/features/foundation/pdf-generator/**
|
|
src/features/foundation/document-template/**
|
|
src/features/crm/quotations/document/**
|
|
src/features/crm/quotations/**
|
|
src/features/foundation/approval/**
|
|
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
|
|
src/db/schema.ts
|
|
```
|
|
|
|
---
|
|
|
|
## Scope 1: Smoke Test With Real Quotation
|
|
|
|
Create or identify one real quotation record in dev database.
|
|
|
|
The record must include:
|
|
|
|
```txt
|
|
customer
|
|
contact
|
|
enquiry optional
|
|
at least one item
|
|
quotation customer role
|
|
scope topic
|
|
exclusion topic
|
|
payment topic
|
|
approved status or approval flow completed
|
|
```
|
|
|
|
Then verify:
|
|
|
|
```txt
|
|
Preview PDF
|
|
Download PDF
|
|
Generate Approved PDF
|
|
View Approved PDF
|
|
```
|
|
|
|
If no real record exists, create a minimal seed/dev fixture.
|
|
|
|
Rules:
|
|
|
|
* dev fixture must be organization-scoped
|
|
* do not hardcode organizationId
|
|
* do not pollute production seed
|
|
* place fixture under dev-only seed or clearly named script
|
|
|
|
---
|
|
|
|
## Scope 2: PDF Output Validation
|
|
|
|
Check generated PDF for:
|
|
|
|
```txt
|
|
file opens correctly
|
|
page count is reasonable
|
|
customer block appears
|
|
quotation code appears
|
|
item table appears
|
|
total amount appears
|
|
scope/exclusion/payment appears
|
|
approval block appears
|
|
signature placeholder appears
|
|
```
|
|
|
|
If layout breaks:
|
|
|
|
* adjust mapping normalization
|
|
* adjust template input preparation
|
|
* do not rewrite template designer
|
|
* do not hardcode quotation-specific hacks into generic pdf generator
|
|
|
|
---
|
|
|
|
## Scope 3: Approved PDF API Validation
|
|
|
|
Validate:
|
|
|
|
```txt
|
|
GET /api/crm/quotations/[id]/pdf-preview
|
|
GET /api/crm/quotations/[id]/pdf-download
|
|
POST /api/crm/quotations/[id]/approved-pdf
|
|
GET /api/crm/quotations/[id]/approved-pdf
|
|
```
|
|
|
|
Expected behavior:
|
|
|
|
* preview returns inline PDF
|
|
* download returns attachment PDF
|
|
* approved-pdf POST only works for approved quotation
|
|
* approved-pdf GET returns stored file if available
|
|
* non-approved quotation cannot generate approved PDF
|
|
|
|
---
|
|
|
|
## Scope 4: Persistence Validation
|
|
|
|
After approved PDF generation verify:
|
|
|
|
```txt
|
|
quotation.approvedPdfUrl populated
|
|
quotation.approvedSnapshot populated
|
|
quotation.approvedTemplateVersionId populated
|
|
quotation attachment metadata created or updated
|
|
audit log generated
|
|
file exists in public/generated/quotations/<organizationId>/
|
|
```
|
|
|
|
If any part is missing, fix only the persistence pipeline.
|
|
|
|
---
|
|
|
|
## Scope 5: Permission Validation
|
|
|
|
Verify permissions:
|
|
|
|
```txt
|
|
crm.quotation.pdf.preview
|
|
crm.quotation.pdf.download
|
|
crm.quotation.pdf.generate_approved
|
|
```
|
|
|
|
Check behavior for:
|
|
|
|
```txt
|
|
super_admin
|
|
admin
|
|
regular user with permission
|
|
regular user without permission
|
|
```
|
|
|
|
Do not rewrite RBAC model.
|
|
|
|
---
|
|
|
|
## Scope 6: Error Handling
|
|
|
|
Improve user-safe/server-safe errors for:
|
|
|
|
```txt
|
|
template not found
|
|
template version not found
|
|
mapping missing
|
|
quotation not approved
|
|
generated file missing
|
|
pdfme generation error
|
|
local storage write error
|
|
permission denied
|
|
```
|
|
|
|
Rules:
|
|
|
|
* API must return meaningful status codes
|
|
* UI should show readable toast/message
|
|
* do not expose stack trace to client
|
|
|
|
---
|
|
|
|
## Scope 7: Documentation / ADR
|
|
|
|
Update:
|
|
|
|
```txt
|
|
docs/implementation/technical-debt.md
|
|
```
|
|
|
|
Confirm or add:
|
|
|
|
```txt
|
|
pdfme font fallback workaround
|
|
local filesystem storage limitation
|
|
missing object storage abstraction
|
|
approved PDF lifecycle not immutable yet
|
|
no full E2E test in CI yet
|
|
```
|
|
|
|
Create ADR if not exists:
|
|
|
|
```txt
|
|
docs/adr/0009-approved-document-storage-lifecycle.md
|
|
```
|
|
|
|
Include:
|
|
|
|
```txt
|
|
Current:
|
|
local public/generated storage
|
|
|
|
Decision:
|
|
acceptable for development/MVP only
|
|
|
|
Future:
|
|
object storage abstraction
|
|
signed URL
|
|
immutable approved artifacts
|
|
retention policy
|
|
```
|
|
|
|
---
|
|
|
|
## Scope 8: Optional Small Fix
|
|
|
|
If approval finalization already has a clean hook point, add a non-blocking TODO or optional manual trigger note for:
|
|
|
|
```txt
|
|
auto-generate approved PDF after final approval
|
|
```
|
|
|
|
Do not force automatic generation in Task H.1 if it risks breaking approval flow.
|
|
|
|
---
|
|
|
|
## ห้ามทำ
|
|
|
|
```txt
|
|
object storage production
|
|
signed URL service
|
|
template designer
|
|
mapping editor
|
|
email notification
|
|
report
|
|
dashboard KPI
|
|
large refactor
|
|
```
|
|
|
|
---
|
|
|
|
## Output
|
|
|
|
After completion, summarize:
|
|
|
|
1. Files Added
|
|
2. Files Modified
|
|
3. Smoke Test Record Used
|
|
4. PDF APIs Verified
|
|
5. Persistence Verified
|
|
6. Permission Verified
|
|
7. Error Handling Improved
|
|
8. ADR / Technical Debt Updated
|
|
9. Remaining Risks
|
|
10. Task I Readiness
|
|
|
|
---
|
|
|
|
## Definition of Done
|
|
|
|
Task H.1 passes when:
|
|
|
|
✔ PDF preview works with a real quotation
|
|
|
|
✔ PDF download works with a real quotation
|
|
|
|
✔ Approved PDF generation works for approved quotation
|
|
|
|
✔ Approved PDF GET returns stored PDF
|
|
|
|
✔ Non-approved quotation cannot generate approved PDF
|
|
|
|
✔ approvedSnapshot is saved
|
|
|
|
✔ approvedPdfUrl is saved
|
|
|
|
✔ approvedTemplateVersionId is saved
|
|
|
|
✔ attachment metadata is created/updated
|
|
|
|
✔ audit log exists for approved PDF generation
|
|
|
|
✔ permissions are enforced
|
|
|
|
✔ errors are user-safe
|
|
|
|
✔ storage lifecycle ADR exists
|
|
|
|
✔ ready for Task I
|