A
AddinSync Portal
Admin Sales System

Selamat Datang 👋

Masukkan kredensial Anda untuk melanjutkan

⚠ Email atau password salah. Coba lagi.
👤
🔒
Sistem dilindungi enkripsi
AddinSync Portal v2.0
© 2025 — Hanya untuk pengguna yang berwenang
AddinSync
⏳
Menu Lainnya
📦Sell In
🗺Rekapan
🎯Target
📈Margin
🧾Invoice
📑Reporting
☁️Backup & Export
📌SOP
🗄Setup DB
⬇Export CSV
🖨Cetak
AddinSync Portal · Supabase
Utama
Laporan Harian
Gudang & Logistik
Keuangan & Analitik
Analitik & Laporan
Referensi
Dashboard
—
🔔 Notifikasi & Alert
Memuat alert…
⏳ Memuat…
Dashboard Penjualan
Ringkasan performa real-time — Semua Produk
Total Setoran
—
Semua sales bulan ini
Karton Terjual
—
Total semua sales
NOO (Outlet Baru)
—
New Outlet Opening
Laba Bersih Owner
—
Margin setelah komisi
Semua Data Terbaru
#TanggalSales Stok AwalStok AkhirTerjual (krt) Setoran (Rp)Laba Owner (Rp) StatusInvoice
Sell In — Barang Masuk
Master barang & pencatatan stok masuk dari supplier
⚠ Tabel koling_sellin belum ada di Supabase. Data Sell In hanya tersimpan di browser ini saja. Buka Setup Database → copy SQL terbaru → jalankan di Supabase SQL Editor → klik 🔄 Refresh. Data lama akan otomatis dipindah ke Supabase.
⚙️ Konfigurasi Satuan Produk
Atur komposisi karton untuk setiap produk. Dipakai untuk kalkulasi stok otomatis.
Tambah Produk Baru
Satuan antara Karton dan Pcs
Contoh: 10 Renceng/Karton
Contoh: 10 Pcs/Renceng
—
Akan dihitung otomatis
📐 Preview: —
# Nama Produk Satuan Tengah Isi per Karton Isi per Satuan Tengah Total Pcs/Karton Formula Tipe Aksi
Input Barang Masuk dari Supplier
Harga beli/modal dari supplier per 1 karton
—
Isi harga modal karton untuk kalkulasi otomatis
—
—
Isi jumlah di atas untuk kalkulasi otomatis
📦 Rekap Stok per Produk Sell In − Sell Out = Stok Akhir (dalam Pcs)
# Nama Produk Satuan Sell In (Pcs) Sell In (Karton) Sell Out (Pcs) Sell Out (Karton) Stok Akhir (Pcs) Stok Akhir (Karton) Status Stok
📋 Riwayat Barang Masuk
#TanggalNama ProdukSupplier KartonPack/RencengPcsTotal Unit Terkecil Harga Modal/Krt Aksi
Master Outlet
Daftarkan outlet terlebih dahulu — kode outlet dibuat otomatis oleh sistem
🏪 Form Pendaftaran Outlet Baru
Isi semua data outlet. Kode outlet akan dibuat otomatis setelah disimpan.
— akan muncul setelah simpan —
🏪 Daftar Outlet Terdaftar  0 outlet
# Kode Outlet Nama Outlet Tipe Alamat Lengkap Kota Contact Person No. HP / WA Tgl. Daftar Aksi
Input Laporan Penjualan
Input sekali untuk 1 toko — tambah produk sebanyak yang diinginkan
📋 Data Sales & Toko
—
🛒 Item Pesanan Toko
Total Nominal Pesanan
—
Rp 0
Laporan Salesman
Pilih tanggal, sales, dan outlet untuk melihat detail laporan
🔍 Filter Laporan
Pilih tanggal dan sales di atas untuk menampilkan laporan.
Rekapan Salesman
Pilih tanggal, sales, dan outlet untuk melihat rekap kunjungan
Pilih tanggal di atas untuk menampilkan rekapan.
Rekap Loading Barang
Total kebutuhan barang per produk dari semua order outlet pada tanggal terpilih — untuk siapkan loading gudang
Total Outlet Order
0
Outlet unik tanggal ini
Total Transaksi
0
Baris order tercatat
Jenis Produk
0
Produk berbeda dipesan
Total Karton
0
Semua produk digabung
📦 Total Kebutuhan Per Produk  0 produk
# Nama Produk Total Karton Total Satuan Tengah Total Pcs Jml Outlet Pesan
🏪 Rincian Per Outlet  0 outlet
# Outlet Sales Produk Karton Satuan Tengah Total (Rp)
Stock Opname Gudang
Bandingkan stok sistem vs stok fisik hasil hitung gudang — cegah selisih barang
Produk Sudah Opname Hari Ini
0
dari 0 produk aktif
Produk Selisih (≠ 0)
0
Perlu pengecekan ulang
Selisih Minus Terbesar
0 krt
Indikasi barang hilang/kurang
Status Hari Ini
—
—
🗂 Input Stock Opname
Hitung fisik barang di gudang lalu input di sini. Stok sistem akan ditampilkan otomatis sebagai pembanding.
Produk Stok Sistem (Krt) Stok Fisik — Karton + Satuan Tengah + Pcs Selisih (Krt)
📜 Histori Stock Opname  0 catatan
# Tanggal Produk Stok Sistem Stok Fisik Selisih Petugas Catatan
Monitoring Margin Harian
Terintegrasi dari data laporan — analisis margin per tim per hari
#TanggalSales Krt Terjual Setoran (Rp)Margin (Rp) StatusCatatan
Manajemen Piutang
Pantau status pembayaran outlet — Cash, Tempo, Jatuh Tempo, dan Lunas
Total Piutang Aktif
Rp 0
Belum lunas, semua outlet
Jumlah Transaksi Tempo
0
Transaksi belum lunas
Sudah Jatuh Tempo
0
Lewat tanggal jatuh tempo
Lunas Bulan Ini
Rp 0
Total pembayaran diterima
💳 Daftar Transaksi  0 transaksi
# Tanggal Outlet Sales Total Tagihan Sudah Dibayar Sisa Piutang Jatuh Tempo Status Aksi
Laporan Laba Rugi
Pendapatan, HPP, dan Beban Operasional — otomatis sesuai periode yang dipilih
Pendapatan (Omzet)
Rp 0
—
Laba Kotor
Rp 0
Pendapatan − HPP
Laba Bersih
Rp 0
Setelah beban operasional
Margin Bersih
0%
Laba Bersih / Pendapatan
LAPORAN LABA RUGI
Laporan Keuangan — Periode: —
PENDAPATAN Rp 0
Total Penjualan (Omzet) Rp 0
HARGA POKOK PENJUALAN (HPP)(Rp 0)
Modal Barang TerjualRp 0
LABA KOTOR Rp 0
BEBAN OPERASIONAL(Rp 0)
Gaji Pokok + Subsidi SalesRp 0
Komisi + Bonus + Kicker SalesRp 0
LABA BERSIH Rp 0
📦 Breakdown Per Produk
# Produk Krt Terjual Pendapatan HPP Laba Kotor
👥 Breakdown Per Sales
Sales Krt Terjual Pendapatan Beban Gaji+Komisi Kontribusi Laba
ℹ️ Pendapatan dihitung berbasis akrual — nilai transaksi penuh diakui sesuai harga jual saat terjadi, termasuk transaksi yang masih piutang/tempo dan belum lunas dibayar outlet. Lihat menu Manajemen Piutang untuk status penagihan.
💳 Catat Pembayaran Piutang
⚙️ Pengaturan Notifikasi & Alert
Format bebas (boleh 08xx atau 62xx) — alert akan dikirim ke nomor ini via WhatsApp.
Stok Menipis
Target Tidak Tercapai
Sales Belum Input Laporan
Buat Invoice
Generate invoice untuk outlet / pedagang — siap cetak
🧾 Pilih Data untuk Invoice
Pilih tanggal, sales, dan outlet — produk otomatis masuk ke invoice
Produk untuk Invoice
No. Invoice
INV-0001
Tanggal: —
Payment: Tunai / Transfer
Sales: — · —
Dari
Addin Jaya
Tangerang, Indonesia
Kepada
—
—
—
NoKodeNama ProdukQtyHargaAmount
TOTAL TAGIHAN—
Total yang harus dibayar
Rp 0
Metode Pembayaran
Tunai / Transfer
Terima kasih telah berlangganan !
Hubungi kami melalui WhatsApp untuk order & informasi.
Jakarta, —
Admin / Sales
Reporting Penjualan
Tarik data periode tertentu · analisa otomatis · grafik interaktif
🔍 Filter Data
Periode Cepat:
Total Setoran
—
Karton Terjual
—
NOO
—
Outlet baru diperoleh
Laba Bersih Owner
—
📈 Tren Setoran Harian
Total setoran per hari dalam periode
📦 Tren Karton Terjual
Karton terjual per hari vs target
👤 Performa per Sales
Perbandingan total karton & setoran tiap sales
🥧 Kontribusi per Tim
Porsi setoran per sales
🤖 Analisa Otomatis
👤 Ringkasan Per Sales
#Nama Sales Hari Kerja Total Krt Rata²/Hari NOO Total Setoran Total Komisi Total THP Laba Owner Performa
📋 Detail Transaksi
#TanggalNama Sales Nama OutletNama Produk Terjual (krt)NOO Setoran (Rp) THP SalesLaba OwnerStatus
TOTAL PERIODE — — — — —
📑
Belum ada data ditarik
Atur filter di atas lalu klik Tarik Data & Analisa
Target & Pencapaian Sales
Set target individual per sales per bulan dan tracking pencapaian otomatis
Set Target Sales
— isi target bulanan dulu
Sales Punya Target
0
—
Capai Target
0
Sales sudah ≥ 100%
Di Bawah Target
0
Perlu perhatian
Rata-rata Pencapaian
—%
Dari semua sales bertarget
📊 Tracking Pencapaian per Sales
# Nama Sales Target (Krt) Target/Hari Sudah Terjual Sisa Target Hari Kerja Avg/Hari Pencapaian Proyeksi Akhir Bulan Aksi
📋 Riwayat Target
# Periode Nama Sales Target Bulan (Krt) Target/Hari Catatan Aksi
Backup & Export Data
Backup otomatis terjadwal, export laporan ke PDF/Excel, dan riwayat backup
Backup Terakhir
Belum pernah
—
Status Jadwal Otomatis
Nonaktif
Jalan otomatis saat aplikasi dibuka
Total Record Saat Ini
0
Transaksi penjualan tersimpan
⏰ Backup Otomatis Terjadwal
Backup akan otomatis ter-download ke folder Download perangkat Anda sesuai interval yang dipilih, setiap kali aplikasi ini sedang dibuka di browser. Backup tidak berjalan jika aplikasi/tab ditutup.
💡 Tips: Karena aplikasi ini berjalan di browser tanpa server sendiri, backup terjadwal hanya bisa berjalan saat aplikasi dibuka. Untuk keamanan data maksimal, kombinasikan dengan backup manual rutin dan pastikan data Supabase Anda juga di-backup dari sisi Supabase (Database → Backups).
⬇ Export Cepat — Semua Data
File Excel (.xlsx) bisa langsung Anda upload ke Google Drive lalu buka dengan Google Sheets (klik kanan file → Buka dengan → Google Sheets), atau drag-and-drop langsung ke Google Sheets untuk import sebagai sheet baru.
📄 Export PDF per Laporan
Tombol "📄 Export PDF" tersedia di pojok kanan atas masing-masing halaman laporan setelah filter/data dimuat.
📜 Riwayat Backup (Sesi Ini)
#WaktuJenisFormatJumlah RecordPemicu
Belum ada riwayat backup pada sesi ini.
SOP & Strategi Operasional
Standar Prosedur Operasional Harian — Tim Sales & Distribusi
⏰ Persiapan Pagi
1. Briefing Pagi
Evaluasi penjualan hari sebelumnya. Tetapkan rute kunjungan & target hari ini. Bahas kendala yang muncul.
2. Cek Kendaraan
Pastikan kondisi kendaraan layak jalan dan bahan bakar cukup untuk rute hari ini.
3. Stock Loading
Ambil barang dari gudang sesuai rencana penjualan. Cek kondisi kemasan & segel sebelum berangkat.
4. Administrasi
Tanda tangan Surat Jalan. Catat stok awal di form laporan harian sebelum berangkat.
🏃 Aktivitas Lapangan
Sales – Kunjungan Rutin
Ikuti rute kunjungan outlet existing sesuai jadwal. Pasang materi promosi di outlet baru bila ada kesempatan.
Sales – Pengembangan Pasar
Cari dan dekati calon pelanggan/outlet baru di luar rute rutin untuk perluasan jaringan distribusi.
Reporting Lapangan
Kirim share location ke grup koordinasi saat tiba di titik kunjungan pertama dan terakhir hari itu.
Penanganan Kompetitor
Pahami kelebihan produk dibanding kompetitor di pasar. Tawarkan fleksibilitas pembelian sesuai kebutuhan outlet.
🧾 Settlement Sore
1. Stock Check
Hitung sisa barang yang dibawa. Cocokkan dengan catatan stok awal sebelum berangkat.
2. Cash Audit
Cocokkan selisih stok terjual dengan nominal setoran. Simpan foto nota/struk outlet sebagai bukti.
3. Update Database
Laporkan data outlet/pelanggan baru yang didapat hari ini ke admin untuk dimasukkan ke sistem.
4. Submit Laporan
Input laporan penjualan harian ke aplikasi sebelum jam kerja berakhir.
🏆 Strategi Bersaing di Pasar
1. Perbandingan Objektif
Pahami kelebihan produk dibanding kompetitor — kualitas, kesegaran, atau keunikan — dan sampaikan secara jujur ke calon pelanggan.
2. Fleksibilitas Order
Tawarkan opsi pembelian dalam jumlah kecil maupun besar sesuai kebutuhan dan skala outlet pelanggan.
3. Program Loyalitas
Berikan insentif atau bonus untuk pelanggan dengan pembelian rutin guna menjaga loyalitas jangka panjang.
4. Insentif Pencapaian
Sales yang melampaui target mendapat insentif tambahan di luar skema komisi reguler.
Setup Database Supabase
Panduan & SQL untuk membuat tabel di Supabase
🔒 Setup Keamanan Login — WAJIB Dilakukan
Aplikasi ini memakai Supabase Auth (login sungguhan, terenkripsi) — bukan password tertulis di kode. Ikuti 3 langkah di bawah sebelum aplikasi bisa dipakai.
Langkah 1 — Buat Akun Login di Supabase
Buka Supabase Dashboard → project Anda → sidebar kiri Authentication → tab Users → klik Add User → Create new user.
Isi Email dan Password akun Anda. Centang Auto Confirm User supaya bisa langsung login tanpa verifikasi email. Klik Create User.
Ulangi untuk setiap orang yang perlu akses (misal 1 akun untuk Anda sebagai admin, 1 akun lagi untuk owner/rekan bisnis).
Langkah 2 — Jalankan SQL Keamanan di Bawah
Copy SQL pada kartu "🔒 SQL — Aktifkan Keamanan Login" di bawah ini → paste ke SQL Editor Supabase → klik Run.
SQL ini akan otomatis membuatkan profil role untuk akun yang baru Anda buat di Langkah 1, dan mengunci seluruh tabel supaya hanya bisa diakses oleh akun yang login.
Langkah 3 — Tetapkan Role (Admin / Owner)
Secara default, akun baru otomatis mendapat role "owner" (bisa lihat semua data & laporan, tapi tidak bisa menghapus data).
Untuk menjadikan akun Anda sebagai "admin" (akses penuh termasuk hapus data), buka Table Editor → tabel profiles → cari baris dengan email Anda → ubah kolom role dari owner menjadi admin → Save.
💡 Setelah 3 langkah ini selesai, login dengan email & password yang Anda buat di Langkah 1. Sistem login lama (username admin/owner/manajer dengan password tertulis di kode) sudah tidak berlaku lagi dan datanya tidak bisa lagi diakses publik tanpa login.
🔒 SQL — Aktifkan Keamanan Login (Jalankan Setelah Langkah 1)
-- ════════════════════════════════════════════════════════════
-- SETUP KEAMANAN — SUPABASE AUTH + ROW LEVEL SECURITY
-- ════════════════════════════════════════════════════════════
-- PENTING: Jalankan SQL ini SETELAH Anda membuat akun login
-- di Authentication → Users (lihat panduan di atas).
-- SQL ini akan mengganti sistem keamanan lama (allow_all / publik)
-- menjadi: HANYA user yang login via Supabase Auth yang bisa akses data.

