Ringkasan Utama
Pada 2025, 85 persen perusahaan B2B menjalankan portal vendor atau pemasok, naik dari 68 persen setahun sebelumnya. Alasannya adalah biaya accounts payable: portal tempat vendor mengirim invoice dan memeriksa status pembayaran sendiri menghapus input manual dan email penagihan di sekitarnya.
Pada 2025, 85% perusahaan B2B menawarkan portal pemasok atau vendor online, naik dari 68% setahun sebelumnya. Kasus bisnis sudah jelas: portal vendor mengurangi biaya pemrosesan AP dengan menghilangkan entri faktur manual, mempercepat siklus pembayaran, dan meningkatkan hubungan pemasok. Untuk perusahaan manufaktur dan dagang Indonesia yang mengelola ratusan vendor — banyak yang masih mengirim faktur PDF melalui email dan menindaklanjuti via WhatsApp — portal vendor adalah peningkatan operasional yang signifikan.
Apa yang Benar-Benar Dibutuhkan Portal Vendor
Portal vendor produksi membutuhkan empat kapabilitas inti: pengiriman faktur (vendor mengunggah PDF faktur, memasukkan item baris, memetakan ke PO), pelacakan pembayaran (vendor dapat melihat status pembayaran untuk setiap faktur), manajemen dokumen (vendor memperbarui detail bank, dokumen pajak, sertifikat hukum), dan komunikasi (pesan terstruktur yang terhubung ke PO atau faktur tertentu).
Autentikasi dan Onboarding Vendor
Saya menggunakan aplikasi Next.js yang menghadap vendor terpisah dengan autentikasi tersendiri. Vendor mendaftar dengan NPWP (nomor registrasi pajak Indonesia), nama bisnis, dan email. Admin ERP menyetujui pendaftaran dan menghubungkan akun vendor ke vendor master di ERP. Autentikasi menggunakan JWT dengan kedaluwarsa lebih pendek (4 jam) daripada pengguna internal.
Vendor Portal Architecture
┌─────────────────────┐ ┌─────────────────────────┐
│ Vendor Portal │ │ Internal ERP │
│ (Next.js PWA) │ │ (Next.js + NestJS) │
│ │ │ │
│ 📋 Submit Invoice │ │ 📊 AP Module │
│ 💳 Track Payment │◄───►│ 📦 Purchase Orders │
│ 📄 Docs Upload │ │ ✅ 3-Way Matching │
│ 💬 Messages │ │ 💰 Payment Batches │
└──────────┬──────────┘ └──────────┬──────────────┘
│ Vendor-scoped JWT │
▼ ▼
┌────────────────────────────────────────────────────┐
│ NestJS API (shared) │
│ │
│ VendorGuard: extracts vendor from JWT │
│ → injects vendor_id into every query │
│ → PostgreSQL RLS enforces row-level isolation │
└──────────────────────┬─────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────┐
│ PostgreSQL (RLS enabled on vendor-facing tables) │
│ │
│ vendors │ purchase_orders │ ap_invoices │ payments│
└────────────────────────────────────────────────────┘Dari pengalaman saya sebagai konsultan ERP lepas (freelance): berikan portal yang ramah mobile kepada vendor, bukan hanya desktop. Banyak kontak pemasok Indonesia beroperasi terutama di mobile — mereka akan memotret faktur dan mengirimkannya dari ponsel. Saya membangun portal sebagai PWA dengan formulir yang dioptimalkan untuk mobile. Pengambilan foto faktur (dengan konversi PDF otomatis menggunakan pdf-lib) adalah fitur yang paling banyak digunakan di bulan pertama.
Pengiriman Faktur dan Three-Way Matching
Alur pengiriman faktur: vendor memilih PO dari PO terbuka mereka, mengkonfirmasi item baris dan kuantitas yang difakturkan, memasukkan nomor dan tanggal faktur, mengunggah PDF, dan mengirimkan. ERP secara otomatis menjalankan three-way matching: kuantitas faktur vs. kuantitas PO vs. kuantitas penerimaan barang. Jika ketiganya cocok dalam toleransi, faktur disetujui otomatis ke antrian pembayaran. Ini menghilangkan 80% pekerjaan pencocokan AP manual.
Visibilitas Status Pembayaran
Vendor dapat melihat pelacak pembayaran untuk setiap faktur: dikirim, dalam peninjauan, disetujui, pembayaran dijadwalkan (dengan perkiraan tanggal pembayaran), dan dibayar (dengan referensi transfer bank). Visibilitas ini hampir sepenuhnya menghilangkan panggilan 'kapan saya akan dibayar?' ke tim AP.
-- PostgreSQL: Row-Level Security for vendor portal
-- Vendors can ONLY see their own data
ALTER TABLE purchase_orders ENABLE ROW LEVEL SECURITY;
ALTER TABLE ap_invoices ENABLE ROW LEVEL SECURITY;
ALTER TABLE payments ENABLE ROW LEVEL SECURITY;
-- Policy: vendor can only see their own POs
CREATE POLICY vendor_po_isolation ON purchase_orders
USING (vendor_id = current_setting('app.vendor_id')::UUID);
CREATE POLICY vendor_invoice_isolation ON ap_invoices
USING (vendor_id = current_setting('app.vendor_id')::UUID);
-- NestJS: Set vendor context before every query
@Injectable()
export class VendorContextMiddleware implements NestMiddleware {
async use(req: Request, res: Response, next: NextFunction) {
const vendor = req.user as VendorJwtPayload;
if (vendor?.vendorId) {
// Set PostgreSQL session variable for RLS
await this.dataSource.query(
"SELECT set_config('app.vendor_id', $1, true)",
[vendor.vendorId]
);
}
next();
}
}
// 3-way matching on invoice submission
async validateInvoiceAgainstPo(dto: SubmitInvoiceDto) {
const po = await this.poRepo.findOneOrFail(dto.poId);
const gr = await this.grRepo.findByPoId(dto.poId);
const grQty = gr.reduce((sum, r) => sum + r.quantity, 0);
const tolerance = 0.02; // 2% tolerance
for (const line of dto.lines) {
const poLine = po.lines.find(l => l.itemId === line.itemId);
if (!poLine) throw new BadRequestException(`Item ${line.itemId} not on PO`);
if (Math.abs(line.quantity - poLine.quantity) / poLine.quantity > tolerance) {
return { status: 'DISCREPANCY', requiresReview: true };
}
}
return { status: 'MATCHED', autoApprove: true };
}Bagaimana Saya Mendekati Ini
Portal vendor adalah aplikasi Next.js terpisah yang memanggil API NestJS yang sama dengan ERP internal, tetapi dengan kunci API yang dibatasi vendor. Modul vendor NestJS memberlakukan vendor_id pada setiap query menggunakan guard kustom yang mengekstrak vendor dari JWT dan menyuntikkannya ke setiap panggilan service.
Portal vendor berisi data keuangan sensitif — jumlah pembayaran, detail rekening bank, dokumen pajak. Row-level security di PostgreSQL harus memastikan setiap vendor hanya dapat melihat data mereka sendiri. Saya memiliki implementasi awal di mana endpoint API yang salah konfigurasi mengembalikan status pembayaran semua vendor jika parameter vendor_id dimanipulasi. Selalu gunakan kebijakan RLS PostgreSQL pada tabel yang menghadap vendor.
Manajemen Dokumen untuk Kepatuhan Vendor
Regulasi pengadaan Indonesia mengharuskan vendor mempertahankan sertifikat PKP (Pengusaha Kena Pajak), NPWP, SIUP (izin usaha), dan untuk beberapa sektor, sertifikasi ISO atau SNI yang masih berlaku. Portal yang saya bangun memungkinkan vendor mengunggah dan memperbarui dokumen-dokumen ini. ERP melacak tanggal kedaluwarsa dan menandai vendor yang dokumennya akan kedaluwarsa dalam 30 atau 60 hari.
Mengukur Dampak
Enam bulan setelah meluncurkan portal vendor untuk klien saya, peningkatan terukur meliputi: waktu pemrosesan AP per faktur turun dari 45 menit menjadi 8 menit, panggilan pertanyaan pembayaran vendor turun 65%, tingkat pembayaran tepat waktu meningkat dari 72% menjadi 91%, dan waktu onboarding vendor berkurang dari 5 hari menjadi 1 hari. CFO klien menyebutnya 'modul tunggal paling berdampak yang kami deploy.'
