Kontak — dari Manual ke Real-time + Terjadwal
❌ Alur LAMA
Sinkronisasi kontak hanya bisa dijalankan manual lewat tombol di halaman Kontak.
Masalahnya
✅ Alur BARU
Tiga hal ditambahkan sekaligus: real-time, terjadwal, dan riwayat lintasan.
Perbandingan berdampingan
| Aspek | ❌ Lama | ✅ Baru |
|---|---|---|
| Pemicu | Hanya tombol manual | Webhook (real-time) + cron 10 menit + tombol manual |
| Kecepatan nomor baru muncul | Menunggu ada yang menekan tombol | Seketika saat pesan pertama masuk |
| Bisa dimatikan per-lingkungan | — | ✅ WHATSAPP_CONTACT_SYNC_ENABLED |
| Kadens bisa diubah | — | ✅ WHATSAPP_CONTACT_SYNC_CRON |
| Riwayat lintasan | ❌ Tidak ada | ✅ Tabel contact_sync_runs |
| Info "sinkron terakhir" | ❌ Tidak ada | ✅ Di subheading halaman Kontak, merah bila gagal |
| Aturan penamaan | Satu jalur | Dipakai bersama dua jalur lewat record() |
| Konfigurasi belum siap | Error | Keluar sukses, tidak mencatat lintasan |
Tiga keputusan desain
1. Kegagalan pencatatan kontak tidak boleh menjatuhkan job
Pesannya sudah tersimpan dan balasan otomatis jauh lebih penting daripada satu baris kontak — yang toh akan disusul sapuan berikutnya.
2. Riwayat lintasan disimpan di database, bukan cache
optimize:clear dijalankan setiap deploy. Kalau riwayat lintasan disimpan di cache, jejaknya hilang setiap kali aplikasi diperbarui — persis pada saat orang paling ingin memastikan sinkronisasi masih hidup.
3. Konfigurasi belum siap ≠ kegagalan
Tanpa pembedaan ini, cron akan merah setiap sepuluh menit di lingkungan yang memang belum punya akun Jasnita, dan halaman Kontak penuh baris "gagal" yang tidak berarti apa-apa.
Aturan penamaan dipusatkan
Kedua jalur memakai ContactSyncService::record() yang sama, sehingga aturannya identik:
platform null berarti "jangan sentuh"Webhook pesan masuk tidak tahu channel apa yang dipakai kontak itu di ChatPanel, jadi ia tidak boleh menebaknya. Kontak baru memakai default whatsapp_cloud; kontak yang sudah ada mempertahankan platform yang tercatat.
Kalau aturannya tidak dipusatkan, jalur webhook bisa menimpa nama yang sudah diedit petugas sementara jalur sapuan tidak — atau sebaliknya. Itu jenis inkonsistensi yang sangat sulit dilacak.
Yang tampil di halaman Kontak sekarang
| Kondisi | Yang ditampilkan |
|---|---|
| Lintasan terakhir sukses | "Sinkron terakhir 18:40 WIB (3 menit lalu, otomatis)" |
| Lintasan terakhir gagal | Versi merah dengan keterangan gagal |
| Belum pernah sinkron | Tidak ada keterangan waktu |
Tombol manual tetap ada sebagai jalan keluar bila otomatisnya macet — dan karena ia lewat ContactSyncRunner yang sama, klik manual ikut memperbarui waktu tersebut.
Fitur pendamping: ekspor Excel
Ditambahkan bersamaan: halaman Kontak bisa mengekspor daftar kontak ke Excel (ContactExcelExporter). Berguna untuk pelaporan dan blast di luar sistem.
Tombol hapus kontak juga dilepas dari panel — sejalan dengan prinsip yang sama pada akun WhatsApp: menghapus baris membuang lebih banyak daripada yang diinginkan.