-- 1. Tabel PROFILES — menyimpan role tiap akun (admin / owner)
CREATE TABLE IF NOT EXISTS profiles (
  id          uuid PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
  email       text,
  role        text NOT NULL DEFAULT 'owner' CHECK (role IN ('admin','owner')),
  nama        text DEFAULT '',
  created_at  timestamptz DEFAULT now()
);
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;

-- Setiap user hanya boleh baca profil dirinya sendiri & semua user lain boleh dibaca (untuk tampilkan nama)
DROP POLICY IF EXISTS "profiles_select_own" ON profiles;
CREATE POLICY "profiles_select_own" ON profiles FOR SELECT USING (auth.uid() = id);

-- Hanya boleh update profil sendiri (bukan ganti role sendiri jadi admin!)
DROP POLICY IF EXISTS "profiles_update_own" ON profiles;
CREATE POLICY "profiles_update_own" ON profiles FOR UPDATE USING (auth.uid() = id);

-- Trigger otomatis: setiap kali ada user baru daftar via Supabase Auth,
-- otomatis dibuatkan row di profiles dengan role default 'owner'.
-- (Ubah role jadi 'admin' manual lewat Table Editor setelah akun dibuat)
CREATE OR REPLACE FUNCTION handle_new_user()
RETURNS trigger AS $$
BEGIN
  INSERT INTO public.profiles (id, email, role)
  VALUES (new.id, new.email, 'owner')
  ON CONFLICT (id) DO NOTHING;
  RETURN new;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users;
