Mục đích: Sau khi xác thực OTP thành công ở DN-001, tenant được tạo ở trạng thái pending_kyc. DN-002 là màn hình duy nhất user được truy cập trong lúc chờ Platform Admin duyệt thủ công (SLA 24h — FR-18). Màn hình hiển thị tiến trình 3 bước, đồng hồ đếm ngược SLA, thông tin hồ sơ đã gửi, và cập nhật ngay tại chỗ khi hồ sơ được duyệt hoặc bị từ chối.
Trong phạm vi (In scope)
Hiển thị 3 trạng thái nghiệp vụ: Đang xét duyệt (mặc định) · Đã duyệt · Bị từ chối (kèm lý do).
Đếm ngược SLA 24h tính từ thời điểm gửi hồ sơ; tự cập nhật trạng thái bằng polling 30 giây.
Kênh liên hệ hỗ trợ và nhắc kiểm tra email (kể cả thư rác).
Ngoài phạm vi (Out of scope)
Thao tác duyệt/từ chối hồ sơ — thuộc Platform Admin trên platform.pccctrace.vn (FR-18).
Là DN Owner vừa gửi hồ sơ đăng ký, tôi muốn theo dõi được hồ sơ của mình đang ở bước nào và còn bao lâu nữa được duyệt, để tôi yên tâm chờ mà không phải gọi điện hỏi hoặc đăng ký lại.
ID
Acceptance criteria (Gherkin)
AC-01
Given tenant ở trạng thái pending_kyc, When mở DN-002, Then hiển thị stepper (bước 2 active), đồng hồ đếm ngược tới hạn SLA, bảng thông tin đã gửi và email nhận thông báo.
AC-02
Given đang mở DN-002, When Platform Admin duyệt hồ sơ, Then trong tối đa 30 giây trang tự chuyển sang trạng thái "Hồ sơ đã được duyệt" kèm nút "Đăng nhập ngay" → DN-003.
AC-03
Given hồ sơ bị từ chối, When mở/đang mở DN-002, Then hiển thị "Hồ sơ chưa đủ điều kiện" kèm lý do từ chối do Admin nhập và CTA khắc phục.
AC-04
Given user pending_kyc cố truy cập URL khác trong app, When điều hướng, Then luôn bị redirect về DN-002 (BR-03 của DN-001).
AC-05
Given hồ sơ được duyệt/từ chối, Then hệ thống đồng thời gửi email kết quả tới email đăng ký (BR-09 của DN-001).
3.Luồng nghiệp vụ
DN-001 OTP verified ──► DN-002 (pending_kyc)
│ poll GET /kyc-status mỗi 30s
├── approved ──► màn "Đã duyệt" + email ──► DN-003 Login
├── rejected ──► màn "Bị từ chối" + lý do + email
│ └── "Bổ sung hồ sơ" ──► đăng ký lại (OQ-07 DN-001, MVP)
└── 404/hết hạn ──► Empty state ──► DN-001 Đăng ký lại
User có thể quay lại DN-002 bất cứ lúc nào bằng cách đăng nhập (DN-003) — khi kyc_status = pending_kyc, mọi điều hướng trong app đều đưa về DN-002.
4.UI elements
Layout: card căn giữa, max-width 560px, nền --neutral. Tham chiếu trực tiếp prototype DN-002 — dùng đúng design tokens trong tokens.css.
Đếm ngược giờ làm việc còn lại (giờ + phút, tabular-nums; caption "Giờ làm việc còn lại"). Kèm dòng "Cam kết duyệt trong 24 giờ làm việc (không tính Thứ 7, Chủ nhật) · Dự kiến trước {giờ} {thứ}, {ngày}" — không dùng từ "SLA" trong UI (thuật ngữ nội bộ). Đồng hồ đứng yên trong T7/CN (không trôi). Về 0 → xem EC-01. Cập nhật mỗi phút, aria-live="polite".
KP-03
Bảng "Thông tin đã gửi"
Info table
MST (mono) · Tên DN · Ngày gửi · Email xác nhận · Badge trạng thái. Dữ liệu từ API, không cho sửa.
KP-04
Notice email
Callout
"Bạn sẽ nhận thông báo kết quả qua email {email}… kiểm tra cả thư rác."
Dòng "Không phải tài khoản của bạn? Đăng xuất" — kết thúc phiên → DN-003.
KP-07
Khối "Đã duyệt"
State block
Icon ✅ + "Hồ sơ đã được duyệt!" + thời điểm duyệt + nút primary "Đăng nhập ngay →" (DN-003).
KP-08
Khối "Bị từ chối"
State block
Icon ⚠️ + lý do từ chối (bắt buộc, do Admin nhập) + nút "📎 Bổ sung hồ sơ" (MVP: dẫn đăng ký lại — OQ-02) + "📞 Liên hệ hỗ trợ".
5.Business rules
ID
Quy tắc
Nguồn
BR-01
User thuộc tenant pending_kyc chỉ truy cập được DN-002; mọi route khác của app redirect về đây (đồng bộ BR-03 của DN-001).
FR-1a, FR-18
BR-02
Hạn SLA = submitted_at + 24 giờ làm việc, không tính Thứ 7 và Chủ nhật (chốt 03/07/2026 — OQ-01). VD: gửi 09:30 thứ Sáu → hạn 09:30 thứ Hai. Server tính và trả sẵn sla_deadline; client chỉ hiển thị + đếm ngược giờ làm việc còn lại, không tự tính. Ngày lễ quốc gia: MVP chưa trừ tự động (xem OQ-01).
FR-18
BR-03
Chỉ Platform Admin chuyển được trạng thái pending_kyc → active / rejected. Khi rejected, lý do từ chối là bắt buộc và hiển thị nguyên văn cho DN.
FR-18
BR-04
Trang tự cập nhật bằng polling 30 giây/lần (nguyên tắc "cập nhật mỗi 30 giây" — không dùng websocket/real-time ở quy mô 30 DN).
UX 07-3
BR-05
Kết quả duyệt/từ chối luôn gửi kèm email tới email đăng ký (BR-09 của DN-001); DN-002 chỉ là kênh hiển thị, email là kênh đảm bảo.
Journey J1
BR-06
Sau khi active, user đăng nhập bình thường và không thấy DN-002 nữa; truy cập trực tiếp URL DN-002 khi đã active → redirect vào app.
BA đề xuất
6.API contract (đề xuất)
6.1 · Lấy trạng thái KYC
GET /api/v1/tenants/me/kyc-status
Authorization: Bearer {access_token} // JWT scope hạn chế khi pending_kyc// 200 OK — pending
{
"kyc_status": "pending_kyc",
"tax_code": "0100000123",
"company_name": "Công ty TNHH PCCC Hà Thành",
"submitted_at": "2026-05-15T09:30:00+07:00", // thứ Sáu
"sla_deadline": "2026-05-18T09:30:00+07:00", // thứ Hai — +24h làm việc, bỏ T7/CN (BR-02)
"notify_email": "info@hathanhpccc.vn"
}
// 200 OK — approved
{ "kyc_status": "active", "approved_at": "2026-05-15T14:22:00+07:00" }
// 200 OK — rejected (lý do bắt buộc)
{ "kyc_status": "rejected", "rejected_reason": "Giấy ĐKKD không rõ ràng, cần bản scan chất lượng cao hơn." }
// Lỗi
401 UNAUTHORIZED // hết phiên → về DN-003
404 NOT_FOUND // không có hồ sơ → Empty state
Ghi chú
Client poll endpoint này mỗi 30s khi tab đang mở (dừng khi tab ẩn — visibilitychange). Response nhẹ (<1KB), không cần cache.
7.Trạng thái màn hình (UI states)
State
Mô tả hiển thị
Pending (default)
Stepper bước 2 active + hero countdown + bảng thông tin + notice email + nút hỗ trợ.
Approved
Stepper bước 3 active, icon ✅, "Hồ sơ đã được duyệt!" + thời điểm duyệt + nút "Đăng nhập ngay →".
Rejected
Stepper bước 2 đỏ "Cần bổ sung", icon ⚠️ + lý do từ chối trong callout đỏ + nút "Bổ sung hồ sơ" và "Liên hệ hỗ trợ".
Loading (skeleton)
Toàn bộ card thay bằng skeleton shimmer khớp layout (stepper tròn ×3, hero, bảng, nút) — dùng khi đang gọi API lần đầu.
Empty
Icon 📭 "Không tìm thấy hồ sơ đăng ký" (404 — hồ sơ không tồn tại / phiên đăng ký hết hạn; wording khách hàng, không nhắc "bản ghi tạm") + nút "Đăng ký lại →" (DN-001).
Error
Icon ⚠️ "Không thể tải trạng thái hồ sơ" + khẳng định dữ liệu không mất + nút "↻ Thử lại" và "Liên hệ hỗ trợ".
Khối demo "State & Spec" trong prototypedn-002-kyc-pending-mockup.html có khối "State & Spec" ở góc phải dưới: preview Loading / Empty / Error / Đã duyệt / Bị từ chối (bấm lại nút đang active để về Pending) + link mở file spec này. Khối này chỉ phục vụ review prototype — không build vào production.
8.Yêu cầu phi chức năng
Độ trễ cập nhật: trạng thái mới hiển thị trong ≤30s sau khi Admin duyệt (1 chu kỳ polling).
Accessibility: countdown dùng aria-live="polite"; badge trạng thái có text, không chỉ dựa màu; stepper đọc được bằng screen reader.
Hiệu năng: trang tĩnh nhẹ, tải <1s; polling không tích luỹ timer khi tab ẩn.
Ngôn ngữ: 100% tiếng Việt, kể cả lý do từ chối (Admin nhập tiếng Việt).
Đơn giản hoá: quy mô 30 DN — polling 30s là đủ, không websocket, không push notification web.
9.Edge cases
ID
Tình huống
Xử lý
EC-01
Quá hạn SLA 24h mà Admin chưa duyệt
Countdown về 0 → đổi thành "Quá hạn xử lý — chúng tôi đang ưu tiên hồ sơ của bạn" + nổi bật nút "Liên hệ hỗ trợ". Không hiển thị số âm.
EC-02
Admin duyệt đúng lúc user đang mở trang
Chu kỳ polling kế tiếp nhận active → chuyển khối Approved ngay tại chỗ, không cần F5.
EC-03
Hồ sơ bị từ chối nhiều lần
Mỗi lần từ chối là bản ghi mới kèm lý do mới; DN-002 luôn hiển thị lý do mới nhất.
EC-04
Email kết quả không đến (spam/bounce)
DN-002 vẫn là nguồn chân lý — notice đã nhắc kiểm tra thư rác; bounce log ở phía Platform Admin.
EC-05
Phiên hết hạn khi đang chờ
Poll trả 401 → redirect DN-003 đăng nhập lại; đăng nhập xong quay về DN-002 (khi vẫn pending).
10.Câu hỏi mở — cần chốt trước khi dev
ID
Câu hỏi
Đề xuất của BA
OQ-01
"24 giờ làm việc" (FR-18) tính thế nào — 24h tuyệt đối hay bỏ qua cuối tuần/ngày lễ?
✅ Chốt 03/07/2026 (PM): tính theo giờ làm việc, không tính Thứ 7 và Chủ nhật (Việt Nam nghỉ T7/CN) — đã ghi vào BR-02, KP-02. Còn mở: ngày lễ quốc gia — MVP chưa trừ tự động, đề xuất Admin chủ động xử lý sớm; tự động hoá lịch nghỉ lễ để Phase 2.
OQ-02
Nút "Bổ sung hồ sơ" khi bị từ chối: upload bổ sung giữ nguyên tenant, hay đăng ký lại từ đầu?
MVP: dẫn về DN-001 đăng ký lại (hồ sơ mới vào queue — đồng bộ OQ-07 DN-001 đã chốt). Phase 2: upload bổ sung giữ nguyên tenant_id.
OQ-03
"Liên hệ hỗ trợ" mở gì — mailto, form, hay hotline?
MVP: mailto:support@pccctrace.vn kèm subject tự điền mã hồ sơ. Form hỗ trợ in-app để Phase 2.
11.Changelog
Version
Ngày
Người
Thay đổi
v1.1
03/07/2026
BA
Chốt OQ-01 theo quyết định PM: hạn duyệt tính theo 24 giờ làm việc, không tính T7/CN — cập nhật BR-02, KP-02, ví dụ API (gửi thứ Sáu → hạn thứ Hai), countdown chỉ đếm giờ làm việc. Ngày lễ quốc gia để Phase 2.
v1.0
03/07/2026
BA
Bản đầu tiên — viết từ prototype dn-002-kyc-pending-mockup.html + PRD FR-1a/FR-18 + screen inventory 07-1; đồng bộ các quyết định OQ đã chốt của DN-001 (spec v1.2).