// Mock data — CV Mitra Logistik (distributor sparepart otomotif, 3 gudang)

const TENANT = {
  name: 'CV Mitra Logistik',
  legal: 'CV Mitra Logistik Nusantara',
  short: 'ML',
  npwp: '02.456.789.1-407.000',
  address: 'Kawasan Industri MM2100 Blok B-12, Cikarang',
  phone: '021-8983-4421',
  segment: 'Distribusi sparepart otomotif & oli industri',
};

const GUDANG_LIST = [
  { id: 'pusat',     name: 'Gudang Pusat — Cikarang',  kota: 'Cikarang',  kapasitas_m3: 4800, area_m2: 2400, kepala: 'Suparman' },
  { id: 'bandung',   name: 'Gudang Bandung',           kota: 'Bandung',   kapasitas_m3: 1800, area_m2:  900, kepala: 'Eko Riyadi' },
  { id: 'surabaya',  name: 'Gudang Surabaya',          kota: 'Surabaya',  kapasitas_m3: 2400, area_m2: 1200, kepala: 'Hartono' },
];

const PERIOD_LIST = [
  { id: '2026-02', label: 'Februari 2026' },
  { id: '2026-03', label: 'Maret 2026' },
  { id: '2026-04', label: 'April 2026' },
  { id: '2026-05', label: 'Mei 2026' },
];
const CURRENT_PERIOD = '2026-04';
const TODAY = '2026-04-22';

const ROLES = {
  gudang: {
    id: 'gudang',
    name: 'Joko Susilo',
    title: 'Operator Gudang',
    initials: 'JS',
    can: { receive: true, issue: true, transfer: true, opname: true, edit_master: false, view_report: false, approve: false },
  },
  kepala: {
    id: 'kepala',
    name: 'Suparman',
    title: 'Kepala Gudang Pusat',
    initials: 'SP',
    can: { receive: true, issue: true, transfer: true, opname: true, edit_master: true, view_report: true, approve: true },
  },
  manajer: {
    id: 'manajer',
    name: 'Linda Hartati',
    title: 'Manajer Operasional',
    initials: 'LH',
    can: { receive: false, issue: false, transfer: false, opname: false, edit_master: true, view_report: true, approve: true },
  },
};

// Kategori sparepart
const KATEGORI = [
  { id: 'all',     label: 'Semua' },
  { id: 'oli',     label: 'Oli & Pelumas' },
  { id: 'filter',  label: 'Filter' },
  { id: 'rem',     label: 'Sistem Rem' },
  { id: 'kelistrikan', label: 'Kelistrikan' },
  { id: 'mesin',   label: 'Komponen Mesin' },
  { id: 'ban',     label: 'Ban & Velg' },
  { id: 'aksesori', label: 'Aksesori' },
];

// Suppliers
const SUPPLIERS = [
  { id: 'SUP-001', name: 'PT Pertamina Lubricants',  contact: 'Bp. Yusuf',     phone: '021-7821-3300', term: 'NET 30' },
  { id: 'SUP-002', name: 'PT Astra Otoparts Tbk',    contact: 'Ibu Maya',      phone: '021-4603-9000', term: 'NET 45' },
  { id: 'SUP-003', name: 'PT Selamat Sempurna',      contact: 'Bp. Agung',     phone: '021-5316-0808', term: 'NET 30' },
  { id: 'SUP-004', name: 'PT Indomobil Suzuki Intl', contact: 'Ibu Ratna',     phone: '021-3911-7100', term: 'NET 60' },
  { id: 'SUP-005', name: 'CV Karya Sentosa',         contact: 'Bp. Hadi',      phone: '022-7234-1102', term: 'NET 14' },
  { id: 'SUP-006', name: 'PT Federal Karyatama',     contact: 'Ibu Fitri',     phone: '021-8089-5500', term: 'NET 30' },
];

// Customers (bengkel/toko)
const CUSTOMERS = [
  { id: 'CUS-001', name: 'Bengkel Maju Jaya Motor',   kota: 'Bekasi',    kontak: 'Bp. Surya',  term: 'NET 14' },
  { id: 'CUS-002', name: 'Toko Sparepart Sumber Rejeki', kota: 'Karawang', kontak: 'Bp. Anton', term: 'NET 30' },
  { id: 'CUS-003', name: 'PT Lautan Berkah Mandiri',  kota: 'Jakarta',   kontak: 'Ibu Wina',   term: 'NET 30' },
  { id: 'CUS-004', name: 'Bengkel Resmi Honda Cibinong', kota: 'Bogor',  kontak: 'Bp. Eko',    term: 'NET 14' },
  { id: 'CUS-005', name: 'CV Roda Mas Bandung',       kota: 'Bandung',   kontak: 'Bp. Dedi',   term: 'NET 30' },
  { id: 'CUS-006', name: 'Bengkel Surabaya Motor',    kota: 'Surabaya',  kontak: 'Bp. Hari',   term: 'NET 14' },
  { id: 'CUS-007', name: 'Toko Sentral Otomotif',     kota: 'Sidoarjo',  kontak: 'Ibu Lia',    term: 'NET 30' },
];

