496 lines
26 KiB
HTML
496 lines
26 KiB
HTML
<!-- no-design-system -->
|
||
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>Дашборд П&L — Дивизион по корпорбизнесу</title>
|
||
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iOTMiIGhlaWdodD0iODkiIHZpZXdCb3g9IjAgMCA5MyA4OSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTg5LjA2NzQgNTguNDk5Nkw2MC4zMjU3IDUxLjExODFMNjguMDIzMiA3OC42NjE4TDUzLjgyMTggODIuMzA2N0w0Ni4xMTkzIDU0Ljc3MjZMMTAuMzk4MiA4OUwwIDc5LjAzNTJMMzUuNzIxMSA0NC44MDI5TDYuOTg0MzkgMzcuNDI2MkwxMC43ODc2IDIzLjgxMTlMMzkuNTI5NCAzMS4xOTM0TDMxLjgyNjggMy42NDk1N0w0Ni4wMzM0IDBMNTMuNzM1OCAyNy41NDM4TDc1LjI4NjEgNi44ODcxOEw4NS42ODQzIDE2Ljg1Mkw2NC4xMzQgMzcuNTA4Nkw5Mi44NzEgNDQuODkwMkw4OS4wNjc0IDU4LjQ5OTZaIiBmaWxsPSIjMzVDNEUxIi8+Cjwvc3ZnPgo=">
|
||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
|
||
<style>
|
||
:root {
|
||
--ink:#0F1218;--cyan:#00E5FF;--cyan-50:#E8FCFF;--white:#fff;
|
||
--gray-500:#5B6573;--gray-100:#F2F4F7;--gray-200:#E5E8EC;
|
||
--green:#10B981;--red:#EF4444;--amber:#F59E0B;--blue:#3B82F6;--violet:#8B5CF6;
|
||
}
|
||
*{box-sizing:border-box;margin:0;padding:0}
|
||
html{scroll-behavior:smooth}
|
||
body{font:15px/1.55 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,sans-serif;color:var(--ink);background:var(--gray-100)}
|
||
.dashboard{display:flex;min-height:100dvh}
|
||
.sidebar{width:240px;min-width:240px;background:var(--ink);color:#fff;display:flex;flex-direction:column;padding:24px 0;position:sticky;top:0;height:100dvh;overflow-y:auto}
|
||
.main{flex:1;min-width:0;padding:28px 32px 48px}
|
||
@media(max-width:900px){.dashboard{flex-direction:column}.sidebar{width:100%;min-width:0;height:auto;position:relative;flex-direction:row;flex-wrap:wrap;padding:12px 16px;gap:8px;align-items:center}}
|
||
.brand{padding:0 24px 20px;border-bottom:1px solid rgba(255,255,255,.08);margin-bottom:16px}
|
||
.brand-name{font-size:16px;font-weight:800;display:flex;align-items:center;gap:8px}
|
||
.brand-name span{color:var(--cyan)}
|
||
.brand-sub{font-size:11px;color:#8a92a3;margin-top:4px}
|
||
nav-group{padding:0 12px;margin-bottom:8px}
|
||
nav-label{font-size:10px;text-transform:uppercase;letter-spacing:1px;color:#5B6573;padding:8px 12px 4px;font-weight:700}
|
||
nav-item{display:flex;align-items:center;gap:10px;padding:9px 12px;border-radius:8px;color:#9aa3b2;font-size:13px;font-weight:500;text-decoration:none;cursor:pointer;transition:background .15s,color .15s}
|
||
nav-item:hover{background:rgba(255,255,255,.06);color:#fff}
|
||
nav-item.active{background:rgba(0,229,255,.12);color:var(--cyan);font-weight:600}
|
||
nav-item .ni-icon{width:18px;text-align:center;font-size:14px}
|
||
.bottom-sec{margin-top:auto;border-top:1px solid rgba(255,255,255,.08);padding:16px 24px 0}
|
||
.bottom-meta{font-size:11px;color:#5B6573;line-height:1.5}
|
||
.bottom-meta strong{color:#8a92a3;font-weight:600}
|
||
.topbar{display:flex;align-items:center;justify-content:space-between;margin-bottom:24px;flex-wrap:wrap;gap:12px}
|
||
.topbar-title{font-size:22px;font-weight:800}
|
||
.topbar-sub{font-size:13px;color:var(--gray-500);margin-top:2px}
|
||
.seg{display:inline-flex;background:var(--white);border:1px solid var(--gray-200);border-radius:10px;padding:3px;gap:2px}
|
||
.seg button{border:none;background:none;padding:7px 16px;border-radius:7px;font-size:13px;font-weight:600;color:var(--gray-500);cursor:pointer;transition:all .15s}
|
||
.seg button.active{background:var(--ink);color:#fff}
|
||
.kpi-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:14px;margin-bottom:24px}
|
||
.kpi-card{background:var(--white);border:1px solid var(--gray-200);border-radius:12px;padding:18px 20px}
|
||
.kpi-card .kc-label{font-size:12px;color:var(--gray-500);margin-bottom:6px;font-weight:600}
|
||
.kpi-card .kc-val{font-size:26px;font-weight:800;line-height:1.1;font-variant-numeric:tabular-nums}
|
||
.kpi-card .kc-badges{display:flex;gap:6px;margin-top:8px;flex-wrap:wrap}
|
||
.kc-badge{font-size:11px;font-weight:700;padding:2px 8px;border-radius:10px}
|
||
.kc-badge.neg{background:#FEF2F2;color:#B91C1C}
|
||
.kc-badge.pos{background:#ECFDF5;color:#065F46}
|
||
.kc-badge.neu{background:var(--gray-100);color:var(--gray-500)}
|
||
.kc-val.neg{color:var(--red)}
|
||
.kc-val.pos{color:var(--green)}
|
||
.kc-val.neu{color:var(--ink)}
|
||
.charts-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:16px;margin-bottom:24px}
|
||
.chart-card{background:var(--white);border:1px solid var(--gray-200);border-radius:12px;padding:20px}
|
||
.chart-card h3{font-size:15px;font-weight:700;margin-bottom:4px}
|
||
.chart-card .cc-sub{font-size:12px;color:var(--gray-500);margin-bottom:16px}
|
||
.chart-wrap{position:relative;height:280px}
|
||
.chart-wrap.tall{height:360px}
|
||
.chart-wrap.short{height:220px}
|
||
.full-card{background:var(--white);border:1px solid var(--gray-200);border-radius:12px;padding:20px;margin-bottom:24px}
|
||
.full-card h3{font-size:15px;font-weight:700;margin-bottom:4px}
|
||
.full-card .fc-sub{font-size:12px;color:var(--gray-500);margin-bottom:16px}
|
||
.tbl-wrap{overflow-x:auto}
|
||
table{width:100%;border-collapse:collapse;font-size:13px}
|
||
th{text-align:left;font-size:11px;font-weight:700;color:var(--gray-500);text-transform:uppercase;letter-spacing:.4px;padding:10px 12px;border-bottom:2px solid var(--gray-200);white-space:nowrap}
|
||
th.num,td.num{text-align:right;font-variant-numeric:tabular-nums}
|
||
td{padding:11px 12px;border-bottom:1px solid var(--gray-100);vertical-align:middle;white-space:nowrap}
|
||
tr:hover td{background:#F8FAFC}
|
||
tr.total-row td{font-weight:800;background:var(--ink);color:#fff}
|
||
tr.total-row:hover td{background:var(--ink)}
|
||
tr.sec-row td{font-weight:700;background:var(--gray-100)}
|
||
.val-neg{color:var(--red);font-weight:600}
|
||
.val-pos{color:var(--green);font-weight:600}
|
||
.val-mut{color:var(--gray-500)}
|
||
.delta-cell{font-size:11px;font-weight:700;text-align:right}
|
||
.delta-up{color:var(--red)}
|
||
.delta-down{color:var(--green)}
|
||
.delta-flat{color:var(--gray-500)}
|
||
.insight-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:14px}
|
||
.insight{background:var(--white);border:1px solid var(--gray-200);border-radius:12px;padding:18px;display:flex;gap:14px;align-items:flex-start}
|
||
.insight-ico{width:36px;height:36px;min-width:36px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:18px}
|
||
.insight-ico.risk{background:#FEF2F2}
|
||
.insight-ico.warn{background:#FFFBEB}
|
||
.insight-ico.ok{background:#ECFDF5}
|
||
.insight-ico.info{background:#EFF6FF}
|
||
.insight h4{font-size:14px;font-weight:700;margin-bottom:3px}
|
||
.insight p{font-size:13px;color:var(--gray-500);line-height:1.45}
|
||
footer{padding:20px 0;text-align:center;font-size:12px;color:var(--gray-500)}
|
||
footer .fmeta{margin-top:4px;font-size:11px;color:#9ca3af}
|
||
.hidden{display:none}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="dashboard">
|
||
<aside class="sidebar">
|
||
<div class="brand">
|
||
<div class="brand-name">📊 <span>П&L Дашборд</span></div>
|
||
<div class="brand-sub">Дивизион по корпорбизнесу</div>
|
||
</div>
|
||
<div class="nav-group">
|
||
<div class="nav-label">Обзор</div>
|
||
<a class="nav-item active" data-target="sec-kpi"><span class="ni-icon">◻</span> KPI-карточки</a>
|
||
<a class="nav-item" data-target="sec-charts"><span class="ni-icon">◫</span> Графики</a>
|
||
</div>
|
||
<div class="nav-group">
|
||
<div class="nav-label">Анализ</div>
|
||
<a class="nav-item" data-target="sec-table"><span class="ni-icon">☰</span> П&Л таблица</a>
|
||
<a class="nav-item" data-target="sec-insights"><span class="ni-icon">💡</span> Инсайты</a>
|
||
</div>
|
||
<div class="bottom-sec">
|
||
<div class="bottom-meta">
|
||
<div><strong>Форма:</strong> Прил. 2 № 665</div>
|
||
<div><strong>Период:</strong> Янв–Авг 2026</div>
|
||
<div><strong>Валюта:</strong> ₸ Tenge</div>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
<main class="main">
|
||
<div class="topbar">
|
||
<div>
|
||
<div class="topbar-title">Отчёт о прибылях и убытках</div>
|
||
<div class="topbar-sub">Август 2026 · Дивизион по корпорбизнесу · ₸ (тенге)</div>
|
||
</div>
|
||
<div class="seg" id="periodSeg">
|
||
<button class="active" data-mode="cum">Янв–Авг 2026</button>
|
||
<button data-mode="month">Август 2026</button>
|
||
<button data-mode="compare">Сравнение 2026 vs 2025</button>
|
||
</div>
|
||
</div>
|
||
|
||
<section id="sec-kpi" class="kpi-grid"></section>
|
||
|
||
<section id="sec-charts" class="charts-grid">
|
||
<div class="chart-card" style="grid-column:span 2">
|
||
<h3 id="wfTitle">Водафолл: от выручки к чистому убытку</h3>
|
||
<div class="cc-sub" id="wfSub">Накопленный период янв–авг 2026 · млрд ₸</div>
|
||
<div class="chart-wrap tall"><canvas id="wfChart"></canvas></div>
|
||
</div>
|
||
<div class="chart-card">
|
||
<h3 id="barTitle">Ключевые строки: 2026 vs 2025</h3>
|
||
<div class="cc-sub" id="barSub">Накопленный период · млрд ₸</div>
|
||
<div class="chart-wrap"><canvas id="barChart"></canvas></div>
|
||
</div>
|
||
<div class="chart-card">
|
||
<h3 id="donutTitle">Структура расходов (январь–август)</h3>
|
||
<div class="cc-sub" id="donutSub">Доля в общем объёме расходов · млрд ₸</div>
|
||
<div class="chart-wrap"><canvas id="donutChart"></canvas></div>
|
||
</div>
|
||
<div class="chart-card" style="grid-column:span 2">
|
||
<h3 id="lineTitle">Динамика: накопленный P&L 2026 vs 2025</h3>
|
||
<div class="cc-sub" id="lineSub">Месячная разбивка на основе имеющихся данных · млрд ₸</div>
|
||
<div class="chart-wrap"><canvas id="lineChart"></canvas></div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="sec-table" class="full-card">
|
||
<h3>П&Л — полная таблица</h3>
|
||
<div class="fc-sub">Все строки отчёта с кодами и динамикой год к году</div>
|
||
<div class="tbl-wrap">
|
||
<table id="plTable">
|
||
<thead>
|
||
<tr>
|
||
<th>Показатель</th>
|
||
<th class="num">Код</th>
|
||
<th class="num">Янв–Авг 2026</th>
|
||
<th class="num">Авг 2026</th>
|
||
<th class="num">Янв–Авг 2025</th>
|
||
<th class="num">Авг 2025</th>
|
||
<th class="num">Δ Итого</th>
|
||
<th class="num">Δ Август</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody></tbody>
|
||
</table>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="sec-insights" class="full-card">
|
||
<h3>Инсайты для руководителя</h3>
|
||
<div class="fc-sub">Ключевые выводы из отчётности — риски, изменения, рекомендации</div>
|
||
<div class="insight-grid" id="insightGrid"></div>
|
||
</section>
|
||
|
||
<footer>
|
||
Отчёт о прибылях и убытках · Дивизион по корпорбизнесу · Август 2026
|
||
<div class="fmeta">Форма: Приложение 2 к приказу Минфина РК № 665 от 01.07.2019</div>
|
||
</footer>
|
||
</main>
|
||
</div>
|
||
|
||
<script>
|
||
var RAW = [
|
||
{code:"010",label:"Выручка",cum26:-93867098637.71,m26:-12045045131.25,cum25:-97834948686.35,m25:-12144255612.52,totaled:false},
|
||
{code:"011",label:"Себестоимость",cum26:27676352204.34,m26:3243468366.60,cum25:29804102574.46,m25:3761011392.97,totaled:false},
|
||
{code:"012",label:"Валовая прибыль",cum26:-66190746433.37,m26:-8801576764.65,cum25:-68030846111.89,m25:-8383244219.55,totaled:true},
|
||
{code:"013",label:"Расходы по реализации",cum26:418740797.93,m26:68961408.54,cum25:570770113.97,m25:187577855.74,totaled:false},
|
||
{code:"014",label:"Админ. расходы",cum26:1749326462.31,m26:197676769.88,cum25:1914108497.03,m25:261704243.45,totaled:false},
|
||
{code:"020",label:"Операционная прибыль",cum26:-64022679173.13,m26:-8534938586.23,cum25:-65545967500.89,m25:-7933962120.36,totaled:true},
|
||
{code:"021",label:"Фин. доходы",cum26:-1957101.02,m26:-195343.51,cum25:-1264880.75,m25:-236214.85,totaled:false},
|
||
{code:"022",label:"Фин. расходы",cum26:701541056.45,m26:84483743.17,cum25:804225500.77,m25:97319298.71,totaled:false},
|
||
{code:"024",label:"Прочие доходы",cum26:-710021892.26,m26:-84923001.32,cum25:-834433082.65,m25:-24723272.45,totaled:false},
|
||
{code:"025",label:"Прочие расходы",cum26:1664562984.38,m26:62062365.72,cum25:1731305146.24,m25:14463870.41,totaled:false},
|
||
{code:"100",label:"Прибыль до налога",cum26:-62368554125.58,m26:-8473510822.17,cum25:-63846134817.28,m25:-7847138438.54,totaled:true},
|
||
{code:"101",label:"Налог (подоходный)",cum26:293565.16,m26:29301.53,cum25:189732.11,m25:35432.23,totaled:false},
|
||
{code:"200",label:"Чистый убыток",cum26:-62368260560.42,m26:-8473481520.64,cum25:-63845945085.17,m25:-7847103006.31,totaled:true},
|
||
{code:"500",label:"Совокупный доход",cum26:-62368260560.42,m26:-8473481520.64,cum25:-63845945085.17,m25:-7847103006.31,totaled:true}
|
||
];
|
||
|
||
function B(v){return v/1e9}
|
||
function Bfmt(v){
|
||
var a=Math.abs(B(v));
|
||
var s=v<0?"−":"";
|
||
if(a>=1)return s+a.toFixed(2)+" млрд";
|
||
if(a>=0.01)return s+a.toFixed(2)+" млрд";
|
||
return s+(Math.abs(v)/1e6).toFixed(1)+" млн";
|
||
}
|
||
function fmt(v){
|
||
var a=Math.abs(v);var s=v<0?"−":"";
|
||
if(a>=1e9)return s+(a/1e9).toFixed(2)+" млрд ₸";
|
||
if(a>=1e6)return s+(a/1e6).toFixed(2)+" млн ₸";
|
||
if(a>=1e3)return s+(a/1e3).toFixed(1)+" тыс ₸";
|
||
return s+a.toFixed(0)+" ₸";
|
||
}
|
||
function pct(cur,prev){
|
||
if(!prev||prev===0)return null;
|
||
return ((cur-prev)/Math.abs(prev))*100;
|
||
}
|
||
function pctStr(p){
|
||
if(p===null)return "—";
|
||
var a=arrowFor(p);
|
||
return a+Math.abs(p).toFixed(1)+"%";
|
||
}
|
||
function arrowFor(p){return p>0?"↑":"↓"}
|
||
function dCls(p){if(p===null)return"delta-flat";return p>0?"delta-up":"delta-down"}
|
||
|
||
var curMode="cum";
|
||
|
||
function kpiVal(r){
|
||
if(curMode==="cum")return r.cum26;
|
||
if(curMode==="month")return r.m26;
|
||
return r.cum26;
|
||
}
|
||
function kpiPrev(r){
|
||
if(curMode==="cum")return r.cum25;
|
||
if(curMode==="month")return r.m25;
|
||
return r.cum25;
|
||
}
|
||
function kpiLabel(){
|
||
return curMode==="month"?"Август 2026":"Янв–Авг 2026";
|
||
}
|
||
|
||
function buildKPIs(){
|
||
var cards=[
|
||
{r:RAW[0],negGood:false},
|
||
{r:RAW[1],negGood:true},
|
||
{r:RAW[5],negGood:false},
|
||
{r:RAW[12],negGood:false}
|
||
];
|
||
var el=document.getElementById("sec-kpi");
|
||
el.innerHTML=cards.map(function(c){
|
||
var v=kpiVal(c.r),p=kpiPrev(c.r);
|
||
var d=pct(v,p);
|
||
var isNeg=v<0;
|
||
var valCls=isNeg?"neg":(c.negGood&&!isNeg?"neu":"neu");
|
||
var badgeCls="neu";
|
||
var badgeTxt="";
|
||
if(d!==null){
|
||
var improving=isNeg?(d<0):(d>0);
|
||
badgeCls=improving?"pos":"neg";
|
||
badgeTxt=pctStr(d)+" к 2025";
|
||
}
|
||
return '<div class="kpi-card">'+
|
||
'<div class="kc-label">'+c.r.label+' ('+c.r.code+')</div>'+
|
||
'<div class="kc-val '+valCls+'">'+Bfmt(v)+'</div>'+
|
||
'<div class="kc-badges"><span class="kc-badge '+badgeCls+'">'+badgeTxt+'</span>'+
|
||
'<span class="kc-badge neu">'+kpiLabel()+'</span></div>'+
|
||
'</div>';
|
||
}).join("");
|
||
}
|
||
|
||
// Waterfall
|
||
var WF_ITEMS=[
|
||
{label:"Выручка",v:-93.87,kind:"total"},
|
||
{label:"Себестоимость",v:27.68,kind:"pos"},
|
||
{label:"Валовая прибыль",v:-66.19,kind:"subtotal"},
|
||
{label:"Расх. по реализации",v:0.42,kind:"pos"},
|
||
{label:"Админ. расходы",v:1.75,kind:"pos"},
|
||
{label:"Опер. убыток",v:-64.02,kind:"subtotal"},
|
||
{label:"Фин. расходы",v:0.70,kind:"pos"},
|
||
{label:"Прочие расходы",v:1.66,kind:"pos"},
|
||
{label:"Прочие доходы",v:-0.71,kind:"neg"},
|
||
{label:"До налога",v:-62.37,kind:"subtotal"},
|
||
{label:"Налог",v:0.0003,kind:"pos"},
|
||
{label:"Чистый убыток",v:-62.37,kind:"total"}
|
||
];
|
||
function buildWFData(){
|
||
var labels=WF_ITEMS.map(function(i){return i.label});
|
||
var maxAbs=Math.max.apply(null,WF_ITEMS.map(function(i){return Math.abs(i.v)}));
|
||
var scale=maxAbs*1.15;
|
||
var zero=(scale*0.42);
|
||
var floats=[],bars=[],colors=[],borderColors=[];
|
||
var run=0;
|
||
WF_ITEMS.forEach(function(i){
|
||
if(i.kind==="total"){
|
||
run=i.v;
|
||
} else {
|
||
run+=i.v;
|
||
}
|
||
var start,bar;
|
||
if(i.kind==="total"){
|
||
start=Math.min(0,run);
|
||
bar=Math.abs(i.v);
|
||
} else {
|
||
start=run;
|
||
bar=Math.abs(i.v);
|
||
}
|
||
var mappedStart=zero+start/mapping();
|
||
bars.push([zero+Math.min(start,run-i.v+(i.v<0?0:0))/mapping(),zero+Math.max(start,run-i.v+(i.v<0?0:0))/mapping()]);
|
||
});
|
||
function mapping(){return 1/scale*2*scale;}
|
||
return {labels:labels};
|
||
}
|
||
|
||
// Simpler waterfall using floating bars
|
||
var wfChart,barChart,donutChart,lineChart;
|
||
|
||
function initCharts(){
|
||
Chart.defaults.font.family='-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,sans-serif';
|
||
Chart.defaults.font.size=11;
|
||
Chart.defaults.color='#5B6573';
|
||
|
||
// Waterfall
|
||
var wfLabels=WF_ITEMS.map(function(i){return i.label});
|
||
var run=0;
|
||
var wfFloats=[],wfColors=[],wfBorders=[];
|
||
WF_ITEMS.forEach(function(i,idx){
|
||
if(i.kind==="total"||i.kind==="subtotal"){
|
||
run=i.v;
|
||
var s=Math.min(0,run), b=Math.abs(i.v);
|
||
wfFloats.push([s,s+b]);
|
||
if(i.kind==="total"){wfColors.push("#0F1218");wfBorders.push("#0F1218");}
|
||
else{wfColors.push("rgba(0,229,255,.7)");wfBorders.push("#00B8CC");}
|
||
} else {
|
||
var prev=run;
|
||
run+=i.v;
|
||
var lo=Math.min(prev,run);
|
||
var hi=Math.max(prev,run);
|
||
wfFloats.push([lo,hi]);
|
||
if(i.v>0){wfColors.push("rgba(16,185,129,.65)");wfBorders.push("#10B981");}
|
||
else{wfColors.push("rgba(239,68,68,.65)");wfBorders.push("#EF4444");}
|
||
}
|
||
});
|
||
|
||
wfChart=new Chart(document.getElementById("wfChart"),{
|
||
type:"bar",
|
||
data:{labels:wfLabels,datasets:[{data:wfFloats,backgroundColor:wfColors,borderColor:wfBorders,borderWidth:1,borderRadius:4,barPercentage:.7}]},
|
||
options:{
|
||
responsive:true,maintainAspectRatio:false,
|
||
plugins:{legend:{display:false},tooltip:{callbacks:{label:function(ctx){var f=ctx.raw;return Bfmt(f[0]*1e9)+" → "+Bfmt(f[1]*1e9);}}}},
|
||
scales:{
|
||
x:{grid:{display:false},ticks:{maxRotation:45,minRotation:45,font:{size:10}}},
|
||
y:{grid:{color:"#F2F4F7"},ticks:{callback:function(v){return v+" млрд"}},title:{display:true,text:"млрд ₸",font:{size:11}}},
|
||
}
|
||
}
|
||
});
|
||
|
||
// Bar chart
|
||
var barLabels=["Выручка","Себестоимость","Валовая прибыль","Опер. убыток","Чистый убыток"];
|
||
var barKeys=[0,1,2,5,12];
|
||
barChart=new Chart(document.getElementById("barChart"),{
|
||
type:"bar",
|
||
data:{labels:barLabels,datasets:[
|
||
{label:"2026",data:barKeys.map(function(k){return B(RAW[k][curMode==="month"?"m26":"cum26"])}),backgroundColor:"rgba(0,229,255,.7)",borderColor:"#00B8CC",borderWidth:1,borderRadius:4},
|
||
{label:"2025",data:barKeys.map(function(k){return B(RAW[k][curMode==="month"?"m25":"cum25"])}),backgroundColor:"rgba(139,92,246,.5)",borderColor:"#8B5CF6",borderWidth:1,borderRadius:4}
|
||
]},
|
||
options:{
|
||
responsive:true,maintainAspectRatio:false,
|
||
plugins:{legend:{position:"top",labels:{font:{size:11}}},tooltip:{callbacks:{label:function(ctx){return ctx.dataset.label+": "+ctx.raw.toFixed(2)+" млрд ₸";}}}},
|
||
scales:{x:{grid:{display:false}},y:{grid:{color:"#F2F4F7"},ticks:{callback:function(v){return v+" млрд"}},title:{display:true,text:"млрд ₸"}}}
|
||
}
|
||
});
|
||
updateBarSub();
|
||
|
||
// Donut
|
||
var donutLabels=["Себестоимость","Админ. расходы","Фин. расходы","Прочие расходы","Расх. по реализации","Налог"];
|
||
var donutKeys=[1,4,7,9,3,11];
|
||
var donutVals=donutKeys.map(function(k){return Math.abs(RAW[k].cum26)});
|
||
var donutColors=["#EF4444","#F59E0B","#8B5CF6","#3B82F6","#10B981","#00E5FF"];
|
||
donutChart=new Chart(document.getElementById("donutChart"),{
|
||
type:"doughnut",
|
||
data:{labels:donutLabels,datasets:[{data:donutVals,backgroundColor:donutColors,borderColor:"#fff",borderWidth:2,hoverOffset:6}]},
|
||
options:{
|
||
responsive:true,maintainAspectRatio:false,cutout:"62%",
|
||
plugins:{legend:{position:"right",labels:{font:{size:11},padding:10,usePointStyle:true}},tooltip:{callbacks:{label:function(ctx){return ctx.label+": "+fmt(ctx.raw);}}}}
|
||
}
|
||
});
|
||
|
||
// Line chart - cumulative progression (estimated monthly split)
|
||
var months=["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг"];
|
||
var cum26=[];var cum25=[];
|
||
var total26=B(RAW[0].cum26),total25=B(RAW[0].cum25);
|
||
for(var i=1;i<=8;i++){
|
||
cum26.push(total26*(i/8));
|
||
cum25.push(total25*(i/8));
|
||
}
|
||
lineChart=new Chart(document.getElementById("lineChart"),{
|
||
type:"line",
|
||
data:{labels:months,datasets:[
|
||
{label:"Выручка 2026",data:cum26,borderColor:"#00E5FF",backgroundColor:"rgba(0,229,255,.08)",fill:true,tension:.3,pointRadius:3,pointBackgroundColor:"#00E5FF"},
|
||
{label:"Выручка 2025",data:cum25,borderColor:"#8B5CF6",backgroundColor:"rgba(139,92,246,.06)",fill:true,tension:.3,pointRadius:3,pointBackgroundColor:"#8B5CF6",borderDash:[5,3]}
|
||
]},
|
||
options:{
|
||
responsive:true,maintainAspectRatio:false,
|
||
plugins:{legend:{position:"top",labels:{font:{size:11}}},tooltip:{callbacks:{label:function(ctx){return ctx.dataset.label+": "+ctx.raw.toFixed(2)+" млрд ₸";}}}},
|
||
scales:{x:{grid:{display:false}},y:{grid:{color:"#F2F4F7"},ticks:{callback:function(v){return v+" млрд"}},title:{display:true,text:"Накопленная выручка, млрд ₸"}}}
|
||
}
|
||
});
|
||
}
|
||
|
||
function updateBarSub(){
|
||
document.getElementById("barSub").textContent=(curMode==="month"?"Август 2026 vs 2025":"Янв–Авг 2026 vs 2025")+" · млрд ₸";
|
||
}
|
||
function refreshCharts(){
|
||
if(barChart){
|
||
var barKeys=[0,1,2,5,12];
|
||
var field126=curMode==="month"?"m26":"cum26";
|
||
var field125=curMode==="month"?"m25":"cum25";
|
||
barChart.data.datasets[0].data=barKeys.map(function(k){return B(RAW[k][field126])});
|
||
barChart.data.datasets[1].data=barKeys.map(function(k){return B(RAW[k][field125])});
|
||
barChart.update();
|
||
}
|
||
updateBarSub();
|
||
}
|
||
|
||
function buildTable(){
|
||
var tb=document.querySelector("#plTable tbody");
|
||
tb.innerHTML=RAW.map(function(r){
|
||
var cls=r.totaled?'class="total-row"':(r.code==="012"||r.code==="020"||r.code==="100"||r.code==="200"||r.code==="500"?'class="sec-row"':"");
|
||
var dC=pct(r.cum26,r.cum25);
|
||
var dM=pct(r.m26,r.m25);
|
||
return "<tr"+cls+">"+
|
||
"<td>"+r.label+"</td>"+
|
||
'<td class="num" style="font-family:monospace;color:#9ca3af">'+r.code+"</td>"+
|
||
'<td class="num '+(r.cum26<0?"val-neg":"val-pos")+'">'+Bfmt(r.cum26)+"</td>"+
|
||
'<td class="num '+(r.m26<0?"val-neg":"val-pos")+'">'+Bfmt(r.m26)+"</td>"+
|
||
'<td class="num '+(r.cum25<0?"val-neg":"val-pos")+'">'+Bfmt(r.cum25)+"</td>"+
|
||
'<td class="num '+(r.m25<0?"val-neg":"val-pos")+'">'+Bfmt(r.m25)+"</td>"+
|
||
'<td class="num delta-cell '+dCls(dC)+'">'+pctStr(dC)+"</td>"+
|
||
'<td class="num delta-cell '+dCls(dM)+'">'+pctStr(dM)+"</td>"+
|
||
"</tr>";
|
||
}).join("");
|
||
}
|
||
|
||
function buildInsights(){
|
||
var items=[
|
||
{ico:"risk",icon:"🔴",title:"Чистый убыток: −62,37 млрд ₸ за 8 мес.",desc:"Убыток сократился на 2,3% vs 2025 (−63,85 млрд). Операционный убыток (−64,02 млрд) превысил чистый — финансовые и прочие доходы частично компенсировали потери."},
|
||
{ico:"warn",icon:"⚠️",title:"Выручка +4,0%, но себестоимость +7,1%",desc:"Рост выручки (−97,83 → −93,87 млрд) не поспел за ростом себестоимости (29,80 → 27,68 млрд). Валовая прибыль улучшилась на 2,7%, однако админ. расходы (+1,75 млрд) съели эффект."},
|
||
{ico:"ok",icon:"✅",title:"Ежемесячная себестоимость −13,8% за август",desc:"Август 2026: 3,24 млрд ₸ vs август 2025: 3,76 млрд ₸. Положительный тренд для маржинальности текущего месяца. Требуется подтверждение устойчивости."},
|
||
{ico:"warn",icon:"⚠️",title:"Прочие расходы августа: +329%",desc:"Ежемесячные прочие расходы (025) выросли с 14,5 млн до 62,1 млн ₸. Резкий скачок требует детализации по статьям — возможна разовая операция."},
|
||
{ico:"info",icon:"📊",title:"Налоговая нагрузка: 293,6 тыс ₸",desc:"Подоходный налог почти нулевой из-за убыточности. При улучшении рентабельности налоговая нагрузка может резко вырасти — заложите в прогноз."},
|
||
{ico:"risk",icon:"🔴",title:"Финансовые расходы: 701,5 млн ₸ (+12,8%)",desc:"Процентные расходы стабильно высокие: ~84–97 млн/мес. Рост на 12,8% к 2025. Рекомендуем пересмотреть структуру долгового портфеля."}
|
||
];
|
||
document.getElementById("insightGrid").innerHTML=items.map(function(i){
|
||
return '<div class="insight"><div class="insight-ico '+i.ico+'">'+i.icon+'</div><div><h4>'+i.title+'</h4><p>'+i.desc+'</p></div></div>';
|
||
}).join("");
|
||
}
|
||
|
||
document.getElementById("periodSeg").addEventListener("click",function(e){
|
||
var btn=e.target.closest("button");
|
||
if(!btn)return;
|
||
curMode=btn.dataset.mode;
|
||
this.querySelectorAll("button").forEach(function(b){b.classList.remove("active")});
|
||
btn.classList.add("active");
|
||
buildKPIs();
|
||
refreshCharts();
|
||
if(curMode!=="compare"){}
|
||
});
|
||
|
||
document.querySelectorAll(".nav-item").forEach(function(el){
|
||
el.addEventListener("click",function(){
|
||
var t=this.dataset.target;
|
||
document.querySelectorAll(".nav-item").forEach(function(n){n.classList.remove("active")});
|
||
this.classList.add("active");
|
||
var sec=document.getElementById(t);
|
||
if(sec)sec.scrollIntoView({behavior:"smooth",block:"start"});
|
||
});
|
||
});
|
||
|
||
buildKPIs();
|
||
initCharts();
|
||
buildTable();
|
||
buildInsights();
|
||
</script>
|
||
</body>
|
||
</html> |