Booking — dari Gratis ke Berbayar
Perubahan alur paling besar di sistem.
❌ Alur LAMA
AI memanggil create_appointment → janji temu langsung dibuat. Selesai.
| Karakteristik alur lama | |
|---|---|
| Objek yang dibuat | Appointment langsung |
| Biaya | Gratis |
| Jumlah langkah | 1 |
| Tabel yang terlibat | appointments |
| Konfirmasi ke pasien | Ditulis AI sendiri |
Masalahnya
✅ Alur BARU
create_appointment tidak lagi meng-insert Appointment. Ia membuat draft + link pembayaran; janji temu sungguhan lahir setelah callback Duitku menyatakan lunas.
| Karakteristik alur baru | |
|---|---|
| Objek yang dibuat pertama | BookingRequest (draft) + Billing + Payment |
| Biaya | DUITKU_RESERVATION_FEE (default Rp25.000) |
| Jumlah langkah | 2 (terbitkan link → konfirmasi lunas) |
| Tabel yang terlibat | booking_requests, billings, payments, appointments |
| Konfirmasi ke pasien | Template tetap di kode, bukan AI |
Perbandingan berdampingan
| Aspek | Lama | Baru |
|---|---|---|
| Kapan jadwal dikunci | Seketika | Setelah pembayaran diterima |
| Tool tambahan | — | check_payment_status |
| Validasi jadwal | Format saja | Format + harus masa depan + anti-penggulungan Carbon |
| Kalau pasien tidak jadi | Janji temu menggantung | Draft otomatis Expired setelah expiry_minutes |
| Kalau pasien minta ganti jadwal | Janji temu kedua | Draft lama → Cancelled, terbit link pengganti |
| Kalau link hilang | — | check_payment_status mengirim ulang link yang sama |
| Kalau uang masuk tapi janji temu gagal | Tidak mungkin terjadi | Draft → Failed, pasien dikabari tindak lanjut manual, ops menindaklanjuti |
| Jaring pengaman | — | Sapuan bookings:reconcile tiap 5 menit |
Yang ikut berubah karena perubahan ini
Deskripsi tool ikut berubah
Lama:
"Buat janji temu untuk pelanggan yang sedang chat."
Baru:
"Mulai booking janji temu untuk pelanggan yang sedang chat. Booking memerlukan biaya reservasi, jadi tool ini TIDAK langsung membuat janji temu: ia mengembalikan
payment_urlyang harus dibayar pelanggan lebih dulu. Janji temu otomatis terkonfirmasi setelah pembayaran diterima. Nominal biaya ditentukan sistem."
Perubahan ini penting karena deskripsi tool adalah satu-satunya cara memberi tahu model bahwa janji temu belum berlaku.
Mode simulator ikut menyesuaikan
| Lama | Baru | |
|---|---|---|
| Pesan | [SIMULASI] akan membuat janji temu dengan {dokter} di {poli} pada {tgl} {jam}. | [SIMULASI] akan membuat link pembayaran reservasi Rp{tarif} untuk janji temu ... Janji temu dikonfirmasi setelah pembayaran diterima. |
| Link | — | https://simulasi.duitku.local/pay/CONTOH (jelas ditandai simulasi) |
| Menyentuh Duitku | Tidak | Tidak |
| Menyentuh database | Tidak | Tidak |
Link simulasi disertakan supaya admin bisa melihat bagaimana AI menyalin payment_url ke balasannya sebelum fitur dinyalakan untuk pasien sungguhan.
Konsekuensi yang diterima secara sadar
Cancelled dan Expired sengaja bukan status terminal di confirmPaid(), karena link lama masih benar-benar bisa dibayar di Duitku sampai kedaluwarsa. Jadi pasien yang membayar dua link akan mendapat dua janji temu.
Ini dirapikan manual oleh ops — jauh lebih murah daripada pasien membayar tanpa mendapat jadwal.
Pasien yang membayar sebuah link lalu memesan janji temu kedua dalam jendela expiry_minutes yang sama tidak menerima pemberitahuan kedaluwarsa untuk booking kedua itu (aturan paidSiblingFor).
Yang hilang cuma satu pengingat, bukan uang atau jadwal — jauh lebih murah daripada memberi tahu pasien yang sudah lunas bahwa jadwalnya belum terkunci.
Membaca data historis
Kalau Anda melihat data dari periode alur lama:
| Yang Anda lihat | Artinya |
|---|---|
Appointment tanpa BookingRequest terkait | Dibuat di era alur lama, atau dibuat manual petugas, atau hasil SIMRS Sync |
Payment tanpa BookingRequest | Reservasi manual dari Chat Rooms (masih berlaku sampai sekarang) |
BookingRequest dengan payment_url kosong | Draft dibuat sebelum kolom itu ada — check_payment_status sengaja menghilangkan kuncinya, bukan mengisi string kosong |