Skip to content

PRD: Người đăng ký bản tin

ModuleKhách hàngPRD IDPRD-SUB-001
Trạng tháiSẵn sàng devFEATSUB
EpicPlaneBANA-1536
Ngày2026-04-03Phiên bảnv1.1
Gói@nx/outreachURDSUB
SurfaceBO · Vận hành
Phụ tráchPhát Nguyễn

TL;DR

Khách truy cập đăng ký bản tin bằng email (kèm chủ đề và ngôn ngữ) và rời đi chỉ với một cú nhấp qua token duy nhất - vòng đời này đã chạy. Back-office hiện có màn danh sách người đăng ký chỉ-đọc (5 cột: email, trạng thái, chủ đề, ngôn ngữ, ngày đăng ký) - đã dựng. Trang thống kê (tổng số, mới trong tháng, đang hoạt động, đã hủy đăng ký) là forward-spec: nền số liệu đã sẵn sàng phía hệ thống, màn hiển thị trên Back Office chưa dựng (🚧). Kết quả: một danh sách gửi thư sạch, email duy nhất, đăng ký/đăng ký lại idempotent.

1. Bối cảnh & Vấn đề

Trang công khai Overture thu thập đăng ký bản tin, nhưng đội vận hành cần trả lời được những câu cơ bản - có bao nhiêu người đăng ký, bao nhiêu người tham gia trong tháng, bao nhiêu người đã rời đi. Việc đăng ký cũng phải an toàn khi lặp lại: gửi cùng một email hai lần không được tạo bản trùng, và địa chỉ đã rời đi trước đó phải tham gia lại được mà không cần dọn dẹp thủ công.

Tính năng này xây dựng vòng đời người đăng ký (đăng ký, hủy đăng ký, đăng ký lại - đã chạy), màn danh sách chỉ-đọc ở back-office (đã dựng), và một trang thống kê chỉ-đọc (chưa dựng - phần tính toán số liệu đã sẵn sàng phía hệ thống, còn thiếu màn hiển thị).

2. Mục tiêu & Loại trừ

Mục tiêu

  • Đăng ký bằng email kèm chủ đề và ngôn ngữ tùy chọn; giữ email duy nhất trong danh sách người đăng ký.
  • Đăng ký idempotent: email đang hoạt động trả về người đăng ký hiện có; email đã vô hiệu hóa sẽ được kích hoạt lại.
  • Hủy đăng ký một cú nhấp qua liên kết token duy nhất - không cần xác thực.
  • Màn danh sách người đăng ký chỉ-đọc ở back-office - xem và lọc, không sửa.
  • Một trang thống kê có xác thực cho back-office - tổng số, mới trong tháng, đang hoạt động, đã hủy đăng ký (🚧 chưa dựng).

Loại trừ

  • Engine chiến dịch Email / SMS - Dự kiến (xem URD §7).
  • Tạo / sửa / xóa người đăng ký từ back-office - danh sách chỉ-đọc có chủ đích; dữ liệu chỉ vào qua form công khai.
  • Phân khúc và nhắm mục tiêu khách hàng.
  • Phân tích giá trị vòng đời của người đăng ký.
  • Gửi email / vận chuyển thư (thuộc phạm vi ngoài module này).

3. Thước đo thành công

Thước đoMục tiêu / tín hiệu
Tính toàn vẹn của danh sáchKhông có email trùng trong số người đăng ký; mỗi người đăng ký có một token hủy đăng ký duy nhất
Tính idempotent của đăng kýĐăng ký lặp cùng một email không tạo mục mới; mục đã vô hiệu hóa được kích hoạt lại sạch sẽ
Độ tin cậy của hủy đăng kýLiên kết token một cú nhấp vô hiệu hóa ngay ở lần gọi đầu; token không hợp lệ bị từ chối là không-tìm-thấy
Khả năng quan sátDanh sách back-office xem và lọc được (đã có); trang thống kê trả về 4 con số khi yêu cầu (khi dựng xong)

4. Persona & Tình huống

PersonaMục tiêu trong tính năng này
Khách truy cậpTham gia bản tin bằng email; rời đi chỉ với một cú nhấp
Đội vận hành (NEXPANDO & VNPAY)Xem và lọc danh sách người đăng ký; theo dõi quy mô, tăng trưởng theo tháng, và số lượng rời đi

