Skip to content

Shared Rules — KPI Lifecycle And Notification

1. Thuật ngữ chuẩn

Thuật ngữNghĩa trong code hiện tạiGhi chú
KPI corekpiHeader KPI definition
Participantkpi_participantĐối tượng KPI: user hoặc branch
Metric relationkpi_metric_relationTarget threshold gắn participant
KPI logkpi_metric_relation_logLog runtime cho metric relation
KPI statskpi_stats, kpi_metric_statsRead models tổng hợp
Branch KPIkpi_branchTarget doanh thu theo branch
Staff KPIkpi_staffTarget doanh thu theo staff
KPI permissionkpi_permissionMapping role cho audience/scope notification
Manual metricmetric thuộc group kpi_metric_group_manualFE nhập tay
Auto metriccác metric còn lạiRuntime backend tự ghi log

2. Status Matrix

StatusNguồn suy raÝ nghĩa
newfrom > nowKPI chưa bắt đầu
inprogressfrom <= now <= to và chưa cancelKPI đang hiệu lực
closedto < now và chưa cancelKPI hết hạn thời gian
canceledcanceled_at IS NOT NULLKPI bị hủy thủ công
doneprogress >= 100% ở một số componentDisplay state phụ, không phải canonical DB state

3. Result Matrix cho participant

Result bucketCách suy ra
not_achievedđiểm tích lũy < ngưỡng need_to_improve
need_to_improveđiểm tích lũy >= need_to_improve và < qualified
qualifiedđiểm tích lũy >= qualified và < exceed_requirements
exceed_requirementsđiểm tích lũy >= exceed_requirements

Kết quả participant vì vậy là computed result từ stats/threshold, không phải cột status vật lý.

4. Actor Matrix

ActorVai trò
Creator KPITạo và chỉnh sửa KPI core
Manager rolesThấy tab metrictarget ở detail
Assignee / participantThấy my-kpi hoặc participant detail theo permission
Branch managerThấy branch-kpi cho branch họ quản lý
Full-view rolesBOD, ITStaff, ITLeader xem participant detail rộng hơn
Scheduler/systemGhi KPI logs và gửi notification định kỳ

5. Invariants quan trọng

SR-001: KPI core không có status engine riêng

  • Create/update/cancel/delete đều đi qua Hasura mutations trực tiếp.
  • status không phải single-source DB field.
  • Mọi bề mặt status hiện dựa vào from, to, canceled_at.

SR-002: Progress runtime không đồng nhất với lifecycle header

  • KPI có thể đang inprogress nhưng progress vẫn là 0.
  • KPI có thể closed nhưng display component vẫn map sang done nếu đạt 100%.
  • QA phải test riêng lifecycle date logic và progress/result logic.

SR-003: Manual metric và auto metric cùng đổ vào kpi_metric_relation_log

  • FE nhập tay qua upsertManualMetrics.
  • Backend events/schedulers ghi qua AddKpiLog.
  • Cùng một read model nhưng hai đường ghi dữ liệu khác nhau.

SR-004: disabledcanceled_at là hai semantics khác nhau

  • disabled = true gần với soft delete/hide khỏi list.
  • canceled_at là hủy KPI đang chạy.
  • Hai field này không nên bị trộn khi đọc yêu cầu nghiệp vụ.

SR-005: kpi_permission chỉ chi phối một phần KPI runtime

  • Route access còn dùng KPI_PERMISSIONSPERMISSIONS_KPI.
  • Participant detail còn dùng checkPermissionParticipant.
  • Scheduler notifications mới dùng kpi_permission để chọn audience nhóm rộng.

6. Boundary Checklist

Khi phân tích bug hoặc change request trong vùng KPI, luôn hỏi:

  1. Đây là KPI core, KPI revenue, hay KPI log runtime?
  2. Vấn đề là lifecycle date/status, hay progress/result computation?
  3. Dữ liệu đang được ghi từ FE manual input hay từ AddKpiLog backend?
  4. Đây là quyền vào route, quyền xem participant, hay quyền nhận notification?
  5. Bug nằm ở event trigger tức thời hay ở scheduler chạy theo giờ/ngày?

7. Rủi ro / Findings

IDFinding
SR-F01KPI_STATUS_DONE là pseudo-state, không nằm trong bộ filter chuẩn KPI_STATUSES.
SR-F02useKPIBuilder.setStartEndDate() dùng from cho cả nhánh to, có dấu hiệu bug filter ngày cuối.
SR-F03Module có nhiều lớp permission song song: route config, runtime dashboard gating, participant permission và kpi_permission.
SR-F04KPI logs phụ thuộc nặng vào upstream domain events; nếu event không bắn, progress sẽ sai dù KPI header vẫn hợp lệ.