CREATE TRIGGER on_auth_user_created
  AFTER INSERT ON auth.users
  FOR EACH ROW EXECUTE FUNCTION handle_new_user();

-- Fungsi bantu: cek apakah user yang sedang login adalah admin
CREATE OR REPLACE FUNCTION is_admin()
RETURNS boolean AS $$
  SELECT EXISTS (
    SELECT 1 FROM profiles WHERE id = auth.uid() AND role = 'admin'
  );
$$ LANGUAGE sql SECURITY DEFINER STABLE;

-- ════════════════════════════════════════════════════════════
-- 2. HAPUS SEMUA POLICY LAMA YANG MENGIZINKAN AKSES PUBLIK (anon)
-- ════════════════════════════════════════════════════════════
DROP POLICY IF EXISTS "Allow anon read"   ON koling_penjualan;
DROP POLICY IF EXISTS "Allow anon insert" ON koling_penjualan;
DROP POLICY IF EXISTS "Allow anon delete" ON koling_penjualan;
DROP POLICY IF EXISTS "Allow anon update" ON koling_penjualan;

DROP POLICY IF EXISTS "Allow anon read"   ON koling_sellin;
DROP POLICY IF EXISTS "Allow anon insert" ON koling_sellin;
DROP POLICY IF EXISTS "Allow anon delete" ON koling_sellin;
DROP POLICY IF EXISTS "Allow anon update" ON koling_sellin;

