Bỏ qua

SRS — App Chấm công (Longdo ERP nội bộ)

Phiên bản: 0.8 — Nháp  |  Người viết: trangth  |  Cập nhật: 29/07/2026  |  Phân quyền: theo file App_chấm công.xlsx  |  Nguồn màn: mockup ui-mockups/longdo-erp/app-longdo-erp/pace-1/cham-cong/

Tài liệu đặc tả yêu cầu phần mềm (SRS) cho App Chấm công nội bộ Longdo (Flutter / Material 3). Tài liệu dành cho Dev đọc để hiện thực hóa — mô tả màn hình theo mockup, logic nghiệp vụ đọc trực tiếp từ code mockup, và phân quyền từng màn.

Bản 0.8 — viết lại bám mockup hiện tại (29/07/2026)

Bản 0.7 mô tả bộ mockup cũ (thư mục app-cham-cong, màn giai-trinh-cong.html). Bộ mockup đã đổi lớn — bản 0.8 này viết lại theo mockup đang có, thay đổi chính:

  • Thư mục nguồn duy nhất: app-longdo-erp/pace-1/cham-cong/. Thư mục app-cham-cong không còn tồn tại — mọi mô tả cũ theo thư mục đó đã bỏ.
  • Màn trung tâm mới: "Công tháng" (cong-thang.html cho Văn phòng, cong-thang-cong-truong.html cho Công trường) — gộp lịch tháng + chi tiết từng ngày + tổng công + tiền phạt + lối vào đơn. Thay cho màn giai-trinh-cong.html (đã xoá) và thay vai trò của nhan-su-checkin-a.html.
  • Đơn của tôi (don-cua-toi.html) tách thành màn riêng, có lọc trạng thái và vuốt để Sửa / Xoá đơn Chờ duyệt.
  • Loại giải trình: ✦ 8 loại, lọc theo khối (thêm Thiếu giờ công, Đi công tác, ✦ Khác) — thay cho 5 loại ở bản 0.7.
  • Công trường bỏ hẳn Đi muộn / Về sớm, thay bằng Thiếu giờ công. ✦ Sửa 19/08/2026: Công trường bỏ hẳn ca chuẩn / khung giờ — chấm công bất kỳ giờ nào trong ngày, giờ giấc linh hoạt hoàn toàn, được chia nhiều phiên trong ngày, chỉ cần tổng đủ 8 giờ = 1 công (thay ca chuẩn 07:00–16:30 và định mức 9,5 giờ). Khối Văn phòng giữ nguyên: 1 phiên / ngày, ca chuẩn 08:00–17:30. Chi tiết: Business Rule — Chấm công & Giải trình công.
  • Tiền phạt / tiền tăng ca lần đầu được đặc tả (§4.5) — mockup đã tính và hiển thị.
  • Bỏ tab "Giải trình / Đăng ký" cạnh tab Chấm công; màn giai-trinh-thanh-cong.html không còn được dùng (form gửi xong hiện toast rồi quay lại).

1. Giới thiệu

1.1 Mục đích

App cho phép nhân viên chấm công vào/ra bằng GPS + nhận diện khuôn mặt, tự theo dõi công tháng của mình (kèm tiền phạt / giờ tăng ca) và tự gửi đơn giải trình / đăng ký; cho HR / Quản lý theo dõi, thống kê, quản lý nhân viên & cấu hình vị trí chấm công — phân quyền theo vai trò và phạm vi đơn vị.

1.2 Phạm vi

Trong phạm viNgoài phạm vi
Tự chấm công vào/ra (GPS + khuôn mặt)Đăng nhập / Quên mật khẩu
Công tháng của bản thân — lịch tháng, chi tiết từng ngày, tổng công, tiền phạt, giờ tăng caMàn duyệt đơn của Quản lý trực tiếp & Nhân sự — thuộc web, module Hành chính – Nhân sự
Giải trình / Đăng ký — tạo, sửa, xoá đơn của bản thân; xem danh sách "Đơn của tôi"Thiết lập tham số nghiệp vụ (định mức công, bậc tiền phạt, đơn giá tăng ca) — làm ở web, đợt sau
Danh sách nhân sự · Trạng thái nhân sự trong ngày · xem công tháng của nhân viên (HR)Bảng lương / chốt lương (app chỉ hiển thị số tiền phạt & tiền tăng ca do server tính)
Thống kê chấm công · Cấu hình vị trí chấm công (geofence)Trang chủ module (trang-chu.html) — dashboard tổng quan, đặc tả ở tài liệu khác
Thông báo chấm công & cài đặt thông báo · Hồ sơ cá nhân · Đổi mật khẩuCác module khác của app (Chat, Danh bạ, Đề xuất, Công việc)

1.3 Thuật ngữ

Thuật ngữÝ nghĩa
Khối Công trườngNhân sự theo dự án (Linh Đàm, Đông Anh, Yên Bái). ✦ Không có ca chuẩn — chấm công bất kỳ giờ nào trong ngày, nhiều phiên/ngày, tính theo tổng giờ của các phiên, không chia buổi.
Khối Văn phòngNhân sự theo phòng ban (IT, Hành chính–Kế toán, Kỹ thuật). Ca chuẩn 08:00–17:30, có mốc đi muộn 08:10.
Công thángMàn trung tâm của nhân viên: lịch tháng + chi tiết ngày + tổng công/quota + tiền phạt + giờ tăng ca + lối vào đơn.
Định mức ngàySố giờ làm cần đạt để tính 1 công: ✦ Văn phòng 8 giờ làm thực (sau khi trừ giờ nghỉ trưa do Nhân sự thiết lập — giờ thô = 8g + nghỉ trưa), ✦ Công trường 8 giờ (tổng thời lượng các phiên trong ngày) — riêng ca chấm 1 lượt xuyên trưa (phiên bao trọn khung nghỉ trưa) thì định mức là 9,5 giờ vì nghỉ trưa nằm trong phiên.
3 nhóm hiển thị ngàyĐủ định mức (xanh) · Thiếu định mức (vàng) · Không công (xám) — xem §4.3.
GeofenceVùng tròn (toạ độ tâm + bán kính m) mà nhân viên phải đứng trong đó mới chấm công được.
LivenessKiểm tra khuôn mặt thật (người sống), chống ảnh/video giả.
Đơn giải trình / đăng kýĐơn nhân viên tự gửi cho một ngày lệch định mức, hoặc đăng ký trước (nghỉ, tăng ca, công tác). ✦ 8 loại, lọc theo khối — xem §4.6.

2. Vai trò & nguyên tắc phân quyền

Vai tròPhạm vi & quyền tổng quát
HR Toàn công ty: xem danh sách nhân sự, trạng thái trong ngày, công tháng & đơn của mọi nhân viên, mọi thống kê, cấu hình vị trí chấm công. Bản thân vẫn tự chấm công & tự gửi đơn ở luồng nhân viên.
Quản lý Giới hạn trong phạm vi quản lý (đơn vị của mình): như HR nhưng chỉ với nhân sự thuộc đơn vị mình; không cấu hình vị trí chấm công.
Nhân viên Chỉ dữ liệu của chính mình: tự chấm công, xem Công tháng của mình, tạo/sửa/xoá đơn của mình. Không thấy danh sách nhân sự, thống kê.

Nguyên tắc lọc theo phạm vi (Dev bắt buộc áp dụng)

Mọi màn quản lý (Danh sách nhân sự, Trạng thái nhân sự, Công tháng của người khác, Thống kê) phải lọc dữ liệu server-side theo phạm vi của người đăng nhập: HR = tất cả; Quản lý = chỉ đơn vị mình phụ trách; Nhân viên = chỉ bản ghi của chính mình. Không dựa vào ẩn/hiện ở client.

Mockup dựng 3 lối vào: Nhân viên Văn phòng · Nhân viên Công trường · HR (chỉ-xem)

✦ Màn chon-vai-tro.html (chỉ để demo cho Dev, không có trong bản chạy thật) mở 3 lối vào: Nhân viên — Văn phòng → cong-thang.html (1 phiên/ngày); Nhân viên — Công trường → cong-thang-cong-truong.html (nhiều phiên/ngày); HR → nhan-su.html. Luồng Quản lý chưa dựng riêng — theo bảng phân quyền, Quản lý dùng đúng bộ màn của HR nhưng dữ liệu bị khoá trong phạm vi đơn vị mình và không có nút "Thêm vị trí chấm công".

HR / Quản lý chỉ XEM, không thao tác hộ nhân viên

Trong mockup, HR mở công tháng của nhân viên bằng cong-thang.html?role=hr&nv=<tên>. Ở chế độ này: tiêu đề đổi thành tên nhân viên + phụ đề "HR đang xem · chỉ đọc"; ẩn nút "Giải trình / Đăng ký", ẩn lối vào "Đơn của tôi", ẩn cảnh báo nhắc giải trình, ẩn nút "Giải trình ngay" trong chi tiết ngày (thay bằng nhãn tĩnh "Chưa giải trình"). Ở màn Đơn, HR không vuốt được để Sửa/Xoá. Duyệt đơn và điều chỉnh tiền phạt làm ở web HCNS, không làm trên app.


3. Ma trận phân quyền theo màn

Màn hìnhHRQuản lýNhân viên
Chấm công (tự chấm) ✓✓✓
Công tháng — của bản thân ✓✓✓
Công tháng — của nhân viên khác ✓ — chỉ đọc, toàn công ty ✓ — chỉ đọc, trong phạm vi mình ✗
Giải trình / Đăng ký (tạo · sửa · xoá) ✓ — cho bản thân✓ — cho bản thân✓ — cho bản thân
Đơn của tôi / Đơn của nhân viên ✓ — xem đơn nhân viên (chỉ đọc) ✓ — trong phạm vi mình (chỉ đọc) ✓ — đơn của mình, sửa/xoá khi Chờ duyệt
Danh sách nhân sự ✓ — full ✓ — chỉ nhân sự thuộc phạm vi mình ✗
Trạng thái nhân sự trong ngày ✓ — full ✓ — trong phạm vi mình ✗
Thống kê ✓ — full ✓ — trong phạm vi mình ✗
Thêm vị trí chấm công ✓✗✗
Thông báo · Cá nhân / Hồ sơ / Đổi mật khẩu ✓✓✓

Điều hướng theo vai trò

  • Nhân viên → vào thẳng Công tháng (FR-09/FR-10); từ đó sang Chấm công (FR-05), Đơn của tôi (FR-11), Form giải trình (FR-08).
  • HR / Quản lý → vào Danh sách nhân sự (FR-01) → chọn 1 người → Công tháng chỉ-đọc của người đó; hoặc Trạng thái nhân sự hôm nay (FR-12), Thống kê (FR-07).
  • Module Chấm công tự chứa thanh điều hướng riêng, vào từ tab Cá nhân của app ERP.

4. Mô hình nghiệp vụ chấm công

4.1 Hai khối nhân sự

