Andrey Epifancev b04c87f47c fix(export): выгрузка форм 1 и 4 — порядок столбцов и заголовки как на экране
Выгрузка Excel листов АХР/КВ/Операц/Структура форм 1 и 4 расходилась с экраном
по нескольким независимым причинам:

- FORM_4: _patch_form4_regular_columns() вызывался дважды — второй вызов
  стирал только что добавленные actual_rsbu_spod_q1..q3, поэтому в выгрузке
  были только «Факт 4 кв + СПОД», без «Факт 1/2/3 кв». Убрал второй вызов
  и больше не удаляю эти ключи в самом патче.
- _patch_form4_actual_rsbu_spod_columns: SQL отдаёт actual_rsbu_spod только
  для 4 кв.; для 1-3 кв. ключ теперь q{n}.actual_quarter (как на экране),
  не q{n}.actual_rsbu_spod (всегда пустой).
- Базовая раскладка FORM1_DEPTH_COLUMNS (отражается и в FORM_4, т.к. она из неё
  строится): убрал collegial.empty и группы "shift" (ключ sum, SQL не отдаёт);
  в q2/q3 добавил comment_correct (adj_comment) сразу после reserve_correct —
  раньше его не было вовсе; в q4 то же поле вынес из rev_correct в отдельный
  comment_correct на то же место (было в начале квартала вместе с комментарием
  корректировки плана). group "approved.plan" переименована из скопированного
  "Резерв Финансового Комитета" в "План {year}"; q4 "quarter_correct" — из
  ошибочного "Факт РСБУ 3 кв" в "Факт РСБУ 4 кв {year_short}".
- render_column_years: добавлен плейсхолдер year_plus_2 (year+2); contract_summary
  получил future_y2 "Платежи в {year_plus_2} году" (раньше его не было, и FORM_4
  patch всё равно дублировал его с неверным {next_year}). На экране «Операц»
  формы 1 такой колонки нет — для неё новая FORM1_OPER_DEPTH_COLUMNS без future_y2.
- FORM4_OPER: proc_plan/proc_method после переименования уезжали в конец блока
  ckk (pop+переприсвоение добавляет ключ в конец словаря) — вернул порядок
  экрана через _reorder_children.
- web/.../FORM_1/{AHR,CAP,OPER}.js: в q4 узел "Комментарий" (adj_comment, GG)
  шёл после "Скорректированный план" (corrected_plan, GH) — переставил перед,
  как в 1-3 кв.

Issue: #253 (AURORA-1905, эпик AURORA-1876, Высокий приоритет)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-30 22:04:02 +04:00

36 lines
1.9 KiB
JavaScript

import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import test from 'node:test';
import { fileURLToPath } from 'node:url';
// AURORA-1905: в 1-3 кв. "Комментарий" (adj_comment) уже шёл сразу после
// "Корректировки из резерва" (adj_reserve), перед "Скорректированный план"
// (corrected_plan); в 4 кв. порядок был нарушен (corrected_plan раньше adj_comment).
const SHEETS = ['AHR', 'CAP', 'OPER'];
function extractDataAccessorKeys(source) {
// Пропускаем секцию "colors" (плоская карта, свой, не относящийся к
// расположению столбцов порядок) — берём только дерево "columns".
const columnsStart = source.indexOf('\n\t\tcolumns: [');
const columnsSource = columnsStart === -1 ? source : source.slice(columnsStart);
const matches = columnsSource.matchAll(/accessorKey:\s*'(data\.[^']+)'/g);
return [...matches].map((m) => m[1]);
}
for (const sheet of SHEETS) {
test(`FORM_1/${sheet}.js: q4 adj_reserve -> adj_comment -> corrected_plan`, () => {
const path = fileURLToPath(new URL(`../constants/FORM_1/${sheet}.js`, import.meta.url));
const keys = extractDataAccessorKeys(readFileSync(path, 'utf8'));
const reserveIndex = keys.indexOf('data.q4.adj_reserve');
const commentIndex = keys.indexOf('data.q4.adj_comment');
const planIndex = keys.indexOf('data.q4.corrected_plan');
assert.notEqual(reserveIndex, -1, 'data.q4.adj_reserve не найден');
assert.notEqual(commentIndex, -1, 'data.q4.adj_comment не найден');
assert.notEqual(planIndex, -1, 'data.q4.corrected_plan не найден');
assert.ok(reserveIndex < commentIndex, 'adj_comment должен идти после adj_reserve');
assert.ok(commentIndex < planIndex, 'adj_comment должен идти перед corrected_plan');
});
}