Luồng cốt lõi: khách truy cập đăng ký bằng email (chủ đề + ngôn ngữ) → email lặp lại hoặc đã từng rời đi được xử lý idempotent → khách hủy đăng ký qua liên kết token → đội vận hành xem danh sách người đăng ký trong back-office; khi trang thống kê dựng xong, đọc thêm 4 con số tăng trưởng.

5. Câu chuyện người dùng

  • Là một khách truy cập, tôi muốn đăng ký bằng email, chủ đề, và ngôn ngữ của mình, để tôi nhận được bản tin.
  • Là một khách truy cập, tôi muốn đăng ký hai lần vẫn an toàn, để không bao giờ tạo đăng ký trùng hay gặp lỗi.
  • Là một khách đã hủy đăng ký trước đó, tôi muốn đăng ký lại và được kích hoạt lại, để tham gia lại mà không cần trợ giúp.
  • Là một khách truy cập, tôi muốn hủy đăng ký chỉ với một cú nhấp qua liên kết token, để việc rời đi không tốn công.
  • đội vận hành, tôi muốn xem và lọc danh sách người đăng ký trong back-office, để biết ai đang trong danh sách.
  • đội vận hành, tôi muốn một trang thống kê về danh sách, để theo dõi tăng trưởng và số lượng rời đi mà không phải đếm tay.

6. Yêu cầu chức năng

#Yêu cầuTrạng tháiURD ref
FR-1Đăng ký bằng email (công khai, không xác thực) với ngôn ngữ và chủ đề tùy chọn✅ đã dựngURD-SUB-001
FR-2Email duy nhất trong số người đăng ký đang hoạt động; token hủy đăng ký sinh duy nhất và khó đoán✅ đã dựngURD-SUB-002
FR-3Đăng ký idempotent - email đang hoạt động trả về người đăng ký hiện có; email đã vô hiệu hóa được kích hoạt lại✅ đã dựngURD-SUB-004
FR-4Hủy đăng ký bằng token (công khai) vô hiệu hóa người đăng ký; token không hợp lệ bị từ chối là không-tìm-thấy✅ đã dựngURD-SUB-003
FR-5Màn danh sách người đăng ký chỉ-đọc ở back-office - 5 cột, 4 cột lọc được✅ đã dựngURD-SUB-005
FR-6Trang thống kê có xác thực - 4 con số: tổng số, mới trong tháng, đang hoạt động, đã hủy đăng ký🚧 chưa dựngURD-SUB-005

FR-1 - Đăng ký bằng email (công khai)

  • Field: email (bắt buộc, đúng định dạng), chủ đề quan tâm (tùy chọn, nhiều giá trị), ngôn ngữ ưu tiên (tùy chọn - Tiếng Việt / English).
  • Không cần đăng nhập; trả về định danh của người đăng ký.
  • Mốc thời gian đăng ký và token hủy đăng ký được cấp lúc tạo.

FR-2 - Email duy nhất & token

  • Email duy nhất trong số người đăng ký đang hoạt động, bảo đảm bằng một quy tắc duy nhất - không bao giờ có hai bản ghi active cùng email.
  • Token hủy đăng ký sinh ra duy nhất và khó đoán (entropy cao), nhưng không bị ràng buộc duy nhất ở tầng lưu trữ.

FR-3 - Đăng ký idempotent

  • Email đang hoạt động → trả về người đăng ký hiện có, không tạo mới, không lỗi.
  • Email đã vô hiệu hóa → kích hoạt lại: thời điểm đăng ký đặt lại về hiện tại, thời điểm hủy đăng ký xóa, trạng thái về hoạt động.
  • Chuyển trạng thái là tất định - cùng đầu vào luôn cho cùng kết quả.

FR-4 - Hủy đăng ký bằng token

  • Một cú nhấp qua liên kết mang token, không cần xác thực → người đăng ký chuyển sang đã hủy đăng ký, thời điểm hủy được ghi.
  • Token không hợp lệ → từ chối là không-tìm-thấy; không lộ thông tin.
  • Hủy đăng ký trên mục đã vô hiệu hóa là idempotent - không lỗi, không đổi gì thêm.