Tiêu chíKhối Công trườngKhối Văn phòng
Đơn vị mẫuLinh Đàm, Đông Anh, Yên BáiIT, Hành chính–Kế toán, Kỹ thuật
Ca chuẩn✦ Không có — chấm bất kỳ giờ nào trong ngày, giờ giấc linh hoạt08:00 – 17:30 (mốc đi muộn 08:10)
Đơn vị tínhCả ngày — chỉ nhìn tổng giờ, không chia buổi. ✦ Tối đa 2 phiên / ngày: phiên 1 trước nghỉ trưa, phiên 2 sau nghỉ trưaCó chia buổi sáng/chiều (nghỉ nửa ngày)
Nghỉ trưa✦ Không trừ — nhân viên chấm ra trước trưa, chấm vào lại sau trưa nên giờ nghỉ nằm ngoài phiên, tự động không được tính✦ Trừ đúng khung nghỉ trưa do Nhân sự thiết lập (không hard-code)
Định mức 1 công✦ 8 giờ — tổng thời lượng các phiên; 9,5 giờ nếu chấm 1 lượt xuyên trưa✦ 8 giờ làm thực — giờ thô cần đạt = 8g + giờ nghỉ trưa đã set
Đi muộn / Về sớmKhông có khái niệm này — chỉ đủ / thiếu tổng giờCó — theo mốc 08:10 và 17:30
Định mức tháng (mẫu)25 công25 công

Tham số nghiệp vụ phải cấu hình được, không hard-code

Các con số trên (ca chuẩn Văn phòng, mốc 08:10, định mức 8 giờ làm thực cả hai khối, khung giờ nghỉ trưa, quota 25 công) trong mockup là hằng số mẫu đặt ở đầu file JS. Bản thật phải đọc từ Thiết lập ở web HCNS theo từng khối / từng đơn vị.

4.2 Tập trạng thái ngày

Khối Văn phòng (cong-thang.html):

Trạng thái Điều kiện
Đủ công Vào trước 08:10 và ra ≥ 17:30; ✦ giờ làm sau khi trừ khung nghỉ trưa do HR set đạt 8 giờ
Đi muộn Giờ vào ≥ 08:10 — số phút muộn tính từ 08:10
Về sớm Giờ ra < 17:30 — số phút sớm tính tới 17:30
Quên chấm công Thiếu 1 trong 2 mốc (chỉ có giờ vào hoặc chỉ có giờ ra)
Tăng ca Có đủ 2 mốc và làm thêm ngoài ca chuẩn — chỉ tính giờ đã được duyệt
Nghỉ Có đơn nghỉ (phép năm / không lương / công tác / khác) áp cho cả ngày hoặc nửa ngày
Vắng Hết ngày làm việc theo lịch mà không có bản ghi chấm công và không có đơn

Khối Công trường (cong-thang-cong-truong.html):

Trạng thái Điều kiện
Đủ định mức ✦ Tổng thời lượng các phiên ≥ định mức ngày — 8 giờ (nghỉ trưa ngoài phiên) hoặc 9,5 giờ (1 lượt xuyên trưa). Chấm giờ nào trong ngày cũng được
Thiếu giờ công ✦ Mọi phiên đều đủ 2 mốc nhưng tổng giờ < định mức ngày — thay cho Đi muộn/Về sớm của Văn phòng
Quên chấm công ✦ Bất kỳ phiên nào trong ngày thiếu 1 trong 2 mốc
Tăng ca Làm vượt định mức — chỉ tính giờ đã duyệt
Nghỉ Có đơn nghỉ (không lương / công tác / khác)
Vắng Không có bản ghi và không có đơn

Khác biệt lớn so với bản 0.7 — Dev đọc kỹ

  • Công trường KHÔNG còn "Đi muộn"/"Về sớm" dưới mọi hình thức. Ngày làm không đủ giờ ở công trường là "Thiếu giờ công", giải trình bằng loại đơn cùng tên.
  • Văn phòng tách riêng "Đi muộn" và "Về sớm" thành 2 sự kiện độc lập trong cùng một ngày (mockup ngày 02/06: vừa đi muộn vừa về sớm → 2 dòng sự kiện, 2 đơn riêng, 2 trạng thái duyệt riêng). Quy ước "gộp 1 nhãn Đi muộn / Về sớm" của bản 0.7 chỉ còn dùng ở màn Chấm công tuần (FR-05a) và các màn Thống kê (FR-07) — ở Công tháng thì luôn tách.
  • Nghỉ phép năm chỉ có ở Văn phòng; form của Công trường ẩn lựa chọn này.

4.3 Ba nhóm hiển thị ngày (dùng chung cả 2 khối)

Ô lịch và badge chi tiết ngày không tô theo 6–7 trạng thái ở §4.2 mà quy về 3 nhóm:

NhómMàu nền ôNgày thuộc nhóm
Đủ định mứcXanhĐủ công · Tăng ca · Nghỉ CÓ LƯƠNG đã được duyệt (phép năm)
Thiếu định mứcVàngĐi muộn · Về sớm · Thiếu giờ công · Quên chấm công · ngày đi làm nhưng có phần nghỉ không công
Không côngXámVắng · Nghỉ không lương · nghỉ chưa duyệt hoặc bị từ chối (cả ngày)

Chấm góc ô lịch — 2 màu (giữ như bản 0.7):

Chấm góc Ý nghĩa
Đỏ + dấu ! Chưa giải trình — ngày lệch định mức chưa có đơn
Tím + dấu ✓ Đã có đơn — gộp chung Chờ duyệt / Đã duyệt / Từ chối (phân biệt khi mở chi tiết)
  • Ngày hôm nay: viền tím (ring) quanh ô; ở Văn phòng ô hôm nay tô nền tím đậm.
  • Ngày cuối tuần và ngày tương lai chưa có dữ liệu: ô trống, không bấm được.

4.4 Quy đổi giờ làm ra công

Khối Giờ làm tính được Công của ngày
Văn phòng ✦ giờ ra − giờ vào − giờ nghỉ trưa (do HR set) min(giờ làm ÷ 8 giờ, 1)
Công trường ✦ Σ (giờ ra − giờ vào) của các phiên đã đóng — bỏ phiên < 5 phút; không trừ nghỉ trưa min(tổng giờ ÷ định mức ngày, 1) với định mức = 8g + 1,5g nếu có phiên bao trọn khung nghỉ trưa

Quy tắc kèm theo (đọc từ mockup):

  • Tối đa 1 công/ngày — phần dôi ra không cộng vào công, mà tính riêng thành giờ tăng ca.
  • ✦ Giờ tăng ca tính RIÊNG theo giờ, KHÔNG quy đổi ra ngày công — áp chung cả hai khối (Văn phòng không chia 8g/ngày, Công trường không chia định mức 8g). Giờ tăng ca đứng thành chỉ số riêng (ô Giờ tăng ca) và vào lương theo đơn giá giờ tăng ca, không làm đổi tổng công tháng. Xem BR-GT-10. (Sửa 19/08/2026.)
  • Nghỉ có lương đã duyệt = 1 công. Nghỉ không lương / chưa duyệt / bị từ chối = 0 công.
  • Ngày hôm nay chưa chấm ra: công hiển thị "—", chưa cộng vào tổng tháng.
  • Thiếu 1 mốc chấm (Quên chấm công): công hiển thị "—" kèm cảnh báo "Chưa chốt công — thiếu lần chấm. Bổ sung giờ để tính công."; ở tổng tháng tạm tính đủ 1 công, chốt lại sau khi đơn bổ sung giờ được duyệt.
  • Thanh tiến độ ở thẻ tổng = tổng công ÷ định mức tháng (mẫu 25 công).

4.5 Tiền phạt & tiền tăng ca

Mockup đã tính và hiển thị 3 khoản. Giá trị dưới đây là mẫu, phải cấu hình được ở Thiết lập.

KhoảnĐơn giá mẫuĐiều kiện phát sinh
Phạt đi muộn50.000 ₫ / lầnChỉ khối Văn phòng. Tính khi ngày đã qua và đơn chưa được duyệt (gồm cả: chưa giải trình, đang chờ duyệt, bị từ chối). Về sớm KHÔNG bị phạt.
Phạt ngày nghỉ1.200.000 ₫ / ngàyCả 2 khối. Tính khi ngày đã qua và đơn ở trạng thái chưa giải trình hoặc bị từ chối — đang chờ duyệt thì chưa tính phạt.
Tiền tăng ca60.000 ₫ / giờCả 2 khối. Chỉ cộng giờ tăng ca đã được duyệt; giờ làm thêm chưa đăng ký / bị từ chối hiển thị nhưng không tính tiền.

✦ Tiền tăng ca KHÔNG hiện ở bản ghi tăng ca của chi tiết ngày (sửa 19/08/2026)

Bản ghi Tăng ca trong khối Sự kiện & giải trình của chi tiết ngày chỉ hiện “Làm thêm <thời lượng>” — bỏ dòng “+ <tiền> đ lương tăng ca”. Lý do: giờ tăng ca là chỉ số riêng, không quy đổi ra ngày công (BR-GT-10); tiền tăng ca thuộc bảng lương. Tiền tăng ca vẫn hiện ở sheet “Giờ tăng ca tháng” (tổng giờ đã duyệt + thành tiền) — đó là màn chuyên cho tăng ca.

Bất nhất trong mockup — cần chốt trước khi code

Điều kiện phạt của đi muộn và của ngày nghỉ đang khác nhau ở trạng thái "Chờ duyệt": đi muộn đang-chờ-duyệt vẫn bị tính phạt, còn nghỉ đang-chờ-duyệt chưa bị tính. Xem §8 mục 1 — cần BA chốt một quy tắc thống nhất.

Ngày tương lai không bao giờ bị phạt

Ngày chưa diễn ra (kể cả đã có đơn bị từ chối) chỉ hiển thị trạng thái, không cộng vào tiền phạt.

4.6 Giải trình / Đăng ký — ✦ 8 loại theo khối

LoạiVăn phòngCông trườngTrường nhập riêng
Nghỉ phép năm✓✗Ngày bắt đầu + buổi → ngày kết thúc + buổi; hiện khối "Phép năm còn lại" (mẫu 12/12 ngày) + dòng tóm tắt "Nghỉ từ Sáng dd/mm → Chiều dd/mm · N công"
Nghỉ không lương✓✓Như trên, không có khối phép năm còn lại
Đi muộn / Về sớm✓✗Chọn Đi muộn / Về sớm · Loại lý do (Cá nhân / Công việc) · Ngày · Từ giờ → Đến giờ (khoảng giờ vắng mặt). Chọn "Lý do công việc" → hiện thêm ô Nội dung công việc
Thiếu giờ công✗✓Ngày · Giờ vào thực tế · Giờ ra thực tế
Quên chấm công✓✓Chọn Quên chấm vào / Quên chấm ra · Ngày · 1 ô giờ thực tế (nhãn đổi theo lựa chọn)
Tăng ca✓✓Ngày · Giờ bắt đầu → Giờ kết thúc · ô Nội dung công việc (thay cho ô Lý do). ✦ Kết quả là số giờ tăng ca — tính riêng, không quy đổi ra ngày công ở cả hai khối (BR-GT-10)
Đi công tác✓✓Từ ngày + buổi → Đến ngày + buổi · Nơi công tác (bắt buộc) · dòng tóm tắt "Đi công tác tại X · Sáng dd/mm → Chiều dd/mm · N công". ✦ Phạm vi Theo giờ (1 ngày + Từ giờ → Đến giờ): khối Công trường phải chọn Phiên 1 / Phiên 2; phạm vi Theo ngày thì không chọn phiên
✦ Khác✓✓Loại đơn mở cho tình huống không khớp 7 loại trên: Ngày · Giờ vào · Giờ ra · Lý do (bắt buộc) · File đính kèm. Đơn duyệt = một phiên làm việc hợp lệ, hợp nhất với phiên đã chấm (không cộng trùng) — xem Business Rule Nhóm H

