Gambaran Umum

Tidak semua produk dijual dalam satu bentuk yang baku. Sangat umum bagi sebuah bisnis untuk menjual satu jenis barang dasar namun dalam berbagai macam spesifikasi. Modul “Varian Produk” diciptakan untuk mengakomodasi kompleksitas ini. Varian adalah opsi turunan dari sebuah produk utama (parent product) yang dapat mempengaruhi harga akhir dan memiliki pelacakan stok (SKU) yang berbeda-beda.

Coba bayangkan sebuah butik pakaian yang menjual kaos desain khusus. Mereka tidak mungkin membuat produk terpisah dengan nama “Kaos Desain A - Ukuran S - Merah”, “Kaos Desain A - Ukuran M - Merah”, dan seterusnya karena akan membuat katalog menjadi ribuan baris yang sangat sulit dikelola. Atau pertimbangkan kedai kopi yang menyajikan “Latte”. Pelanggan dapat memesan dalam ukuran Regular atau Large, dengan sajian Panas (Hot) atau Dingin (Ice).

Dengan sistem varian, pengelola toko cukup membuat satu “Produk Induk” (misalnya “Kaos Desain A” atau “Latte”). Di bawah produk induk tersebut, barulah mereka menentukan atribut variannya (ukuran, warna, suhu). Pendekatan ini membuat katalog sangat bersih di sisi manajemen, namun memberikan kebebasan fleksibilitas transaksi di titik penjualan (kasir).

Alur Kerja

Mari kita ambil skenario bisnis kedai minuman boba. Pengelola toko ingin mendaftarkan menu “Matcha Milk Tea”. Harga dasar minuman ini adalah Rp 20.000.

Pertama, mereka mendaftarkan produk utama “Matcha Milk Tea” seperti biasa di halaman manajemen produk. Kemudian, mereka masuk ke bagian “Varian”. Mereka menyadari bahwa ukuran gelas (cup) memengaruhi harga jual dan bahan baku. Pengelola kemudian membuat grup varian bernama “Ukuran Cup”. Di dalam grup ini, mereka mendefinisikan dua opsi:

  1. Reguler: Tidak ada penambahan harga (penyesuaian harga = Rp 0).
  2. Large: Ada tambahan harga (penyesuaian harga = +Rp 5.000).

Selain itu, karena masing-masing ukuran cup adalah barang fisik yang perlu dilacak stoknya secara akurat, sistem mengizinkan pengelola untuk menghasilkan SKU unik per varian, misalnya MATCH-MILK-REG dan MATCH-MILK-LRG.

Saat kasir melayani pembeli dan menekan tombol “Matcha Milk Tea” di layar POS, sistem tidak akan langsung memasukkannya ke keranjang belanja. Sebaliknya, aplikasi akan memunculkan sebuah pop-up (modal) yang memaksa kasir untuk memilih: “Ukuran apa yang dipesan?”. Jika kasir memilih “Large”, sistem otomatis menambahkan produk induk dengan harga Rp 20.000 ditambah nilai varian Rp 5.000, sehingga total baris pesanan menjadi Rp 25.000.

flowchart TD
    A[Setup: Buat Produk Utama 'Matcha Milk Tea'] --> B{Ada Variasi Harga/Stok?}
    B -- Tidak --> C[Simpan sebagai Produk Tunggal]
    B -- Ya --> D[Buat Grup Varian 'Ukuran']
    
    D --> E["Tambah Opsi: Reguler (+Rp 0)"]
    D --> F["Tambah Opsi: Large (+Rp 5.000)"]
    
    E --> G[Set SKU Varian & Stok]
    F --> G
    
    G --> H[Simpan Relasi Induk & Anak ke Database]
    
    H --> I[Operasional Kasir: Klik 'Matcha Milk Tea']
    I --> J[Tampilkan Modal Pilih Varian]
    J --> K[Kasir Pilih 'Large']
    K --> L[Hitung: Harga Dasar + Harga Varian]
    L --> M[Masukkan ke Keranjang Rp 25.000]

Teknologi & Infrastruktur

Struktur database untuk varian adalah implementasi klasik dari pola hierarki Induk-Anak (Parent-Child) atau Composite Pattern. Produk dasar bertindak sebagai Parent, sementara varian-variannya adalah Child.

