Appearance
Module Overview — Projects Task Lifecycle And Tour Income
1. projects thực tế là task-runtime module có project shell ở ngoài
| Lớp | Thành phần | Vai trò |
|---|---|---|
| Project shell | Project, ProjectCreate, ProjectDetail, project, project_member | Tạo board, cấu hình members, xem detail |
| Task runtime | project_task, TaskCreate, TaskDetail, QuickViewTaskDetail | Create/update task, chuyển trạng thái, chạy subtask và service flow |
| Collaboration runtime | project_task_comment, project_task_file, task_log, project_task_status_log | Comment, file, audit và timeline |
| Tour-income runtime | project_task_assignee, ecommerce_task_log, request_working_schedule, GetListTourLimit | Tour fee, doctor commission, KPI/salary/report coupling |
Điểm quan trọng là UI gọi module này là "project management", nhưng config route và backend runtime cho thấy trọng tâm thực nằm ở task_management và project_task (diva-admin/src/modules/projects/module.ts:145).
2. Surface map
FE routes
| Route family | Vai trò |
|---|---|
/p/project | List project, create/edit/clone project |
/p/project/:id | Project detail, task board |
/p/project/:id/task/create* | Tạo task/subtask từ board hoặc cột |
/p/project/:id/task/:taskId | Task detail đầy đủ |
/p/project/:id/task/view/:taskId | Quick view dialog cho thao tác nhanh |
Runtime backend
| Runtime | Vai trò |
|---|---|
Hasura CRUD trên project_task* | Surface chính cho create/update/delete |
Event project_task_insert, project_task_update_1 | Đồng bộ task log, doctor commission, customer visit, order code |
Event project_task_assignee_* | Notification assignee, KPI log, salary sync, customer note sync, auto-fill tour_money |
Event project_task_comment_*, project_task_file_insert_delete | Comment history, notifications, mirror file sang reference_file |
Scheduler reset_task, task_expired | Reset task automate quá hạn, gửi overdue notification, ghi KPI overdue |
Action GetListTourLimit | Tính read model tour limit/report dựa trên task done + assignee tour fee |
3. Hai dialect status đang cùng tồn tại
Automate board dialect
| Status | Ý nghĩa |
|---|---|
new_branch | Trạng thái mặc định khi create task automate (TaskCreate.tsx:243) |
waiting_branch | Chờ branch hoặc chờ điều kiện bổ sung, có thể do doctor commission request |
accepted_branch | Đã nhận việc |
inprogress_branch | Đang thực hiện |
done_branch | Hoàn tất |
canceled_branch | Hủy |
My-task / personal dialect
| Status | Cách map ở FE |
|---|---|
new | status_id ilike new_% (MyTaskItem.tsx:116) |
reopen | status_id ilike reopen_% |
inprogress | is_inprogress = true |
reviewing | status_id ilike pending_% |
completed | status_id ilike done_% |
cancelled / missed | Dùng enum riêng trong MY_TASK_STATUES (types.ts:102) |
Đây không phải chỉ là vấn đề naming. Nó tạo ra hai mental models khác nhau giữa board runtime và báo cáo/task cá nhân.
4. Lifecycle tổng quát của task
text
Create task in FE
-> Hasura insert project_task + assignees/files/labels
-> event project_task_insert
-> HandleTaskLogUpdate
-> doctor commission sync nếu doctor_task
-> updateTaskCapture(parent) nếu là subtask
-> UpdateOrderCode
Update task / assignee / status
-> Hasura update/delete child rows
-> assignee events
-> notification
-> KPI workload
-> salary/customer note/tour fee sync
-> project_task_update_1
-> updateAllCustomerVisits
-> updateEcommerceTaskLog
-> ProjectTaskCustomerVisitInsertUpdate
Daily schedulers
-> reset_task
-> task_expired5. Assignee runtime không phải field phụ
project_task_assignee có quyền insert/update/delete mở cho role user và treo trực tiếp 3 event trigger insert/update/delete (diva-backend/services/controller/metadata/databases/project/tables/public_project_task_assignee.yaml:68). Vì vậy mọi thao tác đổi assignee đều có side effect runtime thực:
- main assignee insert có thể ghi KPI workload và auto-advance parent task (
project_task_assignee_insert.go:87), - main assignee delete ghi KPI workload âm và đụng salary flow (
project_task_assignee_delete.go:62), - update
tour_moneychạmecommerce_task_log, salary và customer note metadata (project_task_assignee_update.go:146).
6. Scheduler boundary
| Scheduler | Lịch | Hành vi |
|---|---|---|
reset_task | 0 18 * * * (cron_triggers.yaml:241) | Lấy automate tasks due hôm qua, reset status_id = new_branch, rồi xóa toàn bộ assignees (reset_task.go:82) |
task_expired | 0 18 * * * (cron_triggers.yaml:253) | Lấy task overdue chưa done, gửi notification và ghi KPI MetricOverdueTask (notification_task_expired.go:21) |
Việc hai cron chạy cùng giờ là một boundary đáng chú ý. Tối thiểu, cần coi chúng là một batch vận hành chứ không phải 2 timer độc lập.
7. Findings nổi bật
| ID | Finding |
|---|---|
| MO-F01 | Route tree dưới ROUTE_PROJECT_TASK_DETAIL đang duplicate cả ROUTE_PROJECT_TASK_DETAIL_QUICK_VIEW và ROUTE_PROJECT_UPDATE_IN_DETAIL, làm route config khó suy luận và dễ drift (module.ts:96). |
| MO-F02 | Navigation của projects ôm cả entry Hoàn Tiền với moduleId = refund_request_management, cho thấy module boundary ở FE đang bẩn (module.ts:223). |
| MO-F03 | filterTaskAssignerIds() đang trả supporter ids thay vì assigner ids, đây là bug logic chứ không chỉ naming issue (useTaskHelper.ts:115). |
| MO-F04 | Doctor commission cancel path có khả năng update sai record vì query tìm request theo reference_id nhưng mutation lại where id = projectTask.ID (project_task_insert.go:124, project_task_insert.go:229). |
| MO-F05 | Khi task chuyển done_branch, nhánh insert all_customer_visits đang dùng time.Now() thay vì taskNew.DoneAt, làm sai ngày visit trong trường hợp backdate hoặc sửa done time (project_task_update_1.go:236). |
| MO-F06 | reset_task không chỉ reset status mà còn delete assignees. Nếu BA/QA hiểu tên cron theo nghĩa hẹp, rất dễ bỏ sót regression ở workload và reassignment (reset_task.go:84). |