hotfix-add subgroup customer
This commit is contained in:
326
plans/hotfix-1-customer.md
Normal file
326
plans/hotfix-1-customer.md
Normal file
@@ -0,0 +1,326 @@
|
||||
# Hotfix: Add Customer Sub Group to Customer Form
|
||||
|
||||
## Goal
|
||||
|
||||
เพิ่ม field `Customer Sub Group` ในหน้า Add / Edit Customer
|
||||
|
||||
โดยใช้ master option category:
|
||||
|
||||
```txt
|
||||
crm_customer_sub_group
|
||||
```
|
||||
|
||||
และต้อง filter ตาม `Customer Group` ที่เลือก
|
||||
|
||||
Relationship:
|
||||
|
||||
```txt
|
||||
crm_customer_group
|
||||
↓ parent
|
||||
crm_customer_sub_group
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Must Read
|
||||
|
||||
```txt
|
||||
src/features/crm/customers/**
|
||||
src/features/foundation/master-options/**
|
||||
src/app/api/foundation/master-options/route.ts
|
||||
src/db/schema.ts
|
||||
src/db/seeds/foundation.seed.ts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Scope 1: Data Model Check
|
||||
|
||||
ตรวจสอบว่า customer schema มี field สำหรับ sub group แล้วหรือยัง
|
||||
|
||||
Expected field:
|
||||
|
||||
```txt
|
||||
customerSubGroup
|
||||
```
|
||||
|
||||
หรือถ้าใช้ naming เดิม:
|
||||
|
||||
```txt
|
||||
custSubGroup
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
* ถ้ามี field อยู่แล้ว ให้ reuse
|
||||
* ถ้ายังไม่มี ให้เพิ่ม field ใหม่แบบไม่กระทบข้อมูลเดิม
|
||||
* field เป็น optional
|
||||
* เก็บเป็น master option code/value ตาม pattern เดิมของ customerGroup
|
||||
|
||||
---
|
||||
|
||||
## Scope 2: Master Option Category
|
||||
|
||||
เพิ่ม/ยืนยัน category:
|
||||
|
||||
```txt
|
||||
crm_customer_sub_group
|
||||
```
|
||||
|
||||
Sub group ต้องมี parent relationship กับ group:
|
||||
|
||||
```txt
|
||||
crm_customer_group.id
|
||||
↓
|
||||
crm_customer_sub_group.parentId
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
* parentId ต้องชี้ไป customer group option
|
||||
* sub group dropdown ต้อง filter ด้วย parentId
|
||||
* ถ้ายังไม่ได้เลือก customer group ให้ disable sub group dropdown
|
||||
|
||||
---
|
||||
|
||||
## Scope 3: Seed Data
|
||||
|
||||
อัปเดต:
|
||||
|
||||
```txt
|
||||
src/db/seeds/foundation.seed.ts
|
||||
```
|
||||
|
||||
เพิ่ม seed category:
|
||||
|
||||
```txt
|
||||
crm_customer_group
|
||||
crm_customer_sub_group
|
||||
```
|
||||
|
||||
ตัวอย่าง:
|
||||
|
||||
```txt
|
||||
crm_customer_group:
|
||||
- industrial
|
||||
- construction
|
||||
- government
|
||||
- dealer
|
||||
- other
|
||||
|
||||
crm_customer_sub_group:
|
||||
- factory
|
||||
- warehouse
|
||||
- logistics
|
||||
- contractor
|
||||
- consultant
|
||||
- state_enterprise
|
||||
- government_agency
|
||||
- reseller
|
||||
- other
|
||||
```
|
||||
|
||||
Relationship ตัวอย่าง:
|
||||
|
||||
```txt
|
||||
industrial
|
||||
- factory
|
||||
- warehouse
|
||||
- logistics
|
||||
|
||||
construction
|
||||
- contractor
|
||||
- consultant
|
||||
|
||||
government
|
||||
- state_enterprise
|
||||
- government_agency
|
||||
|
||||
dealer
|
||||
- reseller
|
||||
|
||||
other
|
||||
- other
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
* seed idempotent
|
||||
* no hardcoded organizationId
|
||||
* parent option must be created before child options
|
||||
* child options must set parentId
|
||||
* do not duplicate options if seed runs again
|
||||
|
||||
---
|
||||
|
||||
## Scope 4: Customer Schema / Zod
|
||||
|
||||
Update:
|
||||
|
||||
```txt
|
||||
src/features/crm/customers/schemas/customer.schema.ts
|
||||
```
|
||||
|
||||
Add:
|
||||
|
||||
```ts
|
||||
customerSubGroup: z.string().optional().nullable()
|
||||
```
|
||||
|
||||
หรือใช้ field name ที่มีอยู่จริง เช่น:
|
||||
|
||||
```ts
|
||||
custSubGroup: z.string().optional().nullable()
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
* Create Customer ต้องรับ field นี้ได้
|
||||
* Edit Customer ต้อง load ค่าเดิมได้
|
||||
* ถ้าเปลี่ยน customerGroup แล้ว customerSubGroup ไม่อยู่ใต้ parent ใหม่ ให้ clear ค่า customerSubGroup
|
||||
|
||||
---
|
||||
|
||||
## Scope 5: API / Server Service
|
||||
|
||||
Update:
|
||||
|
||||
```txt
|
||||
src/features/crm/customers/server/service.ts
|
||||
src/app/api/crm/customers/route.ts
|
||||
src/app/api/crm/customers/[id]/route.ts
|
||||
src/features/crm/customers/api/types.ts
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
* create customer save customerSubGroup
|
||||
* update customer save customerSubGroup
|
||||
* list/detail return customerSubGroup
|
||||
* validate sub group parent matches selected group ถ้าทำได้ง่าย
|
||||
* if invalid parent-child relation, return user-safe error
|
||||
|
||||
---
|
||||
|
||||
## Scope 6: Customer Form UI
|
||||
|
||||
Update:
|
||||
|
||||
```txt
|
||||
src/features/crm/customers/components/customer-form-sheet.tsx
|
||||
```
|
||||
|
||||
Add field:
|
||||
|
||||
```txt
|
||||
Customer Group
|
||||
Customer Sub Group
|
||||
```
|
||||
|
||||
Behavior:
|
||||
|
||||
* Customer Group dropdown uses `crm_customer_group`
|
||||
* Customer Sub Group dropdown uses `crm_customer_sub_group`
|
||||
* Customer Sub Group filtered by selected group option `parentId`
|
||||
* If no Customer Group selected:
|
||||
|
||||
* disable Customer Sub Group
|
||||
* placeholder: "Select customer group first"
|
||||
* If Customer Group changes:
|
||||
|
||||
* reset Customer Sub Group
|
||||
* If edit mode:
|
||||
|
||||
* load existing Customer Group
|
||||
* load filtered Customer Sub Group
|
||||
* selected value must display correctly
|
||||
|
||||
---
|
||||
|
||||
## Scope 7: Customer List / Detail
|
||||
|
||||
Update if relevant:
|
||||
|
||||
```txt
|
||||
src/features/crm/customers/components/customer-columns.tsx
|
||||
src/features/crm/customers/components/customer-detail.tsx
|
||||
```
|
||||
|
||||
Display:
|
||||
|
||||
```txt
|
||||
Customer Group
|
||||
Customer Sub Group
|
||||
```
|
||||
|
||||
If label lookup is available, show label instead of raw code.
|
||||
|
||||
---
|
||||
|
||||
## Scope 8: Query Freshness
|
||||
|
||||
After create/update:
|
||||
|
||||
* invalidate customer list
|
||||
* invalidate customer detail
|
||||
* form closes after success
|
||||
* table/detail show new customer sub group immediately
|
||||
|
||||
Follow existing CRUD freshness rule.
|
||||
|
||||
---
|
||||
|
||||
## Scope 9: Regression Check
|
||||
|
||||
Verify:
|
||||
|
||||
* create customer with group + sub group
|
||||
* create customer without sub group
|
||||
* edit customer group changes and sub group resets
|
||||
* edit customer retains valid sub group
|
||||
* invalid sub group under another group is rejected or cleared
|
||||
* customer list/detail displays value
|
||||
|
||||
---
|
||||
|
||||
## Explicit Non-Scope
|
||||
|
||||
Do NOT implement:
|
||||
|
||||
```txt
|
||||
Customer group management UI
|
||||
Inline create master option
|
||||
Large RBAC rewrite
|
||||
Customer import/export
|
||||
Dashboard changes
|
||||
Report changes
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Output
|
||||
|
||||
After completion, summarize:
|
||||
|
||||
1. Files Added
|
||||
2. Files Modified
|
||||
3. Schema Field Used/Added
|
||||
4. Master Options Seeded
|
||||
5. Form Behavior Added
|
||||
6. Parent/Child Filtering Behavior
|
||||
7. Validation Added
|
||||
8. Verification Result
|
||||
9. Remaining Risks
|
||||
|
||||
---
|
||||
|
||||
## Definition of Done
|
||||
|
||||
* Add/Edit Customer has Customer Sub Group field
|
||||
* Customer Sub Group uses `crm_customer_sub_group`
|
||||
* Sub Group filters by selected Customer Group parent
|
||||
* Changing Customer Group resets invalid Sub Group
|
||||
* Create customer saves Sub Group
|
||||
* Edit customer saves Sub Group
|
||||
* Detail/list can show Sub Group
|
||||
* Mutation refreshes customer table/detail
|
||||
Reference in New Issue
Block a user