Dalam implementasi kita, varian disimpan dalam tabel terpisah product_variants. Tabel ini merujuk ke tabel utama products. Hal penting di sini adalah pemisahan pencatatan harga. Tabel utama memiliki harga dasar (base price). Tabel varian memiliki kolom price adjustment (penyesuaian harga). Nilai penyesuaian ini bisa positif, negatif, atau nol. Saat kalkulasi total, backend menjumlahkan base_price dari produk induk dengan price_adjustment dari varian terpilih. Ini menjaga konsistensi jika harga dasar produk naik, pengelola tidak perlu mengedit semua harga variannya satu per satu.

Bagi bisnis ritel yang setiap ukurannya memiliki barcode (EAN-13) unik pada kemasannya, tabel varian juga menyediakan kolom unik untuk barcode dan sku. Ini memungkinkan scanner barcode langsung memanggil varian spesifik (misal, langsung memanggil produk Kaos Biru L) tanpa harus melalui produk induknya terlebih dahulu.

Tabel Database Terkait

Nama TabelDeskripsiKolom Penting
productsTabel produk induk (Parent).id, name, base_price, has_variants (boolean flag)
variant_groups(Opsional/Bila kompleks) Kelompok varian (misal: Warna).id, product_id, name
product_variantsDetail kombinasi varian akhir.id, product_id, name (misal: “Biru - L”), sku, barcode, price_adjustment, stock_quantity

Endpoint API

MetodeEndpointFungsi dan Kegunaan
GET/api/v1/products/:id/variantsMengambil seluruh opsi varian untuk satu produk tertentu yang akan ditampilkan di modal kasir.
POST/api/v1/products/:id/variantsMenambahkan opsi varian baru di bawah sebuah produk induk.
PUT/api/v1/products/variants/:variant_idMengubah penyesuaian harga, nama, atau SKU dari sebuah varian.
DELETE/api/v1/products/variants/:variant_idMenghapus varian. Perlu hati-hati agar riwayat transaksi tetap aman.

Keterkaitan dengan Fitur Lain

  1. Sistem Inventori (Stok): Jika produk memiliki varian, maka manajemen stok tidak lagi berada di tingkat produk induk. Produk “Kaos” tidak punya stok. Yang memiliki stok fisik adalah “Kaos Merah S” (misal: 10 pcs) dan “Kaos Biru M” (misal: 5 pcs). Pengurangan dan penambahan barang saat pembelian vendor sepenuhnya mengacu pada ID Varian.
  2. Pemindaian Barcode POS: Saat sebuah produk tidak punya varian, scan barcode mencari di tabel products. Jika menggunakan varian, logika sistem scanner akan memeriksa tabel product_variants terlebih dahulu untuk menemukan kecocokan yang tepat.
  3. Laporan Penjualan: Pemilik bisnis bisa mendapatkan data penjualan di dua level. Level makro: “Berapa total Kaos Desain A yang terjual?” dan level mikro: “Dari seluruh penjualan kaos tersebut, persentase warna apa yang paling laku?”.

Hal Penting yang Perlu Diketahui

  • Penyederhanaan UX Kasir: Menghadapi produk dengan banyak atribut bisa membingungkan kasir. Oleh karena itu, aplikasi frontend merancang modal varian agar kasir harus (wajib) memilih tepat satu opsi varian sebelum bisa melanjutkan. Jika tidak, perhitungan stok dan harga akan error (misal: tidak jelas kaos warna apa yang stoknya harus dikurangi).
  • Flag has_variants: Pada tabel produk induk, kita menempatkan flag boolean has_variants. Ini adalah optimasi query. Kasir bisa tahu secara instan (tanpa query tambahan) apakah saat tombol produk diklik perlu menampilkan pop-up pilihan atau langsung masuk keranjang.
erDiagram
    PRODUCTS ||--|{ PRODUCT_VARIANTS : "dijabarkan menjadi"
    
    PRODUCTS {
        string id PK
        string name "Induk (ex: Kopi Latte)"
        decimal base_price "Harga Dasar (ex: 20000)"
        boolean has_variants "Flag penanda"
    }
    
    PRODUCT_VARIANTS {
        string id PK
        string product_id FK
        string variant_name "Nama Varian (ex: Ukuran Large)"
        decimal price_adjustment "Tambahan harga (ex: +5000)"
        string sku "SKU Khusus Varian"
        int current_stock
    }