['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'])); } ?>