538 lines
9.8 KiB
Markdown
538 lines
9.8 KiB
Markdown
# 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 เต็ม
|