// Master SKU (~36 items, sparepart otomotif)
const PRODUCTS = [
  // Oli
  { sku: 'OLI-PT-5W30-4L',  barcode: '8997012001011', name: 'Pertamina Fastron Techno 5W-30 4L', cat: 'oli',     uom: 'btl', supplier: 'SUP-001', cost: 285_000, price: 348_000, min: 24, max: 120, bin: { pusat: 'A-01-01', bandung: 'A-01-01', surabaya: 'A-01-01' }, stock: { pusat: 86, bandung: 32, surabaya: 48 }, status: 'aktif' },
  { sku: 'OLI-PT-10W40-1L', barcode: '8997012001028', name: 'Pertamina Mesran Super 10W-40 1L',  cat: 'oli',     uom: 'btl', supplier: 'SUP-001', cost:  62_000, price:  78_000, min: 60, max: 360, bin: { pusat: 'A-01-02', bandung: 'A-01-02', surabaya: 'A-01-02' }, stock: { pusat: 240, bandung: 96, surabaya: 144 }, status: 'aktif' },
  { sku: 'OLI-SH-RIM-4L',   barcode: '8997012001035', name: 'Shell Helix HX7 10W-40 4L',         cat: 'oli',     uom: 'btl', supplier: 'SUP-006', cost: 312_000, price: 388_000, min: 18, max:  72, bin: { pusat: 'A-01-03', bandung: 'A-01-03', surabaya: 'A-01-03' }, stock: { pusat: 42, bandung: 18, surabaya: 24 }, status: 'aktif' },
  { sku: 'OLI-FK-MX22-1L',  barcode: '8997012001042', name: 'Federal Matic 20W-40 1L',           cat: 'oli',     uom: 'btl', supplier: 'SUP-006', cost:  38_500, price:  52_000, min: 80, max: 480, bin: { pusat: 'A-01-04', bandung: 'A-01-04', surabaya: 'A-01-04' }, stock: { pusat:  16, bandung: 24, surabaya: 12 }, status: 'aktif' },
  { sku: 'OLI-AHM-MX-08L',  barcode: '8997012001059', name: 'AHM Oil MPX2 0.8L',                 cat: 'oli',     uom: 'btl', supplier: 'SUP-004', cost:  42_000, price:  58_000, min: 60, max: 240, bin: { pusat: 'A-01-05', bandung: 'A-01-05', surabaya: 'A-01-05' }, stock: { pusat: 144, bandung: 60, surabaya: 96 }, status: 'aktif' },
  { sku: 'OLI-GL-INDR-4L',  barcode: '8997012001066', name: 'Gulf Indurance 15W-40 4L (Industri)', cat: 'oli',   uom: 'btl', supplier: 'SUP-005', cost: 248_000, price: 320_000, min:  6, max:  36, bin: { pusat: 'A-02-01', bandung: '—',      surabaya: 'A-02-01' }, stock: { pusat:  18, bandung:  0, surabaya:  8 }, status: 'aktif' },

  // Filter
  { sku: 'FLT-SS-OL-001',   barcode: '8997022001012', name: 'Sakura Filter Oli C-1722 (Avanza)',   cat: 'filter',  uom: 'pcs', supplier: 'SUP-003', cost:  28_000, price:  42_000, min: 40, max: 200, bin: { pusat: 'B-01-01', bandung: 'B-01-01', surabaya: 'B-01-01' }, stock: { pusat: 156, bandung: 64, surabaya: 92 }, status: 'aktif' },
  { sku: 'FLT-SS-OL-002',   barcode: '8997022001029', name: 'Sakura Filter Oli C-1141 (Innova)',   cat: 'filter',  uom: 'pcs', supplier: 'SUP-003', cost:  32_000, price:  48_500, min: 40, max: 200, bin: { pusat: 'B-01-02', bandung: 'B-01-02', surabaya: 'B-01-02' }, stock: { pusat: 124, bandung: 48, surabaya: 72 }, status: 'aktif' },
  { sku: 'FLT-SS-UD-001',   barcode: '8997022001036', name: 'Sakura Filter Udara A-1141 (Innova)', cat: 'filter',  uom: 'pcs', supplier: 'SUP-003', cost:  38_000, price:  56_000, min: 32, max: 144, bin: { pusat: 'B-01-03', bandung: 'B-01-03', surabaya: 'B-01-03' }, stock: { pusat:  88, bandung: 36, surabaya: 52 }, status: 'aktif' },
  { sku: 'FLT-SS-BB-001',   barcode: '8997022001043', name: 'Sakura Filter Bensin FS-1903',        cat: 'filter',  uom: 'pcs', supplier: 'SUP-003', cost:  22_000, price:  34_000, min: 50, max: 240, bin: { pusat: 'B-01-04', bandung: 'B-01-04', surabaya: 'B-01-04' }, stock: { pusat:   8, bandung:  6, surabaya:  4 }, status: 'aktif' },
  { sku: 'FLT-AC-001',      barcode: '8997022001050', name: 'Filter AC Mobil Universal',           cat: 'filter',  uom: 'pcs', supplier: 'SUP-002', cost:  45_000, price:  68_000, min: 40, max: 160, bin: { pusat: 'B-02-01', bandung: 'B-02-01', surabaya: 'B-02-01' }, stock: { pusat:  72, bandung: 24, surabaya: 36 }, status: 'aktif' },

  // Rem
  { sku: 'REM-KP-AVZ-D',    barcode: '8997032001019', name: 'Kampas Rem Depan Avanza/Xenia',       cat: 'rem',     uom: 'set', supplier: 'SUP-002', cost:  98_000, price: 142_000, min: 24, max:  96, bin: { pusat: 'C-01-01', bandung: 'C-01-01', surabaya: 'C-01-01' }, stock: { pusat:  68, bandung: 28, surabaya: 42 }, status: 'aktif' },
  { sku: 'REM-KP-AVZ-B',    barcode: '8997032001026', name: 'Kampas Rem Belakang Avanza/Xenia',    cat: 'rem',     uom: 'set', supplier: 'SUP-002', cost:  72_000, price: 108_000, min: 24, max:  96, bin: { pusat: 'C-01-02', bandung: 'C-01-02', surabaya: 'C-01-02' }, stock: { pusat:  52, bandung: 22, surabaya: 32 }, status: 'aktif' },
  { sku: 'REM-CKR-INV',     barcode: '8997032001033', name: 'Cakram Rem Innova Reborn',            cat: 'rem',     uom: 'pcs', supplier: 'SUP-002', cost: 385_000, price: 528_000, min:  6, max:  24, bin: { pusat: 'C-02-01', bandung: '—',      surabaya: 'C-02-01' }, stock: { pusat:  14, bandung:  0, surabaya:  6 }, status: 'aktif' },
  { sku: 'REM-MIN-DOT4',    barcode: '8997032001040', name: 'Minyak Rem DOT 4 (1L)',               cat: 'rem',     uom: 'btl', supplier: 'SUP-005', cost:  48_000, price:  72_000, min: 40, max: 144, bin: { pusat: 'C-02-02', bandung: 'C-02-02', surabaya: 'C-02-02' }, stock: { pusat:  96, bandung: 36, surabaya: 56 }, status: 'aktif' },
  { sku: 'REM-KP-MTR-001',  barcode: '8997032001057', name: 'Kampas Rem Cakram Motor Bebek',       cat: 'rem',     uom: 'set', supplier: 'SUP-002', cost:  18_500, price:  28_000, min: 80, max: 320, bin: { pusat: 'C-03-01', bandung: 'C-03-01', surabaya: 'C-03-01' }, stock: { pusat: 240, bandung: 96, surabaya: 156 }, status: 'aktif' },

  // Kelistrikan
  { sku: 'KLR-BTR-NS40Z',   barcode: '8997042001016', name: 'Aki GS NS40Z (Avanza)',               cat: 'kelistrikan', uom: 'pcs', supplier: 'SUP-002', cost: 642_000, price: 815_000, min:  8, max:  32, bin: { pusat: 'D-01-01', bandung: 'D-01-01', surabaya: 'D-01-01' }, stock: { pusat:  22, bandung:  9, surabaya: 14 }, status: 'aktif' },
  { sku: 'KLR-BTR-N70',     barcode: '8997042001023', name: 'Aki GS N70 (Truk Ringan)',            cat: 'kelistrikan', uom: 'pcs', supplier: 'SUP-002', cost: 1_180_000, price: 1_460_000, min:  4, max: 16, bin: { pusat: 'D-01-02', bandung: '—',      surabaya: 'D-01-02' }, stock: { pusat:  12, bandung:  0, surabaya:  6 }, status: 'aktif' },
  { sku: 'KLR-BSI-NGK',     barcode: '8997042001030', name: 'Busi NGK G-Power (4pc)',              cat: 'kelistrikan', uom: 'set', supplier: 'SUP-002', cost:  72_000, price: 108_000, min: 40, max: 160, bin: { pusat: 'D-02-01', bandung: 'D-02-01', surabaya: 'D-02-01' }, stock: { pusat:  84, bandung: 32, surabaya: 48 }, status: 'aktif' },
  { sku: 'KLR-BSI-DENSO',   barcode: '8997042001047', name: 'Busi Denso Iridium TT',               cat: 'kelistrikan', uom: 'pcs', supplier: 'SUP-002', cost:  98_000, price: 142_000, min: 48, max: 192, bin: { pusat: 'D-02-02', bandung: 'D-02-02', surabaya: 'D-02-02' }, stock: { pusat:   6, bandung:  4, surabaya:  3 }, status: 'aktif' },
  { sku: 'KLR-LMP-H4',      barcode: '8997042001054', name: 'Lampu Halogen Philips H4 60/55W',     cat: 'kelistrikan', uom: 'pcs', supplier: 'SUP-002', cost:  38_000, price:  56_000, min: 60, max: 240, bin: { pusat: 'D-03-01', bandung: 'D-03-01', surabaya: 'D-03-01' }, stock: { pusat: 132, bandung: 48, surabaya: 76 }, status: 'aktif' },

  // Komponen Mesin
  { sku: 'MSN-BSL-AVZ',     barcode: '8997052001013', name: 'Belt Mesin Avanza 1.3 (set)',         cat: 'mesin',   uom: 'set', supplier: 'SUP-002', cost: 285_000, price: 388_000, min: 12, max:  48, bin: { pusat: 'E-01-01', bandung: 'E-01-01', surabaya: 'E-01-01' }, stock: { pusat:  28, bandung: 11, surabaya: 16 }, status: 'aktif' },
  { sku: 'MSN-WP-INV',      barcode: '8997052001020', name: 'Water Pump Innova 2KD',               cat: 'mesin',   uom: 'pcs', supplier: 'SUP-002', cost: 825_000, price: 1_120_000, min:  4, max: 16, bin: { pusat: 'E-02-01', bandung: '—',      surabaya: 'E-02-01' }, stock: { pusat:   6, bandung:  0, surabaya:  3 }, status: 'aktif' },
  { sku: 'MSN-PCN-MTR-110', barcode: '8997052001037', name: 'Piston Set Motor 110cc (STD)',        cat: 'mesin',   uom: 'set', supplier: 'SUP-005', cost: 145_000, price: 198_000, min: 16, max:  64, bin: { pusat: 'E-03-01', bandung: 'E-03-01', surabaya: 'E-03-01' }, stock: { pusat:  42, bandung: 18, surabaya: 24 }, status: 'aktif' },
  { sku: 'MSN-RNT-MTR',     barcode: '8997052001044', name: 'Rantai Keteng Motor + Tensioner',     cat: 'mesin',   uom: 'set', supplier: 'SUP-005', cost:  88_000, price: 128_000, min: 24, max:  96, bin: { pusat: 'E-03-02', bandung: 'E-03-02', surabaya: 'E-03-02' }, stock: { pusat:  56, bandung: 22, surabaya: 32 }, status: 'aktif' },

  // Ban
  { sku: 'BAN-DUN-185',     barcode: '8997062001010', name: 'Dunlop SP Sport 185/65 R15',          cat: 'ban',     uom: 'pcs', supplier: 'SUP-002', cost: 685_000, price: 875_000, min:  8, max:  32, bin: { pusat: 'F-01-01', bandung: '—',      surabaya: 'F-01-01' }, stock: { pusat:  16, bandung:  0, surabaya:  8 }, status: 'aktif' },
  { sku: 'BAN-BSY-205',     barcode: '8997062001027', name: 'Bridgestone Turanza 205/55 R16',      cat: 'ban',     uom: 'pcs', supplier: 'SUP-002', cost: 1_240_000, price: 1_560_000, min:  6, max: 24, bin: { pusat: 'F-01-02', bandung: '—',      surabaya: 'F-01-02' }, stock: { pusat:  12, bandung:  0, surabaya:  4 }, status: 'aktif' },
  { sku: 'BAN-FDR-IRC',     barcode: '8997062001034', name: 'Ban Motor IRC NR-73 80/90-14',        cat: 'ban',     uom: 'pcs', supplier: 'SUP-005', cost: 168_000, price: 228_000, min: 24, max:  96, bin: { pusat: 'F-02-01', bandung: 'F-02-01', surabaya: 'F-02-01' }, stock: { pusat:  84, bandung: 28, surabaya: 48 }, status: 'aktif' },

  // Aksesori
  { sku: 'AKS-WIPER-22',    barcode: '8997072001017', name: 'Wiper Bosch Aerotwin 22"',            cat: 'aksesori', uom: 'pcs', supplier: 'SUP-002', cost:  82_000, price: 118_000, min: 30, max: 120, bin: { pusat: 'G-01-01', bandung: 'G-01-01', surabaya: 'G-01-01' }, stock: { pusat:  64, bandung: 22, surabaya: 38 }, status: 'aktif' },
  { sku: 'AKS-KLAK-MINI',   barcode: '8997072001024', name: 'Klakson Mini Hella Supertone',        cat: 'aksesori', uom: 'set', supplier: 'SUP-005', cost: 142_000, price: 198_000, min: 12, max:  48, bin: { pusat: 'G-01-02', bandung: 'G-01-02', surabaya: 'G-01-02' }, stock: { pusat:  24, bandung:  8, surabaya: 14 }, status: 'aktif' },
  { sku: 'AKS-KARP-AVZ',    barcode: '8997072001031', name: 'Karpet Dasar Avanza (set 5pc)',       cat: 'aksesori', uom: 'set', supplier: 'SUP-005', cost: 178_000, price: 258_000, min: 16, max:  64, bin: { pusat: 'G-02-01', bandung: 'G-02-01', surabaya: 'G-02-01' }, stock: { pusat:  32, bandung: 12, surabaya: 18 }, status: 'aktif' },
  { sku: 'AKS-PRFM-AC',     barcode: '8997072001048', name: 'Parfum AC Little Tree (12pc box)',    cat: 'aksesori', uom: 'box', supplier: 'SUP-005', cost: 168_000, price: 240_000, min: 12, max:  48, bin: { pusat: 'G-03-01', bandung: 'G-03-01', surabaya: 'G-03-01' }, stock: { pusat:  28, bandung:  9, surabaya: 16 }, status: 'aktif' },
  { sku: 'AKS-CKMT-COV',    barcode: '8997072001055', name: 'Cover Jok Sintetis Universal',        cat: 'aksesori', uom: 'set', supplier: 'SUP-005', cost: 220_000, price: 320_000, min:  8, max:  32, bin: { pusat: 'G-03-02', bandung: 'G-03-02', surabaya: 'G-03-02' }, stock: { pusat:   3, bandung:  2, surabaya:  4 }, status: 'aktif' },
];
const PROD = Object.fromEntries(PRODUCTS.map(p => [p.sku, p]));

