Ruang tunggu yang penuh, pelanggan yang bertanya "sudah nomor berapa?" setiap lima menit, dan petugas yang memanggil nama dengan suara keras adalah tanda alur layanan belum tertata. Masalahnya bukan hanya kenyamanan: pelanggan yang menunggu tanpa kepastian lebih mudah pergi ke tempat lain. Artikel ini membahas cara merancang sistem antrian digital yang sederhana namun andal, baik Anda pemilik usaha yang ingin memilih solusi maupun developer yang akan membangunnya.
Komponen Sistem Antrian Digital
Sistem antrian yang lengkap biasanya punya lima bagian:
- Pengambilan nomor: lewat kios/tablet di lokasi, halaman web dari ponsel (misalnya dengan memindai kode QR di pintu), atau pendaftaran oleh petugas.
- Pemanggilan: petugas loket menekan tombol "panggil berikutnya" dan sistem memberi nomor berikutnya sesuai urutan dan jenis layanan.
- Layar display: TV atau monitor di ruang tunggu yang menampilkan nomor yang sedang dilayani di setiap loket, idealnya dengan suara panggilan.
- Notifikasi: pesan ke ponsel pelanggan saat gilirannya tinggal beberapa nomor lagi, sehingga mereka bisa menunggu di luar.
- Statistik: rata-rata waktu tunggu, rata-rata waktu layanan, dan jam tersibuk.
Tidak semua usaha butuh kelima-limanya sejak awal. Bengkel kecil dengan satu mekanik mungkin cukup dengan pengambilan nomor dan layar display. Klinik dengan beberapa poli butuh pemisahan jenis layanan dan statistik.
Memilih Jenis Solusi
| Pilihan | Kelebihan | Kekurangan | Cocok untuk |
|---|---|---|---|
| Mesin tiket fisik + display | Familiar, tidak perlu ponsel | Biaya perangkat dan kertas, sulit dianalisis | Kantor layanan dengan pengunjung beragam usia |
| Aplikasi antrian SaaS | Cepat dipakai, tanpa server sendiri | Biaya bulanan, data di pihak lain, kustomisasi terbatas | Usaha yang ingin mulai minggu ini |
| Aplikasi web sendiri | Bisa disesuaikan, terhubung dengan data pasien atau pelanggan | Butuh developer dan hosting | Klinik, bengkel, atau usaha yang sudah punya sistem lain |
| Antrian via WhatsApp | Pelanggan tidak perlu instal apa pun | Butuh API WhatsApp resmi, rawan kacau jika manual | Layanan dengan janji temu |
Kriteria memilih yang paling sering terlupa adalah integrasi. Jika nomor antrean klinik tidak tersambung ke data pasien, petugas tetap harus mengetik ulang identitas pasien di sistem lain.
Merancang Alur Sebelum Membuat Aplikasi
- Tentukan jenis layanan. Contoh di bengkel: "Servis Ringan" (kode A), "Servis Berat" (kode B), "Kasir/Pengambilan" (kode C). Setiap jenis punya urutan nomor sendiri.
- Tentukan loket dan layanan yang bisa ditangani. Loket 1 bisa melayani A dan B, loket 2 hanya C. Ini menentukan logika "panggil berikutnya".
- Tetapkan status antrean. Minimal: waiting, called, serving, done, skipped.
- Atur aturan nomor yang dilewati. Apakah pelanggan yang tidak hadir saat dipanggil bisa dipanggil ulang? Berapa kali?
- Tentukan kapan nomor direset. Umumnya setiap hari, sehingga nomor kembali ke A-001.
Desain Tabel Database
Struktur minimal untuk aplikasi antrian bisa seperti ini:
services : id, code (A/B/C), name, avg_minutes
counters : id, name, is_active
counter_service : counter_id, service_id
tickets : id, service_id, number, queue_date, status,
counter_id (nullable), customer_phone (nullable),
called_at, served_at, finished_at, created_at
UNIQUE (service_id, queue_date, number)
Kolom waktu (called_at, served_at, finished_at) adalah bahan statistik, jadi jangan diabaikan. Untuk prinsip merancang relasi seperti ini, lihat merancang ERD sederhana untuk aplikasi.
Mengambil Nomor Tanpa Bentrok di Laravel
Bug paling umum pada aplikasi antrian buatan sendiri adalah dua pelanggan mendapat nomor yang sama karena menekan tombol pada detik yang sama. Penyebabnya: aplikasi membaca nomor terakhir, menambah satu, lalu menyimpan, tanpa penguncian. Solusinya adalah transaksi database dengan lockForUpdate ditambah unique index sebagai pengaman terakhir.
use App\Models\Service;
use App\Models\Ticket;
use Illuminate\Support\Facades\DB;
public function take(Service $service): Ticket
{
return DB::transaction(function () use ($service) {
// Kunci baris layanan agar permintaan lain menunggu giliran
Service::whereKey($service->id)->lockForUpdate()->first();
$last = Ticket::where('service_id', $service->id)
->whereDate('queue_date', today())
->max('number');
return Ticket::create([
'service_id' => $service->id,
'queue_date' => today(),
'number' => ($last ?? 0) + 1,
'status' => 'waiting',
]);
}, attempts: 3);
}
Logika "panggil berikutnya" mirip: dalam transaksi, ambil tiket waiting paling awal untuk layanan yang bisa ditangani loket itu dengan lockForUpdate(), lalu ubah statusnya menjadi called dan isi counter_id serta called_at. Tanpa kunci, dua loket bisa memanggil pelanggan yang sama.
Layar Display dan Suara Panggilan
Untuk layar ruang tunggu ada dua pendekatan. Yang paling sederhana adalah halaman yang meminta data terbaru setiap 3-5 detik (polling) lewat endpoint JSON. Untuk satu lokasi dengan beberapa loket, cara ini sudah memadai dan mudah dirawat. Jika ingin pembaruan instan, gunakan broadcasting Laravel dengan Laravel Reverb atau layanan seperti Pusher sehingga layar menerima event begitu tombol panggil ditekan.
Suara panggilan bisa memakai Web Speech API bawaan browser (speechSynthesis) dengan bahasa id-ID, atau file audio rekaman untuk setiap angka yang dirangkai. Rekaman manusia terdengar lebih jelas, tetapi butuh waktu menyiapkan. Perhatikan juga bahwa browser biasanya memblokir suara otomatis sampai ada interaksi pengguna, jadi siapkan tombol "aktifkan suara" yang ditekan sekali saat layar dinyalakan pagi hari.
Notifikasi dan Estimasi Waktu Tunggu
Estimasi sederhana: jumlah orang di depan dikali rata-rata durasi layanan, dibagi jumlah loket aktif. Misalkan ada 6 orang di depan, rata-rata layanan 8 menit, dan 2 loket aktif, maka estimasinya sekitar 24 menit. Tampilkan sebagai rentang ("sekitar 20-30 menit"), bukan angka pasti, karena durasi layanan selalu bervariasi. Rata-rata durasi sebaiknya dihitung dari data 2-4 minggu terakhir, bukan diisi manual.
Notifikasi "giliran Anda tinggal 3 nomor lagi" dapat dikirim lewat WhatsApp resmi, SMS, atau Telegram. Kirim dari job antrean agar tombol panggil tidak melambat. Pendekatannya dijelaskan di Queue dan Job di Laravel.
Statistik yang Benar-Benar Berguna
- Waktu tunggu =
called_atdikurangicreated_at. Pantau rata-rata dan nilai tertinggi per jam. - Waktu layanan =
finished_atdikurangiserved_at, per jenis layanan dan per loket. - Tingkat lewat = persentase tiket berstatus skipped. Jika tinggi, mungkin estimasi waktu terlalu lama sehingga pelanggan pergi.
- Distribusi per jam = jumlah tiket per jam dalam seminggu, untuk menentukan kapan perlu loket tambahan.
Dari data ini, keputusan operasional jadi lebih mudah, misalnya membuka loket kedua hanya pada jam 09.00-11.00 dan menutupnya di siang hari.
Kesalahan Umum
- Nomor ganda karena tidak ada penguncian. Perbaikan: transaksi,
lockForUpdate, dan unique index. - Display mati saat internet putus. Jika server di cloud, siapkan cadangan koneksi atau pertimbangkan server lokal untuk lokasi dengan internet tidak stabil.
- Tidak ada jalur prioritas. Lansia, ibu hamil, atau pelanggan dengan janji temu butuh aturan sendiri; buat jenis layanan terpisah alih-alih menyerobot urutan secara manual.
- Petugas lupa menekan "selesai" sehingga statistik waktu layanan rusak. Perbaikan: tombol "panggil berikutnya" otomatis menyelesaikan tiket sebelumnya di loket itu.
Checklist Peluncuran
- Uji pengambilan nomor serentak dari beberapa perangkat sekaligus.
- Layar display terbaca dari kursi paling belakang.
- Suara panggilan terdengar jelas dan sudah diaktifkan di browser.
- Petugas sudah dilatih untuk panggil, panggil ulang, lewati, dan selesai.
- Ada prosedur cadangan (nomor kertas) bila listrik atau internet padam.
- Reset nomor harian berjalan otomatis.
Sistem antrian biasanya menjadi pintu masuk ke digitalisasi yang lebih luas, misalnya rekam data pelanggan atau kasir. Jika Anda ingin mempercepat pembangunannya, source code aplikasi layanan berbasis Laravel di GudangCode bisa dipelajari sebagai titik awal.