CYBERSOFT
Đăng nhập

Thực chiến: vòng đời lead→deal, phát hiện trùng/merge & phân quyền RBAC trong CRM

Thực chiến doanh nghiệpCRMAPIPlaywrightThực tế
🗓 1 tháng trước22 phút đọc·👁 1,490 lượt xem👤 393 người đọc

Bài sâu: bối cảnh, kiến trúc dedup/RBAC, bất biến merge/quyền, test plan, ma trận ca, automation, race/bypass, đối soát, CI, AI, phỏng vấn.

1. Bối cảnh doanh nghiệp & phạm vi

Một công ty B2B SaaS trung bình có 220 nhân viên kinh doanh chia thành 18 team theo khu vực và ngành hàng, vận hành một hệ thống CRM nội bộ xử lý khoảng 12.000 lead mới mỗi tháng đến từ nhiều nguồn: form website, hội thảo, quảng cáo, giới thiệu từ đối tác, và nhập tay từ email. Vì lead đến từ nhiều kênh khác nhau, tình trạng trùng lặp (duplicate) rất phổ biến — cùng một khách hàng có thể được ghi nhận 2-3 lần với thông tin liên hệ hơi khác nhau (email viết hoa/thường, số điện thoại có/không mã vùng). Một công ty CRM tương tự từng mất một hợp đồng trị giá 1,8 tỷ đồng vì hai sales ở hai team khác nhau cùng liên hệ một khách hàng theo hai kịch bản giá khác nhau do dữ liệu lead bị trùng mà không ai biết, khiến khách hàng mất niềm tin và huỷ deal.

Phạm vi bài viết bao trùm 3 luồng nghiệp vụ chính: vòng đời lead→deal (capture, qualify, convert, close), phát hiện trùng lặp và merge bản ghi (name matching/dedup) theo nhiều tiêu chí (email chuẩn hoá, số điện thoại, tên công ty tương tự), và phân quyền truy cập (RBAC) theo cấu trúc team/owner để đảm bảo sales chỉ thấy và sửa được lead/deal mà mình hoặc team mình sở hữu, trừ vai trò quản lý cấp cao. Ràng buộc nghiệp vụ quan trọng: mọi thao tác merge phải được ghi log không thể chỉnh sửa (immutable audit trail) để phục vụ tra soát khi có tranh chấp giữa các team về quyền sở hữu khách hàng.

Luồng Lead→Deal & Dedup/RBAC · Lead-to-deal & dedup/RBAC flow Lead Capture Dedup Engine Lead/Deal Service RBAC Gateway Activity Timeline Merge Job Team/Owner Tree Audit Log Bất biến: Merge không mất/nhân bản dữ liệu; RBAC đúng theo team/owner
Kiến trúc luồng Lead→Deal với Dedup Engine và RBAC Gateway

Phạm vi tự động hoá

  • Kiểm thử API cho Dedup Engine: phát hiện trùng, gợi ý merge, thực thi merge
  • Kiểm thử E2E Playwright cho luồng lead→deal và phân quyền theo vai trò
  • Kiểm thử RBAC ở nhiều tầng: UI ẩn/hiện, API chặn, và truy vấn DB trực tiếp
Bài này giả định hệ thống có test-only endpoint để seed lead/deal theo team/owner tuỳ ý và reset trạng thái merge giữa các lần chạy.

2. Kiến trúc & luồng nghiệp vụ

Kiến trúc gồm 5 thành phần chính: Lead Capture (nhận lead từ nhiều nguồn, chuẩn hoá dữ liệu đầu vào), Dedup Engine (so khớp mờ — fuzzy matching — trên email/số điện thoại/tên công ty để tìm ứng viên trùng lặp), Lead/Deal Service (quản lý vòng đời và máy trạng thái), RBAC Gateway (kiểm tra quyền tại mọi request dựa trên team/owner/vai trò), và Activity Timeline (lưu toàn bộ lịch sử tương tác: note, call log, email, task). Khi Dedup Engine phát hiện ứng viên trùng với độ tương đồng vượt ngưỡng cấu hình (ví dụ ≥ 85%), nó không tự động xoá mà tạo một 'merge suggestion' để nhân viên hoặc quản lý xác nhận thủ công trước khi Merge Job thực thi.

