789 Commits

Author SHA1 Message Date
Andrey Epifancev
9a151a19eb Merge remote-tracking branch 'origin/test' into feat/272-aurora-1887-ahr-hide-satellite-rows
# Conflicts:
#	web/src/components/RealtimeTable/RealtimeTable.jsx
#	web/src/components/RealtimeTable/utils/rowUtils.test.js
2026-11-02 21:50:17 +04:00
aep
d12fa0f585 Merge pull request 'AURORA-1900: единые подписи «тыс. руб.» и НДС на экране и в выгрузке' (#291) from feat/289-aurora-1900-unit-vat-labels into test 2026-11-02 20:48:31 +03:00
Andrey Epifancev
e755272787 Merge remote-tracking branch 'origin/test' into feat/289-aurora-1900-unit-vat-labels
# Conflicts:
#	web/src/components/RealtimeTable/constants/FORM_1/SMETA.js
2026-11-02 21:47:53 +04:00
aep
c55a14749a Merge pull request 'AURORA-1899: база разрядности — тыс. руб., масштабировать только денежные колонки' (#288) from feat/285-aurora-1899-denomination-base-thousand into test 2026-11-02 20:45:38 +03:00
Andrey Epifancev
67c192a2e0 Merge remote-tracking branch 'origin/test' into feat/285-aurora-1899-denomination-base-thousand
# Conflicts:
#	web/src/components/RealtimeTable/Cell/Cell/Cell.jsx
2026-11-02 21:45:04 +04:00
aep
12aae02504 Merge pull request 'AURORA-1903: лист «Смета» — своя раскладка колонок для каждой формы' (#287) from feat/286-aurora-1903-smeta-export-layout into test 2026-11-02 20:36:59 +03:00
aep
5fe1264064 Merge pull request 'AURORA-1894: красная рамка у ошибки ячейки, тост без Server error:undefined' (#277) from feat/275-aurora-1894-error-border-toast into test 2026-11-02 20:34:38 +03:00
aep
296f868c4c Merge pull request 'AURORA-1907: признак источника строки АХР и раздельные суммы лимита/сверх лимита' (#271) from feat/270-aurora-1907-source-sheet into test 2026-11-02 20:32:54 +03:00
aep
69e333cf9f Merge pull request 'AURORA-1909: добавление записи на сателлите не захватывает ручную строку АХР' (#268) from feat/265-aurora-1909-ahr-manual-row-capture into test 2026-11-02 20:31:57 +03:00
aep
5317c04d3a Merge pull request 'AURORA-1906: колонка «СПОД» в листах аренды, коммуналки и охраны АХР' (#263) from feat/254-aurora-1906-spod-column into test 2026-11-02 20:30:23 +03:00
Andrey Epifancev
24ca4410f4 feat(labels): единые подписи «тыс. руб.» и НДС на экране и в выгрузке (AURORA-1900)
Экран: {unit}-плейсхолдер (formatHeaderUnit, переиспользует разрядность из
useDenomination/moneyUtils AURORA-1899) в TableHead.jsx, CollapsibleTree.jsx,
templateColumns.js; литерал «тыс. руб.» → {unit} в заголовках FORM_1/FORM_2/
FORM_4/PROJECT (кроме AHR_LIMIT.js — рублёвое исключение не трогаем) и в
своих колонках Свод1/Свод2 (SummaryTable.scaleColumns, Svod2Page.
scaleNumericColumns). Текст НДС на экране не менялся.

Выгрузка: «с учетом НДC» (латинская C, 96 мест в FORM1_DEPTH_COLUMNS и
производных FORM4_*) → плейсхолдер {vat}/{vat_plan}, резолвится по листу
через render_column_years(..., extra=...) — Ф.1 OPER/CAP «с учётом НДС»,
Ф.1 AHR и все листы Ф.4 «без НДС» (соответствует экрану). SMETA_COLUMNS —
«, тыс. руб.» у сумм. Своды — строка метаданных «Единица: тыс. руб.».

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-11-01 20:16:27 +04:00
Andrey Epifancev
733d7a9036 fix(denomination): база разрядности — тыс. руб., масштабировать только денежные колонки
Селектор разрядности (AURORA-1650) считал базой рубли, хотя в базе суммы
хранятся в тыс. руб. (формы 1/4, сателлиты формы 2, лимитные строки АХР
после AURORA-1897). По умолчанию стояло «в руб.», и тысячи показывались
под видом рублей; при выборе «в тыс. руб.» значения делились ещё раз.
Делитель также применялся к количествам, площади, ставке НДС, курсу,
кодам и ID — не только к деньгам. Редактор ячейки не учитывал разрядность.

- web/src/components/RealtimeTable/utils/moneyUtils.js — новый модуль:
  UNIT_IN_RUB, getDisplayFactor(baseUnit, denomination), getMoneyUnit
  (денежная единица колонки по accessorKey/sheetName, с явным
  columnDef.moneyUnit как переопределением), TEXT_COLUMN_IDS (перенесён
  из Cell.jsx), resolveDenomination/DEFAULT_DENOMINATION, AHR_LIMIT_SHEET.
  Модуль не импортирует конфиги форм — работает под node --test.
- useDenomination.js — значение по умолчанию 'thousand', ключ хранения
  со суффиксом _denomination_v2 (старые 'rub'/'thousand' больше не
  читаются со старым смыслом); getDenominationDivisor убран.
- tableColumns.jsx/Cell.jsx — displayDivisor заменён на displayFactor
  (умножение, не деление), множитель считается на колонку через
  getMoneyUnit/getDisplayFactor с учётом sheetName; isEditable запрещает
  редактирование денежной ячейки, если разрядность не базовая; на листе
  AHR_LIMIT множитель всегда 1 (значения в рублях, как есть).
- SettingPanel.jsx — селектор скрыт на листе AHR_LIMIT, рядом с ним
  подсказка «Ввод сумм — в тыс. руб.».
- SvodPage/Svod2Page/ProjectSummariesPage — масштабирование по
  meta.money вместо regex по id/блок-листа текстовых id; построители
  колонок проставляют meta.money на денежных метриках.
- DenominationSelect.jsx — «в млн руб.», «в млрд руб.» без точки.

Тесты: web/src/components/RealtimeTable/utils/moneyUtils.test.js
(node --test), полный набор web/src/components/RealtimeTable/utils —
52/52 зелёных. npm run build проходит.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-11-01 16:08:20 +04:00
Andrey Epifancev
72f48cc559 fix(export): лист "Смета" выгружается по раскладке экрана каждой формы (AURORA-1903)
До этой правки лист "Смета" всех форм выгружался одной плоской
раскладкой SMETA_COLUMNS (41 колонка) — для FORM_2/FORM_4 в выгрузке
были лишние колонки другого направления (поддержка/развитие), которых
нет на экране. Добавлена SMETA_COLUMNS_BY_FORM{"FORM_1","FORM_2","FORM_4"}
с раскладкой колонок строго в порядке экрана каждой формы;
_create_xlsxwriter_sheet_writers теперь выбирает нужный список по
form_type_code. SMETA_COLUMNS остаётся алиасом на FORM_1-раскладку для
обратной совместимости (неиспользуемый openpyxl-словарь, старый тест).

Также TabularSheetWriter.write и XlsxTabularSheetWriter.write теперь
пропускают служебную строку META (как уже делают depth-писатели) —
раньше она давала пустую вторую строку на листе "Смета".

На экране FORM_1/SMETA.js добавлены "Утверждено ИТОГО Год" (Z) и
"Факт ИТОГО Год" (AL) — SQL (v_form_view) всегда их отдавал и
выгрузка Excel их писала, но экран их терял.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-11-01 16:01:25 +04:00
aep
f407b5c296 Merge pull request 'fix(tests): согласовать AURORA-1844/1846/1850 с null-strip из AURORA-1848' (#279) from fix/null-strip-test-contract into test 2026-11-01 11:40:51 +03:00
Andrey Epifancev
d5cbd151c5 fix(tests): согласовать AURORA-1844/1846/1850 с null-strip из AURORA-1848
AURORA-1848 (#239/#242) убрал null-поля из GET листа/сводов (jsonb_strip_nulls),
оставив PATCH как раньше (задокументированный breaking-change в PR, не баг).
После слияния веток в test это разошлось с тестами, написанными до #239/#242:

- sheet_contract.assert_patch_rows_match_sheet сравнивал PATCH и GET побайтно —
  добавлен strip_nulls() на стороне PATCH перед сравнением.
- test_form4_sheet_sums.py сравнивал ответ API с "сырым" v3.jsonb_sum (с null-полями)
  и ожидал явный null в некоторых полях ответа — эталон теперь тоже прогоняется через
  strip_nulls, а прямые ожидания null заменены на .get(...) is None / отсутствие ключа.

Без изменений контракта API: PATCH продолжает отдавать null явно, как в #242.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-11-01 12:39:14 +04:00
aep
8c467804be Merge pull request 'AURORA-1848: лист и своды без null-полей + фронт (B)' (#242) from feat/233-aurora-1848-sheet-json-no-pydantic-b into test 2026-11-01 11:16:08 +03:00
Andrey Epifancev
7514ac9803 fix(realtime): getDataRowId возвращает null вместо undefined, тесты M-8/M-9
После jsonb_strip_nulls у групп/позиций нет ключа line_id, getDataRowId
возвращал undefined, и row_id в сообщении удаления сериализовался в {}
(KeyError на сервере). Возвращаем null, как до фазы B.
Добавлены тесты updateCells (глубокое отсутствие блока, два обновления в батче)
и сверка jsonb_strip_nulls с _strip_nulls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:14:49 +04:00
Andrey Epifancev
2436a6b3f7 docs(openspec): aurora-1848 — решения R-6..R-8 без обсуждения
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:14:49 +04:00
Andrey Epifancev
8015a6cc9d perf(gen): grow не падает на ответах листа без null-полей
form4_ids вычисляет vsp_ids и project_ids из строк FORM_4 через .get
с пропуском отсутствующих ключей, grow_form4_sheet использует её.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:14:49 +04:00
Andrey Epifancev
a34ccdcb9c perf(api): лист и своды без null-полей в data (jsonb_strip_nulls)
row_json_select(strip_nulls) оборачивает data в jsonb_strip_nulls внутри json_build_object;
флаг пробрасывается через get_json/get_svod1_json/get_svod2_json, роутеры листа и сводов
включают его. Проекты, PATCH/POST/DELETE не затронуты.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:14:49 +04:00
Andrey Epifancev
c7c679851d fix(realtime): пустая правка уходит как value: null, а не без ключа (AURORA-1848)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:14:49 +04:00
Andrey Epifancev
be8d41ccb5 test(realtime): правка соавтора по ключу, которого нет в строке (AURORA-1848)
Четыре теста updateCells: вставка отсутствующего блока и поля,
явная запись null, вставка отсутствующего скалярного ключа data.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:14:49 +04:00
Andrey Epifancev
83cb364a9e fix(realtime): красная рамка у ошибки ячейки, тост без Server error:undefined (AURORA-1894)
Cell.jsx: порядок спреда стилей — base → editable/not-editable → locked →
invalid (INVALID_STYLES последним), чтобы красная рамка 2px не перетиралась
EDITABLE_STYLES у вводимых ячеек с ошибкой.

utils/wsErrorUtils.js: getWsErrorMessage(error) — строка возвращается как
есть, объект берёт message || detail, известные технические префиксы
(computed_field:, role_not_allowed:, window_closed:, org_not_assigned)
заменяются понятным текстом, прочее отдаётся без "Server error:".

RealtimeContext.js: toast.error(getWsErrorMessage(data.error)) вместо
`Server error:${data.error.message}` || '', которое всегда давало undefined
для ошибок-строк (|| не срабатывает на непустой строке).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-11-01 12:10:16 +04:00
aep
26ae77878b Merge pull request 'AURORA-1837: статичные стили ячеек в CSS, overscan' (#230) from feat/226-aurora-1837-cell-styles-css into test 2026-11-01 11:05:50 +03:00
aep
9c7a5a4575 Merge pull request 'AURORA-1846: FORM_4 суммы листа без рекурсивного jsonb_sum' (#232) from feat/216-aurora-1846-form4-sheet-sum into test 2026-11-01 11:04:08 +03:00
Andrey Epifancev
1b8f7c7d12 fix(alembic): перенумеровать 0050→0053 во избежание конфликта с #229/#231/#244
#229, #231 и #244 уже заняли 0050-0052 к моменту слияния этого PR.
Переносим form4_sheet_sum на 0053, down_revision=0052, и правим путь
к SQL-файлу в perf/analysis/explain_manual.py.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-11-01 12:03:39 +04:00
aep
9229ee5ce3 Merge pull request 'fix(alembic): устранить дубликат revision=0051 в test (AURORA-1850)' (#274) from fix/0051-migration-collision into test 2026-11-01 11:02:15 +03:00
Andrey Epifancev
ece050d19f fix(alembic): устранить дубликат revision=0051 в test (AURORA-1850)
При слиянии PR #244 в test оказались две миграции с revision="0051"
и down_revision="0050" (upd_form_cells_full_rows из #231 и
upd_form_cells_subtree из #244) — неоднозначная цепочка alembic.
Фикс-коммит с переименованием 0051→0052 для #244 был подготовлен
локально, но потерялся при повторном force-push после блокировки
классификатором permission — слияние прошло с исходной (дублирующейся)
нумерацией. Переносим upd_form_cells_subtree на 0052.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-11-01 12:00:14 +04:00
aep
77f8957719 Merge pull request 'AURORA-1850: правка ячейки пересчитывает только затронутое поддерево' (#244) from feat/235-aurora-1850-upd-form-cells-subtree into test 2026-11-01 10:57:50 +03:00
Andrey Epifancev
2f1dce2c61 docs(openspec): aurora-1850 — рулинг R-2 заменяет skip теста track_functions (M-3)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:47:27 +04:00
Andrey Epifancev
b267905d09 test(sheet): ничья ключа сортировки по-настоящему, F1-AHR-plan, комментарий 0051 (AURORA-1850)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:47:27 +04:00
Andrey Epifancev
47c758e205 docs: ARCHITECTURE — фокусная сборка ответа на правку (AURORA-1850)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-11-01 10:47:27 +04:00
Andrey Epifancev
e396b5a053 test(sheet): защита правки 0037 после 0051 (AURORA-1850)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:47:27 +04:00
Andrey Epifancev
1d18cf812f perf(sql): jit = off на построителях и пути правки (AURORA-1850)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:47:27 +04:00
Andrey Epifancev
1e1f5e3824 perf(sql): дельта АХР через _form_affected_rows, с предками SUB_SUB_ITEM (AURORA-1850)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:47:27 +04:00
Andrey Epifancev
5060f32341 perf(sql): _form_affected_rows собирает только затронутое поддерево (AURORA-1850)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:47:27 +04:00
Andrey Epifancev
6d232064c6 perf(sql): фокус и _sort_rank в построителях FORM_1, новая v_form1_view (AURORA-1850)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:47:27 +04:00
Andrey Epifancev
daad7a4bc0 docs(openspec): aurora-1850 — решения Task 4 (T4.4)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:47:27 +04:00
Andrey Epifancev
6b17d7c076 perf(sql): фокус сателлитов, AHR_LIMIT и OTCH9F в v_form2_view (AURORA-1850)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:47:27 +04:00
Andrey Epifancev
8f82f5fb9b docs(openspec): aurora-1850 — решение по соединению скелета (T3.1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:47:27 +04:00
Andrey Epifancev
8f45544a17 perf(sql): фокус и _sort_rank в построителях FORM_2 AHR/CAP/OPER (AURORA-1850)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:47:27 +04:00
Andrey Epifancev
17f3de602a test(sheet): усиление красных тестов эквивалентности по ревью Task 2 (AURORA-1850)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:47:27 +04:00
Andrey Epifancev
0f889c8d5e docs(openspec): aurora-1850 — решение посева снимка GET (T1.2)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:47:27 +04:00
Andrey Epifancev
5b6c7e244e test(sheet): эквивалентность ответа на правку и полной сборки — красные тесты (AURORA-1850)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:47:27 +04:00
Andrey Epifancev
f1d4f2644c docs(openspec): aurora-1850 — тела функций до 0051 (pg_get_functiondef, ревизия 0050)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:47:27 +04:00
Andrey Epifancev
4c493bb269 docs(openspec): aurora-1850 — рулинги контроллера R-1..R-4, R-14
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:47:27 +04:00
Andrey Epifancev
93ea5b5c42 docs(plan): aurora-1850 — план реализации
План в 10 задач по design.md: тестовая БД dfip_1850 на 0050 и тела функций
до 0051 (D8), красный тест эквивалентности, построители с фокусом и
_sort_rank (FORM_2, затем FORM_1 и v_form1_view), _form_affected_rows,
дельта АХР, jit = off, защита 0037, документация. Решения плана дописаны
в design.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:47:27 +04:00
Andrey Epifancev
661a3571b5 docs(openspec): aurora-1850 — решения 28.10 по JIT и условию мержа, решения контроллера
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:47:27 +04:00
Andrey Epifancev
4251490fa9 docs(openspec): aurora-1850-upd-form-cells-subtree — proposal, spec, design
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:47:27 +04:00
aep
f2c503c292 Merge pull request 'AURORA-1844: upd_form_cells возвращает строки целиком' (#231) from feat/215-aurora-1844-upd-form-cells-full-rows into test 2026-11-01 09:46:45 +03:00