Plan chưa ký — CRM follow-up tự động

Bác sĩ lập kế hoạch điều trị (treatment plan) ở status DRAFT, in phiếu tư vấn cho bệnh nhân. Bệnh nhân về suy nghĩ. Sau 3 ngày vẫn không quay lại ký hợp đồng (accept plan). Hệ thống tự động phát hiện và tạo task customer-care để team gọi theo dõi.

Giao diện timeline plan chưa ký
Timeline: BS tạo plan DRAFT → in phiếu tư vấn → ngày thứ 3 → task auto-create → CC gọi BN → outcome logging

Bối cảnh

Kế hoạch điều trị (plan) ban đầu ở trạng thái DRAFT — nó là một bản quote, chưa phát sinh charge hoặc warranty. Khi bệnh nhân ký (accept), plan chuyển sang APPROVED, lúc này mới sinh charge và warranty. Nếu bệnh nhân chưa ký mà ngày trôi qua, phòng khám mất cơ hội doanh thu.

Diễn viên & quyền cần

Vai tròQuyền cầnNhiệm vụ
Bác sĩdiagnosis.manage, treatment_plan.manageTạo plan DRAFT, in phiếu tư vấn
Scheduler/BullMQ(hệ thống)Chạy job mỗi ngày → phát hiện plan DRAFT quá X ngày chưa accept → tạo task với key idempotent (CI-06)
Customer Carecustomer_care.manage, treatment_plan.readMở queue, gọi BN, ghi outcome (accepted / rejected / reschedule)
Lễ tântreatment_plan.readHỗ trợ when BN quay lại, accept plan

Quy trình từng bước

  1. Bác sĩ lập plan:
    • Mở Patient 360 → tab Treatment → click "Tạo plan mới"
    • Thêm services, set giá, assign doctor per stage
    • Lưu → plan trở thành DRAFT
  2. In phiếu tư vấn:
    • Từ plan detail → nút "In phiếu tư vấn (KHĐT)" → hiển thị form in A4
    • Phiếu tư vấn chứa: thông tin BN, dịch vụ, giá, doctor, chữ ký → bệnh nhân mang về suy nghĩ
  3. Chờ accept (ngày 1-3):
    • Bệnh nhân qua nhà, xem phiếu, suy nghĩ
    • Plan vẫn ở DRAFT → không phát sinh charge hoặc warranty
  4. Ngày thứ 3+: Job scheduler chạy (CI-06 idempotent):
    • BullMQ repeatable scheduler (không @nestjs/schedule) chạy mỗi 4 giờ hoặc ngày một lần
    • Query: "Mọi plan DRAFT thuộc clinic này, branch này, tạo từ > 3 ngày trước"
    • Per mỗi plan: check dedupe key = (clinicId, branchId, planId, reason="follow_up_draft_unaccepted")
    • Nếu key chưa tồn tại → create task customer-care với title "Plan chưa ký — BN cần nhắc", amountAtRisk = plan total
    • Nếu key đã tồn tại → skip (idempotent — không tạo duplicate)
  5. Customer Care gọi BN:
    • Mở Customer Care queue → filter by "Unaccepted plan" hoặc sắp xếp theo amountAtRisk
    • Click task → mở Patient 360 + plan chi tiết
    • Gọi BN: "Em có nhận được phiếu tư vấn không ạ? Có câu hỏi gì không em?"
  6. Ghi outcome:
    • Nếu BN ký plan: Lễ tân / BS mở plan → click "Accept" → plan chuyển APPROVED, phát sinh charge + warranty
    • Nếu BN từ chối: CC ghi outcome "Rejected" → plan chuyển REJECTED, task close
    • Nếu BN hẹn lại: CC set next follow-up date → task reschedule tự động
  7. Task close:
    • Ngay sau khi plan accept / reject / reschedule → task chuyển "RESOLVED"
    • Customer Care timeline ghi lại outcome, ngày, người thực hiện

Kết quả mong đợi

  • Plan DRAFT không ký hơn X ngày → tự động có task follow-up (không phải BS hay lễ tân gọi nhớ)
  • Customer Care team chỉ cần mở queue, xử lý task một cách có hệ thống
  • Sau khi BN accept → plan chuyển APPROVED, charge và warranty phát sinh
  • Outcome được ghi audit → tracking recovery rate & task effectiveness
  • Dashboard Customer Care hiển thị "X plan chưa ký đang đợi follow-up"

Khi nào hỏng & cách xử lý

Vấn đềNguyên nhânCách checkCách fix
Task duplicate xuất hiện 2 lần cho cùng 1 planJob chạy 2 lần trước khi dedupe key flush vào DBCheck Customer Care queue, filter plan IDDedupe logic bảo đảm key = (clinicId, branchId, planId, reason) unique; thử manual re-run job hoặc wait for next flush
Job không chạy — task không tự tạo ngày thứ 3Scheduler down, hoặc cron expression saiKiểm tra app logs: "BullMQ scheduler started", "Customer care task enqueued"Khởi động lại worker role (APP_ROLES=worker); check cron format; xem BullMQ admin panel (if enabled)
Plan accepted nhưng task vẫn openCache invalidation chậm (CI-04)Refresh Customer Care queue, hoặc wait 30 giâyTask sẽ auto-close sau khi cache invalidate; nếu stuck, CC manual mark "RESOLVED"
BN không nhận phiếu tư vấn in ra (sơ suất in)BS quên in, hoặc máy in lỗiMở Patient 360 → plan detail → kiểm tra "Phiếu tư vấn đã in?"Lễ tân in lại từ plan detail hoặc phiếu tra cứu công khai URL

Dấu vết để lại (audit & branch ownership)

Branch ownership (CI-01): Task được tạo với source branch = plan's source branch (từ visit gốc hoặc plan creation point), không phải active UI branch. Khi BN chuyển chi nhánh, timeline vẫn ghi đúng chi nhánh gốc.

Audit trail:

  • Plan create log: doctor, time, initial status DRAFT
  • Task auto-create log: scheduler job, time, dedupe key
  • Task outcome log: CC action, time, outcome type (accepted / rejected / reschedule)
  • Plan status change log: from DRAFT → ACCEPTED (hoặc REJECTED), time, actor
  • Charge auto-create log (khi plan accept): time, amount, stage breakdown
Idempotency (CI-06)

Job scheduler là multi-worker safe. Nếu 2 worker cùng chạy job một lúc, dedupe key (clinicId, branchId, planId, reason) đảm bảo chỉ 1 task được tạo. Retry logic tự động không làm duplicate task — đây là bảo vệ chính của hệ thống CRM.