✦ Thời hạn nộp đơn — 1 tuần kể từ ngày xảy ra sự việc (chốt 19/08/2026)

Gọi D = ngày cần giải trình. Đơn chỉ gửi được tới hết 23:59 ngày D+7; từ 00:00 ngày D+8 ngày D đóng hẳn — báo “Đã quá hạn giải trình”.

  • Áp MỌI loại đơn, không trừ loại nào: quá D+7 là chặn hết.
  • Nghỉ phép năm và Nghỉ không lương là đơn xin nghỉ trước nên còn chặt hơn: chặn toàn bộ ngày quá khứ (kể cả trong 7 ngày); riêng Nghỉ phép năm chặn cả hôm nay.
  • Ngày tương lai: cho mọi loại trừ Quên chấm công và Thiếu giờ công.
  • Áp cả hai khối (Văn phòng · Công trường), không tách luật theo khối.
  • Cửa sổ 7 ngày được phép vắt sang tháng sau.
  • Thay luật cũ “cửa sổ hồi tố = phần còn lại của tháng”.

Chi tiết & bộ ca test: Business Rule — Chấm công & Giải trình công (BR-GT-18 · BR-GT-19).

Trường dùng chung (hiện sau khi đã chọn loại): Lý do (bắt buộc, trừ Tăng ca dùng "Nội dung công việc") · File đính kèm (tuỳ chọn — ảnh / video / tệp) · Người duyệt (chỉ đọc) · nút Gửi đơn.

Cách tính số công của đơn nghỉ / công tác: mỗi ngày = 1 công; bắt đầu từ buổi chiều trừ 0,5; kết thúc buổi sáng trừ 0,5; tối thiểu 0,5 công.

Người duyệt — đã chốt 03/08/2026

Người duyệt cố định, nhân viên không được chọn: Quản lý trực tiếp + Nhân sự (HR) — duyệt song song, cần đủ 2 bên, áp dụng cho mọi loại đơn và cả hai khối. Ở Công trường, chỉ huy trưởng chính là quản lý trực tiếp → không tách quy tắc theo khối. (Khớp form tạo đơn; bottom sheet chi tiết đơn đã sửa 27/08/2026 — mục "Tiến trình duyệt" hiện đủ 2 bên cho mọi loại đơn, xem FR-11.)

Hạn nộp đơn: giải trình được cho quá khứ trong tháng, hạn cuối là ngày cuối tháng

Sửa 05/08/2026 (thay luật "không giải trình cho quá khứ" chốt 03/08/2026): được giải trình cho ngày đã qua, nhưng chỉ trong tháng hiện tại — hạn cuối là hết ngày cuối cùng của tháng. Sang tháng mới, mọi ngày của tháng trước khoá hẳn. Ngày tương lai vẫn đăng ký trước bình thường, không bó trong tháng. Xem BR-GT-09.

Trên giao diện (sửa 28/08/2026 — bỏ dải cảnh báo vàng đầu màn Công tháng nhắc hạn giải trình; màn vào thẳng thẻ tổng tháng rồi tới lịch): trong chi tiết ngày, mọi ngày thuộc tháng đang xem là tháng hiện tại đều có nút "Giải trình ngay"; ngày thuộc tháng trước chưa có đơn hiện nhãn tĩnh "Đã quá hạn" và không cho tạo đơn. (Cửa ngoại lệ cho HR khai bù ngày của tháng đã đóng: chưa mở.)

Đi công tác: tính công, không phụ cấp

Đơn Đi công tác ở trạng thái Đã duyệt → ngày trong đơn được tính công (quy đổi theo buổi như đơn nghỉ), không cần bằng chứng làm việc kèm theo và không có phụ cấp công tác đi kèm. Đơn Chờ duyệt / Từ chối thì không tính công. Xem BR-GT-10.

Trạng thái đơn: Chờ duyệt (vàng) · Đã duyệt (xanh) · Từ chối (đỏ). Đơn bị Từ chối → ngày đó giữ nguyên phần công thiếu và bị tính phạt như chưa giải trình.

Sửa / xoá đơn: nhân viên vuốt ngang một đơn đang Chờ duyệt ở màn Đơn của tôi để lộ 2 nút Sửa (mở lại form ở chế độ ?edit=<mã đơn>, tiêu đề "Sửa đơn giải trình", nút "Cập nhật đơn") và Xoá (có hộp thoại xác nhận). Đơn Đã duyệt / Từ chối không sửa/xoá được.

4.7 Quy tắc chấm công bằng vị trí (geofence)

  1. Mỗi vị trí chấm công gắn với 1 đơn vị, gồm: toạ độ tâm + bán kính cho phép (m).
  2. Khi chấm công, app kiểm tra 3 lớp: (a) khoảng cách tới tâm ≤ bán kính; (b) độ chính xác GPS (±m); (c) chống vị trí giả mạo (mock location).
  3. Ngoài phạm vi → chặn chấm công hoàn toàn (nút khoá); chỉ cho "Thử lại".

Ngoại lệ ghi nhận ở màn Trạng thái nhân sự

Màn trang-thai-nhan-su.html có dữ liệu mẫu "Chấm ngoài phạm vi 180 m — đã ghi nhận kèm ảnh, chờ Nhân sự xác nhận", tức có trường hợp bản ghi ngoài vùng vẫn được lưu và chờ HR xác nhận — mâu thuẫn với quy tắc chặn cứng ở mục 3. Xem §8 mục 3.

4.8 Quy tắc nhận diện khuôn mặt

  • Sau khi vị trí hợp lệ → nhận diện khuôn mặt + liveness (hướng dẫn quay mặt để xác thực người sống).
  • Khi xác nhận, ghi đồng thời ảnh khuôn mặt + toạ độ GPS + giờ chấm + độ khớp.
  • Độ khớp hiển thị dạng phần trăm — biên nhận ở FR-05e hiện chip "Khớp 99%".

Cách tính % khớp và ngưỡng tối thiểu — chưa chốt

Mockup chỉ hiển thị con số %; cách quy đổi từ khoảng cách/độ tương đồng vector đặc trưng khuôn mặt (face embedding) ra %, cùng ngưỡng tối thiểu để chấp nhận, là tham số kỹ thuật phụ thuộc SDK nhận diện được chọn — Dev/kỹ thuật xác nhận, không phải quy tắc BA đặt. Kèm theo đó là hành vi khi dưới ngưỡng (xem §8 mục 7) — mockup chưa dựng nhánh này.


4.9 Chốt kỳ công — hệ thống tự chốt, không có nút

(Chốt 10/08/2026 — đóng vấn đề mở "chấm công đã chốt" ở SRS HCNS.)

Kỳ chấm công không có nút Chốt trên giao diện. Hệ thống tự chốt kỳ tháng M vào 23:59 ngày N của tháng M+1, với N là tham số cấu hình, mặc định 03.

Vì sao tự động, và vì sao không chốt lúc 23:59 ngày cuối tháng

Tự động vì mốc trùng với hạn giải trình đã có (hết tháng — §4.6), nhân viên đã quen; không cần dựng màn quản lý kỳ công; và không ai quên chốt làm kẹt kỳ lương.

Ba ngày đệm vì rủi ro lớn nhất không phải đơn giải trình mà là punch về trễ (thiết bị mất mạng, face-service sync chậm — lần chấm ngày 30 lên hệ thống sáng 01). Chốt cứng lúc nửa đêm là loại oan lần chấm công có thật. Ba ngày đủ để punch trôi về hết và đơn gửi ngày 31 được duyệt kịp, vẫn xong trước khi làm lương.

Phạm vi đóng băng — 5 nhóm:

# Đối tượng Sau khi chốt
1 Dữ liệu punch của kỳ Không nhận thêm, không sửa; punch về trễ ghi vào nhật ký lệch, không đổi công
2 Nhãn trạng thái từng ngày Khoá
3 Số công từng ngày & tổng công tháng Khoá
4 Tiền phạt đi muộn · về sớm · vắng không phép Khoá
5 Đơn giải trình thuộc kỳ Không thêm/sửa/xoá — nhưng luồng duyệt vẫn mở (xem dưới)

Kết sổ ngày còn treo trạng thái — việc mà §4.4 gọi là "chốt lại sau":

Ngày Đang tạm tính Khi chốt
Quên chấm công, có đơn Đã duyệt — Cộng công theo đơn (BR-GT-16)
Quên chấm công, không có đơn đủ 1 công 0 công — hạn giải trình cả tháng đã đủ rộng; giữ 1 công biến quên chấm công thành miễn phí. Tham số cấu hình được (0 / 1 công)
Đơn Từ chối — Giữ nguyên trạng thái lệch, không đủ công (BR-GT-15)
Đơn còn Chờ duyệt chưa tính phạt (§8 mục 1) Chốt theo hiện trạng chưa phạt; kết quả duyệt sau đó đi đường điều chỉnh

Đơn gửi đúng hạn nhưng duyệt không kịp — đơn cần đủ 2 bên: Quản lý trực tiếp + Nhân sự (chốt 03/08/2026, §8 mục 2), nên đơn treo là chuyện có thật. Nhân viên đã làm đúng nghĩa vụ, không được để họ chịu. Ba tầng:

  1. Thúc trước hạn — từ ngày 26 hàng tháng nhắc mỗi người duyệt số đơn còn treo; nhắc nhân viên "còn 2 ngày để giải trình công tháng 6" vào ngày 01 và 03.
  2. Duyệt thay — HR/Admin được duyệt vượt cấp thay Quản lý vắng mặt, bắt buộc ghi lý do, log rõ "Nhân sự duyệt thay Quản lý". Không có đường này thì một người nghỉ phép là kẹt cả kỳ.
  3. Vẫn chốt đúng hạn, đơn treo không mất — đơn đi tiếp luồng duyệt bình thường sau khi chốt. Đơn ở lại kỳ của ngày áp dụng, vĩnh viễn; chỉ hệ quả tiền đi sang kỳ sau.

Đơn ở lại kỳ cũ — chỉ tiền đi sang kỳ mới

Đơn giải trình cho ngày 20/06 mãi mãi là đơn của kỳ tháng 6, dù duyệt ngày 15/07. Chuyển đơn sang kỳ 7 sẽ làm bẩn dữ liệu chấm công tháng 7 (tính công sai, lịch hiện ngày lạ, báo cáo hỏng).

