# Task E: Quotation Production Module ## ALLA OS CRM vNext คุณคือ Senior Full-stack Engineer ให้ implement Quotation production module โดยต่อยอดจาก Task A, B, B.1, C, D ## ต้องอ่านก่อน ```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 Layout.md AGENTS.md .agents/skills/kiranism-shadcn-dashboard src/db/schema.ts src/features/foundation/** src/features/crm/customers/** src/features/crm/enquiries/** src/app/dashboard/crm/** ``` ## เป้าหมาย สร้าง production module สำหรับ: ```txt Quotation Quotation Items Quotation Customers Quotation Topics Quotation Follow-ups Quotation Attachments metadata Quotation Revision Enquiry → Quotation linkage ``` ยังไม่ทำ: ```txt Approval workflow เต็ม PDF generation จริง Report Dashboard KPI จริง Notification ``` ## Core Rules ```txt organizationId = tenant boundary branchId = business sub-scope ``` ทุก quotation ต้องมี `organizationId` Quotation ควรอ้างอิง: ```txt customerId contactId enquiryId optional ``` ห้ามใช้ mock CRM service ห้าม import จาก: ```txt src/features/crm-demo/** src/constants/mock-api* ``` ## Scope E1: Quotation Schema เพิ่ม production schema ใน `src/db/schema.ts` ตารางหลัก: ```txt crm_quotations ``` Fields ขั้นต่ำ: ```txt id organizationId branchId code enquiryId customerId contactId quotationDate validUntil quotationType projectName projectLocation attention reference notes status revision parentQuotationId revisionRemark currency exchangeRate subtotal discount discountType taxRate taxAmount totalAmount chancePercent isHotProject competitor salesmanId isSent sentAt sentVia acceptedAt rejectedAt rejectionReason isActive createdAt updatedAt deletedAt createdBy updatedBy ``` Rules: * `organizationId` required * `customerId` required * `code` unique ภายใน organization * `status`, `quotationType`, `currency`, `discountType` ใช้ master options ถ้ามี * code ใช้ document sequence `quotation -> QT` * create/update/delete ต้อง audit log * ยังไม่ทำ approval table * status `pending_approval` ทำเป็น placeholder ได้ ## Scope E2: Quotation Items Schema เพิ่ม table: ```txt crm_quotation_items ``` Fields ขั้นต่ำ: ```txt id organizationId quotationId itemNumber productType description quantity unit unitPrice discount discountType taxRate totalPrice notes sortOrder createdAt updatedAt deletedAt ``` Rules: * item ต้องอยู่ organization เดียวกับ quotation * totalPrice คำนวณฝั่ง server * quotation total ต้องคำนวณจาก items * ห้ามเชื่อ total จาก client โดยตรง ## Scope E3: Quotation Customers Schema เพิ่ม table: ```txt crm_quotation_customers ``` Fields: ```txt id organizationId quotationId customerId role isPrimary createdAt updatedAt deletedAt ``` Roles: ```txt owner consultant contractor billing ``` Rules: * customer หลักใน quotation ต้องอยู่ใน organization เดียวกัน * contractor สำคัญต่อ reporting ภายหลัง * ยังไม่ทำ report ใน Task E ## Scope E4: Quotation Topics Schema เพิ่ม tables: ```txt crm_quotation_topics crm_quotation_topic_items ``` Topic types: ```txt scope exclusion payment ``` ใช้สำหรับเอกสารใบเสนอราคาในอนาคต ## Scope E5: Follow-ups + Attachments Metadata เพิ่ม tables: ```txt crm_quotation_followups crm_quotation_attachments ``` Attachment ใน Task E เก็บ metadata ก่อน: ```txt fileName originalFileName filePath fileSize fileType description uploadedAt uploadedBy ``` ยังไม่ต้องทำ upload storage จริง ถ้า scope ใหญ่เกินไป ทำ placeholder service ได้ แต่ schema ต้องพร้อม ## Scope E6: API Routes สร้าง route handlers: ```txt src/app/api/crm/quotations/route.ts src/app/api/crm/quotations/[id]/route.ts src/app/api/crm/quotations/[id]/items/route.ts src/app/api/crm/quotations/[id]/items/[itemId]/route.ts src/app/api/crm/quotations/[id]/customers/route.ts src/app/api/crm/quotations/[id]/topics/route.ts src/app/api/crm/quotations/[id]/followups/route.ts src/app/api/crm/quotations/[id]/attachments/route.ts src/app/api/crm/quotations/[id]/revisions/route.ts ``` รองรับ: ```txt GET list POST create GET detail PATCH update DELETE soft delete CRUD items CRUD customers CRUD topics CRUD followups list/create attachment metadata create revision ``` Rules: * ใช้ `requireOrganizationAccess` * ใช้ permission helper * filter ด้วย organizationId เสมอ * customer/contact/enquiry ต้องอยู่ organization เดียวกัน * create quotation ต้อง generate code * revision ต้องสร้าง code suffix หรือ revision record ตาม design * ทุก mutation ต้อง audit Permissions แนะนำ: ```txt crm.quotation.read crm.quotation.create crm.quotation.update crm.quotation.delete crm.quotation.item.manage crm.quotation.customer.manage crm.quotation.topic.manage crm.quotation.followup.manage crm.quotation.attachment.manage crm.quotation.revision.create ``` ## Scope E7: Feature Layer สร้าง: ```txt src/features/crm/quotations/api/types.ts src/features/crm/quotations/api/service.ts src/features/crm/quotations/api/queries.ts src/features/crm/quotations/api/mutations.ts src/features/crm/quotations/schemas/quotation.schema.ts src/features/crm/quotations/server/service.ts src/features/crm/quotations/components/** ``` ใช้ pattern จาก: ```txt src/features/products/** src/features/users/** src/features/crm/customers/** src/features/crm/enquiries/** ``` ## Scope E8: Quotation UI แทน placeholder routes: ```txt /dashboard/crm/quotations /dashboard/crm/quotations/[id] ``` List page ต้องมี: ```txt PageContainer DataTable search status filter quotation type filter branch filter customer filter enquiry filter hot project filter create button edit action view action soft delete action ``` Detail page ใช้ Layout.md Template A Tabs: ```txt Overview Items Customers Topics Follow-ups Attachments Activity Approval Placeholder Document Preview Placeholder ``` ## Scope E9: Quotation Form ใช้: ```txt useAppForm Zod Sheet/Dialog pattern React Query mutation ``` Create/Edit fields: ```txt enquiryId customerId contactId quotationDate validUntil quotationType projectName projectLocation branchId currency exchangeRate status chancePercent isHotProject competitor reference notes ``` Rules: * enquiry dropdown จาก production enquiry API * ถ้าเลือก enquiry ให้ auto-fill customer/contact/project ถ้าทำได้แบบไม่ซับซ้อน * customer dropdown จาก production customer API * contact dropdown filter ตาม customer * status/quotationType/currency ดึงจาก master options * ห้าม hardcode option ใน form ## Scope E10: Item UI ใน Quotation Detail tab: Items ต้องมี: ```txt item list create item edit item delete item subtotal/tax/total summary ``` Rules: * คำนวณ total ฝั่ง server * UI แสดง readonly total summary จาก API ## Scope E11: Revision รองรับ create revision เบื้องต้น Rules: * revision สร้างจาก quotation เดิม * copy quotation header + items + customers + topics * parentQuotationId ชี้กลับ quotation เดิม * revision เริ่ม R01, R02 * ห้าม revise quotation ที่ draft/cancelled ถ้า business rule ต้องการ * mutation ต้อง audit ## Scope E12: Integration ### Enquiry Detail เพิ่ม related quotations tab/list จริงใน: ```txt /dashboard/crm/enquiries/[id] ``` ### Customer Detail เพิ่ม related quotations list placeholder หรือจริงถ้าทำไม่ซับซ้อน ## ห้ามทำใน Task E ```txt Approval table Approval matrix Approval workflow เต็ม PDF generation จริง Excel generation จริง Dashboard KPI จริง Report Notification ``` ## Output หลังทำเสร็จ สรุป: 1. Files Added 2. Files Modified 3. Schema Added 4. API Routes Added 5. UI Routes Completed 6. Permissions Used 7. Audit Integration 8. Document Sequence Integration 9. Enquiry/Customer Integration 10. Revision Support 11. Remaining Risks 12. Task F Readiness ## Definition of Done Task E ผ่านเมื่อ: * Quotation schema พร้อม * Quotation items พร้อม * Quotation customers พร้อม * Quotation topics พร้อม * Quotation follow-ups พร้อม * Attachment metadata พร้อม * Quotation list ใช้ production data * Quotation detail ใช้ production data * Quotation create/edit/delete ใช้งานได้ * Item create/edit/delete ใช้งานได้ * Revision create ใช้งานได้เบื้องต้น * ใช้ organizationId ทุก query * customer/contact/enquiry ต้องอยู่ organization เดียวกัน * ใช้ master options ใน status/type/currency * ใช้ document sequence ตอนสร้าง quotation * ใช้ audit log ทุก mutation * ไม่ import mock CRM * ไม่ทำ Approval workflow เต็ม