// ── Stok Masuk (Goods Receipt) — receiving from suppliers ───────────────────
const PENERIMAAN = [
  {
    id: 'GR-260422-003', tgl: '2026-04-22', gudang: 'pusat', supplier: 'SUP-001', poRef: 'PO-260418-007',
    status: 'pending', // belum diverifikasi, baru landed
    receiver: 'Joko Susilo',
    items: [
      { sku: 'OLI-PT-5W30-4L',  qty: 48, uom: 'btl', cost: 285_000 },
      { sku: 'OLI-PT-10W40-1L', qty: 120, uom: 'btl', cost:  62_000 },
    ],
  },
  {
    id: 'GR-260422-002', tgl: '2026-04-22', gudang: 'pusat', supplier: 'SUP-003', poRef: 'PO-260417-014',
    status: 'partial', // sebagian diterima, sisa back-order
    receiver: 'Joko Susilo', expected: 200, received: 144,
    items: [
      { sku: 'FLT-SS-OL-001', qty: 80, ordered: 100, uom: 'pcs', cost: 28_000 },
      { sku: 'FLT-SS-OL-002', qty: 64, ordered: 100, uom: 'pcs', cost: 32_000 },
    ],
  },
  {
    id: 'GR-260422-001', tgl: '2026-04-22', gudang: 'bandung', supplier: 'SUP-006', poRef: 'PO-260419-002',
    status: 'verified',
    receiver: 'Tono S.', verifier: 'Eko Riyadi', verifiedAt: '08:42',
    items: [
      { sku: 'OLI-FK-MX22-1L', qty: 96, uom: 'btl', cost: 38_500 },
      { sku: 'OLI-SH-RIM-4L',  qty: 24, uom: 'btl', cost: 312_000 },
    ],
  },
  {
    id: 'GR-260421-005', tgl: '2026-04-21', gudang: 'pusat', supplier: 'SUP-002', poRef: 'PO-260415-022',
    status: 'verified',
    receiver: 'Joko Susilo', verifier: 'Suparman', verifiedAt: '15:18',
    items: [
      { sku: 'REM-KP-AVZ-D',   qty: 24, uom: 'set', cost:  98_000 },
      { sku: 'REM-KP-AVZ-B',   qty: 24, uom: 'set', cost:  72_000 },
      { sku: 'KLR-BSI-NGK',    qty: 60, uom: 'set', cost:  72_000 },
      { sku: 'AKS-WIPER-22',   qty: 36, uom: 'pcs', cost:  82_000 },
    ],
  },
  {
    id: 'GR-260421-004', tgl: '2026-04-21', gudang: 'surabaya', supplier: 'SUP-001', poRef: 'PO-260417-019',
    status: 'verified',
    receiver: 'Bambang H.', verifier: 'Hartono', verifiedAt: '11:24',
    items: [
      { sku: 'OLI-PT-5W30-4L',  qty: 24, uom: 'btl', cost: 285_000 },
      { sku: 'OLI-PT-10W40-1L', qty: 72, uom: 'btl', cost:  62_000 },
    ],
  },
  {
    id: 'GR-260420-012', tgl: '2026-04-20', gudang: 'pusat', supplier: 'SUP-005', poRef: 'PO-260414-031',
    status: 'verified',
    receiver: 'Joko Susilo', verifier: 'Suparman', verifiedAt: '14:55',
    items: [
      { sku: 'AKS-KARP-AVZ',   qty: 16, uom: 'set', cost: 178_000 },
      { sku: 'AKS-PRFM-AC',    qty: 12, uom: 'box', cost: 168_000 },
      { sku: 'MSN-RNT-MTR',    qty: 24, uom: 'set', cost:  88_000 },
    ],
  },
  {
    id: 'GR-260419-008', tgl: '2026-04-19', gudang: 'bandung', supplier: 'SUP-002', poRef: 'PO-260412-018',
    status: 'rejected', // ditolak — kerusakan kemasan
    receiver: 'Tono S.', verifier: 'Eko Riyadi', verifiedAt: '10:08',
    notes: 'Kemasan rusak 8 dari 12 unit, semua direturn ke supplier',
    items: [
      { sku: 'KLR-BTR-NS40Z', qty: 12, ordered: 12, uom: 'pcs', cost: 642_000, rejected: 8 },
    ],
  },
];

