Functional Specification · PCCCTrace Web DN

DN-002 — KYC Đang xét duyệt (KYC Pending Status)

Đặc tả chức năng cho developer — trang trạng thái duy nhất mà DN được truy cập sau khi gửi hồ sơ đăng ký, cho tới khi Platform Admin duyệt xong.

Screen IDDN-002
ModuleAuth & Onboarding
ActorDN Owner (tenant pending_kyc)
RequirementsFR-1a MVP, FR-18
Trạng tháiDraft — chờ review
Version / Ngàyv1.1 · 03/07/2026
Màn hình liên quanDN-001 · DN-003

1.Tổng quan & phạm vi

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)

Ngoài phạm vi (Out of scope)

2.User story & Acceptance criteria

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.
IDAcceptance criteria (Gherkin)
AC-01Given 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-02Given đ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-03Given 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-04Given 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-05Given 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.

IDThành phầnLoạiHành vi / Ghi chú
KP-01Stepper 3 bướcProgress indicator"Gửi hồ sơ ✓ → Xét duyệt (active, pulse) → Kích hoạt". Trạng thái duyệt: bước 2 ✓, bước 3 active. Từ chối: bước 2 chuyển đỏ "Cần bổ sung".
KP-02Hero countdownLive timerĐế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-03Bảng "Thông tin đã gửi"Info tableMST (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-04Notice emailCallout"Bạn sẽ nhận thông báo kết quả qua email {email}… kiểm tra cả thư rác."
KP-05Nút "Liên hệ hỗ trợ"Button secondaryMở kênh hỗ trợ (mailto support@pccctrace.vn ở MVP — xem OQ-03).
KP-06Link "Đăng xuất"LinkDò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-07Khối "Đã duyệt"State blockIcon ✅ + "Hồ sơ đã được duyệt!" + thời điểm duyệt + nút primary "Đăng nhập ngay →" (DN-003).
KP-08Khối "Bị từ chối"State blockIcon ⚠️ + 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

IDQuy tắcNguồn
BR-01User 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-02Hạ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-03Chỉ 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-04Trang 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-05Kế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-06Sau 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)

StateMô tả hiển thị
Pending (default)Stepper bước 2 active + hero countdown + bảng thông tin + notice email + nút hỗ trợ.
ApprovedStepper bước 3 active, icon ✅, "Hồ sơ đã được duyệt!" + thời điểm duyệt + nút "Đăng nhập ngay →".
RejectedStepper 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.
EmptyIcon 📭 "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).
ErrorIcon ⚠️ "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 prototype dn-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

9.Edge cases

IDTình huốngXử lý
EC-01Quá hạn SLA 24h mà Admin chưa duyệtCountdown 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-02Admin duyệt đúng lúc user đang mở trangChu kỳ polling kế tiếp nhận active → chuyển khối Approved ngay tại chỗ, không cần F5.
EC-03Hồ sơ bị từ chối nhiều lầnMỗ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-04Email 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-05Phiê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

IDCâ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-02Nú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

VersionNgàyNgườiThay đổi
v1.103/07/2026BAChố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.003/07/2026BABả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).
← Quay lại mockup