Skip to main content
BlogERP

Membangun Portal Vendor dan Supplier Terintegrasi dengan ERP Kustom

Cara merancang dan membangun portal vendor swalayan yang memungkinkan pemasok mengirimkan faktur, melacak pembayaran, memperbarui dokumen, dan berkolaborasi langsung dengan modul pengadaan ERP Anda.

Matthews Wong

Software Engineer

Juni 202511 menit baca
ERP

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.'

FAQ

Pertanyaan Umum

Jawaban singkat untuk pertanyaan yang paling sering diajukan pembaca tentang topik ini.

Apa saja empat kapabilitas inti yang harus dimiliki portal vendor agar bisa terintegrasi dengan baik ke ERP?

Portal vendor produksi membutuhkan empat kapabilitas: pengiriman faktur (mengunggah PDF dan memetakan item ke PO), pelacakan pembayaran (status setiap faktur dapat dilihat vendor), manajemen dokumen (detail rekening bank, dokumen pajak, sertifikat hukum), serta komunikasi terstruktur yang terhubung ke PO atau faktur tertentu. Keempatnya harus tersinkronisasi dengan ERP — portal yang berdiri sendiri tanpa koneksi ke ERP hanya menciptakan silo data paralel.

Bagaimana three-way matching bekerja dalam alur pengiriman faktur?

Saat vendor mengirimkan faktur, ERP secara otomatis mencocokkan tiga angka: kuantitas yang difakturkan, kuantitas di PO, dan kuantitas penerimaan barang. Jika ketiganya cocok dalam batas toleransi, faktur langsung disetujui dan masuk ke antrian pembayaran. Jika ada selisih, faktur ditandai untuk ditinjau oleh tim AP — proses ini menghilangkan sekitar 80% pekerjaan pencocokan AP secara manual.

Mengapa portal vendor dibangun sebagai PWA dengan formulir yang dioptimalkan untuk mobile, bukan aplikasi web desktop biasa?

Banyak kontak pemasok Indonesia beroperasi terutama melalui ponsel, memotret faktur dan mengirimkannya langsung dari mobile. Dengan membangun portal sebagai PWA — termasuk fitur pengambilan foto faktur dengan konversi otomatis ke PDF menggunakan pdf-lib — portal menjadi praktis bagi pengguna tersebut. Fitur foto faktur terbukti menjadi yang paling banyak digunakan di bulan pertama, mengkonfirmasi bahwa portal yang hanya bisa diakses dari desktop akan ditinggalkan oleh vendor.

Celah keamanan apa yang ditemukan saat pengembangan, dan bagaimana cara mengatasinya?

Di awal implementasi, endpoint API yang salah konfigurasi mengembalikan status pembayaran semua vendor jika parameter vendor_id dimanipulasi — ini adalah kerentanan Insecure Direct Object Reference (IDOR). Solusinya adalah menerapkan kebijakan row-level security (RLS) PostgreSQL pada semua tabel yang menghadap vendor, serta memberlakukan vendor_id di setiap query melalui guard kustom NestJS yang mengekstrak identitas vendor dari JWT. Pengujian menyeluruh dengan beberapa akun vendor sebelum go-live sangat penting untuk mendeteksi jenis kerentanan ini.

Apa dampak terukur yang dihasilkan portal vendor enam bulan setelah diluncurkan?

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 sebagai 'modul tunggal paling berdampak yang kami deploy.'