'open']; public function open() { $this->loadAccounts(); $this->show = true; } public function close() { $this->show = false; } public function updatedDecimalFormat() { $this->reformatBalances(); } private function formatBalance($minutes) { if ($this->decimalFormat) { $isNegative = $minutes < 0; $decimal = number_format(abs($minutes) / 60, 2, ',', '.'); $value = ($isNegative ? '-' : '') . $decimal . ' ' . __('h.'); return $value; } return tbFormat($minutes); } private function reformatBalances() { $this->accounts = array_map(function ($account) { $account['balanceFormatted'] = $this->formatBalance($account['balance']); return $account; }, $this->accounts); $this->totalBalanceFormatted = $this->formatBalance($this->totalBalance); } private function loadAccounts() { $profileType = session('activeProfileType'); $profileId = session('activeProfileId'); if (!$profileType || !$profileId) { $this->accounts = []; $this->totalBalance = 0; $this->totalBalanceFormatted = $this->formatBalance(0); return; } // Resolve profile class and verify it has accounts $profile = $profileType::find($profileId); if (!$profile || !method_exists($profile, 'accounts')) { $this->accounts = []; $this->totalBalance = 0; $this->totalBalanceFormatted = $this->formatBalance(0); return; } // Verify authenticated user owns this profile (IDOR prevention) ProfileAuthorizationHelper::authorize($profile); // Load only accounts belonging to the authenticated active profile (IDOR safe) $profileAccounts = $profile->accounts()->get(); if ($profileAccounts->isEmpty()) { $this->accounts = []; $this->totalBalance = 0; $this->totalBalanceFormatted = $this->formatBalance(0); return; } $accountIds = $profileAccounts->pluck('id')->toArray(); // Fetch all balances in a single query (no cache — fresh DB state) $balanceRows = DB::table('transactions') ->whereIn('from_account_id', $accountIds) ->orWhereIn('to_account_id', $accountIds) ->select('from_account_id', 'to_account_id', 'amount') ->get(); // Calculate per-account balance from query results $balanceMap = array_fill_keys($accountIds, 0); foreach ($balanceRows as $row) { if (isset($balanceMap[$row->to_account_id])) { $balanceMap[$row->to_account_id] += $row->amount; } if (isset($balanceMap[$row->from_account_id])) { $balanceMap[$row->from_account_id] -= $row->amount; } } $this->totalBalance = 0; $this->accounts = $profileAccounts->map(function ($account) use ($balanceMap) { $balance = $balanceMap[$account->id] ?? 0; $this->totalBalance += $balance; return [ 'name' => ucfirst(__('messages.' . strtolower($account->name) . '_account')) . ' ' . __('account'), 'balance' => $balance, 'balanceFormatted' => $this->formatBalance($balance), ]; })->toArray(); $this->totalBalanceFormatted = $this->formatBalance($this->totalBalance); $this->totalBalanceDecimal = number_format(abs($this->totalBalance) / 60, 2, ',', '.'); } public function render() { return view('livewire.account-info-modal'); } }