# 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