Điểm khó khi kiểm thử

Điểm khó nhất là việc merge phải bảo toàn toàn bộ lịch sử hoạt động của cả hai bản ghi gốc — nếu lead A có 3 ghi chú và lead B có 2 cuộc gọi, bản ghi sau merge phải có đủ 5 mục, không mất và không nhân đôi khi merge được gọi lặp lại do lỗi mạng. Điểm khó thứ hai là RBAC không chỉ kiểm tra ở tầng UI (ẩn nút) mà phải chặn đúng ở tầng API và thậm chí ở tầng truy vấn dữ liệu, vì một lỗi RBAC bypass kinh điển là API trả về đủ trường dữ liệu dù UI đã ẩn, khiến người dùng có thể lấy dữ liệu qua devtools hoặc gọi API trực tiếp. Điểm khó thứ ba là chuyển trạng thái lead→deal phải theo đúng máy trạng thái hữu hạn, không cho phép nhảy cóc (ví dụ từ NEW thẳng sang WON) dù thông qua API nội bộ hay thao tác hàng loạt (bulk update).

🎯 Sự cố thực tế

Một quý trước, đội vận hành phát hiện một sales viên ở team miền Bắc có thể xem được danh sách deal của team miền Nam qua endpoint export báo cáo (`/reports/export`), dù giao diện chính đã ẩn đúng theo RBAC. Điều tra cho thấy endpoint export được viết bởi một team khác và quên áp dụng middleware kiểm tra quyền theo team, chỉ kiểm tra người dùng đã đăng nhập chứ không kiểm tra phạm vi dữ liệu được phép truy cập.

3. Mô hình dữ liệu & bất biến (oracle)

Mô hình dữ liệu cốt lõi gồm bảng Lead (id, email, phone, companyName, status, teamId, ownerId, createdAt), Deal (id, leadId, stage, amount, teamId, ownerId), MergeRecord (survivorId, mergedIds[], mergedBy, mergedAt, fieldResolution), Activity (id, entityId, type, content, createdAt), và Role (userId, teamId, scope: OWNER|TEAM|ADMIN). Trạng thái lead đi theo máy trạng thái hữu hạn: NEW → CONTACTED → QUALIFIED → CONVERTED (tạo Deal), và Deal đi theo OPEN → NEGOTIATION → WON|LOST — chỉ lead ở trạng thái QUALIFIED mới được phép convert sang Deal.

Bất biến nghiệp vụ bắt buộc (oracle)

  • Bất biến 1: RBAC — user chỉ đọc/ghi được Lead/Deal có teamId thuộc phạm vi quyền của mình (OWNER: chỉ bản ghi của mình; TEAM: mọi bản ghi trong team; ADMIN: toàn hệ thống), tại mọi tầng (UI, API, query)
  • Bất biến 2: merge không mất dữ liệu — tổng số Activity của bản ghi sống sót sau merge = tổng Activity của tất cả bản ghi gốc trước merge
  • Bất biến 3: merge không nhân bản dữ liệu — không có Activity nào xuất hiện 2 lần trong bản ghi sau merge dù merge được gọi lại (idempotent theo mergeRequestId)
  • Bất biến 4: mỗi leadId/dealId chỉ tồn tại đúng 1 trạng thái hiệu lực tại một thời điểm, và chuyển trạng thái chỉ được phép theo cạnh hợp lệ của state machine
  • Bất biến 5: các bản ghi bị merge (mergedIds) phải chuyển sang trạng thái MERGED (không xoá cứng), giữ tham chiếu tới survivorId để truy vết lịch sử
🔒

Nội dung bị khoá

Bạn đang xem bản xem trước. Đăng nhập để mở khoá toàn bộ bài viết và tất cả tài liệu Tester/QA.

Đã xem 24% nội dung
  • Đọc trọn vẹn mọi bài viết
  • Lưu bài & ghi chú cá nhân
  • Theo dõi tiến độ đã đọc
  • Luyện phỏng vấn, ISTQB, Mock
Đăng nhập để đọc tiếp

Chưa có mã? Lấy mã qua Fanpage / Zalo CyberSoft.

0

💬 Bình luận (0)

Bạn có thể đọc mọi bình luận. Đăng nhập để bình luận

Chưa có bình luận nào. Hãy là người đầu tiên!