getUser(); $user = (new UserRepository())->getByLogin($auth_user['login']); $account_repo = new AccountRepository(); $accounts = $user ? $account_repo->getList('*', ['user_id' => $user->id, 'is_delete' => 0], '`order`') : []; $archived_accounts = $user ? $account_repo->getList('*', ['user_id' => $user->id, 'is_delete' => 1], 'title') : []; // Курс ЦБ РФ на не-RUB счета — Services\CurrencyRate; при недоступности источника rate() // возвращает null для конкретного кода, тогда счёт просто не участвует в переводе в рубли // (не показываем непересчитанную сумму как есть — это исказило бы «Доступно сейчас»). $rate_service = CurrencyRate::instance(); $rates = []; foreach ($accounts ?: [] as $account) { if ($account->currency !== 'RUB' && !array_key_exists($account->currency, $rates)) { $rates[$account->currency] = $rate_service->rate($account->currency); } } $rubValue = static function (object $account) use ($rates): float { if ($account->currency === 'RUB') { return (float)$account->summa; } $rate = $rates[$account->currency] ?? null; return $rate !== null ? (float)$account->summa * $rate : 0.0; }; $total = array_sum(array_map( static fn ($account) => $account->include_in_total ? $rubValue($account) : 0, $accounts ?: [] )); // «Всего по всем счетам» — без фильтра include_in_total, для строки под «Доступно сейчас» // (см. дизайн-хендофф App/design_handoff_personal_finance). $total_all = array_sum(array_map($rubValue, $accounts ?: [])); $month = (int)date('n'); $year = (int)date('Y'); $category_repo = new CategoryRepository(); $budget_repo = new BudgetRepository(); $tree = $user ? $category_repo->getTree($user->id) : []; $groups = $user ? (new CategoryGroupRepository())->getForUser($user->id) : []; $plan_month = $user ? array_map( static fn ($months) => $months[$month]['plan_summ'] ?? 0.0, $budget_repo->getYear($user->id, $year) ) : []; // Факт за месяц — реальные transactions (таблица/репозиторий уже есть, UI для их ввода // пока нет, поэтому в живой БД сумма обычно 0 — это корректный факт, не заглушка). $fact_month = $user ? (new TransactionRepository())->getMonthActualByCategory($user->id, $year, $month) : []; // % бюджета по расходам за месяц — план/факт только по expense-статьям (для плашки в шапке). $expense_ids = []; foreach ($tree as $items) { foreach ($items as $c) { if ($c->type === 'expense') { $expense_ids[(int)$c->id] = true; } } } $plan_expense = 0.0; $fact_expense = 0.0; foreach ($expense_ids as $categorie_id => $_) { $plan_expense += $plan_month[$categorie_id] ?? 0.0; $fact_expense += $fact_month[$categorie_id] ?? 0.0; } $pct_expense = $plan_expense > 0 ? round($fact_expense / $plan_expense * 100) : null; $fact_income = 0.0; foreach ($tree as $items) { foreach ($items as $c) { if ($c->type === 'income') { $fact_income += $fact_month[(int)$c->id] ?? 0.0; } } } $month_delta = $fact_income - $fact_expense; $goals = $user ? (new GoalRepository())->getForUser($user->id) : []; return $this->render('index', [ 'user' => $auth_user, 'accounts' => $accounts ?: [], 'archived_accounts' => $archived_accounts ?: [], 'total' => $total, 'total_all' => $total_all, 'tree' => $tree, 'groups' => $groups, 'plan_month' => $plan_month, 'fact_month' => $fact_month, 'pct_expense' => $pct_expense, 'month_delta' => $month_delta, 'goals' => $goals ?: [], 'month' => $month, 'rates' => $rates, ]); } public function testAction(): string { return str_replace( ['href="nocturne.css"', 'src="./support.js"'], ['href="/App/design_handoff_personal_finance/nocturne.css"', ''], file_get_contents(APPPATH . '/design_handoff_personal_finance/Личные финансы.dc.html') ); } }