FR-5 - Danh sách người đăng ký ở back-office (chỉ-đọc)

Màn duy nhất đang có của tính năng này trên Back Office.

CộtLọc đượcHiển thị
Email
Trạng tháiNhãn màu: Đang hoạt động / Đã hủy đăng ký
Chủ đề-Danh sách nhãn, một nhãn mỗi chủ đề
Ngôn ngữNhãn: Tiếng Việt / English
Ngày đăng kýNgày giờ
  • Chỉ-đọc: không có nút tạo, không sửa, không xóa - người đăng ký chỉ vào danh sách qua form công khai.
  • Màn yêu cầu đăng nhập back-office.

FR-6 - Trang thống kê (🚧 chưa dựng)

Hiện trạng: phần tính toán số liệu đã sẵn sàng phía hệ thống; còn thiếu màn hiển thị trên Back Office.

Đặc tả khi dựng:

  • 4 con số: tổng số người đăng ký · mới trong tháng (tham gia kể từ đầu tháng hiện tại) · đang hoạt động · đã hủy đăng ký.
  • Tính trong một lượt tổng hợp duy nhất trên các mục chưa xóa (nhận biết soft-delete); mục đã xóa không được đếm.
  • Yêu cầu phiên đăng nhập; không chặn thêm theo quyền - ai vào được back-office đều đọc được.
  • Nơi hiển thị dự kiến: khối số liệu ngay phía trên bảng danh sách người đăng ký (FR-5), để danh sách và sức khỏe danh sách đọc cùng một chỗ.

Tiêu chí nghiệm thu

Nghiệm thu được ngay (phần đã dựng):

  1. Đăng ký một email mới → người đăng ký xuất hiện trong danh sách back-office với trạng thái Đang hoạt động và ngày đăng ký đúng.
  2. Đăng ký cùng email lần hai → danh sách vẫn chỉ có một dòng cho email đó.
  3. Hủy đăng ký qua liên kết token → dòng tương ứng chuyển nhãn thành Đã hủy đăng ký.
  4. Đăng ký lại email đã hủy → dòng đó trở về Đang hoạt động với ngày đăng ký mới; không sinh dòng thứ hai.
  5. Mở liên kết hủy đăng ký với token sai → nhận phản hồi không-tìm-thấy.
  6. Danh sách back-office hiện đủ 5 cột; lọc theo Email, Trạng thái, Ngôn ngữ, Ngày đăng ký trả về đúng kết quả; cột Chủ đề không có bộ lọc.
  7. Màn danh sách không có nút tạo / sửa / xóa.

Chờ dựng màn (phần thống kê 🚧):

  1. Trang thống kê hiển thị đúng 4 con số; tổng = đang hoạt động + đã hủy (trên các mục chưa xóa).
  2. "Mới trong tháng" chỉ đếm người tham gia kể từ 00:00 ngày đầu tháng hiện tại.
  3. Người đăng ký đã xóa (soft-delete) không xuất hiện trong bất kỳ con số nào.
  4. Truy cập trang thống kê khi chưa đăng nhập → bị từ chối.

7. Yêu cầu phi chức năng

Khía cạnhYêu cầu
Tính toàn vẹn dữ liệuEmail duy nhất trong số người đăng ký đang hoạt động; đăng ký không bao giờ tạo bản trùng; mọi mục có thể soft-delete
Tính idempotentĐăng ký lặp lại là an toàn (trả về hiện có hoặc kích hoạt lại); các chuyển trạng thái là tất định
Phạm vi & phân quyềnĐăng ký/hủy đăng ký công khai không yêu cầu xác thực; danh sách và thống kê back-office yêu cầu phiên đăng nhập; lượt đọc thống kê không chặn thêm theo quyền
Hiệu năng / quy môThống kê tính bằng một lượt tổng hợp duy nhất, không đếm từng dòng
i18nNgôn ngữ ghi nhận theo từng người đăng ký; nhãn hiển thị song ngữ (EN/VI)

8. UX & Luồng