Chênh lệch tiền nạp vào kỳ lương tương ứng nếu kỳ đó còn mở — khoảng đệm giữa chốt công (~03/07) và chốt lương (~10/07) hấp thụ phần lớn ca trễ, không sinh truy lĩnh gì cả. Chỉ khi cả hai kỳ đều đã chốt mới đi đường điều chỉnh sang kỳ sau (FR-PL-CHOT).

Sau khi chốt hệ thống làm gì: ① kết sổ ngày còn treo (bảng trên); ② chụp snapshot bảng công (tổng công · số ngày muộn/sớm/vắng · tiền phạt · giờ tăng ca từng người); ③ khoá 5 nhóm dữ liệu; ④ gỡ cảnh báo "Chưa chốt công — thiếu lần chấm" (ngày đã có kết quả cuối, không còn tạm tính); ⑤ badge Đã chốt trên màn Công tháng; ⑥ mở cổng cho bảng lương lấy số; ⑦ thông báo nhân viên "Bảng công tháng 6 đã chốt"; ⑧ ghi nhật ký (thời điểm · số đơn treo · số ngày kết sổ 0 công).

Mở lại kỳ công — bất đối xứng có chủ đích: đóng tự động, mở thủ công. Chỉ Admin, bắt nhập lý do, ghi log. Dành cho ca thật: máy chấm công hỏng cả ngày, cả tổ mất punch, phát hiện sau khi chốt.

5. Đặc tả màn hình (Yêu cầu chức năng)

Mỗi màn gồm: mục đích · quyền truy cập · thành phần/trường · tương tác · file mockup. Toàn bộ file nằm trong ui-mockups/longdo-erp/app-longdo-erp/pace-1/cham-cong/.

Luồng Nhân viênLuồng HR / Quản lýDùng chung
FR-05 Chấm công (tự chấm) FR-01 Danh sách nhân sự FR-13 Thông báo & cài đặt
FR-09 Công tháng — Văn phòng FR-12 Trạng thái nhân sự trong ngày FR-14 Cá nhân · Hồ sơ · Mật khẩu
FR-10 Công tháng — Công trường FR-07 Thống kê FR-15 Chọn vai trò (chỉ demo)
FR-08 Form giải trình / đăng ký FR-06 Thêm vị trí chấm công —
FR-11 Đơn của tôi FR-04 Thông tin nhân sự —

FR-01. Danh sách nhân sự

File: nhan-su.html · Quyền: HR (full) · Quản lý (phạm vi mình) — Nhân viên không

Mục đích: tìm nhân sự, mở công tháng chỉ-đọc của họ, và vào màn Trạng thái nhân sự trong ngày.

Thành phần Ghi chú
Lối vào "Trạng thái nhân sự hôm nay" thẻ đầu màn, phụ đề "Ai đang làm việc, nghỉ, đi công tác — kèm địa điểm chấm công" → FR-12
Ô tìm kiếm theo tên placeholder "Tìm theo tên nhân sự…"
Lọc theo đơn vị 2 nhóm: Công trường (Linh Đàm / Đông Anh / Yên Bái) · Văn phòng (IT / Hành chính–Kế toán / Kỹ thuật)
Item nhân sự avatar · tên · chức vụ · đơn vị · mũi tên

Tương tác: bấm 1 nhân sự → mở Công tháng chỉ-đọc của người đó, đúng theo khối:

  • Nhân sự Văn phòng → cong-thang.html?role=hr&nv=<tên> (FR-09)
  • Nhân sự Công trường → cong-thang-cong-truong.html?role=hr&nv=<tên> (FR-10)

Đã bỏ so với bản 0.7

Màn này không còn FAB "Thêm nhân viên" (tạo hồ sơ nhân sự làm ở web HCNS), và không còn trỏ sang nhan-su-checkin-a.html.

Dev lưu ý

Mockup: mọi item trỏ về cùng 1 file (chưa truyền id thật, chỉ có nv=<tên>). Dev tham số hoá theo mã nhân viên và chọn màn theo khối của nhân sự đó. Ô tìm kiếm & bộ lọc đơn vị chưa gắn logic — cần hiện thực.

FR-02. Thêm mới nhân viên — đã đưa ra khỏi app

Không còn màn tương ứng trong pace-1/cham-cong/.

Tạo hồ sơ nhân sự thực hiện ở web, module Hành chính – Nhân sự. File them-nguoi-dung.html chỉ còn ở pace-2 (giai đoạn 2, ngoài phạm vi SRS này). Mã FR-02 giữ chỗ để không lệch số hiệu các mã cũ.

FR-03. Xem chấm công của một nhân viên (HR / Quản lý)

File: cong-thang.html?role=hr&nv=… / cong-thang-cong-truong.html?role=hr&nv=… Quyền: HR (full) · Quản lý (nhân sự phạm vi mình) — Nhân viên không

Trước đây là màn riêng nhan-su-checkin-a.html (lịch tháng + ô đếm trạng thái). Nay dùng lại đúng màn Công tháng ở chế độ chỉ-đọc — xem FR-09 / FR-10 và khối "HR / Quản lý chỉ XEM" ở §2.

File cũ vẫn còn trong repo nhưng không còn lối vào

nhan-su-checkin-a.html chỉ còn được mở từ nhan-su-thong-tin-b.html. Dev không hiện thực màn này; nếu BA chốt bỏ hẳn thì xoá cả 2 file ở đợt dọn mockup.

FR-04. Thông tin nhân sự

File: nhan-su-thong-tin-b.html · Quyền: HR (full) · Quản lý (phạm vi mình) — Nhân viên không

Mục đích: hồ sơ liên hệ & công việc của một nhân sự. Vào từ FR-12 (chi tiết một người ở màn Trạng thái nhân sự).

Trường Nhóm Mẫu
Họ tên hồ sơ Nguyễn Văn An
Email Liên hệ nguyen.van.an@longdo.vn
Số điện thoại Liên hệ 0912 345 678
Phòng ban Công việc Phòng Kỹ thuật
Chức vụ Công việc Trưởng nhóm
Vai trò Công việc chip "Quản lý"

Nhân viên không xem được màn này (kể cả hồ sơ của chính mình — hồ sơ cá nhân xem ở FR-14).

FR-05. Chấm công (tự chấm)

File: cham-cong.html → kiem-tra-vi-tri-a.html → (kiem-tra-vi-tri-ngoai-pham-vi.html) → cham-cong-khuon-mat.html → cham-cong-thanh-cong.html Quyền: HR · Quản lý · Nhân viên (tất cả tự chấm công cho bản thân)

Màn chấm công  →  Kiểm tra vị trí  →  Nhận diện khuôn mặt  →  Chấm công thành công
                       │
                       └─(ngoài phạm vi)→  Màn "Ngoài phạm vi" (chặn)

FR-05a. Màn chấm công cá nhân (cham-cong.html)

Thành phần Mẫu
Thẻ hôm nay ngày · chip trạng thái ca (Chưa vào ca / Đang trong ca / Đã ra ca)
Giờ vào · Giờ ra · Đã làm "—" khi chưa chấm
Gợi ý vị trí "Bạn đang ở VP Longdo · trong phạm vi chấm công"
Danh sách "Chấm công tuần này" mỗi dòng: thứ · ngày · vào → ra · chip trạng thái; chạm → bottom sheet chi tiết ngày
Nút tròn "Chấm công vào" ngay trên bottom nav → FR-05b
Chuông thông báo → FR-13
  • Chip trạng thái ở màn này dùng nhãn gộp "Đi muộn / Về sớm" và có thêm nhãn "Chưa chấm công" cho ngày hôm nay/tương lai chưa chấm.
  • Đã bỏ: tab "Giải trình / Đăng ký" cạnh tab Chấm công (bản 0.7 có, nay không còn).

FR-05b. Kiểm tra vị trí (kiem-tra-vi-tri-a.html — Phương án A: bản đồ toàn màn. kiem-tra-vi-tri-b.html / -c.html là 2 phương án không chọn, Dev bỏ qua)

Thành phần Nguồn Mẫu
Bản đồ toàn màn hệ thống vòng geofence nét đứt + pin địa điểm + chấm vị trí người dùng (có halo)
Chip trạng thái nổi hệ thống "Bạn đang trong phạm vi chấm công"
Tên + địa chỉ địa điểm hệ thống VP Longdo · 123 Phố Láng Hạ, Đống Đa, Hà Nội
Khoảng cách GPS cách 8 m
Độ chính xác GPS GPS ±5 m
Nút chính — "Tiếp tục nhận diện khuôn mặt" → FR-05d

Phương án A chỉ hiển thị 2 chỉ số

Mockup A không hiện "Chống vị trí giả mạo" và "Toạ độ hiện tại" — 2 mục đó chỉ có ở phương án B / C (đã loại). Việc kiểm tra mock location vẫn là yêu cầu bắt buộc (§4.7 mục 2) nhưng chạy ngầm: phát hiện vị trí giả mạo thì chặn như trường hợp ngoài phạm vi. Nếu BA muốn hiện kết quả kiểm tra lên UI thì phải bổ sung vào mockup A trước.

FR-05c. Ngoài phạm vi (kiem-tra-vi-tri-ngoai-pham-vi.html) — hiện khoảng cách thực vs bán kính cho phép; nút chấm công vô hiệu hoá; chỉ 1 nút "Thử lại" (luồng "Xin chấm công từ xa" đã bỏ hẳn — mockup còn nút này thì Dev bỏ qua).

FR-05d. Nhận diện khuôn mặt (cham-cong-khuon-mat.html) — thẻ ca (ngày · giờ · "Ca hành chính · 08:00") + khung camera + hướng dẫn liveness động + chip "Phát hiện khuôn mặt thật" → nút "Xác nhận chấm công vào".

FR-05e. Chấm công thành công (cham-cong-thanh-cong.html) — biên nhận: giờ + ngày · họ tên · mã NV · phòng ban · độ khớp khuôn mặt · vị trí + toạ độ · nhắc giờ ra dự kiến. Nút "Xong" → FR-05a.

Chấm công RA

Mockup thể hiện đầy đủ chiều VÀO; chiều RA dùng lại cùng luồng (vị trí + khuôn mặt). Dev hiện thực đối xứng.

FR-06. Thêm vị trí chấm công

File: them-vi-tri-cham-cong.html · Quyền: chỉ HR

Trường Kiểu Bắt buộc Ràng buộc / mẫu
Đơn vị áp dụng chọn 1 ✓ 1 trong 6 đơn vị (3 công trường + 3 phòng ban)
Địa chỉ text — "Số nhà, đường, phường/xã…"
Vĩ độ số thực ✓ 21.1402
Kinh độ số thực ✓ 105.8542
Bán kính cho phép (m) số nguyên ✓ > 0; mẫu 100 (chỉ minh hoạ)
  • Ghim toạ độ trên bản đồ ("Chọn trên bản đồ"); nút "Lưu vị trí chấm công".
  • Không có bán kính mặc định — mỗi vị trí tự set; không tự điền sẵn 100 khi HR bỏ trống.
  • Mockup chưa validate: Dev cần bắt buộc Đơn vị áp dụng, validate toạ độ & bán kính > 0; lưu theo mã đơn vị (không lưu chuỗi hiển thị).