// Open Purchase Orders awaiting delivery
const PO_OPEN = [
  { id: 'PO-260420-031', tgl: '2026-04-20', supplier: 'SUP-002', gudang: 'pusat',    items: 6, value:  18_240_000, eta: '2026-04-24', status: 'sebagian' },
  { id: 'PO-260420-029', tgl: '2026-04-20', supplier: 'SUP-006', gudang: 'pusat',    items: 3, value:  12_480_000, eta: '2026-04-25', status: 'menunggu' },
  { id: 'PO-260419-024', tgl: '2026-04-19', supplier: 'SUP-001', gudang: 'surabaya', items: 4, value:  21_640_000, eta: '2026-04-23', status: 'menunggu' },
  { id: 'PO-260418-021', tgl: '2026-04-18', supplier: 'SUP-005', gudang: 'bandung',  items: 5, value:   8_920_000, eta: '2026-04-26', status: 'menunggu' },
  { id: 'PO-260415-016', tgl: '2026-04-15', supplier: 'SUP-003', gudang: 'pusat',    items: 4, value:  14_280_000, eta: '2026-04-22', status: 'terlambat' },
];

// ── Stok Keluar (Goods Issue) — outbound shipments ─────────────────────────
const PENGIRIMAN = [
  {
    id: 'DO-260422-006', tgl: '2026-04-22', gudang: 'pusat', customer: 'CUS-001', soRef: 'SO-260421-018',
    status: 'pending', picker: 'Joko Susilo',
    items: [
      { sku: 'OLI-PT-10W40-1L', qty: 24, uom: 'btl' },
      { sku: 'FLT-SS-OL-001',   qty: 12, uom: 'pcs' },
      { sku: 'REM-KP-AVZ-D',    qty:  4, uom: 'set' },
    ],
    total: 3_336_000,
  },
  {
    id: 'DO-260422-005', tgl: '2026-04-22', gudang: 'pusat', customer: 'CUS-003', soRef: 'SO-260421-021',
    status: 'picking', picker: 'Joko Susilo',
    items: [
      { sku: 'OLI-PT-5W30-4L',  qty: 12, uom: 'btl' },
      { sku: 'OLI-SH-RIM-4L',   qty:  6, uom: 'btl' },
      { sku: 'KLR-BTR-NS40Z',   qty:  4, uom: 'pcs' },
    ],
    total: 9_788_000,
  },
  {
    id: 'DO-260422-004', tgl: '2026-04-22', gudang: 'surabaya', customer: 'CUS-006', soRef: 'SO-260421-024',
    status: 'shipped', picker: 'Bambang H.', shippedAt: '09:48', courier: 'JNE Trucking',
    items: [
      { sku: 'OLI-PT-10W40-1L', qty: 36, uom: 'btl' },
      { sku: 'BAN-FDR-IRC',     qty:  8, uom: 'pcs' },
    ],
    total: 4_632_000,
  },
  {
    id: 'DO-260422-003', tgl: '2026-04-22', gudang: 'pusat', customer: 'CUS-002', soRef: 'SO-260421-017',
    status: 'shipped', picker: 'Joko Susilo', shippedAt: '08:15', courier: 'Lalamove Truk',
    items: [
      { sku: 'AKS-WIPER-22',    qty: 24, uom: 'pcs' },
      { sku: 'AKS-KARP-AVZ',    qty:  6, uom: 'set' },
      { sku: 'KLR-BSI-NGK',     qty: 18, uom: 'set' },
    ],
    total: 6_276_000,
  },
  {
    id: 'DO-260422-002', tgl: '2026-04-22', gudang: 'bandung', customer: 'CUS-005', soRef: 'SO-260421-014',
    status: 'shipped', picker: 'Tono S.', shippedAt: '07:42', courier: 'Sendiri',
    items: [
      { sku: 'OLI-FK-MX22-1L',  qty: 48, uom: 'btl' },
      { sku: 'REM-KP-MTR-001',  qty: 24, uom: 'set' },
    ],
    total: 3_168_000,
  },
  {
    id: 'DO-260421-018', tgl: '2026-04-21', gudang: 'pusat', customer: 'CUS-004', soRef: 'SO-260420-009',
    status: 'delivered', picker: 'Joko Susilo', shippedAt: '14:30', deliveredAt: '17:45', courier: 'Lalamove Truk',
    items: [
      { sku: 'OLI-AHM-MX-08L',  qty: 60, uom: 'btl' },
      { sku: 'FLT-SS-UD-001',   qty: 12, uom: 'pcs' },
    ],
    total: 4_152_000,
  },
];

