# Task G: Quotation Document Preview / PDF Template Foundation

## ALLA OS CRM vNext

คุณคือ Senior Full-stack Engineer

ให้ implement Quotation Document Preview และ PDF Template Foundation โดยต่อยอดจาก:

```txt
Task A
Task B
Task B.1
Task C
Task D
Task E
Task E.1
Task F
```

## ต้องอ่านก่อน

```txt
docs/implementation/task-a-template-audit.md
docs/implementation/task-b-template-audit.md
docs/implementation/task-b1-foundation-stabilization.md
docs/implementation/technical-debt.md

docs/adr/0007-quotation-revision-strategy.md
docs/adr/0008-attachment-storage-strategy.md

Layout.md
AGENTS.md
.agents/skills/kiranism-shadcn-dashboard

src/features/foundation/**
src/features/crm/customers/**
src/features/crm/enquiries/**
src/features/crm/quotations/**
src/db/schema.ts
```

---

# Goal

สร้าง foundation สำหรับเอกสารใบเสนอราคา

โฟกัสที่:

```txt
Quotation document preview
PDF template metadata
Template versioning
Template placeholder mapping
Approved snapshot preparation
```

ยังไม่ทำ PDF generation จริงแบบ production เต็ม

---

# Scope G1: Template Schema

เพิ่ม tables ถ้ายังไม่มี

```txt
crm_document_templates
crm_document_template_versions
crm_document_template_mappings
crm_document_template_table_columns
```

## crm_document_templates

```txt
id
organizationId

documentType
productType
fileType

templateName
description

isDefault
isActive

createdAt
updatedAt
deletedAt
createdBy
updatedBy
```

documentType example:

```txt
quotation
```

fileType example:

```txt
pdfme
excel
html
```

---

## crm_document_template_versions

```txt
id
organizationId
templateId

version
filePath
schemaJson
previewImageUrl

isActive

createdAt
updatedAt
deletedAt
createdBy
```

---

## crm_document_template_mappings

```txt
id
organizationId
templateVersionId

placeholderKey
sourcePath
dataType

sheetName
defaultValue
formatMask
sortOrder

createdAt
updatedAt
deletedAt
```

dataType:

```txt
scalar
multiline
table
image
```

---

## crm_document_template_table_columns

```txt
id
organizationId
mappingId

columnName
sourceField
columnLetter
sortOrder
formatMask

createdAt
updatedAt
deletedAt
```

---

# Scope G2: Quotation Snapshot Preparation

เพิ่มใน quotation document service

สร้าง function:

```ts
buildQuotationDocumentData(quotationId)
```

ให้ output เป็น normalized object สำหรับ preview/document generation

ต้องรวม:

```txt
company
branch
customer
contact
quotation
items
quotationCustomers
topics
approval
signatures placeholder
```

ตัวอย่าง output:

```ts
{
  company: {},
  branch: {},
  customer: {},
  contact: {},
  quotation: {},
  items: [],
  topics: {
    scope: [],
    exclusion: [],
    payment: []
  },
  approval: {
    status,
    approvedAt,
    approvers: []
  }
}
```

Rules:

* validate organizationId
* ห้าม query ข้าม organization
* ใช้ approved quotation ได้
* draft/pending preview ได้ แต่ต้องแสดง watermark/status badge ใน UI

---

# Scope G3: Template Mapping Resolver

สร้าง service:

```txt
src/features/foundation/document-template/**
```

หรือถ้าเหมาะสม:

```txt
src/features/crm/quotations/document/**
```

Functions:

```ts
resolveTemplateForDocument(params)
resolveTemplateMappings(templateVersionId)
mapDocumentDataToTemplateInput(documentData, mappings)
```

Rules:

* template default ตาม documentType + productType + fileType
* fallback default template ของ documentType
* mapping ต้องไม่ hardcode เฉพาะ quotation มากเกินไป
* sourcePath ใช้ dot path เช่น customer.name, quotation.code, items

---

# Scope G4: API Routes

เพิ่ม route handlers:

```txt
src/app/api/crm/quotations/[id]/document-data/route.ts
src/app/api/crm/quotations/[id]/document-preview/route.ts
src/app/api/crm/document-templates/route.ts
src/app/api/crm/document-templates/[id]/route.ts
src/app/api/crm/document-templates/[id]/versions/route.ts
```