FR-07. Thống kê

Quyền: HR (full) · Quản lý (phạm vi mình) — Nhân viên không

FR-07a. Thống kê (màn chính) (thong-ke.html)

Thành phần Ghi chú
Bộ lọc khoảng ngày Từ ngày – Đến ngày + nút Lọc (giới hạn trong khoảng có dữ liệu)
Segmented khối 🏢 Văn phòng / 🏗 Công trường
Chips chọn công trường chỉ hiện khi chọn khối Công trường
Segmented chế độ xem Lịch / Danh sách + đếm "N nhân viên"
View Lịch mỗi tháng trong khoảng lọc là 1 thẻ; mỗi ngày tô màu theo trạng thái có nhiều nhân viên nhất; chạm ngày → xem theo nhân viên. Chú thích 3 nhóm màu: Đủ công · (Đi muộn/Về sớm · Quên chấm công · Tăng ca) · Vắng / ngày nghỉ
View Danh sách bảng chấm công tháng: nhân sự × ngày + cột tổng
Khối "Tổng hợp" các ô đếm lượt theo trạng thái (Đi muộn/Về sớm · Quên chấm công · Vắng · Đủ công · Tăng ca) → bấm sang FR-07d
Nút lọc phòng ban ở app bar

FR-07b. Chi tiết thống kê 1 nhân sự (chi-tiet-thong-ke.html)

  • Thẻ đầu: avatar · tên · "chức vụ · phòng ban" · chip kỳ (Tháng 06/2026) · nút xuất file.
  • Lưới 2×2: Đủ công (ngày) · Đi muộn / Về sớm (lần) · Nghỉ phép (ngày) · Tăng ca (tổng giờ).
  • Thẻ Tổng kết: Tổng ngày công · Tổng giờ làm · Giờ vào trung bình · Tỉ lệ đúng giờ.
  • Mục Chi tiết theo ngày: mỗi dòng thứ · ngày · vào → ra · tổng giờ · chip trạng thái.

FR-07c–e. Bộ màn thống kê theo đơn vị (bản trước)

thong-ke-cham-cong-hr.html (hub chọn dự án / phòng ban) · thong-ke-phong-ban-chi-tiet.html · thong-ke-du-an-chi-tiet.html · thong-ke-theo-ngay.html · thong-ke-theo-trang-thai.html.

  • Hub: segmented Công trường / Văn phòng → thẻ đơn vị (kèm số người); HR thấy mọi đơn vị + nút "Thêm vị trí" (→ FR-06); Quản lý chỉ thấy đơn vị mình, không có nút Thêm vị trí.
  • Chi tiết phòng ban / dự án: lọc khoảng ngày; View Lịch (heatmap theo trạng thái trội nhất, chạm ngày → panel chi tiết) và View Danh sách (ma trận nhân viên × ngày + cột tổng Công / Muộn-Sớm / Thêm / Vắng / Giờ + hàng Tổng + nút Excel).
  • Thống kê theo ngày: toàn bộ nhân sự trong 1 ngày, dải ô trạng thái + bảng giờ.
  • Thống kê theo trạng thái: liệt kê lượt của 1 trạng thái trong khoảng ngày (nhận ?status=&from=&to=), gom theo ngày.
Chỉ số/tháng Định nghĩa
Công số ngày trạng thái Đủ công
Muộn-Sớm số ngày có Đi muộn và/hoặc Về sớm
Thêm số ngày có Tăng ca
Vắng số ngày Vắng (không tính ngày nghỉ theo lịch)
Giờ Σ max(0, ra − vào)

Chồng lấn — cần BA chốt giữ bộ nào

thong-ke.html (FR-07a) và bộ thong-ke-cham-cong-hr.html + chi tiết phòng ban/dự án (FR-07c–e) làm gần như cùng một việc bằng 2 bố cục khác nhau, đều đang có lối vào (một từ mục lục module, một từ tab Cá nhân). Xem §8 mục 4.

Dev lưu ý — điều hướng & phạm vi

Thẻ đơn vị / ô ngày trong mockup trỏ file cố định (hard-code Đông Anh / Phòng Kỹ thuật / ngày 11/06), chưa truyền tham số. Dev tham số hoá theo mã đơn vị & ngày. Mọi truy vấn thống kê phải áp bộ lọc phạm vi theo vai trò. Nút xuất Excel hiện mới là mô phỏng.

FR-08. Form giải trình / Đăng ký

File: giai-trinh-cong-form.html — nhận ?khoi=vp|ct, ?loai=<mã loại>, ?edit=<mã đơn> Quyền: HR · Quản lý · Nhân viên (tất cả tạo đơn cho bản thân) — nghiệp vụ ở §4.6

Vào form từ đâu: nút "Giải trình / Đăng ký" ở Công tháng (FR-09/FR-10) · nút "Giải trình ngay" trong chi tiết ngày hôm nay (kèm sẵn ?loai=) · nút Sửa khi vuốt đơn Chờ duyệt ở Đơn của tôi (?edit=).

Cấu trúc form: ô Loại giải trình đứng đầu (bắt buộc). Chưa chọn loại thì chỉ hiện ô này — chọn xong mới hiện nhóm trường tương ứng + ô Lý do + File đính kèm + Người duyệt + nút Gửi. Ô chọn loại hiện icon màu theo loại.

Lọc lựa chọn theo khối (tham số ?khoi=):

Khối Số lựa chọn Ẩn
vp — Văn phòng (mặc định) ✦ 7 Thiếu giờ công
ct — Công trường ✦ 6 Nghỉ phép năm, Đi muộn / Về sớm

Chi tiết trường theo từng loại: xem bảng ở §4.6.

Hành vi khác:

  • Ô ngày là ô chỉ đọc, chạm mở dialog lịch Material (điều hướng tháng, chọn ngày, xác nhận).
  • Ô giờ dùng bàn phím số, tự chèn dấu : sau 2 chữ số, tối đa 5 ký tự.
  • Có cảnh báo tự soát cho các cặp giờ của Tăng ca / Đi muộn–Về sớm / Thiếu giờ công.
  • Đổi loại → hiện đúng nhóm trường + reset các khối liên quan.
  • Gửi đơn: hiện toast rồi quay lại màn trước (history.back()). Không còn dùng màn giai-trinh-thanh-cong.html — file này hiện không có lối vào nào.
  • Chế độ sửa (?edit=): tiêu đề "Sửa đơn giải trình", nút "Cập nhật đơn"; dữ liệu đơn cũ do bản thật nạp từ API (mockup chưa nạp).

FR-09. Công tháng — Khối Văn phòng

File: cong-thang.html — nhận ?role=hr, ?nv=<tên> Quyền: mọi vai trò cho bản thân · HR/Quản lý xem người khác ở chế độ chỉ-đọc

Mục đích: màn trung tâm của nhân viên — xem toàn bộ công tháng của mình, biết ngay ngày nào thiếu định mức / bị phạt, và giải trình ngay tại chỗ.

Bố cục từ trên xuống:

# Khối Nội dung
1 App bar nút quay lại (về Cá nhân, hoặc về Danh sách nhân sự khi ?role=hr) · tiêu đề "Công tháng" (chế độ HR: tên nhân viên + phụ đề "HR đang xem · chỉ đọc") · chuông thông báo có chấm đỏ
2 Thanh chọn tháng ‹ › + "Tháng M · YYYY"; nút tháng sau khoá khi đang ở tháng hiện tại
3 Thẻ tổng tháng tổng công / định mức + thanh tiến độ; 3 ô bấm được: Lần đi muộn (kèm tiền phạt) · Ngày nghỉ (kèm tiền phạt) · Giờ tăng ca
4 Cảnh báo chỉ hiện khi hôm nay thiếu định mức và chưa có đơn (ẩn ở chế độ HR)
5 Lịch tháng ô ngày tô theo 3 nhóm (§4.3) + chấm góc 2 màu; chạm ngày → mở khối 6
6 Chi tiết 1 ngày hiện ngay dưới lịch (không phải bottom sheet) — xem bảng dưới
7 Chú giải 4 mục màu nền (Đủ định mức / Thiếu định mức / Không công / Hôm nay) + 2 mục chấm góc
8 Lối vào Đơn của tôi kèm badge "N chờ duyệt" (ẩn ở chế độ HR) → FR-11
9 Nút "Giải trình / Đăng ký" nút chính, mở FR-08 với ?khoi=vp (ẩn ở chế độ HR)

Khối 6 — Chi tiết 1 ngày gồm:

  • Dòng đầu: Thứ, dd/mm + badge nhóm (Đủ định mức / Thiếu định mức / Vắng) + nút đóng.
  • 3 ô: Giờ vào · Giờ ra · Công ngày (thiếu mốc → "—" màu đỏ).
  • Nếu công = "—": dải cảnh báo "Chưa chốt công — thiếu lần chấm. Bổ sung giờ để tính công."
  • Danh sách "Giải trình trong ngày · N" — mỗi sự kiện 1 thẻ: tên sự kiện · chip trạng thái (Chưa giải trình / Chờ duyệt / Đã duyệt / Từ chối) · dòng chi tiết (vd "Vào 08:22 · muộn 12 phút", "Buổi sáng") · dòng tiền (− 50.000 ₫ tiền phạt · quá hạn hoặc + 150.000 ₫ lương tăng ca · 2g 30p) · nút hành động:
    • chưa có đơn và ngày thuộc tháng hiện tại (hôm nay hoặc đã qua trong tháng) → "Giải trình ngay" (mở FR-08 kèm ?loai=)
    • chưa có đơn và ngày thuộc tháng trước → nhãn tĩnh "Đã quá hạn"
    • đã có đơn → "Xem đơn ›" (mở bottom sheet chi tiết đơn)
    • chế độ HR → luôn là nhãn tĩnh "Chưa giải trình"
  • Ngày đủ định mức, không có sự kiện → dải xanh "Đủ định mức — không có gì cần giải trình."

3 bottom sheet thống kê (mở từ 3 ô ở khối 3):

Sheet Nội dung Ghi chú
Đi muộn chỉ liệt kê các lần bị phạt; mỗi dòng dd/mm · Đi muộn · Vào hh:mm · muộn N phút · Phạt 50.000 ₫; dòng tổng "Tổng tiền phạt" Về sớm không xuất hiện vì không bị phạt
Ngày nghỉ chỉ liệt kê ngày bị phạt (chưa giải trình / bị từ chối); mỗi dòng dd/mm · <loại nghỉ> (cả ngày\|sáng\|chiều\|nửa ngày) · Phạt 1.200.000 ₫; dòng tổng ngày Chờ duyệt không vào danh sách
Tăng ca liệt kê các ngày OT đã duyệt: thứ · dd/mm/yyyy, từ – đến, số giờ; dòng tổng "Tổng giờ OT" OT bị từ chối / chưa duyệt không tính

Bấm 1 dòng trong sheet: đã có đơn → mở chi tiết đơn; chưa có đơn → đóng sheet, mở chi tiết ngày tương ứng ở lịch.

