toArray(); if (empty($branches)) { $branches = ['Cabang 1', 'Cabang 2', 'Cabang 3']; // Fallback } $month = $request->get('month'); $year = $request->get('year'); // 1. Data Gabungan $jQuery = JournalDetail::with('journalEntry', 'account') ->whereHas('journalEntry', function($q) use ($month, $year) { if ($month) $q->whereMonth('date', $month); if ($year) $q->whereYear('date', $year); }); $penjualan = (clone $jQuery)->whereHas('account', function($q) { $q->where('code', '401'); })->sum('credit'); $hpp = (clone $jQuery)->whereHas('account', function($q) { $q->where('code', '501'); })->sum('debit'); $labaKotor = $penjualan - $hpp; $opCostsDetails = (clone $jQuery)->whereHas('account', function($q) { $q->where('code', '502'); })->get(); // Format to match existing view $opCostsTotal = $opCostsDetails->map(function($d) { $desc = str_replace('Biaya Operasional: ', '', $d->journalEntry->description); return (object)[ 'label' => $desc, 'branch' => $d->journalEntry->branch, 'amount' => $d->debit ]; }); $totalOpAmount = $opCostsTotal->sum('amount'); $labaBersih = $labaKotor - $totalOpAmount; $dataTotal = [ 'penjualan' => $penjualan, 'pembelian' => $hpp, 'laba_kotor' => $labaKotor, 'operational' => $opCostsTotal, 'total_operational' => $totalOpAmount, 'laba_bersih' => $labaBersih ]; // 2. Per Branch Data $branchData = []; foreach ($branches as $branch) { $bJQuery = JournalDetail::with('journalEntry', 'account') ->whereHas('journalEntry', function($q) use ($month, $year, $branch) { $q->where('branch', $branch); if ($month) $q->whereMonth('date', $month); if ($year) $q->whereYear('date', $year); }); $bPenjualan = (clone $bJQuery)->whereHas('account', function($q) { $q->where('code', '401'); })->sum('credit'); $bHpp = (clone $bJQuery)->whereHas('account', function($q) { $q->where('code', '501'); })->sum('debit'); $bLabaKotor = $bPenjualan - $bHpp; $bOpCostsDetails = (clone $bJQuery)->whereHas('account', function($q) { $q->where('code', '502'); })->get(); $bOpCostsTotal = $bOpCostsDetails->map(function($d) { $desc = str_replace('Biaya Operasional: ', '', $d->journalEntry->description); return (object)[ 'label' => $desc, 'branch' => $d->journalEntry->branch, 'amount' => $d->debit ]; }); $bTotalOpAmount = $bOpCostsTotal->sum('amount'); $bLabaBersih = $bLabaKotor - $bTotalOpAmount; $branchData[$branch] = [ 'penjualan' => $bPenjualan, 'pembelian' => $bHpp, 'laba_kotor' => $bLabaKotor, 'operational' => $bOpCostsTotal, 'total_operational' => $bTotalOpAmount, 'laba_bersih' => $bLabaBersih ]; } return view('neraca_laba_rugi', compact('dataTotal', 'branchData', 'branches')); } public function exportProfitAndLossPdf(Request $request) { $branches = Branch::pluck('name')->toArray(); if (empty($branches)) { $branches = ['Cabang 1', 'Cabang 2', 'Cabang 3']; // Fallback } $month = $request->get('month'); $year = $request->get('year'); $branchFilter = $request->get('branch'); // Target branch calculation $targetBranch = $branchFilter ?: 'Total Gabungan'; $jQuery = JournalDetail::with('journalEntry', 'account') ->whereHas('journalEntry', function($q) use ($month, $year, $branchFilter) { if ($branchFilter && $branchFilter !== 'Total Gabungan') { $q->where('branch', $branchFilter); } if ($month) $q->whereMonth('date', $month); if ($year) $q->whereYear('date', $year); }); $penjualan = (clone $jQuery)->whereHas('account', function($q) { $q->where('code', '401'); })->sum('credit'); $hpp = (clone $jQuery)->whereHas('account', function($q) { $q->where('code', '501'); })->sum('debit'); $labaKotor = $penjualan - $hpp; $opCostsDetails = (clone $jQuery)->whereHas('account', function($q) { $q->where('code', '502'); })->get(); // Format to match existing view expectation $opCostsTotalData = $opCostsDetails->map(function($d) { $desc = str_replace('Biaya Operasional: ', '', $d->journalEntry->description); return (object)[ 'label' => $desc, 'branch' => $d->journalEntry->branch, 'amount' => $d->debit ]; }); $totalOpAmount = $opCostsTotalData->sum('amount'); $labaBersih = $labaKotor - $totalOpAmount; $data = [ 'penjualan' => $penjualan, 'pembelian' => $hpp, 'laba_kotor' => $labaKotor, 'operational' => $opCostsTotalData, 'total_operational' => $totalOpAmount, 'laba_bersih' => $labaBersih, 'branch' => $targetBranch, 'month' => $month, 'year' => $year ]; $pdf = \Barryvdh\DomPDF\Facade\Pdf::loadView('reports.neraca_laba_rugi_pdf', $data); return $pdf->download('laporan_neraca_laba_rugi_' . date('Y-m-d') . '.pdf'); } public function generalLedger() { $branches = Branch::pluck('name')->toArray(); if (empty($branches)) { $branches = ['Cabang 1', 'Cabang 2', 'Cabang 3']; // Fallback } // 1. Total Gabungan // Filter only 'Kas' account (101) to match existing simplified Ledger layout $kasDetails = JournalDetail::whereHas('account', function($q) { $q->where('code', '101'); })->with('journalEntry')->get(); $transactionsTotal = $kasDetails->map(function($d) { return [ 'date' => $d->journalEntry->date, 'account' => 'Kas', 'desc' => $d->journalEntry->description, 'debit' => $d->debit, 'credit' => $d->credit ]; }); // Initial Balance dari nilai stok saat ini $initialBalance = $this->calculateModalFromStock(); $ledgerTotal = $this->processLedger($transactionsTotal, $initialBalance, 'Modal dari Stok'); // 2. Per Branch $branchLedgers = []; foreach ($branches as $branch) { $initialBranchBalance = $this->calculateModalFromStock($branch); $bKasDetails = JournalDetail::whereHas('account', function($q) { $q->where('code', '101'); })->whereHas('journalEntry', function($q) use ($branch) { $q->where('branch', $branch); })->with('journalEntry')->get(); $bTransactions = $bKasDetails->map(function($d) { return [ 'date' => $d->journalEntry->date, 'account' => 'Kas', 'desc' => $d->journalEntry->description, 'debit' => $d->debit, 'credit' => $d->credit ]; }); $branchLedgers[$branch] = $this->processLedger($bTransactions, $initialBranchBalance, 'Modal dari Stok ' . $branch); } return view('buku_besar', compact('ledgerTotal', 'branchLedgers', 'branches')); } private function processLedger($transactions, $initialBalance, $initialDesc) { $ledger = collect(); // Add Initial Transaction $ledger->push([ 'date' => '2025-09-01', // Example date matching mockup 'account' => 'Kas', 'desc' => $initialDesc, 'debit' => $initialBalance, 'credit' => 0, 'balance' => $initialBalance ]); $sortedTrans = $transactions->sortBy('date'); $currentBalance = $initialBalance; foreach ($sortedTrans as $t) { $currentBalance += $t['debit']; $currentBalance -= $t['credit']; $ledger->push([ 'date' => $t['date'], 'account' => $t['account'], 'desc' => $t['desc'], 'debit' => $t['debit'], 'credit' => $t['credit'], 'balance' => $currentBalance ]); } return $ledger; } public function generalJournal() { $branches = Branch::pluck('name')->toArray(); if (empty($branches)) { $branches = ['Cabang 1', 'Cabang 2', 'Cabang 3']; // Fallback } // 1. Total Gabungan $journalTotal = collect(); $details = JournalDetail::with('journalEntry', 'account') ->join('journal_entries', 'journal_details.journal_entry_id', '=', 'journal_entries.id') ->orderBy('journal_entries.date') ->orderBy('journal_entries.id') ->orderBy('journal_details.credit') // debit first ->select('journal_details.*') ->get(); foreach($details as $d) { $journalTotal->push([ 'date' => $d->journalEntry->date, 'desc' => $d->credit > 0 ? ' ' . $d->account->name : $d->account->name, 'reff' => $d->account->code, 'debit' => $d->debit, 'credit' => $d->credit ]); } // 2. Per Branch Data $branchJournals = []; foreach ($branches as $branch) { $journal = collect(); $bDetails = JournalDetail::with('journalEntry', 'account') ->join('journal_entries', 'journal_details.journal_entry_id', '=', 'journal_entries.id') ->where('journal_entries.branch', $branch) ->orderBy('journal_entries.date') ->orderBy('journal_entries.id') ->orderBy('journal_details.credit') // debit first ->select('journal_details.*') ->get(); foreach($bDetails as $d) { $journal->push([ 'date' => $d->journalEntry->date, 'desc' => $d->credit > 0 ? ' ' . $d->account->name : $d->account->name, 'reff' => $d->account->code, 'debit' => $d->debit, 'credit' => $d->credit ]); } $branchJournals[$branch] = $journal; } return view('jurnal_umum', compact('journalTotal', 'branchJournals', 'branches')); } public function equityStatement(Request $request) { $branches = Branch::pluck('name')->toArray(); if (empty($branches)) $branches = ['Cabang 1', 'Cabang 2', 'Cabang 3']; // Laba Bersih = Penjualan (401) - HPP (501) - Biaya (502) $penjualan = JournalDetail::whereHas('account', function($q) { $q->where('code', '401'); })->sum('credit'); $hpp = JournalDetail::whereHas('account', function($q) { $q->where('code', '501'); })->sum('debit'); $biaya = JournalDetail::whereHas('account', function($q) { $q->where('code', '502'); })->sum('debit'); $labaBersih = $penjualan - $hpp - $biaya; // Modal berasal dari nilai stok saat ini berdasarkan biaya perolehan (harga beli), // karena sistem belum punya akun modal nyata. $modalAwal = $this->calculateModalFromStock(); $modalAkhir = $modalAwal + $labaBersih; $data = [ 'modal_awal' => $modalAwal, 'laba_bersih' => $labaBersih, 'prive' => 0, 'modal_akhir' => $modalAkhir ]; return view('perubahan_modal', compact('data', 'branches')); } public function balanceSheet(Request $request) { $branches = Branch::pluck('name')->toArray(); if (empty($branches)) $branches = ['Cabang 1', 'Cabang 2', 'Cabang 3']; // Assets $kas = JournalDetail::whereHas('account', function($q) { $q->where('code', '101'); })->sum('debit') - JournalDetail::whereHas('account', function($q) { $q->where('code', '101'); })->sum('credit'); // Persediaan dari journal (Debit = Awal Persediaan, Credit = Penjualan HPP) $persediaan = JournalDetail::whereHas('account', function($q) { $q->where('code', '102'); })->sum('debit') - JournalDetail::whereHas('account', function($q) { $q->where('code', '102'); })->sum('credit'); $totalAset = $kas + $persediaan; // Liabilities $hutang = 0; // We don't have liability accounts seeded yet // Equity $penjualan = JournalDetail::whereHas('account', function($q) { $q->where('code', '401'); })->sum('credit'); $hpp = JournalDetail::whereHas('account', function($q) { $q->where('code', '501'); })->sum('debit'); $biaya = JournalDetail::whereHas('account', function($q) { $q->where('code', '502'); })->sum('debit'); $labaBersih = $penjualan - $hpp - $biaya; // Modal berasal dari nilai stok saat ini berdasarkan biaya perolehan (harga beli), // karena sistem belum punya akun modal nyata. $modalAwal = $this->calculateModalFromStock(); $modalAkhir = $modalAwal + $labaBersih; $totalPasiva = $hutang + $modalAkhir; $data = [ 'kas' => $kas, 'persediaan' => $persediaan, 'total_aset' => $totalAset, 'hutang' => $hutang, 'modal_akhir' => $modalAkhir, 'total_pasiva' => $totalPasiva ]; return view('neraca_keuangan', compact('data', 'branches')); } private function calculateModalFromStock($branch = null) { $query = Stock::query()->with('product'); if ($branch) { $query->where('branch', $branch); } return (float) $query->get()->sum(function ($stock) { $product = $stock->product; if (!$product) { return 0; } $quantity = (float) $stock->quantity; $purchasePrice = (float) $product->purchase_price; return $quantity > 0 ? $quantity * $purchasePrice : 0; }); } public function cashFlow(Request $request) { $branches = Branch::pluck('name')->toArray(); if (empty($branches)) $branches = ['Cabang 1', 'Cabang 2', 'Cabang 3']; // Penerimaan dari Penjualan (Debit Kas dari Jurnal Penjualan) $penerimaanPenjualan = JournalDetail::whereHas('account', function($q) { $q->where('code', '101'); }) ->whereHas('journalEntry', function($q) { $q->where('reference_type', 'Sale'); })->sum('debit'); // Pengeluaran Pembelian (Kredit Kas dari Pembelian) $pengeluaranPembelian = JournalDetail::whereHas('account', function($q) { $q->where('code', '101'); }) ->whereHas('journalEntry', function($q) { $q->where('reference_type', 'Purchase'); })->sum('credit'); // Pengeluaran Biaya Operasional (Kredit Kas dari Biaya Operasional) $pengeluaranOperasional = JournalDetail::whereHas('account', function($q) { $q->where('code', '101'); }) ->whereHas('journalEntry', function($q) { $q->where('reference_type', 'OperationalCost'); })->sum('credit'); // Modal berasal dari stok, sehingga tidak ada setoran modal terpisah dalam arus kas $setoranModal = 0; $arusKasOperasi = $penerimaanPenjualan - $pengeluaranPembelian - $pengeluaranOperasional; $arusKasPendanaan = $setoranModal; $kenaikanKas = $arusKasOperasi + $arusKasPendanaan; // Saldo Kas Akhir $saldoKas = JournalDetail::whereHas('account', function($q) { $q->where('code', '101'); })->sum('debit') - JournalDetail::whereHas('account', function($q) { $q->where('code', '101'); })->sum('credit'); $data = [ 'penerimaan_penjualan' => $penerimaanPenjualan, 'pengeluaran_pembelian' => $pengeluaranPembelian, 'pengeluaran_operasional' => $pengeluaranOperasional, 'arus_kas_operasi' => $arusKasOperasi, 'setoran_modal' => $setoranModal, 'arus_kas_pendanaan' => $arusKasPendanaan, 'kenaikan_kas' => $kenaikanKas, 'saldo_kas' => $saldoKas ]; return view('arus_kas', compact('data', 'branches')); } }