sanitizeKode($raw); if ($raw === '') { return [ 'kode' => '', 'jenis_id' => null, 'satuan_transaksi' => 'besar', 'barcode_value' => '', ]; } if (preg_match('/^91(\d{8})([12])$/', $raw, $m)) { $id = (int) ltrim((string) $m[1], '0'); $unitDigit = (string) $m[2]; return [ 'kode' => '', 'jenis_id' => $id > 0 ? $id : null, 'satuan_transaksi' => ($unitDigit === '2') ? 'kecil' : 'besar', 'barcode_value' => $raw, ]; } if (preg_match('/^(.*)-(B|K)$/', $raw, $m)) { $base = $this->sanitizeKode((string) $m[1]); $suffix = (string) $m[2]; return [ 'kode' => $base, 'jenis_id' => null, 'satuan_transaksi' => ($suffix === 'K') ? 'kecil' : 'besar', 'barcode_value' => $base . '-' . $suffix, ]; } return [ 'kode' => $raw, 'jenis_id' => null, 'satuan_transaksi' => 'besar', 'barcode_value' => $raw, ]; } public function sanitizeKode(string $kode): string { $kode = strtoupper(trim($kode)); $kode = preg_replace('/\s+/', '', $kode); $kode = preg_replace('/[^A-Z0-9._-]/', '', $kode); return substr($kode, 0, 40); } public function getJenisByKode(string $kode): ?SIMBHPJenis { $parsed = $this->parseBarcode($kode); $jenisId = $parsed['jenis_id'] ?? null; if (!is_null($jenisId) && (int) $jenisId > 0) { return SIMBHPJenis::where('id', (int) $jenisId)->first(); } $kode = $parsed['kode'] ?? ''; if ($kode === '') { return null; } return SIMBHPJenis::where('kodejenis', $kode)->first(); } public function makeBarcodeValue(int $jenisId, string $satuanTransaksi = 'besar'): string { if ($jenisId <= 0) { return ''; } $idPart = str_pad((string) $jenisId, 8, '0', STR_PAD_LEFT); $unitDigit = ($satuanTransaksi === 'kecil') ? '2' : '1'; return '91' . $idPart . $unitDigit; } /** * @return array{has_breakdown: bool, konversi: int, satuan_kecil: string} */ public function getUnitSetting(SIMBHPJenis $jenis): array { $satuanKecil = trim((string) ($jenis->satuan_kecil ?? '')); $konversi = (int) ($jenis->konversi_kecil ?? 1); if ($konversi <= 0) { $konversi = 1; } $hasBreakdown = ($satuanKecil !== '' && $konversi > 1); return [ 'has_breakdown' => $hasBreakdown, 'konversi' => $konversi, 'satuan_kecil' => $satuanKecil, ]; } public function calculateBaseQty(SIMBHPJenis $jenis, int $qtyInput, string $satuanTransaksi = 'besar'): int { $qtyInput = (int) $qtyInput; if ($qtyInput < 0) { $qtyInput = 0; } $setting = $this->getUnitSetting($jenis); $konversi = (int) ($setting['konversi'] ?? 1); if ($konversi <= 0) { $konversi = 1; } if ($satuanTransaksi === 'kecil') { return $qtyInput; } return $qtyInput * $konversi; } public function getStockBaseByJenis(string $jenisNama): int { $jenisNama = trim((string) $jenisNama); if ($jenisNama === '') { return 0; } $row = DB::table('simbhpreport') ->where('jenis', $jenisNama) ->selectRaw("SUM(CASE WHEN pemasukan IS NOT NULL AND pemasukan > 0 THEN COALESCE(qty_base, pemasukan) ELSE 0 END) AS masuk_base") ->selectRaw("SUM(CASE WHEN pengeluaran IS NOT NULL AND pengeluaran > 0 THEN COALESCE(qty_base, pengeluaran) ELSE 0 END) AS keluar_base") ->first(); $masuk = (int) ($row->masuk_base ?? 0); $keluar = (int) ($row->keluar_base ?? 0); return $masuk - $keluar; } /** * @param array $jenisNames * @return array map jenis => saldo_base */ public function getStockBaseByJenisMany(array $jenisNames): array { $jenisNames = array_values(array_filter(array_map(function ($v) { return trim((string) $v); }, $jenisNames))); if (count($jenisNames) === 0) { return []; } $rows = DB::table('simbhpreport') ->whereIn('jenis', $jenisNames) ->select('jenis') ->selectRaw("SUM(CASE WHEN pemasukan IS NOT NULL AND pemasukan > 0 THEN COALESCE(qty_base, pemasukan) ELSE 0 END) AS masuk_base") ->selectRaw("SUM(CASE WHEN pengeluaran IS NOT NULL AND pengeluaran > 0 THEN COALESCE(qty_base, pengeluaran) ELSE 0 END) AS keluar_base") ->groupBy('jenis') ->get(); $map = []; foreach ($rows as $row) { $jenis = (string) ($row->jenis ?? ''); if ($jenis === '') { continue; } $map[$jenis] = ((int) ($row->masuk_base ?? 0)) - ((int) ($row->keluar_base ?? 0)); } foreach ($jenisNames as $jenis) { if (!array_key_exists($jenis, $map)) { $map[$jenis] = 0; } } return $map; } public function formatStockDisplay(int $saldoBase, string $satuanBesar, string $satuanKecil, int $konversi): string { $saldoBase = (int) $saldoBase; $konversi = (int) $konversi; if ($konversi <= 1 || trim($satuanKecil) === '') { return number_format($saldoBase, 0, '.', ',') . ' ' . $satuanBesar; } $besar = intdiv($saldoBase, $konversi); $kecil = $saldoBase % $konversi; return number_format($besar, 0, '.', ',') . ' ' . $satuanBesar . ' + ' . number_format($kecil, 0, '.', ',') . ' ' . $satuanKecil; } }