Bottom sheet chi tiết đơn (dùng chung với FR-11): icon + tên loại + ngày/buổi + chip trạng thái · danh sách dòng key–value (ngày, giờ, chế độ, loại lý do, lý do…) · mục File đính kèm (ảnh/video hiện ô xem trước, tệp hiện thẻ tên + đuôi; trống thì ghi "Trống") · mục Tiến trình duyệt.

Tiến trình duyệt thay cho dòng \"Người phê duyệt\" / \"Trạng thái duyệt\" — chốt 27/08/2026

Bảng key–value không chứa dòng Người phê duyệt và Trạng thái duyệt (trạng thái đã có ở chip trên đầu sheet). Hai thông tin đó gộp vào mục Tiến trình duyệt ở cuối sheet: mỗi bên duyệt 1 dòng — icon trạng thái · tên bước (Quản lý trực tiếp duyệt / Nhân sự) · tên người duyệt (dòng phụ, chữ nghiêng) · kết quả (Chờ duyệt / Đã duyệt / Từ chối). Đủ 2 bước cho mọi loại đơn, cả hai khối (BR-CC-10b). Nếu kết quả duyệt có ghi chú kèm (vd "phiên 2 được tính 3g30") thì hiện thành 1 dòng chú thích ngay dưới tiến trình.

Dữ liệu mẫu để Dev đối chiếu (tháng 6/2026, hôm nay 17/06)

Mockup cài sẵn các tình huống: ngày có 2 sự kiện trong cùng ngày (02/06 đi muộn + về sớm, 04/06 nghỉ nửa ngày + về sớm), nghỉ có lương đã duyệt (18/06 → vẫn đủ công), nghỉ bị từ chối (09/06 → coi như vắng, bị phạt), quên chấm ra (12/06 → công "—"), tăng ca đã duyệt (11/06), ngày tương lai đã đăng ký nghỉ (22/06 → không phạt).

FR-10. Công tháng — Khối Công trường

File: cong-thang-cong-truong.html — nhận ?role=hr, ?nv=<tên> Quyền: như FR-09

Bố cục giống hệt FR-09, khác ở phần nghiệp vụ:

Điểm Văn phòng (FR-09) Công trường (FR-10)
Tiêu đề thẻ tổng "Tổng công tháng M · YYYY" thêm tên dự án — vd "… · Dự án Đông Anh"
3 ô đếm Lần đi muộn (có tiền phạt) · Ngày nghỉ (có tiền phạt) · Giờ tăng ca Ngày thiếu giờ (không có tiền phạt) · Ngày nghỉ (có tiền phạt) · Giờ tăng ca
Sheet thứ nhất "Đi muộn — Tháng M" "Thiếu giờ công" — liệt kê ngày có tổng giờ các phiên chưa đủ định mức ngày
Chi tiết ngày có thể chia buổi sáng / buổi chiều; hiện 1 bản ghi Giờ vào / Giờ ra ✦ không chia buổi; hiện bảng phiên — cột trái mỗi phiên 1 dòng Giờ vào → Giờ ra (không cột thời lượng), cột phải là ô gộp hiện số công của ngày (tính trên tổng các phiên); không có dòng Tổng giờ công, Định mức ngày, cũng không có số công cỡ lớn ở đầu (sửa 20/08/2026 — xem FR-CTP-03)
✦ Số phiên / ngày Đúng 1 — chấm ra là khoá Tối đa 2 — phiên 1 trước nghỉ trưa, phiên 2 sau nghỉ trưa; đóng phiên 2 là khoá nút
✦ Khoảng giữa hai phiên — Mặc định là nghỉ giữa ca / nghỉ trưa: không tính công và không hiển thị dòng nào
✦ Quên chấm công thiếu 1 trong 2 mốc của phiên duy nhất chỉ xảy ra ở phiên cuối và luôn là quên chấm ra — phiên đó hiện Giờ ra —, nhãn ngày Quên chấm công như cũ
✦ Giờ của phiên hở mốc — Không được tính công; các phiên đã đóng vẫn cộng bình thường. Chỉ khi đơn giải trình được duyệt (bổ sung giờ ra) thì phần giờ đó mới vào tổng và ngày mới chốt công — xem BR-CTP-04
Chú giải 4 mục màu + 2 mục chấm góc 4 mục màu (không có khối chấm góc riêng)
Nút tạo đơn ✦ "Giải trình / Đăng ký" → ?khoi=vp giống hệt: "Giải trình / Đăng ký" → ?khoi=ct, cùng kiểu nút và cùng vị trí — nằm dưới lối vào Đơn của tôi (thống nhất 20/08/2026)
Lối vào Đơn của tôi don-cua-toi.html don-cua-toi.html?khoi=ct

Nhãn nút tạo đơn — đã thống nhất (20/08/2026)

Cả hai khối dùng chung nhãn "Giải trình / Đăng ký", cùng kiểu nút và cùng vị trí: đặt dưới lối vào Đơn của tôi. Nhãn cũ của Công trường "Tạo đơn — Giải trình / Đăng ký nghỉ, OT" đã bỏ.

FR-11. Đơn của tôi

File: don-cua-toi.html — nhận ?khoi=ct, ?role=hr, ?nv=<tên> Quyền: mọi vai trò cho đơn của mình · HR/Quản lý xem đơn nhân viên (chỉ đọc)

Mục đích: danh sách toàn bộ đơn giải trình / đăng ký của một người, lọc theo trạng thái.

Thành phần Ghi chú
App bar nút quay lại giữ nguyên tham số khoi / role / nv; tiêu đề "Đơn của tôi" (chế độ HR: "Đơn của nhân viên")
Bộ lọc trạng thái 4 chip: Tất cả · Chờ duyệt · Đã duyệt · Từ chối
Dòng đếm "N đơn" theo bộ lọc đang chọn
Item đơn icon theo loại · tên loại · ngày/khoảng ngày · chip trạng thái; nhóm theo tháng
Trạng thái rỗng "Không có đơn nào — Chưa có đơn ở trạng thái này."
Vuốt ngang một đơn Chờ duyệt lộ 2 nút Sửa (→ FR-08 ?edit=) và Xoá (confirm trước khi xoá) — chỉ nhân viên, chế độ HR không vuốt được
Chạm 1 đơn mở bottom sheet chi tiết đơn (cùng bố cục với FR-09)

FR-12. Trạng thái nhân sự trong ngày

File: trang-thai-nhan-su.html · Quyền: HR (full) · Quản lý (phạm vi mình) — Nhân viên không

Mục đích: nhìn một ngày bất kỳ, biết ai đang làm việc / nghỉ / công tác / chưa chấm công, kèm địa điểm chấm và cảnh báo bất thường.

5 trạng thái trong ngày (khác với trạng thái công ở §4.2):

Trạng thái Có đơn kèm theo?
Đang làm việc không
Nghỉ có (đơn nghỉ)
Đi công tác có (đơn công tác)
Chưa chấm công không
Nghỉ việc không — nhân sự đã nghỉ việc từ ngày X
Thành phần Ghi chú
Thanh ngày ‹ › đổi ngày + nút mở lịch; không đi quá ngày hôm nay
Lưới tóm tắt 3 cột 5 ô đếm theo 5 trạng thái — bấm để lọc danh sách
Tìm kiếm "Tìm nhân sự…"
Lọc đơn vị dropdown: Tất cả · nhóm Công trường (Đông Anh / Linh Đàm / Yên Bái) · nhóm Văn phòng (Phòng IT / Hành chính – Kế toán / Phòng Kỹ thuật)
Dòng đếm + nút "N / M nhân sự · lọc: " · nút Bỏ lọc · nút Nhắc chấm công (chỉ hiện khi còn người Chưa chấm công)
Item nhân sự tên · đơn vị · giờ vào/ra · địa điểm chấm công · chip trạng thái
Cảnh báo trên item vd "Đi muộn 11 phút — chưa có đơn giải trình", "Chấm ngoài phạm vi 180 m — đã ghi nhận kèm ảnh, chờ Nhân sự xác nhận"
Chi tiết 1 người mở panel: nếu có đơn → hiện mã đơn · loại · nơi · từ–đến · nội dung · trạng thái · người duyệt; nút Nhắc chấm công cho người chưa chấm; lối sang FR-04

FR-13. Thông báo & Cài đặt thông báo

File: thong-bao-cham-cong.html · cai-dat-thong-bao.html · Quyền: mọi vai trò

FR-13a. Thông báo — chip lọc Tất cả / Chưa đọc (N); nút đánh dấu tất cả đã đọc; lối vào Cài đặt thông báo; danh sách nhóm theo Hôm nay / Hôm qua / …, mỗi item: icon · tiêu đề · nội dung · giờ · chấm "Chưa đọc". Bấm item → mở màn liên quan (vd cảnh báo đi muộn → chi tiết thống kê; nhắc tan ca → màn Chấm công).

Loại thông báo mẫu: Cảnh báo đi muộn · Sắp đến giờ tan ca · kết quả duyệt đơn.

FR-13b. Cài đặt thông báo — nhóm "Chấm công" với các công tắc bật/tắt từng loại nhắc.

FR-14. Cá nhân · Hồ sơ · Đổi mật khẩu

File: nguoi-dung.html · chinh-sua-ho-so.html · doi-mat-khau.html · Quyền: mọi vai trò, chỉ cho bản thân

  • nguoi-dung.html — thẻ hồ sơ người đang đăng nhập (avatar + chấm trạng thái + tên + "chức vụ · phòng ban") · nút Chỉnh sửa hồ sơ · nhóm Thông tin nhân sự (mã NV, phòng ban, chức vụ) · nhóm Thông tin liên hệ (email, điện thoại) · nhóm Tài khoản (Đổi mật khẩu, Cài đặt thông báo).
  • chinh-sua-ho-so.html — sửa thông tin liên hệ & ảnh đại diện của chính mình.
  • doi-mat-khau.html — đổi mật khẩu.

FR-15. Chọn vai trò (màn demo)

File: chon-vai-tro.html · Không thuộc bản chạy thật

✦ Màn cửa vào để demo cho Dev: 3 thẻ vai trò + bảng so sánh quyền.

Thẻ Mở màn Khác biệt nghiệp vụ
Nhân viên — Văn phòng cong-thang.html Ca chuẩn 08:00–17:30 · 1 phiên / ngày · chi tiết ngày hiện 1 bản ghi Giờ vào / Giờ ra
✦ Nhân viên — Công trường cong-thang-cong-truong.html Không khung giờ · tối đa 2 phiên / ngày · chi tiết ngày hiện danh sách phiên + tổng giờ công · đủ 8g = 1 công
HR / Nhân sự nhan-su.html Chọn người → chi tiết chấm công (?role=hr&nv=), chỉ xem

Màn tự ghi rõ: "Bản chạy thật sẽ tự nhận vai trò theo tài khoản đăng nhập" — nên lựa chọn khối ở đây chỉ là công tắc demo, bản thật lấy khối của nhân viên từ hồ sơ (NhanVien.khoi). Dev không hiện thực màn này.


6. Đặc tả dữ liệu (gợi ý)

🧑 Nhân viên, Đơn vị & Vai trò
NhanVien

Hồ sơ nhân viên + phân quyền

