Ringkasan Utama
Pelacakan batch dan serial menentukan apakah penarikan produk memakan waktu satu sore atau satu minggu. ERP yang mencatat batch mana masuk ke pengiriman mana bisa menjawab dalam hitungan detik pelanggan mana saja yang terdampak, dan kueri itulah seluruh alasan mengapa beban pencatatannya layak ditanggung.
Ketika pelanggan menelepon dan mengatakan produk dari batch produksi tertentu gagal quality control, pertanyaan yang menentukan apakah proses recall selesai dalam satu sore atau memakan waktu seminggu sangatlah sederhana: apakah ERP Anda bisa menunjukkan, dalam hitungan detik, pengiriman, pelanggan, dan lokasi gudang mana saja yang berisi batch tersebut? Bagi bisnis makanan, farmasi, kimia, dan alat kesehatan, traceability batch dan nomor serial bukan sekadar laporan tambahan, melainkan tulang punggung setiap transaksi penerimaan, perpindahan, dan pengiriman dalam sistem.
Artikel ini membahas cara merancang lapisan traceability tersebut pada ERP custom: perbedaan antara pelacakan level lot dan level unit, struktur data yang mendukung keduanya, logika picking first-expired-first-out, dan laporan recall yang menghubungkan satu nomor batch kembali ke setiap pelanggan yang menerimanya.
Pelacakan level lot versus level unit
Tidak semua barang membutuhkan nomor serial unik, dan tidak semua barang teregulasi bisa cukup hanya dengan nomor batch. Badan standar GS1 menjelaskan tiga tingkat granularitas traceability yang langsung berkaitan dengan keputusan desain ERP: identifikasi level kelas hanya dengan kode produk, identifikasi level lot dengan kode produk ditambah nomor batch atau lot, dan identifikasi level unit dengan kode produk ditambah nomor serial unik per unit. Memilih tingkat yang tepat untuk setiap kategori barang adalah keputusan arsitektur pertama, karena hal ini menentukan seberapa detail buku besar perpindahan stok harus mencatat.
- Level kelas: barang komoditas umum di mana satu unit bisa dipertukarkan dengan unit lain dari kode produk yang sama. Tanpa batch, tanpa serial. Paling cepat dipindahkan, paling minim traceability.
- Level lot: barang yang diproduksi atau diterima dalam batch yang berbagi tanggal produksi, tanggal kedaluwarsa, atau sertifikat pemasok yang sama. Satu nomor batch mencakup ratusan hingga ribuan unit. Ini adalah default yang tepat untuk bahan baku, makanan kemasan, dan sebagian besar bahan setengah jadi farmasi.
- Level unit: barang bernilai tinggi atau kritis terhadap keselamatan di mana setiap unit individual membutuhkan riwayatnya sendiri, seperti implan medis, rakitan elektronik bergaransi, atau zat terkontrol. Setiap unit mendapat nomor serial unik selain nomor lotnya.
Jangan memaksakan serialisasi level unit pada semua kategori barang hanya karena sebagian kecil produk membutuhkannya. Pelacakan level serial melipatgandakan jumlah baris yang ditulis buku besar perpindahan pada setiap transaksi, dan sebagian besar tim gudang tidak mungkin memindai seratus serial individual saat picking terburu-buru. Simpan cara ini hanya untuk barang yang benar-benar diwajibkan regulasi atau garansi untuk memiliki riwayat per unit.
Struktur data: lot, unit, dan perpindahan
Skema yang mendukung traceability memisahkan tiga hal yang pada sistem sederhana sering digabung menjadi satu tabel inventaris: lot itu sendiri dengan metadata produksi dan kedaluwarsanya, unit fisik yang mungkin memiliki nomor serial sendiri atau tidak, dan event perpindahan yang menjadi satu-satunya tempat kuantitas benar-benar berubah. Menjaga perpindahan sebagai buku besar append-only, bukan mengubah saldo yang berjalan, adalah yang membuat query recall dan jejak audit tetap bisa dilakukan di kemudian hari, karena Anda selalu bisa merekonstruksi kondisi lot tertentu pada titik waktu mana pun. Ini juga berarti kuantitas on-hand terkini untuk suatu lot tidak pernah disimpan secara langsung, melainkan diturunkan dengan menjumlahkan kuantitas bertanda di seluruh baris perpindahan yang merujuk lot tersebut, yang lebih lambat untuk dibaca tetapi jauh lebih sulit dikorupsi secara diam-diam dibanding kolom saldo yang bisa diubah langsung.
| Konsep | Contoh level lot | Contoh level unit |
|---|---|---|
| Identifier | Batch LOT-2026-0311 | Batch LOT-2026-0311 + serial SN-88213 |
| Kuantitas per record | 500 unit dalam satu baris lot | 1 unit per baris stock_unit |
| Granularitas query recall | Semua pengiriman yang mengandung lot tersebut | Unit yang tepat dan pemiliknya |
Penerimaan, perpindahan, dan picking FEFO
Setiap event fisik, penerimaan pembelian, transfer internal, picking untuk pesanan keluar, atau penahanan quarantine, menulis satu baris ke buku besar perpindahan yang merujuk ke unit atau lot. Pada sisi keluar, inventaris teregulasi hampir selalu membutuhkan FEFO, first-expired-first-out, bukan FIFO yang lebih sederhana yang digunakan untuk barang tidak mudah rusak. FEFO memprioritaskan stok yang paling dekat dengan tanggal kedaluwarsanya terlepas dari kapan stok itu tiba, sehingga meminimalkan write-off dan mencegah stok kedaluwarsa sampai ke pelanggan. Query picking di bawah menunjukkan logika intinya: saring stok yang tersedia untuk barang yang diminta, urutkan berdasarkan tanggal kedaluwarsa menaik, dan ambil hanya sebanyak yang dibutuhkan pesanan.
-- Simplified schema for lot/serial-level stock ledger
create table stock_lot (
id bigint primary key generated always as identity,
item_id bigint not null references item(id),
lot_code text not null,
mfg_date date,
expiry_date date,
unique (item_id, lot_code)
);
create table stock_unit (
id bigint primary key generated always as identity,
lot_id bigint not null references stock_lot(id),
serial_no text unique, -- null when item is lot-tracked only, not serialized
status text not null default 'in_stock' -- in_stock, reserved, shipped, quarantined
);
create table stock_movement (
id bigint primary key generated always as identity,
unit_id bigint references stock_unit(id),
lot_id bigint references stock_lot(id),
qty numeric not null,
movement_type text not null, -- receipt, transfer, pick, ship, adjust
warehouse_id bigint not null references warehouse(id),
ref_doc text, -- PO number, SO number, or transfer id
moved_at timestamptz not null default now()
);
-- FEFO pick candidate query: earliest expiry first, only usable stock
select su.id, sl.lot_code, sl.expiry_date, sl.item_id
from stock_unit su
join stock_lot sl on sl.id = su.lot_id
where su.status = 'in_stock'
and sl.item_id = $1
order by sl.expiry_date asc, sl.id asc
limit $2;Logika FEFO memiliki kasus tepi yang sering menjebak implementasi pertama: lot yang sebagian sudah mendekati kedaluwarsa atau berumur simpan sangat singkat yang tiba dari pemasok lebih dulu daripada stok lama. Jika query picking Anda hanya mengurutkan berdasarkan tanggal kedaluwarsa tanpa juga memeriksa ambang batas sisa umur simpan minimum saat pengiriman, Anda bisa mengirim lot yang kedaluwarsa sebelum sampai ke pelanggan. Tambahkan aturan sisa umur simpan minimum yang bisa dikonfigurasi per kategori barang, bukan hanya pengurutan tanggal kedaluwarsa mentah.
Laporan recall: query yang paling penting
Inti dari seluruh skema di atas adalah menjawab satu pertanyaan dengan cepat: berdasarkan nomor batch atau serial, sebutkan setiap lokasi dan pelanggan hilir yang menerimanya. Laporan recall perlu menyusuri buku besar perpindahan maju dari penerimaan hingga pengiriman, yang mudah dilakukan jika perpindahan selalu merujuk ke id lot atau unit, bukan field teks yang disalin. Urutan penelusuran recall yang umum adalah sebagai berikut:
- Selesaikan nomor batch atau serial ke lot_id atau unit_id internalnya.
- Query semua baris perpindahan yang merujuk id tersebut dengan movement_type ship atau transfer.
- Gabungkan setiap perpindahan pengiriman ke dokumen referensinya untuk mendapatkan pelanggan, sales order, dan tanggal pengiriman.
- Agregasikan menjadi satu laporan yang dikelompokkan per pelanggan, dengan kuantitas yang dikirim dan kuantitas on-hand yang masih tersisa di gudang untuk quarantine segera.
Workflow quarantine dan disposisi
Data traceability hanya berguna jika ERP bisa langsung bertindak berdasarkan data itu. Saat quality control menandai suatu lot, sistem membutuhkan status quarantine yang mencegah lot tersebut dipicking untuk pesanan baru mana pun tanpa menghapus riwayat perpindahannya, diikuti workflow disposisi, kembalikan ke pemasok, musnahkan, atau rework, yang juga tercatat sebagai event perpindahan. Memperlakukan quarantine sebagai flag status pada record lot, diperiksa saat waktu picking, jauh lebih andal dibanding mencoba mengeluarkan stok secara fisik dari setiap pesanan terbuka begitu penahanan diberlakukan.
Modul traceability yang dirancang dengan baik akan terbayar sejak saat pertama laporan recall yang biasanya membutuhkan tim gudang dua hari untuk disusun manual, kini selesai kurang dari satu menit hanya dari satu pencarian nomor batch, lengkap dengan daftar distribusi pelanggan.
Catatan implementasi praktis
Beberapa keputusan secara konsisten membedakan modul traceability yang tahan uji audit sesungguhnya dari yang runtuh saat auditor mengajukan pertanyaan lanjutan. Ini adalah pelajaran yang biasanya baru dipahami dengan cara yang sulit, tepat ketika permintaan recall sungguhan datang pada Jumat sore dan laporannya harus benar sejak percobaan pertama:
- Jangan pernah membiarkan baris perpindahan merujuk ke lot atau nomor serial melalui teks yang disalin. Selalu gunakan foreign key ke tabel lot atau unit, sehingga koreksi pada metadata seperti tanggal kedaluwarsa langsung menyebar ke mana saja secara instan.
- Simpan baik tanggal produksi maupun tanggal kedaluwarsa pada lot, meskipun hanya kedaluwarsa yang dipakai untuk FEFO, karena audit umur simpan dan review kualitas pemasok membutuhkan tanggal produksi secara independen.
- Indeks buku besar perpindahan pada lot_id, unit_id, dan moved_at secara bersamaan. Query recall bersifat read-heavy dan terikat waktu, dan indeks komposit itulah yang menjaga query di atas jutaan baris perpindahan tetap cepat saat kejadian recall sungguhan.

