2
Manifest — khai báo permissions
Permission key theo convention hrm.<group>.<feature>.<action>. fields/scopeVars theo plan data-scope (manifest v1.1). Action ngoài core-12 (checkin, generate, lock) bắt buộc khai customActions.
▸ 2.1 Quy ước đặt key (chuẩn hóa — áp toàn nền tảng)
Key là định danh máy (như AWS service:Action, K8s verb×resource); label là tên hiển thị.
| # | Quy tắc | Ví dụ vi phạm → sửa |
| K1 | Key bất biến sau phát hành; label đổi tự do. Muốn đổi key → qua cơ chế rename có khai báo (manifest renames + grant-rewrite + bump epoch khi upgrade), không sửa tay rời rạc | — |
| K2 | Không lặp ngữ cảnh cha: feature không chứa lại tên module/group | employment-contract → contract · training-program → program |
| K3 | Không để group.feature trùng tên — dấu hiệu nhóm sai hoặc tên quá chung | attendance.attendance, leave.leave → group time · payroll.payroll → payroll.salary |
| K4 | Key không mã hóa nguồn dữ liệu/công nghệ — nguồn là chi tiết của action generate | timesheet-dat → timesheet (nguồn DAT và LMS ngay trong thiết kế) |
| K5 | Danh từ số ít, kebab-case chỉ khi cần phân biệt/ghép nghĩa | job-position giữ (tránh nhầm org.position — chức danh) |
| K6 | Group = section nghiệp vụ ổn định chuẩn HRIS: personnel · time · payroll · recruitment · training · performance · analytics | gộp group attendance + leave → time (Time & Attendance) |
▸ 2.2 Bảng rename — key hiện có (code hrm v1.0.0) → key đích (v2.0.0)
Tham chiếu khi rename code. Grant kind:'module' (owner) không bị ảnh hưởng; grant theo feature/action phải rewrite.
| Key hiện tại | Key đích | Quy tắc | Action thay đổi kèm theo |
| personnel.employee | (giữ) | — | bỏ delete (nghỉ việc = đổi status — giữ audit); giữ import (kit migrate WS3) |
| personnel.employment-contract | personnel.contract | K2 | bỏ delete; approve → bỏ (trạng thái đủ); thêm configure (nhắc hạn) |
| attendance.attendance | time.attendance | K3·K6 | create → checkin/import; bỏ delete (sửa bằng edit có audit); bỏ report/approve |
| leave.leave | time.leave | K3·K6 | bỏ delete (hủy đơn = trạng thái); giữ edit |
| payroll.payroll | payroll.salary | K3 | bỏ create/edit/delete tay → generate từ công thức; thêm lock |
| — (mới) | payroll.timesheet | K4 | view·generate·export |
| recruitment.job-position · recruitment.candidate | (giữ) | K5 | — |
| training.training-program / training-session | training.program / training.session | K2 | — (training.enrollment giữ) |
| performance.kpi-okr · performance.appraisal · analytics.dashboard | (giữ) | — | — |
🔎 Full code cũ → mới (chuỗi đang hardcode ở FE portal/AppGrid):
hrm.personnel.employment-contract.view → hrm.personnel.contract.view
hrm.attendance.attendance.view → hrm.time.attendance.view ·
hrm.leave.leave.view → hrm.time.leave.view
hrm.payroll.payroll.view → hrm.payroll.salary.view ·
hrm.training.training-program.view → hrm.training.program.view
🛠 Checklist rename code (thứ tự): ① manifest hrm (key mới + customActions + version 2.0.0) → ② BE enforce: grep code cũ trong routes/controllers → ③ grant-rewrite rt_role (JSONB) từng DB ws + bump epoch (làm thành cơ chế renames chạy lúc upgrade, không SQL tay) → ④ CP catalog + rbacExportService rà lại → ⑤ FE AppGrid/permPrefix (dài hạn: constants sinh từ manifest — rename vỡ lúc compile, không vỡ âm thầm) → ⑥ docs khác có ghi code cũ (plan data-scope, WS0).
▸ 2.3 Manifest đích (v2.0.0 — JSON hợp lệ)
⚠️ Điều kiện schema: manifest-schema hiện tại đã có customActions nhưng chưa có fields/scopeVars (chờ manifest v1.1 — plan data-scope) và renames (cơ chế K1). Thứ tự: nâng schema trước → npm run catalog:validate pass rồi mới code.
{
"key": "hrm",
"name": "Nhân sự & Lương",
"version": "2.0.0",
"customActions": [
{ "key": "generate", "label": "Sinh bảng", "desc": "Sinh bảng công/bảng lương từ dữ liệu nguồn (DAT/LMS) — không nhập tay." },
{ "key": "checkin", "label": "Điểm danh", "desc": "Ghi nhận chấm công tại chỗ — sinh bản ghi từ sự kiện thiết bị/thao tác nhanh, khác create." },
{ "key": "lock", "label": "Khóa sổ", "desc": "Khóa kỳ lương đã duyệt — bất biến; sai thì điều chỉnh kỳ sau." }
],
"permissions": [
{ "group": "personnel", "feature": "employee", "label": "Nhân viên",
"actions": ["view", "create", "edit", "import", "export"],
"fields": ["phong_ban_id", "chuc_danh_id", "user_id"],
"scopeVars": ["current_employee_id", "current_dept_id"] },
{ "group": "personnel", "feature": "contract", "label": "Hợp đồng lao động",
"actions": ["view", "create", "edit", "configure"] },
{ "group": "time", "feature": "attendance", "label": "Chấm công",
"actions": ["view", "import", "edit", "export", "checkin"] },
{ "group": "time", "feature": "leave", "label": "Nghỉ phép",
"actions": ["view", "create", "edit", "approve"] },
{ "group": "payroll", "feature": "timesheet", "label": "Bảng công GV (giờ DAT/LMS)",
"actions": ["view", "generate", "export"],
"fields": ["ma_gv", "ky"], "scopeVars": ["current_giao_vien_id"] },
{ "group": "payroll", "feature": "salary", "label": "Bảng lương",
"actions": ["view", "generate", "approve", "lock", "export"],
"fields": ["ma_nv", "ky"], "scopeVars": ["current_employee_id"] },
{ "group": "recruitment", "feature": "job-position", "label": "Vị trí tuyển dụng",
"actions": ["view", "create", "edit", "delete"] },
{ "group": "recruitment", "feature": "candidate", "label": "Ứng viên",
"actions": ["view", "create", "edit", "delete"] },
{ "group": "training", "feature": "program", "label": "Chương trình đào tạo",
"actions": ["view", "create", "edit", "delete"] },
{ "group": "training", "feature": "session", "label": "Lớp/buổi đào tạo",
"actions": ["view", "create", "edit", "delete"] },
{ "group": "training", "feature": "enrollment", "label": "Ghi danh đào tạo",
"actions": ["view", "create", "edit", "delete"] },
{ "group": "performance", "feature": "kpi-okr", "label": "KPI / OKR",
"actions": ["view", "create", "edit", "delete", "report"] },
{ "group": "performance", "feature": "appraisal", "label": "Đánh giá",
"actions": ["view", "create", "edit", "delete", "approve", "report"] },
{ "group": "analytics", "feature": "dashboard", "label": "Dashboard nhân sự",
"actions": ["view", "export"] }
]
}
recruitment.* / training.* / performance.* / analytics.* = tùy chọn: ẩn/hiện qua config per-WS, không xoá key khỏi manifest — training tái dùng cho tập huấn định kỳ GV.