Module · WS đào tạo · 07/7/2026

payroll — Lương giáo viên v1.5

Chấm công GV theo giờ dạy thực tế từ dữ liệu DAT / phiên chip — không khai tay; tính lương theo giờ hoặc khoán khóa.

⚠️ Chưa có trong code — scaffold ở v1.5.
ĐÃ THAY THẾ (08/7): không scaffold module này — dùng hrm built-in (feature timesheet-dat + payroll). Trang giữ lại làm spec nghiệp vụ tham chiếu. Xem quan hệ module.
1

Feature / BO / Action

FeatureBO chínhAction
timesheetBảng công từ giờ dạy DAT/chipvieweditgenerate
salaryBảng lương (giờ / khoán)viewexportgenerateapprove
2

Dữ liệu chính

BOTrường chính
Bảng côngKỳ × GV · Σ giờ dạy thực hành (phiên DAT hợp lệ theo ma_gv) · giờ lý thuyết (lms) · điều chỉnh tay (có lý do + người duyệt)
Bảng lươngKỳ × GV · đơn giá giờ / khoán khóa · phụ cấp · khấu trừ · thực lãnh · trạng thái (nháp → duyệt → đã khóa)
3

Quy tắc & liên kết

Quy tắc nghiệp vụ

  • Nguồn giờ duy nhất = phiên DAT hợp lệ + buổi lms — không nhập tay số giờ
  • Điều chỉnh tay phải có lý do + người duyệt (audit)
  • Kỳ lương đã khóa không sửa — sai thì điều chỉnh kỳ sau
  • GV xem được bảng công/lương của chính mình (data scope)

Liên kết chéo

  • dat — phiên hợp lệ theo GV
  • lms — giờ dạy lý thuyết
  • teacher / hr — hồ sơ, hợp đồng, đơn giá
  • finance — chi lương vào sổ

⚠ Câu hỏi mở

  • Công thức lương thực tế của Vĩnh An (giờ/khoán/hỗn hợp)?
  • Kỳ lương theo tháng hay theo khóa?
Quyền

Ma trận phân quyền — ốp vào manifest & seed role

Khối permissions[] dán vào manifest.json; bảng dưới là gán quyền theo vai trò (seed rt_role). Permission key đầy đủ: payroll.main.<feature>.<action>.

▸ permissions[] — manifest.json

[ { "group": "main", "feature": "timesheet", "label": "Bảng công", "actions": [ "view", "edit", "generate" ] }, { "group": "main", "feature": "salary", "label": "Bảng lương", "actions": [ "view", "export", "generate", "approve" ] } ]

⚠️ Action đặc thù (generate) cần bổ sung vào validator manifest — xem plan data-scope P1.

▸ Ma trận vai trò × feature

FeatureQTHTGIAM_DOCKE_TOANNHAN_SUGIAO_VIEN
timesheetRRWRR²
salaryRRAWRR²

R xem · W tạo/sửa · A duyệt · không có quyền · ¹ dữ liệu phân công · ² của chính mình · ³ theo trạng thái hồ sơ. Vai trò không liệt kê = không có quyền.

Đặc thù: +generate bảng công/lương (KE_TOAN)

▸ Quyền mức record (row-level)

(a) Manifest bổ sung fields + scopeVars cho feature bị scope (mở rộng schema — plan data-scope P1; manifest chỉ khai "cái gì scope được", không chứa rule):

[ { "group": "main", "feature": "timesheet", "fields": [ "giao_vien_id" ], "scopeVars": [ "current_giao_vien_id" ] }, { "group": "main", "feature": "salary", "fields": [ "giao_vien_id" ], "scopeVars": [ "current_giao_vien_id" ] } ]

(b) Điều kiện record theo vai trò:

Vai tròFeature (action)Điều kiện record
GIAO_VIENtimesheet, salary (view)giao_vien_id = ctx.current_giao_vien_id (bảng công/lương của mình)

(c) Seed rt_role.grants (kind rule — nhiều rule cùng resource+action = OR):

[ { "kind": "rule", "module": "payroll", "feature": "timesheet", "actions": [ "view" ], "predicate": { "op": "cmp", "field": "giao_vien_id", "cmp": "=", "value": { "ctx": "current_giao_vien_id" } } }, { "kind": "rule", "module": "payroll", "feature": "salary", "actions": [ "view" ], "predicate": { "op": "cmp", "field": "giao_vien_id", "cmp": "=", "value": { "ctx": "current_giao_vien_id" } } } ]

Biến ngữ cảnh: current_user_id — engine có sẵn · current_giao_vien_id/current_ma_gv — module teacher tra từ user đăng nhập (ctxVars, plan P3) · current_nguoi_lxid/current_ma_dk_list — module student tra (1 người nhiều lượt đăng ký) · current_assigned_* — danh sách phụ trách/được phân công.