Staff — Khái niệm & kiến trúc
Domain Staff chủ yếu là frontend hiển thị (Tuke/Topi) trên dữ liệu nhân sự, lịch ca, nghỉ phép. Dưới đây: khái niệm và quy tắc dữ liệu cốt lõi.
Các khái niệm
| Khái niệm | Nghĩa |
|---|---|
| Employee | Bản ghi nhân viên trong một BU. Một người có thể có nhiều Employee (cross-BU). |
| enterpriseUserId | Danh tính người xuyên BU — dùng để gộp (dedupe) các Employee của cùng một người. |
| Roster / Shift | Lịch ca làm; mỗi ca là một Shift có khoảng thời gian. |
| Open Shift | Ca đã publish nhưng chưa gán nhân viên (EmployeeId = null) để staff có thể claim. |
| Leave | Một ngày nghỉ có Date, TimeStart, TimeEnd bắt buộc và vòng trạng thái request→approve. |
| TrackingCode | Mã phân loại; TypeId = Leave hoặc Shift. Form leave chỉ hiện loại Leave. |
| Availability | Khung giờ staff có thể được xếp làm; lặp theo thứ trong một date range. |
| Shifts Leave | Leave gắn một active published shift qua ShiftId. |
| Open Leave | Leave không có ShiftId; không đồng nghĩa với Open Shift. |
| Timetable | Thời khóa biểu hiển thị (Syncfusion ScheduleComponent). |
| Staff Medical | Nhóm trường y tế của hồ sơ nhân viên (Dietary / Neurotypes / Additional Information); hiện/ẩn và bắt buộc do từng BU tùy chỉnh. |
Quy tắc dedupe trong Weekly Planner
Một người chỉ được một dòng trong planner, kể cả khi có nhiều bản ghi:
- Người có cả bản ghi BU-đang-chọn lẫn cross-BU → giữ
employeeIdcủa BU đang chọn làm canonical resource id. - Người không có cả hai identity → vẫn là dòng riêng.
- Sort áp dụng sau role-filter + merge. Không gồm staff archived (đã loại theo employee-link contract).
Invariant:
INV-ROSTER-WP-001 v3.
Staff Roster trên Admin Portal
Weekly Planner thuộc Admin Portal → Staff → Roster → Weekly Planner. Planner chạy bằng Tuke route (độc lập hoặc embed trong admin host app_type=aoadmin).
- Khi embed trong admin host, điều hướng về surface cha dùng kênh
postMessagehiện có. - Migration sang Tuke giữ nguyên ordering, cross-BU dedupe, approved-only absence và
On Leave.
Rule source: Staff Roster – Weekly Planner move to Tuke.
Availability và hai cách tạo Leave
Availability mô tả khi nào staff có thể làm, không phải ca đã xếp hoặc thời gian nghỉ:
- Một range có ngày bắt đầu/kết thúc và các time slot theo thứ.
- Leave policy chỉ đọc active available slot; không sửa hoặc liên kết Leave với Availability.
Shifts: chọn một hoặc nhiều active published shifts của đúng staff, BU và ngày.Open: nhập thời gian không gắn shift; không được giao một published shift cùng ngày.- Hai khoảng chỉ chạm boundary không được tính là giao nhau.
Ví dụ thực tế: Nam có published shift
09:00–17:00, xin nghỉ13:00–15:00. → Leave bám ca đã xếp. → Chọn Shifts; hệ thống lưuShiftId, khoảng nghỉ nằm trong ca.
Ví dụ thực tế: Lan chưa có shift Thứ 4, xin nghỉ
13:00–15:00. → Leave không bám ca. → Chọn Open; hệ thống kiểm tra restriction và Availability trước khi lưu.
Leave Request Restrictions
Mỗi Business Unit chọn một policy trong Timesheet settings:
| Setting | Staff tạo Open | Admin tạo Open |
|---|---|---|
Published Shifts Only | Không được phép | Không được phép |
Shifts & Availability | Phải nằm trọn một active availability slot | Ngoài availability có warning; được confirm |
No Restrictions | Availability không chặn | Ngoài availability có warning; được confirm |
- Setting thiếu hoặc null được đọc thành
No Restrictions. Published Shifts Onlychỉ render nội dung Shifts; API vẫn chặn Open nếu bypass UI.- Staff không thể dùng admin confirmation để vượt policy.
- Create và edit đều chạy lại policy theo actor và BU từ authenticated context.
- Warning chưa được admin confirm thì không có record nào được ghi.
Ví dụ thực tế: An available
09:00–17:00, xin Open Leave16:00–18:00dướiShifts & Availability. → Khoảng nghỉ vượt slot. → Staff bị chặn; admin confirm warning.
Quy tắc tạo và lưu Leave
- Mỗi
EmployeeAbsenceđại diện đúng mộtDate;TimeStart < TimeEndtrong cùng ngày. - Mỗi record mang
BusinessUnitIdriêng, set từ Employee lúc tạo; là căn cứ scope, không đụng leave khác BU. - Form không có
StartDate,EndDatehoặcAll Day. - Shifts Leave phải nằm trọn trong shift; người dùng được rút ngắn Leave Time.
- Shifts filter mặc định từ ngày hiện tại của BU đến Thứ 6 kế tiếp.
- Staff chỉ lọc current/future date; admin được lọc past/current/future date.
- Open Leave không được giao active published shift; nếu giao phải dùng Shifts.
- Preview hiển thị từng record, tổng số record, tổng thời lượng và warning.
- Save gửi một atomic batch; một candidate lỗi thì toàn bộ batch không được ghi.
- Một active leave slot trùng employee, ngày và giờ bị chặn bằng
SLOT_DUPLICATE. - Edit chỉ cập nhật record đã chọn và chạy lại toàn bộ validation.
Ví dụ thực tế: Admin chọn ba published shifts rồi Review & Save. → Shift thứ hai bị unpublish. → Cả ba candidate đều không được ghi.
Invariant:
INV-EMPLOYEE-ABSENCE-001/003/004/006/008/010 v1,INV-LEAVE-RESTRICTION-002..005 v1.
Quy tắc hiển thị Leave trùng ca
Khi xếp/sửa ca, popup hiện trường Leave (read-only) nếu có leave giao với khoảng ca:
- Đánh giá bằng giao khoảng thời gian (date-time interval intersection), không phải so trùng ngày.
- Trường gồm ngày/giờ leave + tracking code; ẩn khi không giao.
Invariant:
INV-ROSTER-LEAVE-DISPLAY-001 v1. Áp dụng cho Weekly Planner shift popup, Timesheet rows, và Timesheet exports.
Quy tắc Open Shift
Open Shift là EmployeeShift đã publish nhưng chưa gán nhân viên:
EmployeeId = nullvàIsPublished = true→ Open Shift.EmployeeId = nullnhưng chưa publish → draft của admin, staff không thấy để claim.- Shift đã có
EmployeeId→ không còn là Open Shift. - Claim thành công chỉ khi shift vẫn chưa gán staff tại thời điểm claim.
Ví dụ thực tế: Linh và Mai cùng claim ca
07:00–09:00. → Tránh một ca hai người nhận. → Một claim thành công; claim còn lại nhận conflict và danh sách refresh.
Invariant:
INV-OPENSHIFT-001 v1,INV-OPENSHIFT-002 v1.
Quy tắc Tracking Code
- Form admin create/edit/approve chỉ hiển thị code có
TrackingCode.TypeId = Leave. - Code loại Shift bị loại khỏi selector của leave.
- Form staff chỉ hiện Reason; không hiện hoặc ghi Tracking Code và Notes.
- Notes chỉ hiển thị cho admin được phép; staff không thấy Notes trong leave detail.
Quy tắc hồ sơ y tế (Staff Medical Customization)
Mỗi Business Unit cấu hình các nhóm trường y tế của hồ sơ nhân viên:
| Nhóm trường | Khóa customization | Ý nghĩa |
|---|---|---|
| Dietary | StaffDietary_Enabled / StaffDietary_Required | Chế độ ăn |
| Neurotypes/Other Conditions | StaffLearningCondition_Enabled / StaffLearningCondition_Required | Đặc điểm thần kinh / tình trạng khác |
| Additional Information | StaffAdditionalInformation_Enabled / StaffAdditionalInformation_Required | Thông tin bổ sung |
- Mỗi nhóm có một toggle
Enabled(On/Off) và mộtRequired(Optional/Mandatory). - Default mọi nhóm là disabled + not required cho mọi provider, trừ khi BU cấu hình khác.
- Thiếu một/nhiều row customization khi resolve → mỗi entry thiếu hành xử như
false. - Form chỉ render nhóm khi
Enabled = true; validation bắt buộc chỉ áp dụng khi nhóm enabled vàRequired = true. - Nhóm disabled nhưng
Required = true→ vẫn ẩn và không chặn submit. - Nhóm disabled có dữ liệu đã lưu → không xóa; khi bật lại dữ liệu khả dụng trở lại.
Ví dụ thực tế: Admin tắt nhóm Additional Information khi staff đã nhập ghi chú. → Không mất dữ liệu khi ẩn. → Bật lại nhóm, ghi chú cũ hiện ra như cũ.
Invariant:
INV-SMC-001,INV-SMC-002,INV-SMC-003 v1.
Archive nhân viên và trạng thái login
Archiving (xóa mềm) một staff sẽ tắt login trong cùng thao tác:
- Cùng lúc đặt
StatusId = ArchivedvàLoginStatusId = Initialised(login disabled). - Dòng archived không hiển thị "Login Enabled"; hiện tag đỏ "Login Disabled".
- Áp dụng cho cả hai surface: Admin Portal
Employee(POST /api/employee/{id}/Archive) và Enterprise PortalEnterpriseUser(POST /api/enterprisestaff/{id}/Archive). - Archive staff đã ở
LoginStatusId = Initialised→ giữ nguyên. - Restore không tự bật lại login:
LoginStatusIdgiữ nguyên giá trị lúc archived; bật login là hành động tường minh riêng.
Ví dụ thực tế: Admin restore staff đã archive. → Không tự cấp lại quyền login. →
Employee.StatusId = ApprovednhưngLoginStatusIdvẫnInitialised; muốn đăng nhập phải bật lại thủ công.
Invariant:
INV-EMP-006,INV-EMP-007 v1.
Quy tắc sort & UI thuần hiển thị
Nhiều spec Staff là display-only (không đổi persistence/API):
| Nơi | Quy tắc |
|---|---|
| Availability time slots | Sort theo start time tăng dần, theo từng thứ. |
| Edit Time Slot popup templates | Sort theo start time tăng dần (trong tập đã load). |
| Timetable controls | Một bộ điều khiển duy nhất; header ScheduleComponent là source of truth cho range/view. |
| Staff Home header | Title trái; action area phải theo thứ tự cố định. |
| Leave drawer | Layout gọn, paired date/time; thu gọn khi viewport hẹp. |
Kiến trúc (mức cao)
Frontend lo composer, preview và hiển thị. Tux luôn tính lại shift, Availability, restriction, actor và BU trước atomic mutation; không tin preview từ client.
Tiếp theo: Case thường gặp.