PRD: Quản lý nhân viên
| Module | Quản lý User | PRD ID | PRD-EMP-001 |
| Trạng thái | Sẵn sàng dev | FEAT | EMP |
| Epic | — | Plane | BANA-1567 |
| Ngày | 2026-05-25 | Phiên bản | v1.0 |
| Gói | @nx/identity | URD | EMP |
| Surface | Client · Chủ/QL | ||
| Phụ trách | Phát Nguyễn | ||
Quản lý nhân viên là gì
Chủ sở hữu đưa merchant lên hệ thống rồi cần nhân sự để vận hành nó. Mục Đội ngũ tại trang Client là nơi chủ sở hữu tạo tài khoản nhân viên, gắn từng người với một hay nhiều merchant cụ thể trong organizer, và off-board khi cần - không còn phải dùng chung một đăng nhập hay cấp quyền tràn lan cho tất cả mọi người.
Bảng nhân viên và form phân quyền tái dùng cơ chế vai trò - merchant sẵn có (xem Roles & Scoping): mỗi nhân viên được gán một hoặc nhiều cặp vai trò - merchant, vai trò nằm trong dải cho phép giữa Customer và mức trần cao nhất của hệ thống.
Công tắc Cấp quyền đăng nhập
Công tắc Cấp quyền đăng nhập tách rõ hai loại nhân viên - người có tài khoản đăng nhập riêng để tự vào app, và người chỉ được theo dõi trong hệ thống mà chưa cần đăng nhập - và quyết định luôn cách off-board: nhân viên đang có đăng nhập thì vô hiệu hóa được, nhân viên chưa có đăng nhập thì chỉ gỡ được.
Một nhân viên, từ tạo tới off-board
| Bước | Việc xảy ra |
|---|---|
| 1. Tạo | Chủ sở hữu điền thẻ Thông tin cá nhân, thêm cặp vai trò-merchant ở thẻ Phân quyền |
| 2. Cấp đăng nhập (tùy chọn) | Bật công tắc Cấp quyền đăng nhập kèm username → nhân viên đăng nhập được ngay |
| 3. Cấp đăng nhập về sau | Với nhân viên chưa có đăng nhập, bật công tắc ở màn Sửa → hệ thống tự gửi tin đặt mật khẩu |
| 4. Vận hành | Cập nhật phân quyền, đặt lại mật khẩu tại thẻ Bảo mật khi nhân viên quên |
| 5. Off-board | Nhân viên có đăng nhập → vô hiệu hóa; nhân viên chưa có đăng nhập → gỡ ở bảng nhân viên |
Chỗ dễ sai nhất
Hai guard chặn off-board nhầm người
Chủ sở hữu không tự gỡ được chính mình, và không gỡ được nhân viên đang giữ vai trò Owner ở bất kỳ merchant nào - kể cả khi thao tác đúng quyền sở hữu organizer và merchant.
1. Mục tiêu & Loại trừ
Mục tiêu
- Chủ sở hữu tạo nhân viên tại mục Đội ngũ qua một form hai thẻ: Thông tin cá nhân và Phân quyền.
- Gán một hoặc nhiều cặp vai trò - merchant cho mỗi nhân viên; vai trò chọn theo từng merchant và giới hạn trong dải Customer - trần hệ thống.
- Công tắc Cấp quyền đăng nhập điều khiển việc nhân viên có tài khoản đăng nhập (username) hay không, cả lúc tạo lẫn lúc sửa sau này.
- Cập nhật phân quyền thay toàn bộ danh sách cặp vai trò - merchant cũ bằng danh sách mới nhập.
- Vô hiệu hóa nhân viên đang có đăng nhập, hoặc gỡ bất kỳ nhân viên nào - trừ chính mình và trừ người đang giữ vai trò Owner.
- Đặt lại mật khẩu cho nhân viên ngay từ màn Sửa, không cần nhân viên tự yêu cầu.
- Xác thực người thao tác thực sự sở hữu organizer và mọi merchant liên quan trước khi ghi bất kỳ thay đổi nào.
Loại trừ
- Tạo vai trò tùy biến / quản lý permission động → Permissions.
- Hệ thống mời người dùng qua email hoặc điện thoại.
- Audit / lịch sử đăng nhập cho các thao tác của nhân viên.
2. Thước đo thành công
| Thước đo | Mục tiêu / tín hiệu |
|---|---|
| Đúng phạm vi | Nhân viên chỉ thao tác được trên các merchant có trong thẻ Phân quyền của mình, không rò rỉ chéo merchant |
| An toàn quyền sở hữu | 100% yêu cầu tạo/sửa/gỡ bị từ chối khi người thao tác không sở hữu organizer hoặc một merchant có tên trong yêu cầu |
| Tự kích hoạt | Tỷ lệ nhân viên được cấp quyền đăng nhập tự đặt mật khẩu qua tin gửi tới, không cần đội vận hành can thiệp, tăng dần |
| Off-boarding sạch | Nhân viên đã vô hiệu hóa hoặc gỡ bỏ không đăng nhập lại được; không ca nào lọt qua guard tự-gỡ hoặc gỡ-Owner |
3. Persona & Tình huống
| Persona | Mục tiêu trong tính năng này |
|---|---|
| Owner | Tạo, phân quyền, cập nhật, vô hiệu hóa hoặc gỡ nhân viên tại mục Đội ngũ |
| Employee | Đăng nhập bằng username riêng (khi được cấp) và chỉ thao tác trên merchant có trong thẻ Phân quyền của mình |
Kịch bản chính: Owner tạo một nhân viên với thông tin cá nhân, một hoặc nhiều cặp vai trò-merchant, và bật công tắc Cấp quyền đăng nhập kèm username → nhân viên đăng nhập được ngay → về sau Owner cập nhật phân quyền, cấp/thu hồi đăng nhập, đặt lại mật khẩu, hoặc vô hiệu hóa/gỡ khi cần off-board.
4. User Stories
| # | Là một | Tôi muốn | Để |
|---|---|---|---|
| 01 | owner | tạo nhân viên với thông tin cá nhân và một hoặc nhiều cặp vai trò-merchant | nhân sự chỉ thao tác đúng merchant tôi gán |
| 02 | owner | bật công tắc Cấp quyền đăng nhập ngay lúc tạo | nhân viên vào được app luôn mà không phải chờ tôi cấp thêm |
| 03 | owner | tạo nhân viên mà chưa cấp quyền đăng nhập | theo dõi nhân sự chưa cần vào hệ thống |
| 04 | owner | bật công tắc này sau ở màn Sửa | cấp đăng nhập cho một nhân viên đã tạo trước đó mà không phải tạo lại từ đầu |
| 05 | owner | tắt công tắc này | thu hồi toàn bộ quyền đăng nhập của một nhân viên ngay lập tức |
| 06 | owner | cập nhật phân quyền của một nhân viên | chuyển nhân sự giữa các merchant trong một lần lưu |
| 07 | owner | đặt lại mật khẩu cho nhân viên ngay từ màn Sửa | hỗ trợ khi họ quên mật khẩu mà không cần họ tự yêu cầu |
| 08 | owner | hệ thống chặn tôi tự gỡ chính mình hoặc gỡ người đang giữ vai trò Owner | tránh off-board nhầm và mất quyền quản trị organizer |
| 09 | employee | đăng nhập bằng username riêng và chỉ thấy merchant của mình | góc nhìn khớp với trách nhiệm của tôi |
5. Yêu cầu chức năng
| # | Yêu cầu | Trạng thái | URD ref |
|---|---|---|---|
FR-001 | Bảng nhân viên hiển thị bảy cột: username, email, số điện thoại, họ, tên, vai trò (badge chỉ hiển thị tên vai trò), và trạng thái. • Trạng thái nhận một trong năm giá trị: Hoạt động / Vô hiệu hóa / Bị chặn / Lưu trữ / Không rõ. • Mỗi dòng có hai hành động: Sửa và Gỡ. | ✅ | URD-EMP-001 |
FR-002 | Form Tạo nhân viên có thẻ Thông tin cá nhân: họ (bắt buộc), tên (bắt buộc), email (bắt buộc), danh sách số điện thoại (tùy chọn, thêm được nhiều số), và ngày vào làm (bắt buộc). | ✅ | URD-EMP-001 |
FR-003 | Form có thẻ Phân quyền để gán cặp vai trò - merchant cho nhân viên. • Thao tác từ merchant trụ sở chính: có ô chọn merchant và thêm được nhiều dòng cặp vai trò - merchant. • Thao tác từ một merchant thường: form khóa đúng một cặp vào merchant hiện tại, không có ô chọn merchant và không thêm được dòng. • Danh sách vai trò để chọn vẫn hiển thị cả vai trò đã ngừng hoạt động, nhưng không chọn được các vai trò đó. • Vai trò gán cho một cặp phải nằm giữa mức Customer và mức trần cao nhất của hệ thống; chọn một vai trò ngoài dải này rồi bấm Lưu sẽ bị từ chối. | ✅ | URD-EMP-002 |
FR-004 | Form có công tắc Cấp quyền đăng nhập. • Ở màn Tạo, bật công tắc mở thêm thẻ Xác thực để nhập username (bắt buộc) và ô Trạng thái (mặc định Hoạt động); nhân viên tạo xong đăng nhập được ngay bằng username đó. • Tắt công tắc thì nhân viên được tạo bình thường nhưng chưa có đăng nhập. | ✅ | URD-EMP-004 |
FR-005 | Ở màn Sửa, với nhân viên chưa có đăng nhập, chủ sở hữu bật công tắc Cấp quyền đăng nhập và nhập username. Hệ thống tự gửi tin đặt mật khẩu để nhân viên tự đặt mật khẩu lần đầu. | ✅ | URD-EMP-004 |
FR-006 | Ở màn Sửa, với nhân viên đang có đăng nhập, chủ sở hữu tắt công tắc Cấp quyền đăng nhập. Username và mật khẩu của nhân viên bị gỡ, nhân viên mất quyền đăng nhập ngay lập tức. | ✅ | URD-EMP-004 |
FR-007 | Màn Sửa có thẻ Bảo mật với nút Đặt lại mật khẩu, gửi một yêu cầu đặt lại mật khẩu tới nhân viên đang có đăng nhập. Luồng nhận và đặt mật khẩu mới đặc tả tại PRD-AUTH-001. | ✅ | URD-EMP-004 |
FR-008 | Cập nhật phân quyền ở thẻ Phân quyền thay toàn bộ danh sách cặp vai trò - merchant cũ bằng danh sách mới nhập. Sau cập nhật, nhân viên chỉ còn thấy đúng các merchant có trong danh sách mới. | ✅ | URD-EMP-006 |
FR-009 | Vô hiệu hóa một nhân viên chỉ thực hiện được khi nhân viên đó đang có quyền đăng nhập. • Thao tác bằng cách đổi ô trạng thái nằm trong thẻ Xác thực của màn Sửa. • Nhân viên bị vô hiệu hóa không đăng nhập được nhưng dữ liệu vẫn giữ nguyên. | ✅ | URD-EMP-007 |
FR-010 | Nhân viên chưa có quyền đăng nhập không có ô trạng thái để vô hiệu hóa. Với nhóm này, hành động Gỡ ở bảng nhân viên là cách duy nhất để off-board. | ✅ | URD-EMP-007 |
FR-011 | Gỡ nhân viên bị chặn ở hai trường hợp. • Chủ sở hữu không tự gỡ được chính mình. • Không gỡ được nhân viên đang giữ vai trò Owner ở bất kỳ merchant nào. | ✅ | URD-EMP-007 |
FR-012 | Mọi thao tác tạo, sửa, hoặc gỡ nhân viên đều kiểm tra người thao tác thực sự sở hữu organizer và mọi merchant có tên trong yêu cầu, trước khi ghi bất kỳ thay đổi nào. | ✅ | URD-EMP-008 |
FR-013 | Sau khi được cấp quyền đăng nhập, nhân viên chỉ đăng nhập và thao tác được trên đúng các merchant có tên trong thẻ Phân quyền của mình. | ✅ | URD-EMP-003 · URD-EMP-005 |
FR-014 | Thêm một người đã có tài khoản vào organizer ngay tại màn Nhân viên. • Nhập định danh (username, email hoặc số điện thoại) để tìm đúng người, rồi gán cặp vai trò - merchant như một nhân viên bình thường. • Không tạo tài khoản mới, không đụng tới mật khẩu hay hồ sơ của người đó. | 🚧 | URD-MORG-002 |
5.1 Tiêu chí nghiệm thu
- Mở mục Đội ngũ tại trang Client → bảng nhân viên hiện bảy cột (username, email, số điện thoại, họ, tên, vai trò, trạng thái) và hai nút Sửa/Gỡ trên mỗi dòng.
- Bấm Tạo nhân viên, điền họ, tên, email, ngày vào làm ở thẻ Thông tin cá nhân, thêm một cặp vai trò-merchant ở thẻ Phân quyền, không bật công tắc Cấp quyền đăng nhập, rồi bấm Lưu → nhân viên được tạo, chưa có đăng nhập.
- Lặp lại luồng trên nhưng bật công tắc Cấp quyền đăng nhập và nhập username → nhân viên được tạo và đăng nhập được ngay bằng username đó.
- Ở thẻ Phân quyền thao tác từ merchant trụ sở chính, chọn một merchant rồi mở danh sách vai trò → thấy cả vai trò đang hoạt động và vai trò đã ngừng hoạt động, nhưng chỉ chọn được vai trò đang hoạt động; chọn vai trò ngoài phạm vi Customer - mức trần hệ thống rồi bấm Lưu → bị từ chối. Ở một merchant thường, thẻ Phân quyền khóa sẵn đúng một cặp vào merchant hiện tại và không có ô chọn merchant.
- Mở màn Sửa một nhân viên chưa có đăng nhập, bật công tắc Cấp quyền đăng nhập, nhập username, bấm Lưu → username được thêm, hệ thống tự gửi tin đặt mật khẩu cho nhân viên.
- Mở màn Sửa một nhân viên đang có đăng nhập, tắt công tắc Cấp quyền đăng nhập, bấm Lưu → username và mật khẩu của nhân viên bị gỡ, nhân viên không đăng nhập được nữa.
- Ở màn Sửa một nhân viên đang có đăng nhập, bấm nút Đặt lại mật khẩu ở thẻ Bảo mật → một yêu cầu đặt lại mật khẩu được gửi tới nhân viên đó.
- Ở thẻ Phân quyền của màn Sửa, xóa hết cặp vai trò-merchant cũ, thêm cặp mới rồi bấm Lưu → nhân viên chỉ còn thấy đúng merchant trong danh sách mới.
- Ở thẻ Xác thực của một nhân viên đang có đăng nhập, đổi ô trạng thái sang Vô hiệu hóa → nhân viên không đăng nhập được nữa nhưng dòng của họ vẫn còn nguyên trên bảng.
- Mở một nhân viên chưa có đăng nhập → không thấy ô trạng thái để vô hiệu hóa; muốn off-board thì bấm Gỡ ở bảng nhân viên.
- Bấm Gỡ trên chính dòng của bản thân mình → bị từ chối.
- Bấm Gỡ trên một nhân viên đang giữ vai trò Owner ở bất kỳ merchant nào → bị từ chối.
- Tạo hoặc sửa nhân viên với một merchant không thuộc quyền sở hữu của mình → bị từ chối, không có gì được ghi.
- Một nhân viên đã được cấp quyền đăng nhập, đăng nhập rồi thử thao tác trên một merchant ngoài thẻ Phân quyền của mình → không truy cập được.
- Ở màn Nhân viên, thêm một người đã có tài khoản bằng username của họ, gán một cặp vai trò - merchant rồi bấm Lưu → người đó thấy organizer này ở launchpad trong lần đăng nhập kế tiếp; tài khoản, mật khẩu và hồ sơ hiện có giữ nguyên.
6. Yêu cầu phi chức năng
| Khía cạnh | Yêu cầu |
|---|---|
| Toàn vẹn dữ liệu | Tài khoản, các cặp vai trò-merchant, và username (nếu công tắc Cấp quyền đăng nhập đang bật) được tạo/cập nhật cùng nhau - lỗi giữa chừng thì không có gì được ghi |
| Tenancy & authz | Mọi thao tác tạo/sửa/gỡ được xác thực theo quyền sở hữu organizer và merchant của người thao tác; không gán được vai trò ngoài dải Customer - trần cao nhất của hệ thống |
| Bảo mật | Mật khẩu chỉ lưu dạng băm, không bao giờ hiển thị hay trả về dạng bản rõ |
| Soft-delete | Gỡ nhân viên là một soft-delete - dữ liệu được giữ lại, không xóa vật lý |
| Phạm vi (scoping) | Nhân viên chỉ thao tác được trên merchant có trong thẻ Phân quyền của mình |
| i18n | Nhãn cột bảng, tên trường form và nhãn trạng thái là song ngữ (Anh / Việt) |
7. UX & Luồng
Bảng nhân viên, form Tạo/Sửa, và các guard gỡ nằm trong mục Đội ngũ tại trang Client. Luồng nhận và đặt mật khẩu sau khi được cấp quyền đăng nhập hoặc sau khi bấm Đặt lại mật khẩu được đặc tả tại PRD-AUTH-001, không lặp lại ở đây.
8. Dữ liệu & Miền nghiệp vụ
| Entity | Vai trò |
|---|---|
| Tài khoản nhân viên | Danh tính nhân viên - hồ sơ, trạng thái, và soft-delete |
| Thông tin cá nhân | Họ, tên, email, danh sách số điện thoại, ngày vào làm |
| Cặp vai trò - merchant | Từng dòng phân quyền gắn một vai trò với một merchant cụ thể; toàn bộ danh sách bị thay khi cập nhật |
| Định danh đăng nhập (username) và mật khẩu | Chỉ tồn tại khi công tắc Cấp quyền đăng nhập đang bật; mật khẩu lưu dạng băm |
| Trạng thái | Hoạt động / Vô hiệu hóa / Bị chặn / Lưu trữ / Không rõ - chỉ áp dụng cho nhân viên đang có đăng nhập |
| Organizer / Merchant | Nguồn quyền sở hữu - dùng để xác thực chủ sở hữu sở hữu organizer và mọi merchant liên quan |
Chỉ mang tính khái niệm - mô hình dữ liệu đầy đủ trong developer domain model.
9. Phụ thuộc & Giả định
Phụ thuộc vào
| # | Feature | Phụ thuộc điều gì |
|---|---|---|
| 01 | Vai trò & phạm vi (URD-ROLE - Phân quyền) | dải vai trò hợp lệ (Customer - trần cao nhất của hệ thống) và cơ chế lọc phạm vi mà mục Đội ngũ tái dùng; việc thêm người đã có tài khoản vào organizer thuộc MORG. |
| 02 | Authentication (PRD-AUTH-001) | luồng nhận và đặt mật khẩu khi bật công tắc Cấp quyền đăng nhập hoặc khi bấm Đặt lại mật khẩu. |
| 03 | Commerce | organizer và merchant là nguồn quyền sở hữu dùng để xác thực mọi thao tác. |
Giả định
| # | Giả định | Sai thì sao |
|---|---|---|
| 01 | Chủ sở hữu thao tác đã sở hữu một organizer với ít nhất một merchant. | Không có gì để gán cặp vai trò-merchant vào; form Phân quyền không có merchant nào hợp lệ để chọn. |
| 02 | Cấu hình gửi tin đặt mật khẩu đã sẵn sàng trước khi công tắc Cấp quyền đăng nhập được bật. | Nhân viên được cấp username nhưng không nhận được tin đặt mật khẩu, bị kẹt ngoài không vào được app. |
10. Kế hoạch phát hành & Tiêu chí
| Khía cạnh | Kế hoạch |
|---|---|
| Phase | P2 của tính năng EMP - xem danh mục tính năng URD |
| Rollout | Mọi merchant; không feature flag |
| Migration | Không có migration dữ liệu phá hủy |
| Tiêu chí phát hành | Tạo → phân quyền → đăng nhập kiểm chứng đầu-cuối cho cả hai nhánh bật/tắt công tắc Cấp quyền đăng nhập; guard tự-gỡ và gỡ-Owner hoạt động đúng; xác thực quyền sở hữu từ chối đúng mọi trường hợp không sở hữu |
| Theo dõi | Tỷ lệ tạo/sửa nhân viên lỗi, tỷ lệ từ chối do quyền sở hữu, tỷ lệ gửi tin đặt mật khẩu thành công |
Tham chiếu
- URD: Quản lý Người dùng - EMP
- Liên quan: Thành viên đa organizer · Vai trò & phạm vi - URD Phân quyền · Xác thực & xác minh tài khoản
- Module: Quản lý Người dùng - URD
- Developer: @nx/identity · domain model
Rủi ro & Câu hỏi mở
| # | Rủi ro / câu hỏi | Giảm thiểu / trạng thái |
|---|---|---|
| 01 | Cấp quyền truy cập một merchant mà chủ sở hữu không sở hữu | Quyền sở hữu được xác thực trước khi ghi bất kỳ cặp vai trò-merchant nào |
| 02 | Off-board nhầm người đang giữ vai trò Owner | Guard chặn gỡ nhân viên đang giữ vai trò Owner ở bất kỳ merchant nào |
| 03 | Chủ sở hữu tự gỡ chính mình, mất quyền quản trị organizer | Guard chặn tự-gỡ |
| 04 | Nhân viên chưa có đăng nhập không vô hiệu hóa được | Off-board nhóm này bằng hành động Gỡ thay vì Vô hiệu hóa |
Câu hỏi thường gặp
| # | Câu hỏi | Trả lời |
|---|---|---|
| 01 | Bật công tắc Cấp quyền đăng nhập lúc tạo khác gì lúc sửa? | Lúc tạo, bật kèm nhập username thì nhân viên vào app được ngay. Lúc sửa, bật cho một nhân viên chưa có đăng nhập thì hệ thống tự gửi tin đặt mật khẩu để họ tự đặt lần đầu. |
| 02 | Tắt công tắc ở màn Sửa thì chuyện gì xảy ra? | Username và mật khẩu của nhân viên bị gỡ, nhân viên mất quyền đăng nhập ngay lập tức. |
| 03 | Vì sao có nhân viên không vô hiệu hóa được? | Vô hiệu hóa chỉ áp dụng cho nhân viên đang có đăng nhập. Nhân viên chưa có đăng nhập chỉ gỡ được ở bảng nhân viên. |
| 04 | Đặt lại mật khẩu ở màn Sửa khác gì bật/tắt công tắc? | Đặt lại mật khẩu chỉ gửi yêu cầu đặt mật khẩu mới cho một nhân viên đang có đăng nhập sẵn (xem PRD-AUTH-001). Công tắc quyết định nhân viên có đăng nhập hay không. |
| 05 | Tôi gỡ được ai? | Gỡ được mọi nhân viên, trừ chính mình và trừ người đang giữ vai trò Owner ở bất kỳ merchant nào. |
| 06 | Cập nhật phân quyền có cộng dồn với danh sách cũ không? | Không - danh sách cặp vai trò-merchant mới thay thế toàn bộ danh sách cũ. |