// Pending Sales Orders (need to be picked)
const SO_OPEN = [
  { id: 'SO-260422-031', tgl: '2026-04-22', customer: 'CUS-007', gudang: 'surabaya', items: 5, value:  4_280_000, due: '2026-04-23', priority: 'normal' },
  { id: 'SO-260422-028', tgl: '2026-04-22', customer: 'CUS-001', gudang: 'pusat',    items: 3, value:  2_840_000, due: '2026-04-23', priority: 'tinggi' },
  { id: 'SO-260422-024', tgl: '2026-04-22', customer: 'CUS-005', gudang: 'bandung',  items: 4, value:  3_120_000, due: '2026-04-24', priority: 'normal' },
  { id: 'SO-260421-029', tgl: '2026-04-21', customer: 'CUS-003', gudang: 'pusat',    items: 8, value: 12_480_000, due: '2026-04-22', priority: 'tinggi' },
  { id: 'SO-260421-026', tgl: '2026-04-21', customer: 'CUS-002', gudang: 'pusat',    items: 6, value:  5_840_000, due: '2026-04-23', priority: 'normal' },
];

// ── Transfer antar-gudang ──────────────────────────────────────────────────
const TRANSFER = [
  {
    id: 'TR-260422-002', tgl: '2026-04-22', from: 'pusat', to: 'bandung',
    status: 'in-transit', sender: 'Joko Susilo', sentAt: '06:30', eta: '2026-04-23',
    items: [
      { sku: 'OLI-PT-5W30-4L',  qty: 18 },
      { sku: 'FLT-SS-OL-001',   qty: 36 },
      { sku: 'REM-KP-AVZ-D',    qty: 12 },
    ],
  },
  {
    id: 'TR-260422-001', tgl: '2026-04-22', from: 'pusat', to: 'surabaya',
    status: 'pending', sender: 'Joko Susilo',
    items: [
      { sku: 'KLR-BTR-N70',     qty:  6 },
      { sku: 'BAN-DUN-185',     qty:  8 },
      { sku: 'MSN-WP-INV',      qty:  3 },
    ],
  },
  {
    id: 'TR-260420-004', tgl: '2026-04-20', from: 'pusat', to: 'bandung',
    status: 'received', sender: 'Joko Susilo', sentAt: '06:30', receivedAt: '2026-04-21 14:20', receiver: 'Eko Riyadi',
    items: [
      { sku: 'OLI-PT-10W40-1L', qty: 60 },
      { sku: 'AKS-WIPER-22',    qty: 24 },
    ],
  },
  {
    id: 'TR-260418-007', tgl: '2026-04-18', from: 'surabaya', to: 'bandung',
    status: 'received', sender: 'Hartono', sentAt: '14:00', receivedAt: '2026-04-19 11:30', receiver: 'Eko Riyadi',
    items: [
      { sku: 'BAN-FDR-IRC',     qty: 24 },
      { sku: 'AKS-KARP-AVZ',    qty: 12 },
    ],
  },
];