DROP POLICY IF EXISTS "Allow anon read"   ON koling_outlet;
DROP POLICY IF EXISTS "Allow anon insert" ON koling_outlet;
DROP POLICY IF EXISTS "Allow anon delete" ON koling_outlet;
DROP POLICY IF EXISTS "Allow anon update" ON koling_outlet;

DROP POLICY IF EXISTS "Allow anon read"   ON koling_piutang_bayar;
DROP POLICY IF EXISTS "Allow anon insert" ON koling_piutang_bayar;
DROP POLICY IF EXISTS "Allow anon delete" ON koling_piutang_bayar;
DROP POLICY IF EXISTS "Allow anon update" ON koling_piutang_bayar;

DROP POLICY IF EXISTS "Allow anon read"   ON koling_stock_opname;
DROP POLICY IF EXISTS "Allow anon insert" ON koling_stock_opname;
DROP POLICY IF EXISTS "Allow anon delete" ON koling_stock_opname;
DROP POLICY IF EXISTS "Allow anon update" ON koling_stock_opname;

DROP POLICY IF EXISTS "allow_all_targets" ON koling_targets;

-- ════════════════════════════════════════════════════════════
-- 3. POLICY BARU — HANYA USER LOGIN (authenticated) YANG BOLEH AKSES
--    Semua role (admin & owner) boleh READ, INSERT, UPDATE.
--    HANYA admin yang boleh DELETE.
-- ════════════════════════════════════════════════════════════

