Quy Tắc Nghiệp Vụ Chung
Các quy tắc nghiệp vụ chung áp dụng xuyên suốt toàn bộ hệ thống
Tên dự án: [Tên dự án]
Ngày tạo: 2026-06-12
Phiên bản: v1.0
BA phụ trách: [Tên BA]
Ngôn ngữ tài liệu: Tiếng Việt
Tài liệu này định nghĩa các quy tắc nghiệp vụ chung áp dụng xuyên suốt toàn bộ hệ thống.
| Nhóm quy tắc | CR | Số lượng |
|---|
| Trường nhập liệu theo loại | CR-01 → CR-04 | 4 |
| Dữ liệu từ API | CR-05 | 1 |
| Thông báo hệ thống | CR-06 → CR-08 | 3 |
| Hành vi form & điều hướng | CR-09 → CR-10 | 2 |
| Danh sách & phân trang | CR-11 → CR-12 | 2 |
| Upload file | CR-13 | 1 |
| Ràng buộc xóa | CR-14 | 1 |
| Tổng | | 14 |
Áp dụng cho toàn bộ trường nhập liệu dạng số nguyên hoặc thập phân.
| Tiêu chí | Quy tắc | Thông báo lỗi |
|---|
| Ký tự hợp lệ — số thập phân | Cho phép: chữ số 0–9, dấu -, ., ,. Khi gõ ký tự ngoài danh sách → Block — ký tự không xuất hiện trong ô, không hiển thị thông báo | — |
| Ký tự hợp lệ — số nguyên | Cho phép: chữ số 0–9, dấu -, ,. Khi gõ dấu . → Block — ký tự không xuất hiện trong ô, không hiển thị thông báo | — |
| Paste chuỗi sai định dạng | Từ chối toàn bộ chuỗi — không điền gì vào ô. Hiển thị lỗi inline màu đỏ bên dưới trường ngay lập tức | "Định dạng số không hợp lệ" |
| Dấu thập phân thứ 2 | Khi gõ dấu . thứ 2 → Block — ký tự không xuất hiện trong ô, không hiển thị thông báo | — |
| Tiêu chí | Quy tắc | Thông báo lỗi |
|---|
| Số thập phân — phần nguyên | Tối đa 15 chữ số phần nguyên. Khi gõ chữ số thứ 16 →Block — ký tự không xuất hiện trong ô, không hiển thị thông báo | — |
| Số thập phân — phần thập phân | Tối đa 5 chữ số sau dấu .. Khi gõ chữ số thứ 6 → Block — ký tự không xuất hiện trong ô, không hiển thị thông báo | — |
| Paste vượt giới hạn | Từ chối toàn bộ chuỗi, không tự cắt. Hiển thị lỗi inline ngay lập tức | "[Tên trường] không được vượt quá [max] ký tự!" |
| Tiêu chí | Quy tắc |
|---|
| Số 0 đầu thừa | Khi gõ chữ số thứ 2 sau 0 đầu → tự xóa 0 thừa. VD: gõ 09 → hiển thị 9 |
| Khoảng trắng đầu/cuối | Giữ nguyên khi đang gõ. Tự xóa khi out-click |
Bắt đầu bằng dấu . | Tự thêm 0 phía trước khi out-click. VD: .9 → 0.9 |
| Tiêu chí | Quy tắc | Thông báo lỗi |
|---|
| Placeholder | Hiển thị*"Nhập [tên trường]"* khi ô trống | — |
| Trường bắt buộc bị bỏ trống | Khi out-click hoặc nhấn Lưu → hiển thị lỗi inline màu đỏ bên dưới trường + viền đỏ. Lỗi tự biến mất khi user nhập ký tự hợp lệ | "Vui lòng nhập [tên trường]" |
| Tiêu chí | Quy tắc |
|---|
| Khoảng trắng đầu/cuối | Giữ nguyên khi đang gõ (không ảnh hưởng UX). Tự xóa khi out-click |
| Chỉ nhập khoảng trắng | Coi là bỏ trống — áp dụng rule bắt buộc nếu có |
| Loại trường | Giới hạn | Hành vi khi đạt giới hạn |
|---|
| Textbox | 255 ký tự | Không block khi gõ. Khi out-click hoặc nhấn Lưu → hiển thị lỗi inline màu đỏ bên dưới trường + viền đỏ quanh trường |
| Textarea | 500 ký tự | Không block khi gõ. Khi out-click hoặc nhấn Lưu → hiển thị lỗi inline màu đỏ bên dưới trường + viền đỏ quanh trường |
| Search box | 255 ký tự | Block — ký tự thứ 256 không được nhập vào ô, không hiển thị thông báo |
| Loại trường | Placeholder |
|---|
| Textbox | "Nhập [tên trường]" |
| Textarea | "Nhập [tên trường]" |
| Search box | "Tìm kiếm theo [tiêu chí tìm kiếm]…" — ghi rõ tiêu chí, VD: "Tìm theo mã hoặc tên…" |
⚠️ Required timing đồng nhất cho TẤT CẢ loại trường: "Khi out-click hoặc nhấn Lưu"
| Tiêu chí | Quy tắc | Thông báo lỗi |
|---|
| Trường bắt buộc — thời điểm báo lỗi | Khi out-click hoặc nhấn Lưu → hiển thị lỗi inline màu đỏ bên dưới trường + viền đỏ. Lỗi tự biến mất khi user nhập ký tự hợp lệ | "Vui lòng nhập [tên trường]" |
| Vượt max — Textbox/Textarea | Không block khi gõ. Khi out-click hoặc nhấn Lưu → hiển thị lỗi inline màu đỏ bên dưới trường + viền đỏ | "[Tên trường] không được vượt quá [max] ký tự!" |
| Chưa đủ min | Không block khi gõ. Khi out-click hoặc nhấn Lưu → hiển thị lỗi inline màu đỏ bên dưới trường + viền đỏ | "[Tên trường] nhập chưa đủ [min] ký tự!" |
| Tiêu chí | Quy tắc |
|---|
| Real-time search | Lọc và hiển thị kết quả ngay khi gõ từng ký tự, không cần nhấn Enter |
| Phân biệt hoa/thường | Không phân biệt (case-insensitive) |
| Dấu tiếng Việt | Không phân biệt dấu (accent-insensitive). VD: "nguyen" tìm được "Nguyễn" |
| Tiêu chí | Quy tắc | Thông báo lỗi |
|---|
| Trạng thái mặc định | Hiển thị*"Chọn [tên trường]"* (placeholder). Không có option nào được chọn sẵn, trừ khi UC quy định giá trị default cụ thể | — |
| Tìm kiếm | Gõ ký tự vào ô → lọc danh sách real-time, không phân biệt hoa thường. Không tìm thấy → hiển thị*"Không tìm thấy kết quả"* trong vùng dropdown | — |
| Tên option dài | Cắt ngắn với ... trong ô. Hover → tooltip hiển thị đầy đủ | — |
| Sau khi chọn | Đóng dropdown, hiển thị giá trị đã chọn trong ô. Không có icon ✕ xóa lựa chọn | — |
| Mở lại dropdown | Option đang chọn được highlight (checked/bold) trong danh sách | — |
| Trường bắt buộc — thời điểm báo lỗi | Khi out-click hoặc nhấn Lưu → hiển thị lỗi inline màu đỏ bên dưới trường + viền đỏ. Lỗi tự biến mất khi user chọn hợp lệ | "Vui lòng chọn [tên trường]" |
⚠️ Chỉ áp dụng khi UC ghi rõ component là "Dropdown Multiple Selection". KHÔNG tự suy luận.
| Tiêu chí | Quy tắc | Thông báo lỗi |
|---|
| Hiển thị đã chọn | Mỗi option được chọn hiển thị dạng tag có icon ✕ để xóa nhanh | — |
| Tag tràn | Các tag vượt chiều ngang gom thành counter tag +N | — |
| Tìm kiếm | Gõ ký tự → lọc danh sách real-time, không phân biệt hoa thường | — |
| Không tìm thấy | Hiển thị*"Không tìm thấy kết quả"* trong vùng dropdown | — |
| Xóa hết | Ô trở về placeholder | — |
| Trạng thái mặc định | Không có option nào được chọn sẵn, trừ khi UC quy định giá trị default cụ thể. Placeholder:"Chọn [tên trường]" | — |
| Trường bắt buộc — thời điểm báo lỗi | Khi out-click hoặc nhấn Lưu → hiển thị lỗi inline màu đỏ bên dưới trường + viền đỏ. Lỗi tự biến mất khi user chọn hợp lệ | "Vui lòng chọn [tên trường]" |
| Tiêu chí | Quy tắc |
|---|
| Gõ keyword | Lọc danh sách real-time, không phân biệt hoa thường |
| Không tìm thấy | Hiển thị*"Không tìm thấy kết quả"* |
| Xóa hết keyword — filter dropdown | Về option default của filter (thường là*"Tất cả"*). Nếu filter không có option default → về trạng thái blank (không chọn gì). UC phải ghi rõ option default |
| Xóa hết keyword — form dropdown bắt buộc | Giữ trạng thái trống, hiển thị lại placeholder |
Áp dụng cho filter trên màn hình danh sách. KHÔNG áp dụng cho dropdown trong form nhập liệu.
| Tiêu chí | Quy tắc |
|---|
| Option "Tất cả" | Bắt buộc có ở đầu danh sách trên mọi filter dropdown |
| Giá trị mặc định | Khi mở màn hình lần đầu → mặc định chọn*"Tất cả"*, hiển thị toàn bộ bản ghi |
| Kết quả | Hiển thị ngay sau khi thay đổi filter, không cần xác nhận |
⚠️ Phân biệt bắt buộc: "Không tìm thấy" ≠ "Lỗi kỹ thuật". KHÔNG gộp 2 case này thành 1 rule.
| Tiêu chí | Quy tắc | Thông báo |
|---|
| Trước khi gọi API | Trường ở trạng tháiDisabled — chờ kết quả | — |
| API trả về dữ liệu | Auto-fill giá trị vào trường + giữDisabled (khóa, không cho sửa) | Toast (góc trên phải, tự tắt 5 giây) nếu UC quy định. Nội dung toast do UC ghi rõ → xem bảng toast mapping trong UC tương ứng. Nếu UC không ghi → raise QnA |
| API trả về null/rỗng (không tìm thấy) | Trường chuyển sangEnabled — user nhập thủ công | Toast (góc trên phải, tự tắt 5 giây) nếu UC quy định. Nội dung toast do UC ghi rõ → xem bảng toast mapping trong UC tương ứng. Nếu UC không ghi → raise QnA |
| API lỗi kỹ thuật (timeout, lỗi kết nối) | Trườnggiữ nguyên Disabled — KHÔNG cho nhập thủ công. User phải tải lại trang | Toast lỗi (góc trên phải, tự tắt 5 giây): "Không thể tra cứu thông tin. Vui lòng tải lại trang để thử lại" |
| Tình huống | Loại hiển thị | Thông báo |
|---|
| Tải trang lần đầu — không có mạng | Thông báo lỗi căn giữa màn hình (dạng empty state).KHÔNG dùng toast | "Không thể kết nối. Vui lòng kiểm tra mạng và thử lại" |
| Action thất bại — lỗi mạng | Toast lỗi (góc trên phải, tự tắt 5 giây) | "Không thể kết nối. Vui lòng kiểm tra mạng và thử lại" |
| Lỗi máy chủ (500) | Toast lỗi (góc trên phải, tự tắt 5 giây) | "Hệ thống đang bận. Vui lòng thử lại sau" |
| Không tìm thấy trang (404) | Thông báo lỗi căn giữa màn hình + nút**[Về trang chủ]**. KHÔNG dùng toast | "Trang không tìm thấy hoặc đã bị xóa" |
| Hết thời gian chờ | Toast lỗi (góc trên phải, tự tắt 5 giây) | "Yêu cầu đã hết thời gian chờ. Vui lòng thử lại" |
| Phiên đăng nhập hết hạn (401) | Toast lỗi (góc trên phải, tự tắt 5 giây) → sau đó tự động redirect về trang đăng nhập | "Phiên đăng nhập hết hạn" |
⚠️ KHÔNG để vùng nội dung danh sách trống hoàn toàn. Phải đủ 3 thành phần.
| Thành phần | Quy tắc |
|---|
| (1) Icon | Icon minh họa ngữ cảnh của màn hình |
| (2) Text | Theo mẫu*"Chưa có [tên đối tượng] nào"* — điền tên đối tượng cụ thể theo màn hình trong UC. KHÔNG dùng generic "Không có dữ liệu" |
| (3) CTA Button | Nút*"Thêm mới"* — chỉ hiển thị nếu user có quyền tạo mới. Ẩn nếu không có quyền |
Phân biệt 2 loại:
| Loại | Text | CTA |
|---|
| Danh sách thật sự rỗng | "Chưa có [tên đối tượng] nào" | Có nút Thêm mới (nếu có quyền) |
| Tìm kiếm/lọc không có kết quả | "Không tìm thấy kết quả" | Không có CTA |
| Trường đơn lẻ có giá trị null | Hiển thị**"-"** (dấu gạch ngang) | — |
Quy tắc chung: Tất cả text empty state không có dấu chấm . ở cuối. Vị trí: căn giữa vùng nội dung chính.
| Loại thông báo | Quy tắc dấu câu | Ví dụ |
|---|
| Lỗi bắt buộc / định dạng / trùng lặp | Không có dấu chấm ở cuối | "Vui lòng nhập [tên trường]" |
| Lỗi vượt max/min length | Kết thúc bằng ! | "[Tên trường] không được vượt quá 255 ký tự!" |
| Toast thành công / thất bại | Không có dấu chấm ở cuối | "Thêm mới [tên đối tượng] thành công" |
| Text empty state | Không có dấu chấm ở cuối | "Chưa có phòng khám nào" |
Áp dụng cho màn hình nhập liệu có form.
| Điều kiện | Mô tả |
|---|
| Form dirty | User đã thay đổi bất kỳ trường nào so với lúc tải form |
| Điều hướng | Nhấn [Hủy], chuyển tab, breadcrumb, hoặc bất kỳ phương thức nào rời màn hình đang sửa |
| Không kích hoạt | Form chưa thay đổi gì → điều hướng bình thường, không hiện popup |
| Thành phần | Nội dung |
|---|
| Tiêu đề | "Dữ liệu chưa được lưu" |
| Nội dung | "Bạn có chắc chắn muốn rời khỏi trang này không? Dữ liệu chưa lưu sẽ bị mất" |
| Nút [Hủy] | Đóng popup, ở lại màn hình hiện tại |
| Nút [Đồng ý] | Đóng popup, thực hiện điều hướng. Dữ liệu chưa lưu bị hủy |
| Nút | Hành vi | Toast kết quả |
|---|
| Lưu thêm mới | Validate toàn bộ form khi nhấn. Nếu có lỗi → hiển thị lỗi inline màu đỏ bên dưới từng trường + viền đỏ, không submit. Nếu hợp lệ → lưu, hiển thị toast | Toast thành công (góc trên phải, tự tắt 5 giây): "Thêm mới [tên đối tượng] thành công". Nếu server lỗi → Toast lỗi: "Không thể thêm mới [tên đối tượng]. Vui lòng thử lại sau" |
| Lưu chỉnh sửa | Validate toàn bộ form khi nhấn. Nếu có lỗi → lỗi inline màu đỏ bên dưới từng trường + viền đỏ, không submit. Nếu hợp lệ → lưu, hiển thị toast | Toast thành công (góc trên phải, tự tắt 5 giây): "Cập nhật [tên đối tượng] thành công". Nếu server lỗi → Toast lỗi: "Không thể cập nhật [tên đối tượng]. Vui lòng thử lại sau" |
| Hủy / Đóng | Nếu form dirty → hiển thị popup CR-09. Nếu chưa thay đổi → đóng trực tiếp | — |
| Xóa | Bắt buộc hiển thị popup xác nhận (CR-10.2) trước khi xóa | — |
⚠️ Bắt buộc đủ 4 thành phần. KHÔNG ghi chung chung "Hiển thị popup xác nhận".
| Thành phần | Nội dung |
|---|
| Tiêu đề | "Xác nhận xóa" |
| Nội dung | "Bạn có chắc chắn muốn xóa [tên đối tượng] [tên/mã bản ghi] không? Hành động này không thể hoàn tác." |
| Nút [Hủy] | Đóng popup, không xóa, dữ liệu giữ nguyên |
| Nút [Xóa] | Đóng popup → thực hiện xóa. Thành công:Toast thành công (góc trên phải, tự tắt 5 giây): "Xóa [tên đối tượng] thành công". Thất bại: Toast lỗi (góc trên phải, tự tắt 5 giây): "Không thể xóa [tên đối tượng]. Vui lòng thử lại sau" |
⚠️ KHÔNG dùng placeholder [tên hành động] chung chung. Phải liệt kê rõ từng hành động thực tế từ UC vào bảng. Nếu UC chưa xác định → raise QnA với BA.
| Thành phần | Nội dung |
|---|
| Tiêu đề | "Xác nhận [tên hành động cụ thể từ UC]" |
| Nội dung | "Bạn có chắc chắn muốn [tên hành động cụ thể] không? Hành động này không thể hoàn tác." |
| Nút [Hủy] | Đóng popup, hủy hành động |
| Nút [Đồng ý] | Thực hiện hành động. Thành công:Toast thành công (góc trên phải, tự tắt 5 giây) — nội dung do UC quy định. Thất bại: Toast lỗi (góc trên phải, tự tắt 5 giây): "Không thể [tên hành động cụ thể]. Vui lòng thử lại sau" |
| Tiêu chí | Quy tắc |
|---|
| Số bản ghi mặc định | 10 bản ghi / trang |
| Tùy chọn số bản ghi | 10, 20, 50, 100. Thay đổi → tải lại danh sách, quay về trang 1 |
| Nút [Trang trước] | Disabled khi đang ở trang 1 |
| Nút [Trang sau] | Disabled khi đang ở trang cuối |
| Thông tin hiển thị | "Hiển thị [start]–[end] / [total] bản ghi" |
| Tình huống | Kiểu loading |
|---|
| Tải trang / danh sách lần đầu | Skeleton screen — hiển thị khung placeholder đúng layout thật, KHÔNG dùng spinner toàn trang |
| Chuyển trang / lọc / tìm kiếm danh sách | Spinner overlay trên bảng danh sách — giữ nguyên layout, không reload toàn trang |
| Submit form / gọi API khi nhấn nút | Nút bấm chuyển sangDisabled + spinner — ngăn nhấn lại. Tự phục hồi khi API trả về kết quả |
Áp dụng cho màn hình có tính năng upload. Màn hình áp dụng ghi rõ trong UC chi tiết.
⚠️ Giới hạn số file, dung lượng, định dạng PHẢI lấy từ UC. KHÔNG hardcode mặc định. Nếu UC không ghi rõ → raise QnA với BA.
| Tiêu chí | Giá trị | Nguồn |
|---|
| Số lượng file tối đa | [Lấy từ UC] | UC phải ghi rõ |
| Định dạng cho phép | [Lấy từ UC] | UC phải liệt kê extension cụ thể |
| Dung lượng tối đa mỗi file | [Lấy từ UC] | UC phải ghi rõ (VD: 5 MB, 10 MB) |
| Trường hợp | Thông báo lỗi |
|---|
| File sai định dạng | "File [tên file] không đúng định dạng. Chỉ chấp nhận [danh sách định dạng từ UC]" |
| Vượt số file tối đa | "Đã đạt giới hạn tối đa [N] file đính kèm" |
| File vượt dung lượng | "Vui lòng chọn file có dung lượng ≤ [N] MB" |
| Lỗi máy chủ khi upload | Toast lỗi (góc trên phải, tự tắt 5 giây): "Không thể tải file lên. Vui lòng thử lại sau" |
| Màn hình | Trạng thái |
|---|
| Tạo mới / Chỉnh sửa | Enabled — có thể thêm/xóa file |
| Xem chi tiết | Disabled (chỉ xem) — chỉ hiển thị danh sách file |
Áp dụng cho toàn bộ hành động Xóa trên hệ thống.
| Trường hợp | Hành vi | Thông báo |
|---|
| Bản ghi chưa được liên kết | Cho phép xóa → hiển thị popup xác nhận CR-10.2 | — |
| Bản ghi đã liên kết (có ràng buộc khóa ngoại) | Từ chối xóa — đóng popup, không thực hiện xóa | Toast lỗi (góc trên phải, tự tắt 5 giây): "Không thể xóa [tên đối tượng] đang được sử dụng" |
⚠️ Phải xác định rõ trong UC từng đối tượng có thể bị ràng buộc và bởi module nào. Nếu UC không đề cập → raise QnA với BA.
| Thuật ngữ | Giải thích |
|---|
| [Thuật ngữ] | [Điền từ project_context.md → GLOSSARY] |
| Ngày | Phiên bản | Mục cập nhật | Before | After | Ghi chú |
|---|
| 2026-06-12 | v1.0 | Khởi tạo | — | CR-01 → CR-14 | AI tạo tự động |