510 lines
8.3 KiB
Markdown
510 lines
8.3 KiB
Markdown
# 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
|