Appearance
Shared Rules — CRM Ticket Workflow
1. Thuật ngữ chuẩn
| Thuật ngữ | Nghĩa trong code hiện tại | Ghi chú |
|---|---|---|
| Ticket | crm.ticket | Work item trung tâm cho chăm sóc/tư vấn/follow-up |
| Result | ticket.result_id | Kết quả xử lý của ticket hiện tại; có thể quyết định sinh ticket mới |
| Status | ticket.status_id | Trạng thái lifecycle như new, assigned, completed, canceled |
| Assignee | ticket.assignee_id | Người trực tiếp xử lý ticket |
| In charge / curator | ticket.in_charge_id | Người theo dõi/phụ trách rộng hơn assignee |
| Parent ticket | parent_ticket_id | Ticket trước đó trong chain |
| Root ticket | root_ticket_id | Gốc chuỗi ticket |
| Source | source_id | Nguồn sinh ticket như hotline, CRM staff, chain result, scheduler |
| Ticket distribute | ticket_distribute | Pointer nhớ last-assignee cho auto-distribution |
| Incall | incall_call, incall_call_log, incall_extension | Runtime hotline/call center gắn với ticket |
2. Source Matrix
| Source | Ý nghĩa business hiện trong FE | Origin thực tế |
|---|---|---|
ticket_source_1 | Trực page, phát triển cộng đồng, phát triển thị trường, hotline, ADS, HQ Sale | Chủ yếu external lead/hotline surface |
ticket_source_2 | Telesales, chăm sóc khách hàng | CRM staff tạo trực tiếp |
ticket_source_3 | Tạo bởi kết quả của ticket trước đó | changeStatusTicket/duplicate chain |
ticket_source_4 | Lịch hẹn xác nhận, công việc hoàn thành, đơn hàng hoàn thành, thanh toán thành công, phát sinh đơn hàng | Scheduler consolidate_ticket_4 |
ticket_source_5 | Tạo từ lịch hẹn tư vấn | Appointment-driven |
ticket_source_6 | Tạo từ đánh giá công việc | Upstream evaluation flow |
ticket_source_7 | Tạo từ nhãn liên hệ sai số | Contact label/wrong-number cleanup |
ticket_source_8 | Sinh nhật hôm nay và thực thu tối thiểu 1 triệu | Scheduler consolidate_ticket_8 |
sourceDescriptions đang nằm trực tiếp ở FE (Tickets.tsx:128-158), nên nếu business đổi taxonomy mà quên sửa code thì tooltip sẽ drift ngay.
3. Status Matrix
| Status family | Ý nghĩa |
|---|---|
ticket_status_new | Ticket mới, thường chưa có assignee |
ticket_status_assigned | Ticket đã có assignee và đang được xử lý |
ticket_status_completed | Ticket hiện tại hoàn tất; có thể kéo theo ticket kế tiếp |
ticket_status_canceled | Ticket dừng / hủy |
Điểm đáng chú ý:
- FE có auto-transition
new -> assignednếu save vớiassigneeId. - FE cũng có nhánh
assigned -> newnếu bỏ assignee rồi save. - Kết quả (
result_id) thường được chốt cùng lúc với complete, nhưng rule sinh ticket mới không nằm ở FE mà nằm ở backend duplicate flow.
4. Actor Matrix
| Actor | Vai trò |
|---|---|
| Telesales / CSKH staff | Xử lý ticket được giao, follow-up, call |
| Telesales / CSKH leader | Thấy rộng hơn, edit rộng hơn, assignment surface |
| Call center / hotline operator | Runtime call và log cuộc gọi |
Admin / BOD | Scope rộng, không bị bó bởi setSpecialDataByRole() |
| Scheduler / system | Tạo source 4, source 8, nhắc lịch, auto-distribute |
5. Action / Scheduler Matrix
| Name | Type | Vai trò |
|---|---|---|
assignMultipleTicket | Hasura action | Bulk assign ticket theo branch và target role |
changeStatusTicket | Hasura action | Validate transition và xử lý duplicate/new ticket chain |
callcenterCallData | Hasura action + REST endpoint | Ghi nhận trạng thái cuộc gọi inbound/outbound |
callcenterCallOutEvent | Hasura action + REST endpoint | Ghi event cuộc gọi đi |
secureIncall | Hasura action | Contract bảo mật khi khởi tạo call |
consolidate_ticket_4 | Cron | Sinh source 4 tickets lúc 18:30 hằng ngày |
consolidate_ticket_8 | Cron | Sinh source 8 tickets lúc 18:20 hằng ngày |
distribute_ticket | Cron | Auto-assign ticket lúc 21:00 hằng ngày |
remind_ticket_today | Cron | Nhắc ticket due/overdue lúc 01:00 |
remind_ticket_tomorrow | Cron | Nhắc ticket có appointment ngày mai lúc 09:30 |
6. Invariants quan trọng
SR-001: changeStatusTicket là lifecycle engine thật
- FE có thể gọi mutation create/update trước, nhưng transition hợp lệ cuối cùng vẫn bị chặn ở
ticket.ValidateNewStatus(...). - Nhánh
TicketCompletedgọiticket.Duplicate(...)thay vì update trực tiếp (change_status_ticket.go:44-57).
SR-002: Result không phải lúc nào cũng kết thúc chuỗi ticket
FE có whitelist resultNotGenerateNewTicket() gồm:
cancel_consultant_appointmentcancel_servicewrong_numberwrong_informationcompleted
Nếu complete trả new_ticket_id và result không nằm trong whitelist này, UI sẽ chuyển thẳng sang ticket mới (TicketCreate.tsx:174-181, TicketCreate.tsx:305-319).
SR-003: Auto-distribution chỉ nhớ last assignee ở scheduler path
assignMultipleTickettính assignee theo branch/role nhưng không ghiticket_distribute.distribute_ticketvừa update ticket vừa insertticket_distributecho assignee cuối mỗi target (distribute_ticket.go:132-147).
Hệ quả:
- manual assign và auto-distribute không chia sẻ fairness state hoàn toàn,
- audit logic cần tách rõ ticket được giao bởi action hay bởi cron.
SR-004: Visibility của ticket đang phụ thuộc mạnh vào FE builder
TicketBuildWhere.setSpecialDataByRole() đáng ra phải thêm:
- ticket unassigned theo
belong_to, - ticket đang assign cho current user,
- ticket current user là
in_charge, - ticket theo
target_idvới assigned roles.
Nhưng do _or.concat(...) không reassign, hai nhánh assignee/in-charge bị mất (useTicketBuilder.ts:143-187).
SR-005: Call log và ticket có thể được nối sau khi ticket vừa tạo
Nếu newCallObj tồn tại trong localStorage, TicketCreate sẽ update incall_call.ticket_id ngay sau khi create/update ticket thành công (TicketCreate.tsx:210-220).
7. Boundary Checklist
Khi phân tích bug hoặc change request trong vùng này, luôn hỏi:
- Ticket đến từ source nào: manual, chain result, hay scheduler?
- Case này đang đi qua create/update form hay đi thẳng qua
changeStatusTicket? - Assignment xảy ra bởi bulk action hay cron
distribute_ticket? - Ticket có đang gắn appointment hoặc call log không?
- Visibility issue nằm ở Hasura permission hay nằm ở
TicketBuildWherephía FE?
8. Rủi ro / Findings
| ID | Finding |
|---|---|
| SR-F01 | Source taxonomy hiện sống một phần trong tooltip FE, một phần trong scheduler/backend; rất dễ drift. |
| SR-F02 | Result semantics và status semantics đang bị trộn trong save flow, nên QA nếu chỉ test status matrix sẽ thiếu chain-generation behavior. |
| SR-F03 | Assignment fairness/history không đồng nhất vì manual path và cron path không dùng cùng persistence rule. |
| SR-F04 | Ticket visibility cho non-leader CRM roles có dấu hiệu sai thật do bug _or.concat(...). |