-- koling_penjualan
CREATE POLICY "auth_read_penjualan"   ON koling_penjualan FOR SELECT USING (auth.role() = 'authenticated');
CREATE POLICY "auth_insert_penjualan" ON koling_penjualan FOR INSERT WITH CHECK (auth.role() = 'authenticated');
CREATE POLICY "auth_update_penjualan" ON koling_penjualan FOR UPDATE USING (auth.role() = 'authenticated') WITH CHECK (auth.role() = 'authenticated');
CREATE POLICY "admin_delete_penjualan" ON koling_penjualan FOR DELETE USING (is_admin());

-- koling_sellin
CREATE POLICY "auth_read_sellin"   ON koling_sellin FOR SELECT USING (auth.role() = 'authenticated');
CREATE POLICY "auth_insert_sellin" ON koling_sellin FOR INSERT WITH CHECK (auth.role() = 'authenticated');
CREATE POLICY "auth_update_sellin" ON koling_sellin FOR UPDATE USING (auth.role() = 'authenticated') WITH CHECK (auth.role() = 'authenticated');
CREATE POLICY "admin_delete_sellin" ON koling_sellin FOR DELETE USING (is_admin());

-- koling_outlet
CREATE POLICY "auth_read_outlet"   ON koling_outlet FOR SELECT USING (auth.role() = 'authenticated');
CREATE POLICY "auth_insert_outlet" ON koling_outlet FOR INSERT WITH CHECK (auth.role() = 'authenticated');
CREATE POLICY "auth_update_outlet" ON koling_outlet FOR UPDATE USING (auth.role() = 'authenticated') WITH CHECK (auth.role() = 'authenticated');
CREATE POLICY "admin_delete_outlet" ON koling_outlet FOR DELETE USING (is_admin());