// ── Stock Opname sessions ──────────────────────────────────────────────────
const OPNAME = [
  {
    id: 'OPN-260422-A', tgl: '2026-04-22', gudang: 'pusat', zone: 'A — Oli & Pelumas',
    status: 'in-progress', petugas: ['Joko Susilo', 'Bambang H.'], pengawas: 'Suparman',
    target: 18, counted: 12, variance: 2, // 12 dari 18 SKU sudah dihitung
    started: '08:00',
  },
  {
    id: 'OPN-260420-D', tgl: '2026-04-20', gudang: 'pusat', zone: 'D — Kelistrikan',
    status: 'completed', petugas: ['Joko Susilo'], pengawas: 'Suparman',
    target: 14, counted: 14, variance: 3,
    started: '08:00', finished: '11:42',
    adjustments: [
      { sku: 'KLR-BSI-DENSO', system: 18, actual: 13, diff: -5, reason: 'Hilang/rusak' },
      { sku: 'KLR-LMP-H4',    system: 124, actual: 132, diff: +8, reason: 'Salah catat masuk' },
      { sku: 'KLR-BTR-NS40Z', system:  24, actual:  22, diff: -2, reason: 'Selisih stok' },
    ],
  },
  {
    id: 'OPN-260415-B', tgl: '2026-04-15', gudang: 'bandung', zone: 'B — Filter',
    status: 'completed', petugas: ['Tono S.'], pengawas: 'Eko Riyadi',
    target: 12, counted: 12, variance: 1,
    started: '07:30', finished: '10:15',
    adjustments: [
      { sku: 'FLT-SS-BB-001', system:  8, actual:  6, diff: -2, reason: 'Sample diambil teknisi' },
    ],
  },
  {
    id: 'OPN-260410-FULL', tgl: '2026-04-10', gudang: 'surabaya', zone: 'FULL (semua zone)',
    status: 'completed', petugas: ['Bambang H.', 'Hartono', 'Yono S.'], pengawas: 'Hartono',
    target: 36, counted: 36, variance: 7,
    started: '06:00', finished: '18:30', notes: 'Opname kuartalan rutin',
  },
];