รองรับ:

```txt
GET quotation document data
GET quotation document preview data
GET/POST document templates
GET/PATCH/DELETE document template
GET/POST template versions
```

ยังไม่ต้องทำ binary PDF download

---

# Scope G5: Preview UI

ใน:

```txt
/dashboard/crm/quotations/[id]
```

แทน Document Preview Placeholder ด้วย real preview tab

Preview ต้องแสดง:

```txt
quotation header
customer block
project info
items table
price summary
scope/exclusion/payment topics
approval block
signature placeholders
status watermark/badge
```

ใช้ Layout.md และ shadcn dashboard style

ห้ามสร้าง design system ใหม่

---

# Scope G6: Template Settings UI

เพิ่ม route ถ้ายังเป็น placeholder:

```txt
/dashboard/crm/settings/templates
```

UI ขั้นต่ำ:

```txt
Template list
Template versions
Default template badge
Active/inactive badge
Mapping count
```

ยังไม่ต้องทำ template designer แบบ drag/drop

ทำได้แค่ metadata CRUD หรือ read-only listing ก่อน

---

# Scope G7: pdfme Template Seed

ถ้ามี template json อยู่แล้ว ให้ seed เป็น default quotation pdfme template

Seed:

```txt
documentType = quotation
fileType = pdfme
productType = default
templateName = ALLA Quotation Standard
version = 1.0
schemaJson = existing pdfme template json
isDefault = true
isActive = true
```

Mapping placeholders:

```txt
customer_name -> customer.name
customer_addr -> customer.address
customer_tel -> customer.phone
customer_email -> customer.email
customer_att -> contact.name
project_name -> quotation.projectName
site_location -> quotation.projectLocation
quotation_date -> quotation.quotationDate
quotation_code -> quotation.code
quotation_price -> quotation.totalAmount
currency -> quotation.currency
exclusion_data -> topics.exclusion
item_topic -> topics.scope
```

ถ้าไม่มี template json ใน repo ให้สร้าง seed placeholder template schemaJson แบบ minimal

---

# Scope G8: Approved Snapshot Preparation

ยังไม่ต้อง generate PDF จริง

แต่ให้เตรียม service function:

```ts
prepareApprovedQuotationSnapshot(quotationId)
```

ใช้สำหรับอนาคตเมื่อ quotation approved แล้ว

Output:

```ts
{
  quotationId,
  approvedAt,
  documentData,
  templateVersionId,
  templateInput
}
```

ยังไม่ต้องเขียนลง approvedPdfUrl ถ้ายังไม่มี PDF generator

---

# Permissions

เพิ่มถ้ายังไม่มี:

```txt
crm.document_template.read
crm.document_template.create
crm.document_template.update
crm.document_template.delete
crm.quotation.document.preview
```

---

# Audit

Audit mutation:

```txt
crm_document_template
crm_document_template_version
crm_document_template_mapping
```

Preview GET ไม่ต้อง audit

---

# ห้ามทำ

```txt
PDF binary generation
Excel binary generation
File upload storage
Drag/drop template designer
Report
Dashboard KPI
Notification
```

---

# Output

หลังทำเสร็จ สรุป:

1. Files Added
2. Files Modified
3. Schema Added
4. API Routes Added
5. Preview UI Added
6. Template Settings UI Added
7. Template Seed Added
8. Mapping Resolver Added
9. Approved Snapshot Prep Added
10. Remaining Risks
11. Task H Readiness

---

# Definition of Done

Task G ผ่านเมื่อ:

✔ document template schema พร้อม

✔ template version schema พร้อม

✔ mapping schema พร้อม

✔ quotation document data service พร้อม

✔ template resolver พร้อม

✔ quotation preview tab แสดงข้อมูลจริง

✔ template settings route ใช้งานได้ขั้นต่ำ

✔ pdfme default template seed พร้อม หรือ fallback minimal seed พร้อม

✔ approved snapshot preparation พร้อม

✔ ยังไม่ generate PDF binary จริง

✔ ยังไม่ทำ template designer

✔ ยังไม่ทำ report/dashboard