CộtKiểuMô tả
ma_nvSTRING PKMã NV (đăng nhập)
ho_tenSTRINGHọ tên
emailSTRINGEmail
sdtSTRINGĐiện thoại
khoiENUMKhối (Văn phòng / Công trường)
don_vi_idFKĐơn vị trực thuộc
chuc_vuSTRINGChức vụ
vai_troENUMVai trò phân quyền
quan_ly_truc_tiep_idFKQuản lý trực tiếp
quota_phep_namINTEGERMẫu 12 ngày/năm
nghi_viec_tuDATEDùng ở FR-12
mat_khau_hashSTRINGMật khẩu (hash)
DonVi

Dự án (công trường) hoặc phòng ban (văn phòng)

CộtKiểuMô tả
idPKMã đơn vị
tenSTRINGLinh Đàm / Phòng IT…
loaiENUMLoại đơn vị
quan_ly_idFKQuản lý phụ trách (xác định phạm vi)
ThietLapChamCong

Tham số nghiệp vụ theo khối / đơn vị — thay cho hằng số hard-code trong mockup

CộtKiểuMô tả
pham_viENUMkhoi | don_vi
gio_vao_chuanTIMEVP 08:00 · CT 07:00
gio_ra_chuanTIMEVP 17:30 · CT 16:30
moc_di_muonTIME08:10
nghi_trua_phutINTEGERVP 60 · CT 0
dinh_muc_phutINTEGER✦ 480 (8g làm thực) cho cả hai khối. VP: trừ khung nghỉ trưa trước khi so. CT: ca xuyên trưa cộng thêm thời lượng khung nghỉ trưa → 570 (9,5g)
quota_cong_thangINTEGERMẫu 25
tien_phat_di_muonINTEGERMẫu 50.000 ₫
tien_phat_nghiINTEGERMẫu 1.200.000 ₫
don_gia_tang_caINTEGERMẫu 60.000 ₫/giờ
📍 Vị trí & Bản ghi chấm công
ViTriChamCong

Geofence của 1 đơn vị (FR-06)

CộtKiểuMô tả
idPKMã vị trí
don_vi_idFKĐơn vị áp dụng
dia_chiSTRINGĐịa chỉ
vi_doDECIMALLatitude
kinh_doDECIMALLongitude
ban_kinh_mINTEGERBán kính (m)
BanGhiChamCong

1 dòng = 1 nhân viên × 1 ngày

CộtKiểuMô tả
idPKMã bản ghi
ma_nvFKNhân viên
ngayDATENgày
gio_vaoTIMENull nếu chưa vào
gio_raTIMENull nếu chưa ra
trang_thaiENUMTrạng thái ngày (theo khối — §4.2)
nhom_hien_thiENUMNhóm hiển thị (§4.3)
cong_ngayDECIMALNull khi chưa chốt (thiếu mốc chấm)
phut_tang_caINTEGERChỉ giờ đã duyệt mới tính tiền
tien_phatINTEGER§4.5
do_khop_matDECIMALHiển thị "Khớp N%" ở biên nhận (§4.8)
vi_doDECIMALGPS lúc chấm
kinh_doDECIMALGPS lúc chấm
trong_vungBOOLEANKèm khoảng cách lệch nếu false
anh_matTEXTĐường dẫn ảnh
📝 Đơn giải trình / Đăng ký
DonGiaiTrinh

1 đơn giải trình/đăng ký của 1 nhân viên (FR-08, FR-11)

CộtKiểuMô tả
idPKMã đơn (mẫu GT-2607)
ma_nvFKNgười gửi (tự giải trình cho bản thân)
loaiENUM✦ 8 loại, lọc theo khối (§4.6)
loai_conENUMPhân nhánh trong loại
ly_do_loaiENUMẢnh hưởng việc có được cộng lại công hay không
tu_thoi_diemDATETIMETuỳ loại
den_thoi_diemDATETIMETuỳ loại
buoi_bat_dauENUMDùng để tính 0,5 công
buoi_ket_thucENUMDùng để tính 0,5 công
so_congDECIMALTối thiểu 0,5
gio_vao_thuc_teTIMENull nếu không nhập
gio_ra_thuc_teTIMENull nếu không nhập
noi_cong_tacSTRINGChỉ loại Đi công tác
ly_doTEXTBắt buộc
file_dinh_kemTEXTẢnh / video / tệp
trang_thaiENUMChờ duyệt / Đã duyệt / Từ chối
ly_do_tu_choiTEXTChỉ có khi trạng thái = Từ chối
BuocDuyetDon

Tiến trình duyệt — mỗi bên duyệt 1 dòng (hiển thị ở mục "Tiến trình duyệt")

CộtKiểuMô tả
don_idFKĐơn giải trình
ben_duyetENUMBên phải duyệt
nguoi_duyet_idFKNgười duyệt cụ thể
ket_quaENUMKết quả của bước này
thoi_diemDATETIMENull khi chưa duyệt

7. Yêu cầu phi chức năng (tóm tắt)

  • Bảo mật phân quyền: lọc dữ liệu theo vai trò + phạm vi ở server (xem §2).
  • Tham số nghiệp vụ cấu hình được: mọi mốc giờ, định mức, đơn giá phạt/tăng ca đọc từ Thiết lập, không hard-code (xem §4.1, §4.5).
  • Tính tiền ở server: app chỉ hiển thị số công, tiền phạt, tiền tăng ca — không tự tính lại.
  • GPS/định vị: đo khoảng cách tới tâm geofence; cảnh báo độ chính xác kém; phát hiện mock location.
  • Khuôn mặt: liveness + so khớp đạt ngưỡng; lưu ảnh chấm công.
  • Xuất Excel: các màn thống kê cần xuất file thật (mockup mới mô phỏng).
  • Hiệu năng: lịch/bảng thống kê tải nhanh theo khoảng ngày; phân trang khi danh sách lớn.
  • Khả dụng: mọi ô ngày, ô đếm, item đơn đều là vùng chạm ≥ 44 px; có aria-label mô tả trạng thái ngày (mockup đã làm) — bản Flutter giữ tương đương bằng Semantics.

8. Vấn đề mở — cần BA chốt trước khi Dev code

7 điểm phát sinh khi đối chiếu SRS với mockup mới

  1. Điều kiện tính phạt khi đơn đang "Chờ duyệt" chưa thống nhất — đi muộn đang chờ duyệt bị tính phạt, nghỉ đang chờ duyệt chưa bị tính. Đề xuất: chờ duyệt thì chưa tính phạt cho cả hai, chốt lại khi có kết quả duyệt. Xem §4.5.
  2. ~~Người duyệt: 1 bên hay 2 bên?~~ — đã chốt 03/08/2026: 2 bên = Quản lý trực tiếp + Nhân sự (HR), duyệt song song, cần đủ 2 bên, mọi loại đơn, không tách theo khối (chỉ huy trưởng công trường cũng là quản lý trực tiếp). Sheet chi tiết đơn trong mockup đã sửa 27/08/2026 — hiện đủ 2 bước kèm tên người duyệt, ở cả hai khối. Xem §4.6.
  3. Chấm công ngoài phạm vi: chặn cứng hay ghi nhận chờ duyệt? — §4.7 mục 3 nói chặn hoàn toàn, nhưng FR-12 có dữ liệu "Chấm ngoài phạm vi 180 m — đã ghi nhận kèm ảnh, chờ Nhân sự xác nhận". Hai luồng này loại trừ nhau.
  4. Giữ bộ màn Thống kê nào? — thong-ke.html (FR-07a, mới) và bộ thong-ke-cham-cong-hr.html + chi tiết phòng ban/dự án (FR-07c–e, cũ) trùng chức năng. Đề xuất: giữ FR-07a làm màn chính, giữ thong-ke-theo-ngay / thong-ke-theo-trang-thai làm màn con, bỏ hub + 2 màn chi tiết cũ.
  5. ~~Nhãn nút tạo đơn khác nhau giữa 2 khối~~ — đã chốt 20/08/2026: cả hai khối dùng "Giải trình / Đăng ký", đặt dưới lối vào Đơn của tôi.
  6. Màn Kiểm tra vị trí có hiện kết quả chống giả mạo & toạ độ không? — phương án A (đã chọn) chỉ hiện Khoảng cách + Độ chính xác GPS; 2 mục "Chống vị trí giả mạo" và "Toạ độ hiện tại" chỉ có ở phương án B/C đã loại. Nghiệp vụ vẫn bắt buộc kiểm tra mock location — cần chốt có hiển thị lên UI hay chạy ngầm, nếu hiển thị thì BA bổ sung vào mockup A. Xem §5 FR-05b.
  7. Nhận diện khuôn mặt dưới ngưỡng thì làm gì? — mockup cham-cong-khuon-mat.html chỉ dựng luồng thành công, chưa có màn/thông báo khi không khớp. Cần chốt: thông báo hiển thị, số lần thử tối đa, và hành vi sau khi hết lượt (báo liên hệ HR? mở luồng chấm công thủ công?). Kèm theo: cách quy đổi vector đặc trưng ra % khớp và ngưỡng tối thiểu (§4.8) — phần này Dev/kỹ thuật xác nhận theo SDK.

Đã chốt từ các bản trước — vẫn giữ nguyên

  • Bán kính geofence: không có giá trị mặc định, mỗi vị trí tự set (§5 FR-06).
  • Nền tảng so khớp khuôn mặt: dùng vector đặc trưng (face embedding); thông số ngưỡng do Dev/kỹ thuật xác nhận theo SDK được chọn (chi tiết còn mở — mục 7 ở trên).
  • Mốc 08:10 (Văn phòng): vào trước 08:10 không tính muộn/không phạt; từ 08:10 tính muộn (tính từ 08:10) và bắt đầu phạt. Công trường không có khái niệm đi muộn.
  • "Xin chấm công từ xa": bỏ hẳn, không làm.
  • Đơn vị đếm thống kê: "lượt" gom theo "ngày".
  • Nhân viên không xem Tab Thông tin nhân sự (FR-04) — hồ sơ cá nhân xem ở FR-14.
  • Tạo tài khoản / hồ sơ nhân sự: làm ở web HCNS, không có trong app (FR-02).
  • Màn duyệt đơn: ở web HCNS, không thuộc app này.
  • Chấm góc lịch 2 màu (Chưa giải trình / Đã giải trình) — không cần đủ 4 màu như web.
  • Đăng nhập & Trang chủ module: tách khỏi phạm vi SRS này.

Việc dọn mockup còn tồn (BA làm)

  • giai-trinh-thanh-cong.html — không còn lối vào nào, cân nhắc xoá.
  • nhan-su-checkin-a.html — chỉ còn vào được từ nhan-su-thong-tin-b.html, chức năng đã bị Công tháng thay thế.
  • Mục lục pace-1/index.html chưa liệt kê các màn mới: cong-thang.html, cong-thang-cong-truong.html, don-cua-toi.html, giai-trinh-cong-form.html, chon-vai-tro.html, trang-thai-nhan-su.html.
  • Các file nháp tiền tố _ (bản so sánh phương án) đã được dọn sau khi chốt và áp vào mockup chính — thư mục cham-cong/ không còn file _*.html.

