This commit is contained in:
phaichayon
2026-06-15 16:34:41 +07:00
parent 1d2406483e
commit eae0dee1f2
40 changed files with 9982 additions and 132 deletions

537
plans/task-e.md Normal file
View File

@@ -0,0 +1,537 @@
# 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 เต็ม