# 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