Handbook
Cara kerja sistem ini, fungsi tiap menu, dan cara membaca data. Jika baru, mulai dari Konsep inti.
Konsep inti (baca dulu)
Sistem ini dibangun di atas satu aturan: setiap perubahan stok meninggalkan jejak permanen. Stok tidak pernah diedit atau dihapus. "Stok saat ini" yang Anda lihat adalah jumlah berjalan dari sebuah buku besar (ledger) yang hanya-tambah — daftar pergerakan yang hanya bertambah. Koreksi adalah baris baru yang membatalkan baris lama, bukan penghapusan.
- Ledger tidak bisa diubah. Tabel
stock_ledgermelarangUPDATEdanDELETE. Apa pun tidak bisa diam-diam diubah setelah kejadian. - Cache saldo. Angka yang Anda lihat dibaca dari cache cepat (
stock_balances), bukan dengan menjumlahkan seluruh riwayat setiap kali. Cache diperbarui dalam transaksi yang sama dengan baris ledger, jadi selalu konsisten. - Tidak diketahui ≠ nol. Produk yang belum punya stok awal menampilkan
—, bukan0. Nol berarti "kami menghitung nol"; tanda hubung berarti "kami belum pernah menetapkan saldo." Produk tidak-diketahui memunculkan anomali Saldo awal belum ada sampai stok datang. - Alasan ≠ saluran. Setiap pergerakan mencatat kenapa (alasan: penjualan, bonus, rusak…) dan lewat mana (saluran: Shopee, TikTok, offline, gudang). Keduanya tidak pernah dicampur — mencampurnya membuat spreadsheet lama tidak bisa diaudit.
- FEFO. Stok keluar meninggalkan batch terdekat kadaluwarsa duluan ("First-Expire, First-Out"), otomatis menjangkau beberapa batch. Operator tidak pernah memilih batch — sistem yang memilih.
- Lingkup perdagangan. Setiap baris diklasifikasikan Online (jualan marketplace), Offline (jualan manual di gudang), atau Internal (inbound, stock-take, pembatalan) — diturunkan dari saluran, jadi tidak bisa salah-input.
Cara membaca baris ledger
Halaman Ledger bisa menampilkan tiap baris sebagai kalimat biasa. Bentuknya:
−12 SALE via SHOPEE (Online) · AURA MASK · B2405 · ORDER #4471 · 2 Jun 14:20- − atau + — minus berarti stok keluar, plus berarti stok masuk.
- alasan via saluran (lingkup) — kenapa, lewat-mana, dan kategori turunannya.
- sumber — apa penyebab baris:
ORDER,RETURN,MANUAL,OPNAME,INBOUND, atauIMPORT, plus id singkat. - ↩ pembatalan — jika ada, baris ini membatalkan baris sebelumnya (mis. cancel-setelah-ship). Klik untuk melihat baris aslinya.
Baris yang sama juga muncul di tampilan tabel dengan filter (alasan, saluran, lingkup, tanggal) dan paginasi "Older".
Dashboard
Apa ini: halaman utama. Bacaan cepat apa yang perlu perhatian hari ini.
Cara membaca:
- Baris urgensi — jumlah anomali terbuka, klaim TikTok yang jatuh tempo segera, batch mendekati kadaluwarsa, dan produk tanpa saldo awal. Angka bukan-nol tertaut ke halaman yang menjelaskannya.
- Rekap lingkup — berapa banyak stok keluar online vs offline vs internal periode ini.
- Stok terbaru — saldo per batch saat ini. Tanda hubung berarti saldo tidak diketahui (bukan nol).
Kapan bertindak: setiap angka merah atau amber. Ikuti tautan ke Reconcile, Returns, atau Products untuk menyelesaikannya.
Products
Apa ini: katalog master — produk, batch-nya, dan resep bundle.
Cara membaca: tiap produk menampilkan SKU, nama, status aktif, dan apakah saldonya sudah diinisialisasi. Badge Not initialized berarti saldo tidak diketahui (tampil —); inbound pertama atau stock-take memperbaikinya.
Siapa bisa mengubah: membuat produk, batch, dan resep bundle hanya untuk admin. Operator hanya bisa lihat.
Catatan: bundle adalah listing marketplace yang terdiri dari beberapa produk. Definisikan sekali di sini (mis. bundle "PACK-A" = 1× Produk X + 2× Produk Y); tidak ada stok di tingkat bundle — stok ada di komponennya.
Inbound
Apa ini: catat barang diterima dari pabrikan kontrak (maklon).
Cara pakai: pilih produk, masukkan kode batch, tanggal kadaluwarsa, dan jumlah diterima. Sistem menemukan atau membuat batch lalu menulis baris +qty INBOUND_MAKLON.
Efek samping: inbound pertama untuk sebuah produk menginisialisasi saldonya — dari saat itu ia menampilkan angka nyata bukan —.
Manual out
Apa ini: catat stok keluar dari gudang di luar pesanan marketplace — sample, bonus, promo, atau barang rusak/kadaluwarsa ditarik dari batch.
Cara pakai: pilih alasan dan saluran. Form menegakkan disiplin alasan≠saluran untuk Anda:
- Sale / Bonus / Promo / Sample → harus pakai saluran penjualan (Shopee / TikTok / Offline).
- Damaged / Expired → saluran Warehouse, dan Anda bisa pilih batch spesifik untuk dikeluarkan (mengesampingkan FEFO).
Cara membaca hasil: FEFO memilih batch otomatis (kecuali Damaged/Expired). Jika stok kurang, baris negatif sengaja ditulis dan anomali Saldo negatif muncul — kebocoran ditampilkan, bukan disembunyikan.
Orders
Apa ini: pesanan marketplace dan siklus hidupnya. Pesanan datang dari pipeline event (simulator sekarang, webhook nyata nanti).
Cara membaca status:
- Reserved — pesanan dibuat, barang belum dikirim. Belum ada baris ledger.
- Shipped / In transit — barang sudah keluar fisik. Baris ledger
SALEsudah ditulis. - Delivered — sampai ke pelanggan.
- Cancelled — jika dibatalkan sebelum ship, ledger tidak tersentuh; jika setelah ship, baris pembatalan mengembalikan barang ke batch aslinya.
- Return requested / Returned — lihat Returns.
Drill-down: pilih pesanan untuk melihat itemnya dan baris ledger persis yang dihasilkannya.
Returns
Apa ini: antrian inspeksi untuk barang yang dikembalikan.
Cara pakai: untuk tiap retur, tentukan kondisi:
- Restock — barang bagus; kembali ke batch asli (
+RETURN_RESTOCK). - Damaged — barang nyata tapi tidak bisa dijual; masuk batch karantina (tidak dijual) agar tetap tertelusuri tanpa mencemari stok jualan.
- Lost — tidak ada barang kembali; tidak ada yang ditambah ke stok. Kerugian dicatat di retur agar selisih punya cerita.
Batas klaim TikTok: retur TikTok punya jendela klaim 40 hari. Saat dalam 7 hari dan belum diinspeksi, badge peringatan "Nd left" muncul — inspeksi sebelum jendela tutup.
Stock-take (opname)
Apa ini: hitung stok fisik dan rekonsiliasikan dengan catatan.
Cara pakai:
- Mulai stock-take. Sistem menyimpan snapshot saldo tercatat per batch.
- Hitung buta. Masukkan yang Anda lihat secara fisik — angka tercatat disembunyikan saat input agar tidak bias.
- Tampilkan selisih. Lihat tercatat vs dihitung vs selisih (dihitung − tercatat).
- Drill ke sebuah produk untuk melihat semua pergerakan sejak stock-take terakhir, dikelompokkan per alasan — cerita ke mana unit-unit pergi.
- Finalize (admin). Untuk setiap selisih bukan-nol, baris
OPNAME_ADJUSTMENTditulis agar ledger cocok dengan hitungan fisik. Setelah finalize, saldo == yang Anda hitung.
Reconcilekhusus admin
Apa ini: pemindai anomali dan daftar kerjanya. Admin saja.
Cara pakai: klik Run reconciliation. Pemindai menulis satu anomali per masalah. Lalu kerjakan daftarnya: drill tiap ke sumbernya (pesanan / retur / baris ledger / produk) dan Resolve dengan catatan setelah ditangani.
Apa yang dipindai: scan bersifat point-in-time — membaca state saldo/produk saat ini ditambah window deadline ke depan. Tidak terikat satu hari; bisa dijalankan kapan saja, sesering dibutuhkan. Cek Balance drift menjumlahkan ledger di sisi server (satu query terkelompok), jadi tetap cepat saat history membesar.
Threshold bisa diatur. Buka panel Thresholds untuk menentukan berapa hari memicu stuck reservation, window klaim TikTok, dan peringatan kadaluwarsa. Threshold tersimpan berlaku pada scan berikutnya. Default: 7 / 7 / 30 hari.
Kosong: "Nothing to reconcile" dengan tanda centang berarti pembukuan konsisten. Lihat Jenis anomali di bawah untuk arti tiap tanda.
Ledger
Apa ini: jejak audit lengkap — setiap pergerakan yang pernah dicatat. Ini buktinya.
Cara pakai: filter per alasan, saluran, lingkup perdagangan, produk, batch, atau tanggal. Pakai Older untuk pindah haluran ke belakang (paginasi keyset — tetap cepat sejauh apa pun).
Dua tampilan: tabel default, atau ?view=sentence untuk kalimat baris biasa (lihat Cara membaca baris ledger).
Read-only: Anda tidak bisa mengedit apa pun di sini. Untuk mengoreksi kesalahan, gunakan pembatalan (Manual out / cancel-setelah-ship) atau stock-take — jangan edit manual.
Import (spreadsheet lama)khusus admin
Apa ini: serap spreadsheet lama klien sebagai riwayat awal. Admin saja.
Cara pakai: tempel format lebar/pivot (produk, sisa stok, lalu blok per-tanggal RETUR / SHOPEE / MANUAL / TIKTOK). Pilih cara memperlakukan kolom MANUAL — ia mencampur penjualan offline + bonus + sample di sumber:
- Offline SALE (default) — impor sebagai penjualan offline dengan catatan "belum terverifikasi". Jujur bahwa granularitas hilang.
- Penyesuaian umum — tandai sebagai warisan, dikecualikan dari penjualan bersih.
Selalu dry-run dulu. Pratinjau menunjukkan berapa baris akan dibuat dan anomali apa muncul sebelum commit. Impor ulang file yang sama tidak menduplikasi (idempoten). Produk "sisa stok" kosong diimpor dengan saldo tidak diketahui ("baris merah" lama) — benar, karena saldonya memang tidak diketahui.
Export
Apa ini: unduh XLSX multi-sheet untuk diserahkan ke auditor, akuntan, atau klien.
Cara pakai: pilih sheet yang diinginkan dan rentang tanggal:
- Current Stock — snapshot per produk/batch saat ekspor (saldo tidak diketahui tampil
—, bukan 0). - Period Summary — online vs offline vs internal dalam rentang.
- Stock-Take Report — selisih + drill per-alasan untuk satu stock-take.
- Ledger — jejak audit mentah dalam rentang.
Read-only. Ekspor adalah proyeksi ledger, bukan sumber kebenaran baru. Jangan pernah diedit lalu diimpor balik sebagai "koreksi" — itu merusak ketidakbisaubahan. Koreksi hanya lewat pembatalan atau stock-take.
Simulatorkhusus admin
Apa ini: suntik event marketplace untuk menguji atau demo pipeline. Admin saja.
Cara pakai: suntik satu event (pesanan baru → ship → deliver → cancel → return), atau tempel batch CSV/JSON. lalu klik Process pending untuk menerapkan.
Kenapa penting: simulator menulis ke tabel event yang sama yang akan dipakai webhook marketplace nyata. Saat API hidup nanti, inti tidak berubah — ia hanya menyisipkan ke tabel yang sama dengan source='WEBHOOK'.
Jenis anomali (arti masing-masing)
Pemindai Reconcile memunculkan ini. Tiap bisa di-drill ke sumbernya dan diselesaikan dengan catatan.
- Negative balance — sebuah batch di bawah nol (stok keluar yang tidak ada). Telusuri kekurangannya; biasanya inbound terlewat atau alokasi berlebih.
- Balance drift — cache tidak cocok dengan jumlah ledger (dihitung di sisi server). Seharusnya tidak pernah terjadi di sistem sehat; menandakan bug cache/trigger. Jalankan
rebuild_balances()setelah menyelidiki. - Stuck reservation — pesanan masih Reserved melewati ambang stuck (default 7 hari, bisa diatur). Apakah ship tanpa event sampai, atau sudah mati?
- TikTok claim due — jendela klaim 40 hari sebuah retur TikTok tutup dalam ambang window klaim (default 7 hari, bisa diatur) dan belum diinspeksi. Inspeksi sekarang.
- Expiry warning — batch dengan stok kadaluwarsa dalam ambang kadaluwarsa (default 30 hari, bisa diatur). Jual atau keluarkan sebelum kadaluwarsa.
- Orphan movement — baris ledger tanpa sumber, atau SKU listing yang tidak terpetakan ke produk/bundle yang dikenal.
- Unbalanced reversal — baris pembatalan yang kuantitasnya tidak cocok dengan aslinya.
- No initial balance — produk aktif tanpa stok awal yang ditetapkan ("baris merah" spreadsheet). Masukkan stok lewat inbound atau stock-take untuk menghapusnya.
Peran (roles)
- ADMIN — akses penuh: data master (produk, batch, bundle), finalize stock-take, rekonsiliasi harian, importer lama, dan simulator.
- OPERATOR — kerja harian: inbound, manual out, inspeksi retur, penghitungan stock-take, dan simulator. Tidak bisa mencapai halaman admin (tersembunyi di nav dan redirect jika diketik manual).
Batasan tingkat-aksi (mis. hanya admin bisa finalize stock-take atau menyelesaikan anomali) ditegakkan di dalam tiap aksi, bukan hanya di nav.