-- koling_piutang_bayar
CREATE POLICY "auth_read_piutang"   ON koling_piutang_bayar FOR SELECT USING (auth.role() = 'authenticated');
CREATE POLICY "auth_insert_piutang" ON koling_piutang_bayar FOR INSERT WITH CHECK (auth.role() = 'authenticated');
CREATE POLICY "auth_update_piutang" ON koling_piutang_bayar FOR UPDATE USING (auth.role() = 'authenticated') WITH CHECK (auth.role() = 'authenticated');
CREATE POLICY "admin_delete_piutang" ON koling_piutang_bayar FOR DELETE USING (is_admin());

-- koling_stock_opname
CREATE POLICY "auth_read_opname"   ON koling_stock_opname FOR SELECT USING (auth.role() = 'authenticated');
CREATE POLICY "auth_insert_opname" ON koling_stock_opname FOR INSERT WITH CHECK (auth.role() = 'authenticated');
CREATE POLICY "auth_update_opname" ON koling_stock_opname FOR UPDATE USING (auth.role() = 'authenticated') WITH CHECK (auth.role() = 'authenticated');
CREATE POLICY "admin_delete_opname" ON koling_stock_opname FOR DELETE USING (is_admin());

-- koling_targets
CREATE POLICY "auth_read_targets"   ON koling_targets FOR SELECT USING (auth.role() = 'authenticated');
CREATE POLICY "auth_insert_targets" ON koling_targets FOR INSERT WITH CHECK (auth.role() = 'authenticated');
CREATE POLICY "auth_update_targets" ON koling_targets FOR UPDATE USING (auth.role() = 'authenticated') WITH CHECK (auth.role() = 'authenticated');
CREATE POLICY "admin_delete_targets" ON koling_targets FOR DELETE USING (is_admin());

SELECT 'Keamanan database berhasil diaktifkan! Hanya user login yang bisa akses data. ✅' AS status;
📋 Informasi Koneksi
Supabase Project URL
https://geqqiippwyadiofoifuw.supabase.co
Nama Tabel
koling_penjualan
Status
Memeriksa…
🚀 Langkah Setup
1. Buka Supabase Dashboard
Login ke supabase.com → pilih project Anda
2. Buka SQL Editor
Sidebar kiri → SQL Editor → New Query
3. Jalankan SQL di bawah
Copy SQL di bawah → paste → klik Run
4. Test Koneksi
Klik tombol 🔌 Test Koneksi di pojok kanan atas
🗄 SQL — Buat Tabel koling_penjualan
-- Jalankan SQL ini di Supabase SQL Editor
-- Dashboard → SQL Editor → New Query → paste → Run