// ── Daily inbound/outbound trend (April 2026) ──────────────────────────────
const DAILY_FLOW = [
  { date: '2026-04-01', in:  86, out:  72 }, { date: '2026-04-02', in:  72, out:  68 },
  { date: '2026-04-03', in:  94, out:  82 }, { date: '2026-04-04', in: 124, out:  98 },
  { date: '2026-04-05', in:  68, out:  88 }, { date: '2026-04-06', in:  78, out:  72 },
  { date: '2026-04-07', in:  92, out:  84 }, { date: '2026-04-08', in: 108, out:  92 },
  { date: '2026-04-09', in:  86, out:  78 }, { date: '2026-04-10', in:  98, out:  86 },
  { date: '2026-04-11', in: 142, out: 102 }, { date: '2026-04-12', in:  72, out:  64 },
  { date: '2026-04-13', in:  88, out:  76 }, { date: '2026-04-14', in: 104, out:  92 },
  { date: '2026-04-15', in: 116, out:  88 }, { date: '2026-04-16', in:  82, out:  78 },
  { date: '2026-04-17', in:  96, out:  84 }, { date: '2026-04-18', in: 134, out: 108 },
  { date: '2026-04-19', in:  78, out:  72 }, { date: '2026-04-20', in: 124, out:  98 },
  { date: '2026-04-21', in: 142, out: 116 }, { date: '2026-04-22', in:  68, out:  42 }, // today (in progress)
];

// ── KPI snapshots ──────────────────────────────────────────────────────────
const KPI = {
  totalSKU: 36,
  totalGudang: 3,
  nilaiStok: 4_286_400_000,    // total inventory valuation across all warehouses
  utilisasiPusat: 0.78,
  utilisasiBandung: 0.62,
  utilisasiSurabaya: 0.71,
  inboundHariIni: 168,         // unit total
  outboundHariIni: 124,
  poTerlambat: 1,
  soDueHariIni: 2,
  selisihOpnameYTD: -1_240_000, // nilai selisih (negatif = shortage)
  turnoverDays: 38,            // days inventory outstanding
};

// ── Floor map zones (for Pusat warehouse SVG) ──────────────────────────────
// Layout: 6 rack zones (A-G excluding F bisa, jadi A-G=7); we'll use 6
// Each zone has occupancy 0-1, area-percent (visual proportion), and category
const FLOOR_ZONES = [
  { id: 'A', label: 'Oli & Pelumas',      x:  4, y:  6, w: 36, h: 22, occupancy: 0.74, racks: 12, category: 'oli' },
  { id: 'B', label: 'Filter',             x: 42, y:  6, w: 24, h: 22, occupancy: 0.68, racks:  8, category: 'filter' },
  { id: 'C', label: 'Sistem Rem',         x: 68, y:  6, w: 28, h: 22, occupancy: 0.52, racks: 10, category: 'rem' },
  { id: 'D', label: 'Kelistrikan',        x:  4, y: 32, w: 30, h: 24, occupancy: 0.86, racks: 10, category: 'kelistrikan' },
  { id: 'E', label: 'Komponen Mesin',     x: 36, y: 32, w: 28, h: 24, occupancy: 0.94, racks:  8, category: 'mesin' },
  { id: 'F', label: 'Ban & Velg',         x: 66, y: 32, w: 30, h: 24, occupancy: 0.42, racks:  6, category: 'ban' },
  { id: 'G', label: 'Aksesori',           x:  4, y: 60, w: 60, h: 22, occupancy: 0.58, racks: 12, category: 'aksesori' },
  { id: 'STG', label: 'Staging / Loading',x: 66, y: 60, w: 30, h: 22, occupancy: 0.30, racks:  0, category: 'staging' },
];