Màn hình chính: form đăng ký bản tin công khai trên trang Overture, và màn danh sách người đăng ký trong back-office (đã dựng). Trang thống kê dự kiến là khối số liệu phía trên danh sách (🚧).

9. Dữ liệu & Miền nghiệp vụ

Khái niệmVai trò
Người đăng kýMục trong danh sách gửi thư - email (duy nhất), trạng thái (đang hoạt động / đã hủy đăng ký), ngôn ngữ, chủ đề, thời điểm đăng ký và hủy đăng ký, và một token hủy đăng ký duy nhất
Tóm tắt thống kêMột bản đọc chỉ-đọc trên người đăng ký: tổng số, mới trong tháng, đếm theo trạng thái

Chỉ ở mức khái niệm - mô hình dữ liệu và bất biến đầy đủ nằm trong Outreach domain model.

10. Phụ thuộc & Giả định

Phụ thuộc vào

  • Năng lực outreach - chứa vòng đời người đăng ký và số liệu thống kê.
  • Back-office - bề mặt hiển thị danh sách (đã có) và thống kê (chưa dựng).
  • Trang công khai Overture - nguồn các đăng ký bản tin.

Giả định

  • Trang công khai có thể gọi các hành động đăng ký/hủy đăng ký không xác thực.
  • Người dùng back-office xác thực để xem danh sách và thống kê.

11. Rủi ro & Câu hỏi mở

Rủi ro / câu hỏiGiảm thiểu / trạng thái
Đăng ký trùng do gửi lặp lạiĐăng ký là idempotent; email duy nhất toàn cục
Đoán / phát lại token hủy đăng kýToken entropy cao, khó đoán; token không hợp lệ bị từ chối; hủy đăng ký idempotent trên mục đã vô hiệu hóa
Màn thống kê chưa dựng - đội vận hành chưa tự đếm được tăng trưởngForward-spec FR-6 giữ nguyên yêu cầu; nền số liệu đã sẵn phía hệ thống, chỉ còn dựng màn hiển thị
Chưa có engine chiến dịch để hành động trên danh sáchNgoài phạm vi; ghi nhận là Dự kiến trong URD
Chi phí thống kê khi danh sách lớn dầnMột lượt tổng hợp duy nhất; xem lại caching nếu back-office truy vấn dày

12. Kế hoạch phát hành & Tiêu chí ra mắt

Khía cạnhKế hoạch
PhaseP2 - tính năng Khách hàng SUB trong danh mục tính năng URD; FR-1..FR-5 đã dựng, FR-6 chưa
RolloutMọi deployment; không có feature flag
MigrationKhông (mục mới; không backfill dữ liệu)
Tiêu chí ra mắtNhóm "nghiệm thu được ngay" (§6, mục 1-7) đạt toàn bộ; nhóm thống kê (mục 8-11) nghiệm thu khi màn FR-6 dựng xong
Giám sátTăng trưởng người đăng ký (mới trong tháng), tỷ lệ rời đi, tỷ lệ lỗi hủy đăng ký

13. FAQ

Điều gì xảy ra nếu cùng một email đăng ký hai lần? Đăng ký là idempotent - một email đang hoạt động trả về người đăng ký hiện có, và một email đã vô hiệu hóa trước đó được kích hoạt lại. Không có mục trùng nào được tạo.

Hủy đăng ký có cần đăng nhập không? Không - đó là một liên kết công khai một cú nhấp mang token duy nhất. Ngược lại, danh sách và thống kê ở back-office thì yêu cầu đăng nhập.

Back-office hiện xem được gì? Màn danh sách người đăng ký chỉ-đọc: email, trạng thái, chủ đề, ngôn ngữ, ngày đăng ký - lọc được theo 4 cột (trừ chủ đề). Không tạo/sửa/xóa từ đây.

Trang thống kê đã có chưa? Chưa - đây là forward-spec (🚧). Phần tính toán số liệu đã sẵn sàng phía hệ thống; màn hiển thị trên Back Office sẽ dựng theo FR-6: 4 con số, dự kiến đặt ngay phía trên danh sách.

Người đăng ký đã xóa có được đếm không? Không - thống kê chỉ tổng hợp trên các mục chưa xóa (nhận biết soft-delete).

Tham chiếu

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.