';
}
function toast(msg, tone) {
var d = document.createElement("div");
d.className = "toast"; if (tone) d.setAttribute("data-tone", tone);
d.textContent = msg;
$("toasts").appendChild(d);
setTimeout(function () { d.style.transition = "opacity .3s"; d.style.opacity = "0"; setTimeout(function () { d.remove(); }, 320); }, 3600);
}
function fileStatus(i) {
if (!S.recognize && !S.manual) return ["info", "В очереди"];
if (S.manual) return ["warn", "Вручную"];
var tpl = FILES[i][1];
if (tpl === "2024") return ["ok", "Т 2024 · 8/8"];
if (tpl === "2025") return ["ok", "Т 2025 · 8/8"];
return ["ok", "Т 2026 · 8/8"];
}
function logs() {
var l = BASE_LOGS.slice();
if (S.recognize || S.manual) l = l.concat(DONE_LOGS);
return l;
}
/* ---------- shell ---------- */
function renderSidebar() {
var items = STEPS.map(function (st) {
var cur = S.screen === st.id;
var badge = "";
if (st.id === "check") badge = allChecked() ? "15/15" : checkedCount() + "/15";
return '';
});
items.push('');
$("sbNav").innerHTML = '
' + items.join("") + '
';
var f = $("sbFootMeta");
if (f) f.textContent = S.memoSent ? "отправлено" : "15 компаний";
}
function renderTopbar() {
var t = "";
if (S.screen === "upload") t = "Загрузка и распознавание";
else if (S.screen === "check") t = "Проверка данных и отклонений";
else if (S.screen === "memo") t = "Формирование записки";
else t = "О решении";
$("topTitle").innerHTML = '' + t + 'пакет к 15:00 понедельника';
}
function showScreen(id) {
var ok = canOpen(id);
if (!ok) { toast("Сначала завершите предыдущий шаг", "warn"); return; }
var need = id !== S.screen;
if (need && id === "memo" && !allChecked()) {
toast("Сначала отметьте все 15 компаний как проверенные", "warn"); return;
}
if (need && id === "memo" && !S.unitFixed) {
toast("Сначала исправьте расхождения единиц измерения", "warn"); return;
}
S.screen = id; save();
renderSidebar(); renderTopbar();
var r = { upload: viewUpload, check: viewCheck, memo: viewMemo, about: viewAbout }[id];
var el = $("view");
el.innerHTML = r();
document.querySelector(".kt-ai-main").scrollTop = 0;
bind(id);
closeMobile();
}
function canOpen(id) {
if (id === "upload") return true;
if (id === "check") return !!S.recognize;
if (id === "memo") return !!S.recognize;
return true;
}
function closeMobile() { var sb = $("sidebar"); if (sb) sb.removeAttribute("data-open"); $("scrim").classList.remove("on"); }
function stepHtml(curId) {
var h = "";
STEPS.forEach(function (st, i) {
var open = canOpen(st.id);
var done = canOpen({ upload: "check", check: "memo", memo: "done" }[st.id]);
var cur = curId === st.id;
var cls = [];
if (cur) cls.push('data-cur="true"');
if (done) cls.push('data-done="true"');
if (!open && !cur) cls.push('data-disabled="true"');
if (i > 0) h += '';
h += '' + (done ? ic("check") : st.n) + "" + st.t + "";
});
return '
' + h + "
";
}
function pageHead(title, sub, right) {
return '
' + title + "
" + (sub || "") + "
" +
(right ? '
' + right + "
" : "") + "
";
}
/* ================= ЭКРАН 1 — загрузка и распознавание ================= */
function viewUpload() {
var fileRows = FILES.map(function (f, i) {
var st = fileStatus(i);
return '
";
}).join("");
var progress = S.recognize || S.manual ? 100 : 0;
var banner, tone;
if (S.manual) { tone = "warn"; banner = "Распознавание остановлено: данные перенесены в ручной режим. Проверьте столбцы и верните автоматический режим."; }
else if (S.recognize) { tone = "ok"; banner = "Рассмотрены все форматы, все 15 файлов сопоставлены, данные перенесены в единый свод. Расхождение единиц отмечено у ООО «Телеком-4»."; }
else { tone = "info"; banner = "15 файлов получено из одного ящика. Запустите распознавание — система сопоставит форматы и извлечёт показатели."; }
var bannerHtml = '
Показатели: выручка, EBITDA, CAPEX, дебиторская задолженность — план и факт. Сопоставление по 3 вариантам шаблонов.
' +
'
Журнал действий ИИ
' +
'
' + logHtml + "
" +
"
" +
'
Извлечённые показатели
план и факт по 15 компаниям, млн тг
' +
'
Показатель
' + extractedHead + "
" +
extractedRows + "
";
}
/* ================= ЭКРАН 2 — проверка данных и отклонений ================= */
var chk = { metric: "all" };
function viewCheck() {
var cc = checkedCount();
var devCount = DEVS.length;
var unitFixOk = S.unitFixed;
var kpis =
kpi("Компаний в сводном файле", "15 / 15", "план и факт, август") +
kpi("Отклонения от плана более 10%", devCount, "Телеком-2, -3, -5, -7, -9, -13, -14") +
kpi("Единицы измерения", unitFixOk ? "исправлены" : "1 требует проверки", "ООО «Телеком-4» · выручка в файле в тыс. тг") +
kpi("Статус проверки", cc + " / 15", (unitFixOk && allChecked()) ? "можно переходить к записке" : "отмечайте строки по одной");
return pageHead("Проверка данных и отклонений", "Единый свод, созданный ИИ · проверьте перенос данных и отклонения от плана более 10%",
'' +
'") +
stepHtml("check") +
'
' + kpis + "
" +
'
Единый свод
' +
'
' +
'
' +
'' +
'' +
'' +
'' +
'' +
"
" +
'' +
"
" +
'' +
'
Подсветка: «×1 000» — расхождение единиц измерения, «+N%» — отклонение факта от плана. Строки с отклонениями более 10% помечены красным. Клик по строке — отметить данные как проверенные; клик по ячейке с ошибкой — исправить вручную.
' +
"
" + unitBanner;
}
function metricKey(m) {
if (m === "rev") return { plan: "vp", fact: "vf", dev: "dRev", ok: "revOk" };
if (m === "ebit") return { plan: "ep", fact: "ef", dev: "dEbit", ok: "ebitOk" };
if (m === "cap") return { plan: "cp", fact: "cf", dev: "dCap", ok: "capOk" };
if (m === "dz") return { plan: "dp", fact: "df", dev: "dDz", ok: "dzOk" };
return null;
}
function metricLabel(m) {
return { rev: "Выручка, млн тг", ebit: "EBITDA, млн тг", cap: "CAPEX, млн тг", dz: "Дебиторская задолженность, млн тг" }[m] || "";
}
function rowStatusHtml(c, i) {
if (S.checked[i]) return chip("ok", "Проверено");
return '";
}
function cellHtml(c, planKey, factKey, devKey, isRevUnit) {
if (isRevUnit && c.vp1000 && !S.unitFixed) {
return '
';
}
function renderSumTable() {
var box = $("sumTable");
if (!box) return;
var m = chk.metric;
var headExtra = m === "all"
? "
Выручка, млн тг
EBITDA, млн тг
CAPEX, млн тг
ДЗ, млн тг
"
: "
Выручка
EBITDA
" + metricLabel(m) + "
";
var rows = coRows();
var any = rows.indexOf("
Статус
" +
(any ? rows + (m === "all" ? totalRowHtml() : "") : emptyRowHtml()) +
"";
var n = $("fNote");
if (n) n.textContent = note;
}
/* ================= ЭКРАН 3 — формирование записки ================= */
function memoBody() {
var s = CO.reduce(function (a, b) { a.vp += b.vp / (b.vp1000 ? 1000 : 1); a.vf += b.vf / (b.vp1000 ? 1000 : 1); a.ep += b.ep; a.ef += b.ef; return a; }, { vp: 0, vf: 0, ep: 0, ef: 0 });
var dV = dev(s.vf, s.vp), dE = dev(s.ef, s.ep);
var devLines = DEVS.map(function (c) {
var parts = [];
if (c.revOk) parts.push("выручка " + signPct(c.dRev) + "%");
if (c.ebitOk) parts.push("EBITDA " + signPct(c.dEbit) + "%");
if (c.capOk) parts.push("CAPEX " + signPct(c.dCap) + "%");
if (c.dzOk) parts.push("ДЗ " + signPct(c.dDz) + "%");
return "• " + c.name + " — " + parts.join(", ");
}).join("\n");
var unitLine = S.unitFixed
? "Единицы измерения ООО «Телеком-4» исправлены: выручка переведена из тысяч в миллионы тенге."
: "Внимание: у ООО «Телеком-4» в файле выручка в тысячах тенге — требуется ручная проверка единиц.";
return "Свод по 15 дочерним компаниям за август 2026 г.\n\n" +
"По группе: выручка " + fmt(s.vf) + " млн тг (" + signPct(dV) + "% к плану), EBITDA " + fmt(s.ef) + " млн тг (" + signPct(dE) + "% к плану).\n" + unitLine + "\n" +
"Компании с отклонениями от плана более 10% (" + DEVS.length + "):\n" + devLines + "\n\n" +
"Рекомендации: разобрать причины отклонений по компаниям из списка выше.\n";
}
function viewMemo() {
var kpis =
kpi("Показателей в записке", "8", "выручка, EBITDA, CAPEX, ДЗ — план/факт") +
kpi("Отклонений более 10%", String(DEVS.length), "компаний в списке") +
kpi("Статус проверки", checkedCount() + " / 15", allChecked() ? "все компании проверены" : "осталось " + (15 - checkedCount())) +
kpi("Готовность", S.memoSent ? "отправлено" : "к отправке", "дедлайн: пн 15:00");
var devLinesHtml = DEVS.map(function (c) {
var parts = [];
if (c.revOk) parts.push('выручка ' + signPct(c.dRev) + "%");
if (c.ebitOk) parts.push('EBITDA ' + signPct(c.dEbit) + "%");
if (c.capOk) parts.push('CAPEX ' + signPct(c.dCap) + "%");
if (c.dzOk) parts.push('ДЗ ' + signPct(c.dDz) + "%");
return "
• " + esc(c.name) + " — " + parts.join(", ") + "
";
}).join("");
var sentBanner = S.memoSent
? '
Записка отправлена на согласование · финансовый директор · сегодня
'
: '
Дедлайн: понедельник, 15:00 · записка уходит финансовому директору после согласования текста
';
return pageHead("Формирование записки", "Итоговый документ для финансового директора · показатели подставлены из проверенного свода",
'' +
'' +
'") +
stepHtml("memo") +
'
' + kpis + "
" +
'
' +
'
Предпросмотр документа
' +
'
На: финансовый директор · От: сводящий · август 2026
' +
"
Свод по 15 дочерним компаниям
" +
"
Выручка группы " + fmt(CO.reduce(function (a, b) { return a + b.vf / (b.vp1000 ? 1000 : 1); }, 0)) + " млн тг, EBITDA " + fmt(CO.reduce(function (a, b) { return a + b.ef; }, 0)) + " млн тг. Отклонения от плана более 10% — у " + DEVS.length + " компаний.
" +
'
' + devLinesHtml + "
" +
"
" + (S.unitFixed ? "Единицы измерения всех компаний согласованы." : "У ООО «Телеком-4» требуют проверки единицы измерения выручки.") + "