9. Tiêu chí nghiệm thu (chính)

AC-1 — Phân quyền theo phạm vi (Quản lý)

Given người đăng nhập là Quản lý phòng Kỹ thuật When mở Danh sách nhân sự / Trạng thái nhân sự / Thống kê Then chỉ thấy nhân sự & dữ liệu thuộc phòng Kỹ thuật; không truy cập được dữ liệu đơn vị khác (kể cả gọi API trực tiếp).

AC-2 — Nhân viên bị giới hạn

Given người đăng nhập là Nhân viên When vào module Chấm công Then vào thẳng Công tháng của bản thân; không thấy Danh sách nhân sự, Trạng thái nhân sự, Thống kê, Thêm vị trí.

AC-3 — HR xem công tháng nhân viên ở chế độ chỉ đọc

Given HR mở Danh sách nhân sự → chọn 1 nhân viên khối Văn phòng Then mở Công tháng của người đó với tiêu đề = tên nhân viên + phụ đề "HR đang xem · chỉ đọc"; không có nút "Giải trình / Đăng ký", không có lối vào "Đơn của tôi", không vuốt được để Sửa/Xoá đơn; nút quay lại về Danh sách nhân sự.

Trường hợp biên — nhân viên thuộc khối Công trường → mở đúng màn cong-thang-cong-truong, không phải màn Văn phòng.

AC-4 — Chấm công vào thành công

Given nhân viên trong bán kính geofence When bấm "Chấm công vào" → vị trí hợp lệ → khuôn mặt đạt ngưỡng → "Xác nhận" Then lưu bản ghi (giờ + toạ độ + ảnh + độ khớp) và hiển thị biên nhận (chip "Khớp N%"); trạng thái ca → "Đang trong ca".

Chưa nghiệm thu được — nhánh khuôn mặt dưới ngưỡng khớp chưa có trong mockup, chờ chốt ở §8 mục 7.

AC-5 — Chặn chấm công ngoài phạm vi

Given nhân viên ngoài bán kính cho phép When mở màn kiểm tra vị trí Then hiển thị "Ngoài phạm vi", nút chấm công khoá, chỉ có nút "Thử lại"; không tạo bản ghi. (Phụ thuộc §8 mục 3.)

AC-6 — Trạng thái & công của ngày, khối Văn phòng

✦ Given ca 08:00–17:30, mốc muộn 08:10, định mức 8 giờ làm thực sau khi trừ khung nghỉ trưa do HR set (mẫu 1,5 giờ → giờ thô cần 9,5 giờ) When vào 08:22, ra 16:40 Then ngày đó có 2 sự kiện riêng: "Đi muộn — Vào 08:22 · muộn 12 phút" và "Về sớm — Ra 16:40 · sớm 50 phút"; ô lịch nhóm Thiếu định mức (vàng); công ngày = (16:40 − 08:22 − nghỉ trưa) ÷ 8g làm tròn 1 chữ số thập phân — với nghỉ trưa 1,5g thì = (8g18 − 1g30) ÷ 8g ≈ 0,9.

Trường hợp biên — vào 08:08: không tính đi muộn, không phạt.

Trường hợp biên — chỉ check-in, không check-out → trạng thái "Quên chấm công", công ngày hiển thị "—" kèm cảnh báo "Chưa chốt công".

Trường hợp biên — nghỉ phép năm đã duyệt cả ngày → ô lịch xanh (Đủ định mức), công ngày = 1.

Trường hợp biên — nghỉ phép năm bị từ chối → ô lịch xám (Không công), công = 0, bị tính phạt ngày nghỉ.

AC-7 — Trạng thái & công của ngày, khối Công trường

✦ Given định mức 8 giờ tính trên tổng các phiên (ca xuyên trưa thì 9,5 giờ), không có khung giờ — chấm giờ nào trong ngày cũng hợp lệ, không có khái niệm đi muộn When phiên 1 07:00 – 11:30 (4g30) và phiên 2 13:00 – 16:00 (3g00) → tổng 7g30 Then trạng thái = "Thiếu giờ công" (7,5 < 8 giờ), ô lịch vàng, công ngày = 7,5 ÷ 8 ≈ 0,9; giờ nghỉ trưa 11:30 – 13:00 không được tính; không phát sinh phạt đi muộn; loại đơn giải trình gợi ý = "Thiếu giờ công".

✦ Trường hợp biên — phiên 04:30 – 08:30 + 18:00 – 22:00 (tổng 8g) → Đủ công, vì Công trường không còn ràng buộc khung giờ.

✦ Trường hợp biên — phiên chiều chỉ có mốc vào → cả ngày = Quên chấm công, công —.

✦ Trường hợp biên — chấm 1 lượt 07:00 – 16:00 (bao trọn khung nghỉ trưa) → 9g < 9,5g → Thiếu giờ công; chấm 07:00 – 17:00 → 10g ≥ 9,5g → Đủ công.

✦ Trường hợp biên — phiên dưới 5 phút (bấm nhầm) → bỏ hẳn, không cộng giờ và không hiện ở danh sách phiên.

AC-8 — Tiền phạt & tiền tăng ca ở thẻ tổng tháng

Given trong tháng có 3 lần đi muộn chưa được duyệt và 2 ngày nghỉ bị từ chối, tổng OT đã duyệt 5 giờ Then ô "Lần đi muộn" hiện 3 và − 150.000 ₫; ô "Ngày nghỉ" hiện tiền phạt tương ứng; ô "Giờ tăng ca" hiện 5g 00p.

Trường hợp biên — ngày tương lai đã có đơn bị từ chối: không cộng vào tiền phạt.

Trường hợp biên — mở sheet "Đi muộn": danh sách chỉ có các lần bị phạt, không có dòng "Về sớm" nào.

AC-9 — Hạn giải trình: hết tháng

Given trong tháng hiện tại có ngày thiếu định mức chưa có đơn When mở chi tiết ngày hôm nay → Then có nút "Giải trình ngay", mở form đã chọn sẵn đúng loại. When mở chi tiết một ngày đã qua nhưng cùng tháng chưa có đơn → Then vẫn có nút "Giải trình ngay". When mở chi tiết một ngày thuộc tháng trước chưa có đơn → Then hiện nhãn "Đã quá hạn", không cho tạo đơn.

AC-10 — Loại đơn lọc theo khối

Given nhân viên khối Công trường mở form giải trình Then danh sách loại có 6 lựa chọn, không có Nghỉ phép năm và Đi muộn / Về sớm, có Thiếu giờ công.

Given nhân viên khối Văn phòng → Then có 7 lựa chọn, không có Thiếu giờ công.

AC-11 — Sửa / xoá đơn Chờ duyệt

Given nhân viên có 1 đơn trạng thái Chờ duyệt ở màn Đơn của tôi When vuốt ngang đơn đó → Then lộ 2 nút Sửa và Xoá; bấm Sửa mở form ở chế độ sửa (tiêu đề "Sửa đơn giải trình", nút "Cập nhật đơn"); bấm Xoá phải xác nhận trước khi xoá.

Trường hợp biên — đơn Đã duyệt hoặc Từ chối: không vuốt ra được nút nào.

Trường hợp biên — người xem là HR (?role=hr): không vuốt được, tiêu đề màn là "Đơn của nhân viên".

AC-12 — Trạng thái nhân sự trong ngày

Given HR mở màn Trạng thái nhân sự cho ngày hôm nay Then lưới 5 ô đếm đúng số người theo 5 trạng thái; bấm 1 ô thì danh sách chỉ còn người thuộc trạng thái đó và dòng đếm ghi "N / M nhân sự · lọc: "; nút Nhắc chấm công chỉ hiện khi còn người Chưa chấm công; không chọn được ngày sau hôm nay.

AC-13 — Cấu hình vị trí (HR)

Given HR mở "Thêm vị trí", chưa chọn Đơn vị áp dụng · When bấm Lưu · Then báo lỗi bắt buộc; chỉ lưu khi đủ đơn vị + toạ độ hợp lệ + bán kính > 0 (không tự điền giá trị mặc định).


Phụ lục A — Bản đồ màn ↔ file mockup

Tất cả file thuộc ui-mockups/longdo-erp/app-longdo-erp/pace-1/cham-cong/.

Mã Màn File mockup Ghi chú
FR-01 Danh sách nhân sự nhan-su.html
FR-02 Thêm mới nhân viên — Đã chuyển sang web HCNS
FR-03 Xem chấm công của 1 nhân viên cong-thang.html?role=hr · cong-thang-cong-truong.html?role=hr thay nhan-su-checkin-a.html
FR-04 Thông tin nhân sự nhan-su-thong-tin-b.html vào từ FR-12
FR-05a Chấm công cá nhân cham-cong.html
FR-05b Kiểm tra vị trí (Phương án A) kiem-tra-vi-tri-a.html -b / -c không dùng
FR-05c Ngoài phạm vi kiem-tra-vi-tri-ngoai-pham-vi.html
FR-05d Nhận diện khuôn mặt cham-cong-khuon-mat.html
FR-05e Chấm công thành công cham-cong-thanh-cong.html
FR-06 Thêm vị trí chấm công them-vi-tri-cham-cong.html chỉ HR
FR-07a Thống kê (màn chính) thong-ke.html
FR-07b Chi tiết thống kê 1 nhân sự chi-tiet-thong-ke.html
FR-07c Hub thống kê theo đơn vị thong-ke-cham-cong-hr.html bộ cũ — chờ chốt §8 mục 4
FR-07c Chi tiết phòng ban / dự án thong-ke-phong-ban-chi-tiet.html · thong-ke-du-an-chi-tiet.html bộ cũ
FR-07d Thống kê theo ngày thong-ke-theo-ngay.html
FR-07e Thống kê theo trạng thái thong-ke-theo-trang-thai.html nhận ?status=&from=&to=
FR-08 Form giải trình / đăng ký giai-trinh-cong-form.html ?khoi= ?loai= ?edit=
FR-09 Công tháng — Văn phòng cong-thang.html màn trung tâm
FR-10 Công tháng — Công trường cong-thang-cong-truong.html
FR-11 Đơn của tôi don-cua-toi.html ?khoi= ?role= ?nv=
FR-12 Trạng thái nhân sự trong ngày trang-thai-nhan-su.html
FR-13 Thông báo · Cài đặt thông báo thong-bao-cham-cong.html · cai-dat-thong-bao.html
FR-14 Cá nhân · Hồ sơ · Đổi mật khẩu nguoi-dung.html · chinh-sua-ho-so.html · doi-mat-khau.html
FR-15 Chọn vai trò chon-vai-tro.html chỉ demo, không code

File không thuộc phạm vi SRS này: trang-chu.html (dashboard module — tài liệu khác) · giai-trinh-thanh-cong.html (không còn lối vào) · nhan-su-checkin-a.html (đã bị FR-09/FR-10 thay thế) · thong-ke-danh-sach-cac-cach.html (công cụ so layout nội bộ) · kiem-tra-vi-tri-b.html / -c.html (phương án không chọn) · các file tiền tố _ (bản nháp nội bộ).