CREATE TABLE IF NOT EXISTS koling_penjualan (
  id          bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  created_at  timestamptz DEFAULT now(),
  tgl         date NOT NULL,
  nama        text NOT NULL,
  -- kolom tim dihapus (sistem tidak lagi menggunakan Tim 1/Tim 2)
  awal        numeric DEFAULT 0,
  akhir       numeric DEFAULT 0,
  terjual     numeric DEFAULT 0,
  noo         int  DEFAULT 0,
  outlet      text DEFAULT '',
  alamat      text DEFAULT '',
  hp          text DEFAULT '',
  produk      text DEFAULT 'Produk A',
  setoran     numeric DEFAULT 0,
  kom_dasar   numeric DEFAULT 0,
  bonus       numeric DEFAULT 0,
  kick        numeric DEFAULT 0,
  tot_kom     numeric DEFAULT 0,
  thp         numeric DEFAULT 0,
  laba        numeric DEFAULT 0,
  status_bayar  text DEFAULT 'cash',
  jatuh_tempo   date,
  sisa_piutang  numeric DEFAULT 0,
  created_by    text DEFAULT ''   -- email user yang menginput data ini (audit trail)
);

-- Jika tabel sudah ada sebelumnya, tambahkan kolom baru ini (aman dijalankan berulang):
ALTER TABLE koling_penjualan ADD COLUMN IF NOT EXISTS status_bayar text DEFAULT 'cash';
ALTER TABLE koling_penjualan ADD COLUMN IF NOT EXISTS jatuh_tempo date;
ALTER TABLE koling_penjualan ADD COLUMN IF NOT EXISTS sisa_piutang numeric DEFAULT 0;
ALTER TABLE koling_penjualan ADD COLUMN IF NOT EXISTS terjual_ren numeric DEFAULT 0;
ALTER TABLE koling_penjualan ADD COLUMN IF NOT EXISTS created_by text DEFAULT '';

-- PENTING: Jika tabel lama Anda masih punya kolom "tim" (Tim 1/Tim 2),
-- jalankan baris ini untuk menghapusnya total beserta seluruh datanya:
ALTER TABLE koling_penjualan DROP COLUMN IF EXISTS tim;

-- Aktifkan Row Level Security (RLS)
ALTER TABLE koling_penjualan ENABLE ROW LEVEL SECURITY;

-- Tabel Target Sales Individual
CREATE TABLE IF NOT EXISTS koling_targets (
  id          bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  created_at  timestamptz DEFAULT now(),
  nama        text NOT NULL,
  periode     text NOT NULL,
  target_krt_bulan numeric DEFAULT 0,
  target_krt_harian numeric DEFAULT 0,
  catatan     text DEFAULT ''
);
ALTER TABLE koling_targets ENABLE ROW LEVEL SECURITY;

-- ⚠️ CATATAN KEAMANAN: Policy akses (siapa boleh baca/tulis/hapus) TIDAK
-- dibuat di sini secara sengaja. Jalankan SQL pada kartu
-- "🔒 SQL — Aktifkan Keamanan Login" di atas untuk mengatur akses yang aman
-- (hanya user yang login via Supabase Auth yang bisa mengakses data ini).

-- Index untuk performa query berdasarkan tanggal
CREATE INDEX IF NOT EXISTS idx_koling_tgl  ON koling_penjualan (tgl DESC);
CREATE INDEX IF NOT EXISTS idx_koling_nama ON koling_penjualan (nama);

-- Verifikasi tabel berhasil dibuat
SELECT 'Tabel koling_penjualan berhasil dibuat! ✅' AS status;

-- ──────────────────────────────────────────────
-- TABEL SELL IN (Barang Masuk) — jalankan juga!
-- ──────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS koling_sellin (
  id          bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  created_at  timestamptz DEFAULT now(),
  tgl         date NOT NULL,
  produk      text NOT NULL,
  supplier    text DEFAULT '',
  qty_krt     numeric DEFAULT 0,
  qty_ren     numeric DEFAULT 0,
  total_ren   numeric DEFAULT 0,
  harga_modal numeric DEFAULT 0
);

ALTER TABLE koling_sellin ENABLE ROW LEVEL SECURITY;
-- ⚠️ Policy akses diatur di kartu "🔒 SQL — Aktifkan Keamanan Login" di atas.
CREATE INDEX IF NOT EXISTS idx_sellin_tgl ON koling_sellin (tgl DESC);

SELECT 'Tabel koling_sellin berhasil dibuat! ✅' AS status;

