['income'=>float, 'expense'=>float]] — текущий год * @var array $monthly_prev То же — предыдущий год ($year - 1), для панели «год к году» * @var object[] $expense_cats [{categorie_id, title, total}] — расходы текущего месяца по категориям * @var array $plan_month [categorie_id => plan_summ] — план текущего месяца по тем же категориям */ $month_names = [ 1 => 'Янв', 2 => 'Фев', 3 => 'Мар', 4 => 'Апр', 5 => 'Май', 6 => 'Июн', 7 => 'Июл', 8 => 'Авг', 9 => 'Сен', 10 => 'Окт', 11 => 'Ноя', 12 => 'Дек', ]; $month_names_gen = [ 1 => 'январь', 2 => 'февраль', 3 => 'март', 4 => 'апрель', 5 => 'май', 6 => 'июнь', 7 => 'июль', 8 => 'август', 9 => 'сентябрь', 10 => 'октябрь', 11 => 'ноябрь', 12 => 'декабрь', ]; $cat_colors = ['var(--accent)', 'var(--blue)', 'var(--teal)', 'var(--green)', 'var(--orange)', 'var(--pink)', 'var(--amber)', 'var(--purple)']; $total_income = array_sum(array_column($monthly, 'income')); $total_expense = array_sum(array_column($monthly, 'expense')); $expense_cat_total = array_sum(array_map(fn($c) => (float)$c->total, $expense_cats)); $prev_year = $year - 1; $next_year = $year + 1; // ---------- панель 1: доходы/расходы по месяцам (полилинии) ---------- $chart_max = 0.0; for ($m = 1; $m <= 12; $m++) { $chart_max = max($chart_max, $monthly[$m]['income'] ?? 0, $monthly[$m]['expense'] ?? 0); } $toPoints = static function (string $key) use ($monthly, $chart_max): string { $points = []; for ($m = 1; $m <= 12; $m++) { $x = 10 + ($m - 1) / 11 * 700; $y = $chart_max > 0 ? 150 - (($monthly[$m][$key] ?? 0) / $chart_max * 140) : 150; $points[] = round($x, 1) . ',' . round($y, 1); } return implode(' ', $points); }; $income_points = $toPoints('income'); $expense_points = $toPoints('expense'); // ---------- панель 4: прогноз до конца года — грубая линейная экстраполяция по среднему // месячному балансу с начала года (не модель, честно подписано в тексте панели ниже) ---------- $is_current_year = $year === (int)date('Y'); $elapsed = $is_current_year ? $month : 12; // прошлый год — считаем законченным целиком $ytd_balance = 0.0; $running = []; $running_balance = 0.0; for ($m = 1; $m <= $elapsed; $m++) { $running_balance += ($monthly[$m]['income'] ?? 0.0) - ($monthly[$m]['expense'] ?? 0.0); $ytd_balance = $running_balance; $running[] = $running_balance; } $avg_monthly = $elapsed > 0 ? $ytd_balance / $elapsed : 0.0; $remaining = max(0, 12 - $elapsed); $forecast_total = $ytd_balance + $avg_monthly * $remaining; $spark_max = $running !== [] ? max(array_map('abs', $running)) : 0.0; $spark_points = []; $spark_n = count($running); foreach ($running as $i => $value) { $x = $spark_n > 1 ? 10 + $i / ($spark_n - 1) * 220 : 10; $y = $spark_max > 0 ? 30 - ($value / $spark_max * 25) : 30; $spark_points[] = round($x, 1) . ',' . round($y, 1); } // ---------- панель 5: год к году по кварталам (баланс доход-расход) ---------- $quarterBalance = static function (array $monthly, int $quarter): float { $sum = 0.0; for ($m = ($quarter - 1) * 3 + 1; $m <= $quarter * 3; $m++) { $sum += ($monthly[$m]['income'] ?? 0) - ($monthly[$m]['expense'] ?? 0); } return $sum; }; $quarters = []; for ($q = 1; $q <= 4; $q++) { $quarters[$q] = ['prev' => $quarterBalance($monthly_prev, $q), 'cur' => $quarterBalance($monthly, $q)]; } $quarter_max = 1.0; foreach ($quarters as $q) { $quarter_max = max($quarter_max, abs($q['prev']), abs($q['cur'])); } ?>

Аналитика

‹ ›
Год к дате
Доходы и расходы по месяцам
Нет данных за год
Доходы Расходы
Структура расходов
Нет расходов за месяц
$cat) { $pct = round((float)$cat->total / $expense_cat_total * 100); $color = $cat_colors[$i % count($cat_colors)]; $gradient_parts[] = "$color {$cursor_pct}% " . ($cursor_pct + $pct) . '%'; $cursor_pct += $pct; $legend[] = ['title' => $cat->title, 'pct' => $pct, 'color' => $color]; } ?>
%
План vs факт
Нет расходов за месяц
categorie_id] ?? 0.0; $fact = (float)$cat->total; $pct = $plan > 0 ? round($fact / $plan * 100) : ($fact > 0 ? 100 : 0); $over = $plan > 0 && $fact > $plan; ?>
title, ENT_QUOTES, 'UTF-8') ?> ₽
Прогноз
Тренд до конца года
Недостаточно данных для прогноза
При текущем темпе к декабрю = 0 ? 'останется' : 'не хватит' ?> ≈ ₽ = 0 ? 'сверх текущих трат' : '' ?> — грубая оценка по среднему темпу прошедших 0 ? 'месяцев' : 'месяцев года' ?>, не модель.
Год к году
Сравнение периодов
$val): ?> 0 ? max(2, abs($val['prev']) / $quarter_max * 90) : 2; $h_cur = $quarter_max > 0 ? max(2, abs($val['cur']) / $quarter_max * 90) : 2; ?>
Q