Desain Sistem · Arsitektur · Design System · Prototipe
ApotekHijau — kasir apotek yang tetap jalan saat internet mati
Point of Sale untuk apotek Indonesia: offline-first, sadar interaksi obat, paham stok pecahan sampai butir tablet, dan berbicara HL7 FHIR R4 ke SATUSEHAT, KFA, serta BPJS.
Apotek tidak menjual "produk", ia menyerahkan dosis. Pasien membeli ½ strip, apoteker meracik 1½ tablet per bungkus, dan stok harus tetap benar. Karena itu satuan penyimpanan sistem ini bukan strip melainkan butir tablet — dan seluruh harga, stok, racikan, serta laporan diturunkan dari satu angka itu.
Keputusan kedua: kasir apotek bekerja di layar sentuh dengan tangan sibuk dan koneksi tidak menentu. Maka tidak ada keyboard bawaan (semua lewat keypad kustom), dan tidak ada layar yang menunggu jaringan — transaksi selesai di lokal, sinkronisasi menyusul.
1 strip = 10
butir tablet sebagai satuan atom penyimpanan
0 ms
ketergantungan jaringan untuk menyelesaikan transaksi
7 mesin
aturan inti yang menjaga keselamatan & pembukuan
Coba di sini · model stok atom
Blister Paracetamol 500 mg
Ketuk butiran untuk menjual eceran. Angka di bawah adalah cara sistem menyimpan dan menampilkan stok.
116 striptampilan kasirst = 1160 tab
Stok awal: 116 strip utuh. Menjual 3 butir membuat satu strip “terbuka”.
Masalah yang dipecahkan
Empat kondisi nyata di apotek yang membuat kasir ritel biasa gagal dipakai.
01 Obat bisa saling melawan
Ibuprofen bersama Aspirin menaikkan risiko perdarahan lambung. Dua produk berbeda bisa memuat parasetamol yang sama hingga dosis harian terlampaui. Kasir tidak boleh menjadi satu-satunya penjaga; sistem harus mengingatkan saat barang masuk keranjang, bukan setelah struk tercetak.
02 Yang dibeli sering bukan satu kemasan
"Beli paracetamol 5 butir saja" adalah transaksi normal. Begitu pula racikan puyer dengan ½ atau 1½ tablet per bungkus. Stok yang disimpan per strip akan langsung salah pada transaksi pertama.
03 Obat keras tidak boleh lepas tanpa resep
Golongan Keras dan pelayanan BPJS punya syarat administratif yang wajib lengkap. Sistem harus menolak, bukan sekadar memperingatkan, dan menawarkan jalan yang benar.
04 Internet apotek tidak bisa diandalkan
Kewajiban lapor ke SATUSEHAT tidak boleh menghentikan pelayanan. Transaksi harus tuntas di perangkat, lalu diantrekan dan dikirim ulang otomatis dengan jejak yang bisa diaudit.
Konsekuensi desain. Empat kondisi di atas melahirkan tujuh mesin aturan di tab Mesin Inti. Setiap mesin punya satu tanggung jawab dan bisa diuji terpisah — itulah alasan sistem ini dirancang sebagai kumpulan aturan, bukan kumpulan formulir.
Prinsip perancangan
Lima aturan yang dipakai untuk memutuskan saat ada pilihan yang saling bertentangan.
Prinsip
Penerapan konkret di produk
Keselamatan mendahului kecepatan
Interaksi obat dan duplikasi zat aktif diperiksa pada setiap penambahan item, bukan di akhir. Obat keras diblokir di jalur OTC, dengan satu ketukan untuk pindah ke jalur resep.
Lokal dulu, jaringan menyusul
Sumber kebenaran ada di perangkat. Sinkronisasi berupa antrean dengan status, percobaan ulang, dan tabel audit yang bisa dibuka petugas.
Satuan terkecil sebagai kebenaran
Stok disimpan dalam butir. Strip hanyalah cara menampilkan. Pecahan tablet selalu dibulatkan ke atas untuk stok dan harga, dan pembulatan itu ditampilkan terbuka.
Tidak ada uang yang berpindah tanpa jejak
Laci dicatat bruto–kembalian–net, bukan hanya net. Buku kas, selisih penutupan, dan klaim non-tunai dipisahkan.
Satu tangan, layar sentuh
Semua masukan lewat keypad kustom dan pemilih ber-pencarian. Tidak ada dropdown bawaan, tidak ada keyboard OS yang menutupi setengah layar.
Peran & hak akses
Sistem dipakai tiga peran dengan kewenangan berbeda; back-office terpisah dari kasir.
🩺 Apoteker (APA) SIPA
Buka / tutup shiftpenuh
Layani resep & racikanpenuh
Konfirmasi interaksi obatwajib
Serah obat keras / OWApenuh
👤 TTK / Kasir STRTTK
Transaksi OTCpenuh
Racikanbutuh apoteker
Kas masuk / keluardengan catatan
Tutup shifthitung kas wajib
🗂️ Back-office CRUD
Master obat & hargasumber KFA
Paket obatkurasi
Master signaetiket
Aturan interaksikurasi apoteker
Kasir mengunci diri sendiri saat shift tertutup: seluruh penambahan item, pembayaran, dan pelanjutan pesanan diblokir sampai ada modal awal kas yang tercatat. Ini membuat setiap rupiah punya pemilik shift.
Peta layar
Enam layar tetap plus satu layar yang hanya muncul bila mode debug dinyalakan. Navigasi memakai bilah bawah pada ponsel dan rail samping pada tablet.
🧾 Kasir
Jalur utama transaksi. Pemilih jenis penjualan, paket siap jual, pencarian, grid obat dengan stok & tombol eceran, tombol racik, dan keranjang.
gerbang jenisgerbang obat keraseceran ½ stripbuilder racikankunci shift
💊 Obat
Master obat hasil sinkron KFA: komposisi zat aktif sebagai chip, kode KFA, golongan, harga strip & eceran, stok, dan daftar interaksi yang diketahui.
cari zat aktifdetail + FHIR idefek kombinasi
📦 Paket
Bundel racikan back-office (Paket Flu, Maag, Diare…) dengan rincian isi, penghematan, dan pemeriksaan keamanan kombinasi.
jual satu ketukancek interaksi paket
📥 Pesanan
Satu antrean untuk tiga sumber: draft kasir, pesanan online/WhatsApp, dan resep digital SATUSEHAT. Bendera warna + filter berhitung.
flag sumberfilterlanjutkan ke keranjang
🔁 Shift
Buka/tutup shift, buku kas, dan laporan. Riwayat shift berpaginasi; ketuk untuk detail berisi ringkasan kas dan transaksi shift itu (paginasi kedua) dengan tombol kembali.
bruto → kembalian → netselisih kasdrill-down
⚙️ Setelan
Tema, status integrasi SATUSEHAT/KFA/FHIR, sinkron otomatis, dan sakelar mode debug.
temastatus integrasisakelar debug
🐞 Debug bersyarat
Muncul hanya bila mode debug aktif. Tabel antrean sinkron berpaginasi dengan filter status, arah push/pull, jumlah percobaan, dan ukuran payload; plus simulasi offline dan pemicu data masuk.
audit sinkronsimulasi offlinekirim antrean
Arsitektur lapis
Empat lapis dengan satu aturan keras: lapis aplikasi tidak pernah memanggil jaringan secara langsung. Semua keluar-masuk data melalui antrean sinkron.
Antarmuka kasirLapis 1 · perangkat
Layar sentuh apotek: ponsel portrait sampai tablet. Menyusun tampilan dari state lokal dan tidak pernah menunggu balasan server.
ketuk obat
│
├─ gerbang_jenis OTC / Resep / BPJS sudah dipilih? ──tidak──▶ minta pilih jenis
├─ gerbang_keras golongan Keras di jalur OTC? ──ya────▶ tawarkan pindah ke Resep
├─ stok_atom tersedia ≥ kebutuhan butir? ──tidak──▶ tolak / sarankan eceran
├─ interaksi_obat ada interaksi / duplikasi baru? ──ya────▶ konfirmasi apoteker
│
▼
keranjang ──▶ kas_laci hitung bruto/kembalian/net ──▶ simpan lokal
│
┌────────────────────────────────────────┴───────────┐
▼ ▼
potong stok butirantrean_sinkron (pending)
catat mutasi ke layar sukses MedicationDispense · InventoryReport
+ Claim (BPJS) · MedicationRequest (resep)
Kenapa antrean, bukan panggilan langsung. Dengan antrean, kegagalan jaringan menjadi kondisi normal yang punya status dan tombol coba-lagi — bukan kesalahan yang membatalkan transaksi. Petugas melihat sendiri berapa data yang belum terkirim.
Model data
Sembilan entitas inti. Perhatikan stok pada Obat: satuannya butir, bukan kemasan — di situlah seluruh ketelitian sistem bermula.
Obat Medication
id · kode_kfaidentitas
nama · bentuktampilan
zat_aktif[]kunci interaksi
golonganbebas…keras
harga_kemasanrupiah
stokbutir (atom)
satuan · isi_kemasanstrip = 10
Aturan Interaksi kurasi
zat_a · zat_bpasangan
tingkatberat/sedang/ringan
efekteks chip
sarantindakan apoteker
Paket back-office
nama · deskripsikurasi
item[]obat + jumlah
harga_paket< jumlah satuan
Racikan compound
namaetiket
bentukpuyer/kapsul/sirup
jumlahbungkus
komponen[]obat + dosis/bungkus
signadari master
jasa_racikrupiah
Baris Keranjang line
jenisobat/paket/racikan
satuankemasan / butir
jumlahsesuai satuan
Pesanan / Draft order
sumberkasir/online/resep
pasiennama + WA
jenis_penjualanotc/resep/bpjs
data_resepno · dokter · BPJS
isi[]baris keranjang
Shift PaymentRecon
petugas · buka · tutupjejak
kas_awalmodal
tunai_brutoditerima
kembaliandiserahkan
qris · bpjsnon-laci
kas_aktual · selisihhitung fisik
Transaksi MedDispense
nomor · waktuidentitas
jenis_penjualanotc/resep/bpjs
metodetunai/qris/bpjs
tunai_diterimabruto
kembaliankeluar laci
mutasi_stok[]butir per obat
catatan_interaksiaudit klinis
Antrean Sinkron queue
id_lokalidempotensi
entitas · resourceFHIR
arahpush / pull
status4 keadaan
percobaan · ukuranaudit
Aturan turunan. Harga eceran per butir = harga kemasan ÷ isi kemasan, dibulatkan ke Rp100 agar tidak muncul pecahan rupiah yang tak bisa dibayar. Konversi tampilan stok: strip = ⌊butir ÷ 10⌋, sisa ditampilkan sebagai tablet lepas.
Mesin sinkronisasi
Empat status, dua arah, dan satu prinsip: kegagalan tidak pernah menghalangi pelayanan.
STATUS pending ──kirim──▶ synced
│
├──gagal──▶ failed ──coba ulang otomatis──▶ pending
└──versi server lebih baru──▶ conflict ──▶ tinjauan petugas
ARAH push ⬆ transaksi · stok · klaim BPJS · penyelesaian resep
pull ⬇ master obat (KFA) · harga · resep digital · pesanan online
PEMICU (1) selesai transaksi → antrekan otomatis
(2) timer berkala → kirim antrean saat online
(3) tombol manual → "Kirim antrean" di layar Debug
(4) kembali online → antrean dikirim menyusul
Idempotensi
Setiap baris antrean membawa id_lokal yang dikirim sebagai identifier. Pengiriman ulang setelah timeout tidak menciptakan penyerahan obat ganda di SATUSEHAT.
Urutan yang dijaga
Penyelesaian resep tidak boleh terkirim sebelum penyerahan obatnya. Antrean karena itu diproses berdasarkan urutan pembuatan per entitas, bukan paralel bebas.
Konflik data master
Master obat dan harga selalu pull — perangkat tidak pernah menang. Jika harga berubah setelah transaksi terjadi, transaksi tetap memakai harga saat penjualan dan perbedaan itu terlihat di audit.
Yang dilihat petugas
Lencana di kepala layar: Tersinkron, n antre sinkron, atau Offline · n antre. Satu ketukan membuka tabel audit lengkap.
Simulasi antrean offlineinteraktif
● tersinkron · 0 antre
ID
Entitas
Resource FHIR
Arah
Status
Coba
Matikan koneksi, lalu buat beberapa transaksi — pelayanan tetap jalan dan antrean menumpuk dengan status pending.
Mesin 1 · Interaksi & duplikasi zat aktif
Mesin klinis paling penting. Bekerja pada level zat aktif, bukan nama produk — sehingga tetap menangkap bahaya walau pasien membeli merek berbeda.
Cara kerja
Ratakan keranjang. Paket diurai jadi obat penyusunnya; racikan diurai jadi komponennya. Hasilnya satu daftar zat aktif beserta produk asalnya.
Cari pasangan berbahaya. Setiap aturan interaksi diuji terhadap daftar itu; kecocokan hanya dihitung bila kedua zat berasal dari produk berbeda.
Cari duplikasi. Satu zat aktif yang muncul dari dua produk berbeda ditandai berat — inilah penyebab overdosis parasetamol yang paling sering terjadi.
Bandingkan sebelum & sesudah. Yang dikonfirmasi ke apoteker hanya temuan baru akibat item yang sedang ditambahkan, supaya tidak ada peringatan berulang.
Titik pemunculan
Kapan
Bentuk
Sebelum item masuk
Kartu obat diberi tanda ⚠ interaksi pada grid kasir
Saat item ditambahkan
Modal konfirmasi berisi chip temuan + saran; butuh persetujuan
Di keranjang
Panel ringkasan berat vs. perlu-perhatian, atau tanda aman
Saat meracik
Cek antar komponen langsung di dalam builder
Di master obat
Daftar interaksi yang diketahui pada detail obat
Setelah transaksi
Jumlah catatan interaksi tersimpan sebagai jejak audit klinis
Coba mesin interaksiinteraktifpilih beberapa obat seperti isi keranjang
Kenapa chip, bukan paragraf. Kasir membaca sambil melayani. Chip berwarna dengan tingkat keparahan di depan bisa dipindai dalam satu detik; penjelasan panjang diletakkan sesudahnya sebagai saran tindakan.
Mesin 2 · Stok atom & penjualan pecahan
Satu obat bisa terjual sebagai strip utuh, ½ strip, butiran lepas, bagian dari paket, atau komponen racikan — semuanya memotong stok yang sama.
PENYIMPANAN stok disimpan dalam butir 116 strip → st = 1160TAMPILAN ⌊st ÷ 10⌋ strip + sisa tab 1155 → "115 strip + 5 tab"HARGA ECERAN ⌈(harga_strip ÷ 10) ÷ 100⌉ × 100 Rp3.500 → Rp400 / butirKETERSEDIAAN tersedia = stok − seluruh butir yang sudah dipesan di keranjang
(baris strip · baris eceran · komponen paket · komponen racikan)
PECAHAN kebutuhan butir = ⌈dosis × jumlah⌉ 1½ tab → dibebankan 2 tab
pembulatan ditampilkan terbuka di builder racikan & layar sukses
Sebelum pembelian
Kartu obat menampilkan stok terbaca (116 strip) dan, untuk sediaan tablet, tombol +½ strip beserta harga per butir. Detail obat memuat harga kemasan, harga eceran, dan stok dalam dua satuan.
Saat pembelian
Eceran menjadi baris tersendiri: 5 tab (½ strip) · Rp400/tab, dengan stepper per butir. Strip dan eceran obat yang sama hidup berdampingan sebagai dua baris, dan lencana kartu menulis 1+5t.
Sesudah pembelian
Layar sukses menampilkan panel mutasi stok per obat: −16 tab → sisa 114 strip + 4 tab. Kelipatan sepuluh ditulis sebagai strip agar cocok dengan cara petugas menghitung fisik.
📋
Implikasi stok opname. Karena strip yang sudah dibuka tercatat sebagai butir lepas, penghitungan fisik gudang bisa dicocokkan persis: sistem tahu ada berapa strip utuh dan berapa butir terbuka.
Kalkulator stok & pembulataninteraktif
Dosis per bungkus:
× jumlah:
Mesin 3 · Gerbang jenis penjualan
Jenis transaksi ditentukan lebih dulu, karena ia mengubah obat apa yang boleh keluar, data apa yang wajib, dan siapa yang menagih.
item pertama ditambahkan
│
▼
jenis sudah dipilih? ──tidak──▶ modal pilih jenis ──▶ item tertunda ikut masuk otomatis
│ ya
▼
┌─────────────┬──────────────────────┬───────────────────────────────┐
│ OTC │ RESEP │ BPJS │
├─────────────┼──────────────────────┼───────────────────────────────┤
│ bebas ✓ │ semua golongan ✓ │ semua golongan ✓ │
│ terbatas ✓ │ no. resep wajib │ no. resep + dokter wajib │
│ OWA ✓ dicatat│ nama dokter wajib │ no. kartu BPJS wajib │
│ keras ditolak│ racikan ✓ │ racikan ✓ │
│ racikan ditolak│ bayar tunai/QRIS │ tagihan pasien Rp0 │
│ │ │ → terbit SEP + FHIR Claim │
└─────────────┴──────────────────────┴───────────────────────────────┘
penolakan selalu menawarkan jalan keluar: "Ganti ke Resep" (satu ketukan, item langsung masuk)
pindah balik ke OTC ditolak selama keranjang masih memuat obat keras
Coba gerbang penjualaninteraktif
Jenis:
Mesin 4 · Racikan
Racikan adalah produk yang dibuat saat itu juga: punya komposisi, bentuk sediaan, jumlah, aturan pakai, dan jasa peracikan.
Struktur builder
Nama racikan — keypad teks, dipakai di etiket dan struk.
Bentuk sediaan — puyer, kapsul, atau sirup; mengubah satuan (bungkus/kapsul/botol) dan tarif jasa racik.
Jumlah & jasa racik — keypad angka.
Aturan pakai (signa) — dipilih dari master, bukan diketik bebas, agar etiket konsisten.
Komponen — dicari lewat keypad, dosis diatur stepper pecahan ¼ / ½ / ¾ / 1.
Kenapa stepper, bukan keypad, untuk dosis. Pecahan tidak bisa diketik di papan angka tanpa memaksa kasir berpikir desimal. Stepper menghilangkan pengetikan sekaligus mencegah dosis tak lazim seperti 0,37 tablet.
Perhitungan & keamanan
butir dibebankan = ⌈dosis × jumlah⌉ per komponen
harga komponen = butir_dibebankan × harga_eceran
total racikan = Σ harga komponen + jasa racik
½ tab × 3 bungkus = 1½ tab → dibulatkan 2 tab
ditampilkan di builder sebagai peringatan oranye
Cek interaksi antar komponen berjalan langsung di dalam builder — dua NSAID dalam satu puyer langsung tertangkap.
Validasi stok per komponen sebelum simpan; saat mengedit racikan yang sudah di keranjang, reservasi lama dibebaskan dulu agar tidak menghitung ganda.
Signa wajib — racikan tanpa aturan pakai tidak boleh masuk keranjang.
Di keranjang, racikan tampil sebagai kartu dengan komposisi dan tombol Edit, bukan stepper jumlah.
Mesin 5 · Kas laci & kembalian
Uang fisik bergerak dua arah dalam satu transaksi. Mencatat hanya nilainya membuat selisih kas mustahil ditelusuri.
total Rp45.000 · pelanggan bayar Rp100.000
laci ⬅ masuk +Rp100.000 (tunai_bruto)
laci ➡ keluar −Rp55.000 (kembalian)
────────────────────────────────
net = +Rp45.000 (= penjualan tunai)
kas laci seharusnya = kas_awal + net tunai + kas masuk lain − kas keluar
selisih = kas aktual dihitung − kas laci seharusnya
QRIS & BPJS dicatat terpisah sebagai non-laci: menambah omzet, tidak menambah uang fisik.
Simulasi kembalianinteraktif
Total:Dibayar:
Layar sukses menampilkan kembalian dalam ukuran besar plus saran pecahan uang (1 × Rp50.000, 1 × Rp5.000) — mengurangi salah serah pada jam ramai, dan mempercepat kasir baru.
Mesin 6 & 7 · Shift dan antrean pesanan
6 Siklus shift
tertutup ──buka (modal awal wajib)──▶ berjalan
▲ │
│ transaksi · kas masuk/keluar
│ │
└──tutup (hitung kas fisik wajib)──────┘
│
├─ bekukan laporan → riwayat
└─ antrekan PaymentReconciliation
Saat tertutup, kasir tertutup lapisan kunci: menambah item, membayar, dan melanjutkan pesanan semuanya diblokir. Riwayat shift berpaginasi; ketuk untuk melihat ringkasan kas dan daftar transaksi shift tersebut yang juga berpaginasi.
7 Antrean pesanan tiga sumber
🏪 draft kasir simpan keranjang berjalan
🌐 online/WA masuk sebagai CommunicationRequest
🩺 resep SATUSEHAT masuk sebagai MedicationRequest
│
▼
satu antrean · bendera warna + filter berhitung
│
"Lanjutkan / Proses / Layani"
│
▼
keranjang terisi + jenis penjualan & data pasien
ikut dipulihkan (resep berkartu → langsung BPJS)
Bila kasir sedang memegang keranjang lain, keranjang itu otomatis diamankan menjadi draft sebelum pesanan baru dimuat — tidak ada pesanan yang hilang karena tergesa.
Fondasi 01 · Warna
Hijau apotek sebagai warna kerja, ditambah satu set warna yang bukan pilihan estetis: penandaan golongan obat mengikuti simbol resmi yang sudah dikenal apoteker.
Palet inti
Hijau apotek#0E9F6EAksi utama, status aktif, nilai positif
Hijau lembut#DFF3EALatar terpilih, thumbnail, chip aktif
Tinta#0A2318Teks utama, toast, bilah gelap
Redup#5B7268Teks sekunder, label, satuan
Kertas mint#EFF6F1Latar aplikasi & dokumen
Penandaan golongan obat — mengikuti simbol resmi
Obat Bebas #1E9E52 Bebas Terbatas #1E5EE5 Obat Keras #D0021B OWA #7A3FD1
Lingkaran hijau, biru, dan merah-ber-K adalah bahasa yang sudah dipakai apoteker setiap hari di kemasan. Memakainya di layar berarti tidak ada yang perlu dihafal ulang — dan kesalahan membaca golongan menjadi jauh lebih kecil.
Warna status
Aman / tersinkron#0E8A5FTanpa interaksi, kas pas, terkirim
Perlu perhatian#B96A00Interaksi sedang, antrean pending, pembulatan
Bahaya / gagal#D93843Interaksi berat, stok habis, sinkron gagal
BPJS & eceran#1E5EE5Klaim, tombol ½ strip, sumber online
Mode gelap memakai token yang sama dengan nilai berbeda; seluruh komponen menarik warna dari variabel, sehingga tidak ada warna yang ditulis langsung di komponen.
Fondasi 02 · Tipografi
Dua wajah huruf dengan tugas terpisah, plus satu wajah mono khusus data yang harus bisa dieja: kode KFA, nomor resep, dan nama resource FHIR.
Angka selalu tabular. Seluruh nominal memakai font-variant-numeric: tabular-nums agar kolom rupiah pada laporan dan tabel sinkron tetap lurus saat nilainya berubah.
Fondasi 03 · Bentuk, jarak & gerak
Radius & jarak
Token
Nilai
Dipakai
--r-s
8–9px
Tag, tombol kecil, sel keypad
--r-m
13–14px
Kartu obat, tombol utama, panel
--r-l
16–22px
Sheet, modal, kartu ringkasan
Chip
99px
Chip interaksi, filter, bendera sumber
Ritme
kelipatan 4
Padding 8/12/16, jarak antar kartu 9–12
Target sentuh
Tombol keypad 52px, sel kartu obat ≥ 96px, tombol aksi utama 44px. Semua dirancang untuk ibu jari, bukan kursor.
Gerak — bertema perawatan
Garis EKGLayar masuk — menandai sistem hidup
2.6s linear
🫀
Denyut jantungTitik status shift & peringatan interaksi
1.8s
Jatuh tabletItem masuk keranjang, baris antrean baru
.3s ease
Kapsul berputarSedang mengirim antrean sinkron
.8s linear
Seluruh animasi berhenti bila sistem operasi meminta prefers-reduced-motion. Gerak hanya dipakai untuk menandai perubahan keadaan — tidak ada animasi dekoratif pada jalur transaksi.
Komponen inti
Sembilan komponen yang menyusun hampir seluruh antarmuka.
Dua mode: angka (dengan 000, Hapus, ⌫) dan teks QWERTY. Mode raw untuk nomor HP & kartu BPJS agar tidak diberi pemisah ribuan. Batal mengembalikan nilai semula.
Picker ber-pencarian
Dropdown master dengan pencarian keypad, pencocokan ke label maupun keterangan, tanda ✓ pada pilihan aktif, dan jalan keluar "ketik manual".
Kartu obat
Emoji sediaan, nama, harga kemasan, golongan, stok terbaca, tombol eceran, lencana jumlah di keranjang, dan tanda interaksi.
Chip interaksi
Tingkat keparahan di depan, lalu pasangan zat dan efeknya. Warna mengikuti token status.
Sheet keranjang
Muncul dari bawah pada ponsel, mengambang di tengah pada tablet. Memuat data pasien, baris item, panel interaksi, dan ringkasan.
Komponen
Peran & aturan
Stepper pecahan
Khusus dosis racikan; melangkah ¼ tablet dan menampilkan lambang pecahan, bukan desimal.
Tabel berpaginasi
Dipakai antrean sinkron, riwayat shift, dan transaksi per shift. Pola sama: filter berhitung, ukuran halaman, nomor ringkas dengan elipsis.
Bendera sumber
Menandai asal pesanan (kasir / online / resep) di antrean, keranjang, dan baris laporan.
Layar sukses
Kembalian besar, saran pecahan uang, arus laci tiga kolom, mutasi stok, dan catatan integrasi.
Keypad angka
Bendera sumber
🏪 Kasir🌐 Online · WA🩺 Resep SATUSEHAT
Responsif — portrait sampai tablet
Satu tata letak yang berubah pada tiga titik henti; kasir apotek memakai ponsel, tablet meja, atau keduanya bergantian.
< 640px
Ponsel portrait
Bilah tab di bawah, grid obat 2 kolom, sheet naik dari bawah, keranjang mengambang di atas bilah tab.
≥ 640px
Ponsel besar
Sheet dan modal menjadi kartu mengambang dengan sudut penuh, bukan menempel di tepi bawah.
≥ 760px
Tablet portrait
Grid obat 3 kolom, kartu statistik 4 kolom, isi dokumen melebar.
≥ 900px
Tablet landscape
Bilah tab bawah berganti menjadi rail navigasi vertikal di kiri; bilah keranjang pindah ke pojok kanan bawah agar tidak menutupi grid.
≥ 1100px
Meja kasir lebar
Grid obat 4 kolom dengan lebar isi dibatasi supaya jarak baca tetap nyaman.
Alur 01 · Penjualan OTC dengan kembalian
Jalur tersibuk. Tujuh ketukan dari layar kunci sampai struk, tanpa satu pun keyboard sistem.
buka shift modal awal kas via keypad → kasir terbuka, laci punya pemilik
│
pilih jenis OTC (muncul otomatis saat item pertama)
│
tambah obat kartu obat · atau tombol +½ strip untuk eceran
│ └─ mesin interaksi memeriksa keranjang setiap kali
│
buka keranjang isi data pasien (nama + WA) bila ingin struk WhatsApp
│
bayar total Rp45.000 · terima Rp100.000 via keypad
│ └─ catatan hidup: "masuk +100.000 · keluar −55.000 · net +45.000"
▼
layar sukses kembalian Rp55.000 besar + saran pecahan (1×50rb, 1×5rb)
arus laci 3 kolom · mutasi stok per obat
antrean: MedicationDispense + InventoryReport
Alur 02 · Resep digital dari SATUSEHAT
SATUSEHAT ──pull MedicationRequest──▶ antrean Pesanan (bendera 🩺)
│ no. resep · dokter · faskes
│ pasien + no. WA
▼
ketuk "Layani"
│
┌──────────────────────────────────────┴─────────────────────────┐
│ keranjang terisi jenis penjualan dipilih otomatis │
│ data pasien terisi ada no. kartu BPJS? → BPJS, jika tidak → Resep │
│ obat keras diizinkan data resep terisi dari berkas │
└──────────────────────────────────────┬─────────────────────────┘
▼
bayar / terbitkan SEP
│
push MedicationDispense ─┼─ push MedicationRequest (selesai dilayani)
└─ push Claim bila BPJS
Resep yang datang lewat jalur ini tidak bisa dilayani sebagai OTC — jenis penjualannya sudah ditentukan berkas, bukan oleh kasir.
Alur 03 · Racikan puyer anak
ketuk 🧪 Racik
│
├─ jenis belum dipilih? → minta pilih jenis ─┐
├─ jenis = OTC? → "racikan wajib resep" → Ganti ke Resep (1 ketukan)
│ │
▼ ▼
builder nama · bentuk (puyer/kapsul/sirup) · jumlah · jasa racik
signa ← dipilih dari master, dicari lewat keypad
komponen ← cari obat → stepper ¼ ½ ¾ 1
│
├─ interaksi antar komponen dicek langsung
└─ ½ tab × 3 bungkus = 1½ tab → dibulatkan 2 tab (ditandai oranye)
▼
simpan → kartu racikan di keranjang (dengan tombol Edit)
▼
bayar → stok komponen dipotong dalam butir, tampil di mutasi stok
Alur 04 · Pesanan online / WhatsApp
pelanggan chat WA ──▶ CommunicationRequest ──pull──▶ antrean Pesanan (bendera 🌐)
│ nama · no. WA · catatan
▼
ketuk "Proses"
│
keranjang aktif sedang terpakai? → diamankan jadi draft dulu
▼
lanjut seperti transaksi biasa
▼
struk & pengingat minum obat dikirim balik ke WA
Tiga sumber pesanan hidup di satu layar karena beban kerjanya sama: keranjang yang menunggu diselesaikan. Yang berbeda hanya asal-usul dan syaratnya — itulah yang dibawa oleh bendera warna dan filter berhitung.
Peta integrasi
Empat sistem luar, masing-masing dengan sumber daya dan arah yang jelas.
Sistem
Resource / kanal
Arah
Dipicu oleh
KFA Browser
Medication
⬇ pull
Sinkron master obat: nama, kode KFA, komposisi, golongan
Back-office
ChargeItemDefinition
⬇ pull
Harga, paket obat, master signa, aturan interaksi
SATUSEHAT
MedicationRequest
⬇ pull
Resep digital masuk dari faskes
SATUSEHAT
MedicationDispense
⬆ push
Setiap transaksi selesai — penyerahan obat
SATUSEHAT
MedicationRequest
⬆ push
Menandai resep selesai dilayani
Internal
InventoryReport
⬆ push
Mutasi stok dalam satuan butir
BPJS Kesehatan
Claim
⬆ push
Transaksi BPJS — tagihan pasien Rp0, SEP terbit
Shift
PaymentReconciliation
⬆ push
Penutupan shift beserta selisih kas
WhatsApp Business
CommunicationRequest
⬇ pull
Pesanan pelanggan masuk sebagai draft
WhatsApp Business
pesan keluar
⬆ push
Struk digital & pengingat minum obat
Kepatuhan. Golongan obat, kewajiban resep, pencatatan pelayanan OWA, dan pelaporan penyerahan obat mengikuti ketentuan Kemenkes. Standar pertukaran datanya HL7 FHIR R4 — perhatikan penulisannya HL7, bukan FL7.
Sifat non-fungsional
≤ 1 dtk
dari ketukan bayar sampai layar sukses, tanpa jaringan
100%
transaksi tuntas saat offline; antrean menyusul otomatis
bawaan sistem — seluruh masukan lewat keypad & picker kustom
Keamanan & jejak
Masuk dengan PIN per petugas; peran menentukan kewenangan.
Kasir terkunci di luar shift — tidak ada transaksi tanpa pemilik.
Setiap konfirmasi interaksi tersimpan sebagai catatan klinis pada transaksi.
Kas: bruto, kembalian, buku kas, dan selisih penutupan tercatat terpisah.
Ketahanan
Sumber kebenaran lokal; jaringan bersifat tambahan.
Pengiriman ulang idempoten berbasis id lokal.
Draft menahan keranjang yang belum selesai, termasuk racikan utuh.
Mode debug membuka audit sinkron tanpa perlu alat luar.
Peta jalan
Urutan yang dipilih mengikuti risiko: keselamatan dan ketelitian stok lebih dulu, otomatisasi menyusul.
Fase 1 · selesai
Kasir yang aman
Interaksi obat, gerbang jenis penjualan, paket, racikan, stok atom, shift & kas, antrean pesanan tiga sumber, audit sinkron.
Fase 2 · berikutnya
Etiket & formularium
Cetak etiket putih/biru dari master signa. Formularium BPJS: obat tidak ditanggung → pasien bayar selisih. Plafon klaim per resep.
Fase 3
Gudang & kedaluwarsa
Stok opname dengan penghitungan strip terbuka, batch & tanggal kedaluwarsa, peringatan stok menipis, usulan pemesanan.
Fase 4
Percakapan dua arah
Konfirmasi pesanan WA (terima/tolak), pengingat tebus ulang obat rutin, riwayat pembelian per pasien.
Fase 5
Banyak cabang
Sinkron antar cabang, transfer stok, laporan gabungan, dan peran pengawas dengan tampilan ringkas.
Catatan untuk halaman pendarat. Empat demo interaktif di dokumen ini — blister stok, pemeriksa interaksi, gerbang penjualan, dan kembalian — dirancang agar bisa dipindahkan apa adanya ke halaman pemasaran. Masing-masing berdiri sendiri, tidak butuh data server, dan menjelaskan satu nilai jual dalam satu ketukan.