-- ──────────────────────────────────────────────
-- TABEL MASTER OUTLET — jalankan juga!
-- ──────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS koling_outlet (
  id          bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  created_at  timestamptz DEFAULT now(),
  kode_outlet text NOT NULL UNIQUE,
  nama        text NOT NULL,
  tipe        text DEFAULT 'warung',
  alamat      text DEFAULT '',
  kecamatan   text DEFAULT '',
  kota        text DEFAULT '',
  hp          text DEFAULT '',
  contact_person text DEFAULT '',
  catatan     text DEFAULT ''
);

ALTER TABLE koling_outlet ENABLE ROW LEVEL SECURITY;
-- ⚠️ Policy akses diatur di kartu "🔒 SQL — Aktifkan Keamanan Login" di atas.
CREATE INDEX IF NOT EXISTS idx_outlet_nama ON koling_outlet (nama);
CREATE INDEX IF NOT EXISTS idx_outlet_kode ON koling_outlet (kode_outlet);

SELECT 'Tabel koling_outlet berhasil dibuat! ✅' AS status;

-- ──────────────────────────────────────────────
-- TABEL HISTORI PEMBAYARAN PIUTANG — jalankan juga!
-- ──────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS koling_piutang_bayar (
  id           bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  created_at   timestamptz DEFAULT now(),
  penjualan_id bigint NOT NULL,
  tgl_bayar    date NOT NULL,
  jumlah_bayar numeric NOT NULL DEFAULT 0,
  metode       text DEFAULT 'cash',
  catatan      text DEFAULT ''
);

ALTER TABLE koling_piutang_bayar ENABLE ROW LEVEL SECURITY;
-- ⚠️ Policy akses diatur di kartu "🔒 SQL — Aktifkan Keamanan Login" di atas.
CREATE INDEX IF NOT EXISTS idx_piutang_bayar_pjid ON koling_piutang_bayar (penjualan_id);

SELECT 'Tabel koling_piutang_bayar berhasil dibuat! ✅' AS status;

-- ──────────────────────────────────────────────
-- TABEL STOCK OPNAME GUDANG — jalankan juga!
-- ──────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS koling_stock_opname (
  id            bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  created_at    timestamptz DEFAULT now(),
  tgl           date NOT NULL,
  produk        text NOT NULL,
  stok_sistem_krt   numeric DEFAULT 0,
  stok_fisik_krt    numeric DEFAULT 0,
  stok_fisik_tengah numeric DEFAULT 0,
  stok_fisik_pcs    numeric DEFAULT 0,
  selisih_krt   numeric DEFAULT 0,
  catatan       text DEFAULT '',
  petugas       text DEFAULT ''
);

ALTER TABLE koling_stock_opname ENABLE ROW LEVEL SECURITY;
-- ⚠️ Policy akses diatur di kartu "🔒 SQL — Aktifkan Keamanan Login" di atas.
CREATE INDEX IF NOT EXISTS idx_opname_tgl ON koling_stock_opname (tgl);
CREATE INDEX IF NOT EXISTS idx_opname_produk ON koling_stock_opname (produk);

SELECT 'Tabel koling_stock_opname berhasil dibuat! ✅' AS status;
🚨 WAJIB JALANKAN INI — Fix Kolom Harga Modal
Tabel koling_sellin Anda belum punya kolom harga_modal. Jalankan SQL ini dulu, baru bisa simpan barang masuk.
-- ⚠️ JALANKAN INI DI SUPABASE SQL EDITOR
-- Dashboard Supabase → SQL Editor → New Query → Paste → Run

-- Tambah kolom harga_modal jika belum ada
ALTER TABLE koling_sellin ADD COLUMN IF NOT EXISTS harga_modal numeric DEFAULT 0;

-- Verifikasi berhasil
SELECT column_name, data_type FROM information_schema.columns
WHERE table_name = 'koling_sellin' AND column_name = 'harga_modal';
⚠️ Hapus Semua Data
Hapus seluruh data penjualan dan sell in dari database Supabase. Tindakan ini tidak dapat dibatalkan.
✏️ Edit Barang Masuk
📦 Data Barang
💰 Harga Modal
Isi / perbarui harga modal dari supplier per karton
—
Isi harga modal untuk kalkulasi otomatis
📊 Jumlah Barang
—
✏️ Edit Data Penjualan
📋 Data Sales & Toko
🛒 Data Produk & Penjualan