Inbox chat 2 chiều với khách tuyển sinh qua Zalo OA ngay trên web Vĩnh An: khách quét QR/nhắn OA → hội thoại vào inbox → NV tuyển sinh tư vấn → chốt → 1 nút tạo hồ sơ học viên (đổ sẵn tên/SĐT vào form tiếp nhận WS1). Đối tượng chat là khách vãng lai (lead) — không phải user OpenGate.
zalochat KHÔNG giữ token/secret — đọc config + gửi tin qua hàm chung lớp 1.
| Feature | BO chính | Action |
|---|---|---|
| conversation | Hội thoại (1 khách Zalo = 1 hội thoại) | vieweditassignclose |
| message | Tin nhắn 2 chiều + đính kèm | viewsend |
Đã chốt 15/7: đợt đầu mọi NV tuyển sinh thấy tất cả hội thoại + cột "người phụ trách"; data-scope theo assigned_to để giai đoạn sau.
| BO · bảng | Trường chính |
|---|---|
| Hội thoại zalochat_conversation | zalo_user_id (UNIQUE, khóa từ webhook) · tên/avatar Zalo · SĐT (nhập tay khi khách cho — khóa nối lớp 3) · last_user_msg_at (mốc cửa sổ 48h) · assigned_to (employee, bridge users.employee_id) · trạng thái (mới/đang tư vấn/đã chốt/đóng) · unread + preview · lead_ref (hồ sơ WS1 khi chốt — đo hiệu quả kênh) |
| Tin nhắn zalochat_message | hướng in/out · loại (text/image/file/sticker/khac) · nội dung · attachment_path (ảnh CCCD/khám SK — tải về silo ngay, URL Zalo có hạn) · zalo_msg_id UNIQUE (webhook retry không nhân đôi) · sender_employee_id · trạng thái gửi ok/lỗi (+lý do, vd ngoài 48h) |
| Đợt | Nội dung |
|---|---|
| 1 — nền (lớp 1) | Bước 11.1→11.4 spec nền: system_settings + quyền integrations + form config + OAuth connect. Prerequisite: app Zalo riêng Vĩnh An (domain đã verify 14/7) |
| 2 — chat MVP | webhook message → conversation/message · inbox 3 cột · gửi text · cửa sổ 48h · assign · mọi NV thấy tất cả |
| 3 | attachment 2 chiều · SSE · nút "Tạo hồ sơ" nối WS1 · auto-reply ngoài giờ · thống kê (hội thoại/NV, tỉ lệ chốt) |
| Sau | ZNS template (nhắc lịch khai giảng/thi — cần zalo_user_link) · data-scope theo assigned_to |
| # | Task | Nơi | Nghiệm thu |
|---|---|---|---|
| Z0 | Owner tạo app developers.zalo.me, gắn OA, khai redirect_uri + webhook URL theo domain vinhan | thao tác tay | Có app_id/secret; domain verify xong 14/7 |
| Z1.1 | Bảng system_settings + helper get/set | core/built-in/system | Ghi/đọc key qua helper; tạo bằng migration |
| Z1.2 | Feature integrations vào manifest system; backfill + bump epoch | core/built-in/system | Owner có quyền; API config không 403 |
| Z1.3 | GET/PUT config + form FE (secret mask) trong Quản trị → Tích hợp | system + /admin | Lưu/reload OK; secret không lộ full |
| Z1.4 | OAuth connect/callback → token, connected=true, oa_name | system | Kết nối → "Đã kết nối: <oa_name>" |
| Z1.5 | Refresh token lazy (refresh_token XOAY VÒNG — ghi đè mỗi lần) | system | Ép hết hạn → lần gọi kế tự refresh + lưu |
| Z1.6 | Webhook + verify X-ZEvent-Signature + forward event message | system | Chữ ký sai → 401; đúng → handler nhận |
| Z2.1 | Scaffold opengate-app-zalochat: manifest + migration 2 bảng | modules/ (store) | Cài qua Store; bảng + quyền hiện RBAC |
| Z2.2 | Handler event → upsert conversation + insert message (idempotent zalo_msg_id) | zalochat BE | Tin thật vào OA → hiện; retry không nhân đôi |
| Z2.3 | API list/get/assign/close/đã-đọc (guard đủ) | zalochat BE | Token TUYEN_SINH dùng được; thiếu quyền 403 |
| Z2.4 | Gửi text qua lớp 1 + chặn ngoài cửa sổ 48h (tin lỗi + lý do) | zalochat BE | Trong cửa sổ: khách nhận; ngoài: lỗi rõ |
| Z2.5 | FE inbox 3 cột + thanh cửa sổ 48h + assign; polling 5s | zalochat FE | Chat 2 chiều với khách thật; cửa sổ đóng → input disable |
| Z3.1 | Attachment 2 chiều (tải về silo, allowlist+cap) | zalochat | Ảnh CCCD hiện trong chat; gửi ảnh khách nhận |
| Z3.2 | SSE thay polling | zalochat | Tin mới hiện < 2s không reload |
| Z3.3 | Nút "Tạo hồ sơ" → form WS1 đổ sẵn, ghi lead_ref | zalochat + student | Hồ sơ link ngược hội thoại; đếm nguồn Zalo |
| Z3.4 | Auto-reply ngoài giờ + thống kê | zalochat | Ngoài giờ có lời chào; dashboard đúng số |
Thứ tự bắt buộc: Z0 → Z1.1→Z1.4 → Z1.6 → Z2.x → Z3.x. Z1.5 làm trước Z2.4.
Permission key đầy đủ: zalochat.chat.<feature>.<action>. close/send khai customActions (tiền lệ shexchange).
| Feature | QTHT | GIAM_DOC | TUYEN_SINH | QL_DAO_TAO |
|---|---|---|---|---|
| conversation | R | R | W·assign·close | R |
| message | R | R | R·send | R |
R xem · W tạo/sửa. Đợt đầu TUYEN_SINH thấy tất cả hội thoại; data-scope assigned_to = ctx.current_employee_id giai đoạn sau (plan data-scope).