// ── Notifikasi / activity stream ───────────────────────────────────────────
const ACTIVITY = [
  { id: 'A1', time: '09:18', type: 'gr',   text: 'GR-260422-003 dari Pertamina Lubricants menunggu verifikasi', who: 'Joko Susilo', urgent: true },
  { id: 'A2', time: '08:52', type: 'so',   text: 'SO-260421-029 (CUS-003) jatuh tempo hari ini, belum di-pick', who: 'sistem',     urgent: true },
  { id: 'A3', time: '08:42', type: 'gr',   text: 'GR-260422-001 (Federal Karyatama) telah diverifikasi', who: 'Eko Riyadi', urgent: false },
  { id: 'A4', time: '08:15', type: 'do',   text: 'DO-260422-003 dikirim via Lalamove Truk ke Sumber Rejeki', who: 'Joko Susilo', urgent: false },
  { id: 'A5', time: '08:00', type: 'opn',  text: 'OPN-260422-A dimulai (Zone A — Oli & Pelumas)',         who: 'Joko Susilo', urgent: false },
  { id: 'A6', time: '07:42', type: 'do',   text: 'DO-260422-002 dikirim ke Roda Mas Bandung',              who: 'Tono S.',    urgent: false },
  { id: 'A7', time: '06:30', type: 'tr',   text: 'TR-260422-002 (Pusat → Bandung) berangkat',              who: 'Joko Susilo', urgent: false },
];

// ── Slow-moving / aging ────────────────────────────────────────────────────
const SLOW_MOVING = [
  { sku: 'OLI-FK-MX22-1L',  daysSinceLast: 14, stock: 52,  value:  2_002_000 },
  { sku: 'KLR-BSI-DENSO',   daysSinceLast: 11, stock: 13,  value:  1_274_000 },
  { sku: 'BAN-DUN-185',     daysSinceLast:  9, stock: 24,  value: 16_440_000 },
  { sku: 'BAN-BSY-205',     daysSinceLast:  8, stock: 16,  value: 19_840_000 },
  { sku: 'OLI-GL-INDR-4L',  daysSinceLast:  7, stock: 26,  value:  6_448_000 },
  { sku: 'AKS-CKMT-COV',    daysSinceLast:  6, stock:  9,  value:  1_980_000 },
];

// ── Helpers ────────────────────────────────────────────────────────────────

function rupiah(n, opts = {}) {
  if (n == null || isNaN(n)) return '—';
  const sign = n < 0 ? '-' : '';
  const abs = Math.abs(Math.round(n));
  if (opts.compact && abs >= 1_000_000_000) return sign + (abs / 1_000_000_000).toFixed(2).replace('.', ',') + ' M';
  if (opts.compact && abs >= 1_000_000)     return sign + (abs / 1_000_000).toFixed(1).replace('.', ',') + ' jt';
  if (opts.compact && abs >= 1_000)         return sign + (abs / 1_000).toFixed(0) + 'rb';
  const str = abs.toLocaleString('id-ID');
  return (opts.sym ? 'Rp ' : '') + sign + str;
}

function formatDateID(iso) {
  if (!iso) return '—';
  const m = ['Jan','Feb','Mar','Apr','Mei','Jun','Jul','Agu','Sep','Okt','Nov','Des'];
  const d = new Date(iso);
  return `${d.getDate()} ${m[d.getMonth()]} ${d.getFullYear()}`;
}

function periodLabel(id) {
  return PERIOD_LIST.find(p => p.id === id)?.label || id;
}

function gudangLabel(id) {
  return GUDANG_LIST.find(g => g.id === id)?.name || id;
}

function gudangShort(id) {
  return ({ pusat: 'Pusat', bandung: 'Bandung', surabaya: 'Surabaya', all: 'Semua' })[id] || id;
}

function totalStockSKU(p) {
  return Object.values(p.stock).reduce((a, b) => a + b, 0);
}

function stockStatus(p) {
  const total = totalStockSKU(p);
  if (total === 0) return 'kosong';
  if (total < p.min) return 'kritis';
  if (total < p.min * 1.5) return 'rendah';
  if (total > p.max) return 'over';
  return 'normal';
}

function hash(s) {
  let h = 0;
  for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) >>> 0;
  return h;
}

function statusTone(s) {
  return ({
    pending: 'warn', partial: 'warn', verified: 'success',
    rejected: 'danger', picking: 'warn', shipped: 'accent',
    delivered: 'success', 'in-transit': 'accent', received: 'success',
    'in-progress': 'accent', completed: 'success',
    aktif: 'success', kritis: 'danger', rendah: 'warn',
    normal: 'neutral', kosong: 'danger', over: 'warn',
    tinggi: 'danger', menunggu: 'neutral', sebagian: 'warn', terlambat: 'danger',
  })[s] || 'neutral';
}

function statusLabel(s) {
  return ({
    pending: 'Menunggu', partial: 'Sebagian', verified: 'Diverifikasi',
    rejected: 'Ditolak', picking: 'Pick', shipped: 'Dikirim',
    delivered: 'Diterima', 'in-transit': 'Dlm. Perjalanan', received: 'Diterima',
    'in-progress': 'Berjalan', completed: 'Selesai',
    aktif: 'Aktif', kritis: 'Kritis', rendah: 'Rendah',
    normal: 'Normal', kosong: 'Kosong', over: 'Over-stock',
    tinggi: 'Tinggi', menunggu: 'Menunggu', sebagian: 'Sebagian', terlambat: 'Terlambat',
  })[s] || s;
}

Object.assign(window, {
  TENANT, GUDANG_LIST, PERIOD_LIST, CURRENT_PERIOD, TODAY, ROLES,
  KATEGORI, SUPPLIERS, CUSTOMERS, PRODUCTS, PROD,
  PENERIMAAN, PO_OPEN, PENGIRIMAN, SO_OPEN, TRANSFER, OPNAME,
  DAILY_FLOW, KPI, FLOOR_ZONES, ACTIVITY, SLOW_MOVING,
  rupiah, formatDateID, periodLabel, gudangLabel, gudangShort,
  totalStockSKU, stockStatus, hash, statusTone, statusLabel,
});
