AURORA-1938: фонд экономии считается на «Смете РФ» (FORM_2), откат FORM_4-части 0055 (#335) #336

Merged
aep merged 5 commits from feat/335-aurora-1938-form2-transfer-econ into test 2026-11-12 17:45:55 +03:00
Owner

Closes #335. Jira: AURORA-1938 (возврат тестировщика 12.11, комментарий 10035871).

Причина

PR #262 (миграция 0055) считал перенос в фонд экономии в v_form4_sheet_sections. Но «Смета РФ» в UI — это FORM_2 (web/src/constants/constants.jsx), FORM_4 — «Проектная деятельность»; сид v3.form_type называет FORM_4 «Смета РФ поддержка», отсюда ошибка. На FORM_2 q*.transfer_econ оставался сырым полем, «Всего» складывало пустое значение.

Что сделано

Миграция 0063_form2_transfer_econ_calc (24062ed):

  • v3.v_form2_sheet_sections (тело из 0052): фонд экономии считается по шаблону Шаблон_РФ_поддержка.xlsm (АХР_П/КВ_П/Операц: CB/DM/EV/GA), в строках и групповых итогах:
    • Q1 = остаток после факта − (задержка актов + задержка закупок + экономия РФ) − перенос в Q3 − перенос в Q4
    • Q2 = остаток − сумма подколонок переноса в Q3 − перенос в Q4
    • Q3 = остаток − сумма подколонок переноса в Q4
    • Q4 = остаток
      «Всего» использует рассчитанный фонд и равен остатку после факта. Лист, JSON, дельты патча и выгрузка Excel читают через эту функцию.
  • v3._apply_form_cell (тело из 0055): запись q*.transfer_econ отклоняется (computed_field) для FORM_2, а не для FORM_4.
  • v3.v_form4_sheet_sections: откат FORM_4-части 0055 (тело из 0033) — поле снова сырое и редактируемое, как ожидает фронт FORM_4.

Свод 2 (1304be1): v3.v_svod2_rf (тело из 0057, в той же миграции 0063) отдаёт q1..q4.transfer_to_economy формы 2 по той же формуле, что лист, — свод совпадает со «Сметой РФ». Свод «ГО» (FORM_1, FORM_4) не менялся. Golden svod2_legacy_golden.json перегенерирован для RF: изменились только transfer_to_economy (64 значения) и 5 хэшей.

Фронт (9c88711): isComputedColumn / isCellEditable принимают formType; на FORM_2 q1..q4.transfer_econ не редактируется (FORM_4 без изменений).

Проверка

  • api/tests/integration/test_form2_transfer_econ.py (14 кейсов: АХР/КВ/Операц, второй сценарий, групповые строки, запрет записи, Свод 2 — совпадение с листом и независимость от сырого поля) — красные до миграции, зелёные после; test_form4_transfer_econ.py переписан на регрессию отката.
  • Backend полный прогон: 913 passed / 10 failed / 4 skipped — 10 известных падений чистой test, новых нет.
  • Frontend: 282 passed / 1 failed (известный SMETA.test.js); cellEditability.test.js 15/15.

Важно при мерже

R-1: номер 0063, down_revision = "0059" — номера 0060–0062 заняты открытыми #315/#323/#331. При мерже перецепить down_revision на последнюю влитую миграцию. Открытые PR эти функции (включая v_svod2_rf) не пересоздают — затирания тел нет.

Rulings I made

  • R-1 — номер миграции 0063 с down_revision 0059 (перецепить при мерже).
  • R-2 — тесты FORM_2 читают поля через .get(): API не отдаёт null-ключи в INPUT-строках.
  • R-3 — FORM_4-тест переписан на регрессию отката, а не удалён.
  • R-4 — formType параметром в общие isComputedColumn/isCellEditable (глобальный список сломал бы FORM_4).
  • R-5 — цвет redColumn у колонки фонда не менялся: редактируемость определяется cellEditability.js, не цветом.
  • R-6 — в v_svod2_rf формула фонда повторена, а не вызвана из v_form2_sheet_sections (тяжёлая plpgsql-функция по листу, не годится для постраничного свода). При изменении формулы листа менять и здесь.
  • R-7 — RF-часть golden свода 2 перегенерирована (изменение намеренное, diff проверен: только фонд и хэши).
  • R-8 — строки RF без записей квартала получают transfer_to_economy: 0 (как на листе), раньше объект квартала был пустым.

Согласовано с человеком: Свод 2 чинить в этом же PR; вычитать сумму подколонок переноса (как в шаблоне BT=SUM(BU:BW)), сырое transfer_to_qN и план следующего квартала не трогать; FORM_4-часть 0055 откатить.

Findings

Маркер Суть Статус
R-1 миграция 0063 / down_revision 0059 fixed 24062ed
R-2 .get() в тестах FORM_2 fixed 24062ed
R-3 FORM_4-тест → регрессия отката fixed 24062ed
R-4 formType в cellEditability fixed 9c88711
R-5 цвет колонки не менялся fixed 9c88711
R-6 формула фонда повторена в v_svod2_rf fixed 1304be1
R-7 перегенерирован RF-golden свода 2 fixed 1304be1
R-8 0 вместо пустого объекта квартала в своде RF fixed 1304be1
O-1 СВОД 2 читал сырое transfer_to_economy FORM_2 — разошёлся бы с листом fixed 1304be1
O-2 групповые строки FORM_2 включают target_change в план квартала, строки — нет (старое расхождение) deferred
O-3 открытые PR 0060–0062 могли бы пересоздавать те же функции rejected — проверено: не пересоздают
O-4 план 1984 и шапка 0055 называют FORM_4 «Сметой РФ» deferred
O-5 bounded-задача — design.md нет, рулинги перенесены в PR rejected — по процессу bounded
O-7 свод «ГО» покрывает FORM_4, где фонд снова сырой — согласовано с откатом rejected — без действий
O-8 svod2_lines выводит строку при ненулевом сыром transfer_to_economy — возможны «пустые» строки FORM_2 со старым значением deferred
O-9 старые сырые значения transfer_to_economy FORM_2 остаются в БД (нигде не видны), без очистки deferred
O-10 исполнитель свода в отчёте указал 908 passed, контрольный прогон контроллера — 913 passed / 10 известных rejected — неточность отчёта, код в порядке
O-11 перед мержем в test уже были 0060–0062, а 0063 шла от 0059 — две головы alembic fixed 7f18b0a (down_revision 0062; функции 0063 в 0060–0062 не пересоздаются; backend 1054 / 10 известных, фронт 264/264)
O-6 transfer_to_qN («Перенос в следующий квартал», итог) хранится отдельно от подколонок, хотя в шаблоне = их сумма; план следующего квартала строится из него — расхождение с шаблоном в�� втором сценарии тестировщика deferred → AURORA-2054 (вопрос заказчику)

Внимание ревьюерам: бэк — формулы групповых строк и откат FORM_4 (Цыганков); фронт — проброс formType в RealtimeTable.jsx/tableColumns.jsx (Потапова).

🤖 Generated with Claude Code

Closes #335. Jira: AURORA-1938 (возврат тестировщика 12.11, комментарий 10035871). ## Причина PR #262 (миграция 0055) считал перенос в фонд экономии в `v_form4_sheet_sections`. Но «Смета РФ» в UI — это **FORM_2** (`web/src/constants/constants.jsx`), FORM_4 — «Проектная деятельность»; сид `v3.form_type` называет FORM_4 «Смета РФ поддержка», отсюда ошибка. На FORM_2 `q*.transfer_econ` оставался сырым полем, «Всего» складывало пустое значение. ## Что сделано Миграция `0063_form2_transfer_econ_calc` (24062ed): - `v3.v_form2_sheet_sections` (тело из 0052): фонд экономии считается по шаблону `Шаблон_РФ_поддержка.xlsm` (АХР_П/КВ_П/Операц: CB/DM/EV/GA), в строках и групповых итогах: - Q1 = остаток после факта − (задержка актов + задержка закупок + экономия РФ) − перенос в Q3 − перенос в Q4 - Q2 = остаток − сумма подколонок переноса в Q3 − перенос в Q4 - Q3 = остаток − сумма подколонок переноса в Q4 - Q4 = остаток «Всего» использует рассчитанный фонд и равен остатку после факта. Лист, JSON, дельты патча и выгрузка Excel читают через эту функцию. - `v3._apply_form_cell` (тело из 0055): запись `q*.transfer_econ` отклоняется (`computed_field`) для FORM_2, а не для FORM_4. - `v3.v_form4_sheet_sections`: откат FORM_4-части 0055 (тело из 0033) — поле снова сырое и редактируемое, как ожидает фронт FORM_4. Свод 2 (1304be1): `v3.v_svod2_rf` (тело из 0057, в той же миграции 0063) отдаёт `q1..q4.transfer_to_economy` формы 2 по той же формуле, что лист, — свод совпадает со «Сметой РФ». Свод «ГО» (FORM_1, FORM_4) не менялся. Golden `svod2_legacy_golden.json` перегенерирован для RF: изменились только `transfer_to_economy` (64 значения) и 5 хэшей. Фронт (9c88711): `isComputedColumn` / `isCellEditable` принимают `formType`; на FORM_2 `q1..q4.transfer_econ` не редактируется (FORM_4 без изменений). ## Проверка - `api/tests/integration/test_form2_transfer_econ.py` (14 кейсов: АХР/КВ/Операц, второй сценарий, групповые строки, запрет записи, Свод 2 — совпадение с листом и независимость от сырого поля) — красные до миграции, зелёные после; `test_form4_transfer_econ.py` переписан на регрессию отката. - Backend полный прогон: 913 passed / 10 failed / 4 skipped — 10 известных падений чистой test, новых нет. - Frontend: 282 passed / 1 failed (известный SMETA.test.js); `cellEditability.test.js` 15/15. ## Важно при мерже **R-1:** номер `0063`, `down_revision = "0059"` — номера 0060–0062 заняты открытыми #315/#323/#331. При мерже перецепить `down_revision` на последнюю влитую миграцию. Открытые PR эти функции (включая `v_svod2_rf`) не пересоздают — затирания тел нет. ## Rulings I made - R-1 — номер миграции 0063 с down_revision 0059 (перецепить при мерже). - R-2 — тесты FORM_2 читают поля через `.get()`: API не отдаёт null-ключи в INPUT-строках. - R-3 — FORM_4-тест переписан на регрессию отката, а не удалён. - R-4 — `formType` параметром в общие `isComputedColumn`/`isCellEditable` (глобальный список сломал бы FORM_4). - R-5 — цвет `redColumn` у колонки фонда не менялся: редактируемость определяется `cellEditability.js`, не цветом. - R-6 — в `v_svod2_rf` формула фонда повторена, а не вызвана из `v_form2_sheet_sections` (тяжёлая plpgsql-функция по листу, не годится для постраничного свода). При изменении формулы листа менять и здесь. - R-7 — RF-часть golden свода 2 перегенерирована (изменение намеренное, diff проверен: только фонд и хэши). - R-8 — строки RF без записей квартала получают `transfer_to_economy: 0` (как на листе), раньше объект квартала был пустым. Согласовано с человеком: Свод 2 чинить в этом же PR; вычитать сумму подколонок переноса (как в шаблоне BT=SUM(BU:BW)), сырое `transfer_to_qN` и план следующего квартала не трогать; FORM_4-часть 0055 откатить. ## Findings | Маркер | Суть | Статус | |---|---|---| | R-1 | миграция 0063 / down_revision 0059 | fixed 24062ed | | R-2 | `.get()` в тестах FORM_2 | fixed 24062ed | | R-3 | FORM_4-тест → регрессия отката | fixed 24062ed | | R-4 | `formType` в cellEditability | fixed 9c88711 | | R-5 | цвет колонки не менялся | fixed 9c88711 | | R-6 | формула фонда повторена в `v_svod2_rf` | fixed 1304be1 | | R-7 | перегенерирован RF-golden свода 2 | fixed 1304be1 | | R-8 | 0 вместо пустого объекта квартала в своде RF | fixed 1304be1 | | O-1 | СВОД 2 читал сырое `transfer_to_economy` FORM_2 — разошёлся бы с листом | fixed 1304be1 | | O-2 | групповые строки FORM_2 включают `target_change` в план квартала, строки — нет (старое расхождение) | deferred | | O-3 | открытые PR 0060–0062 могли бы пересоздавать те же функции | rejected — проверено: не пересоздают | | O-4 | план 1984 и шапка 0055 называют FORM_4 «Сметой РФ» | deferred | | O-5 | bounded-задача — design.md нет, рулинги перенесены в PR | rejected — по процессу bounded | | O-7 | свод «ГО» покрывает FORM_4, где фонд снова сырой — согласовано с откатом | rejected — без действий | | O-8 | `svod2_lines` выводит строку при ненулевом сыром `transfer_to_economy` — возможны «пустые» строки FORM_2 со старым значением | deferred | | O-9 | старые сырые значения `transfer_to_economy` FORM_2 остаются в БД (нигде не видны), без очистки | deferred | | O-10 | исполнитель свода в отчёте указал 908 passed, контрольный прогон контроллера — 913 passed / 10 известных | rejected — неточность отчёта, код в порядке | | O-11 | перед мержем в test уже были 0060–0062, а 0063 шла от 0059 — две головы alembic | fixed 7f18b0a (down_revision 0062; функции 0063 в 0060–0062 не пересоздаются; backend 1054 / 10 известных, фронт 264/264) | | O-6 | `transfer_to_qN` («Перенос в следующий квартал», итог) хранится отдельно от подколонок, хотя в шаблоне = их сумма; план следующего квартала строится из него — расхождение с шаблоном в�� втором сценарии тестировщика | deferred → AURORA-2054 (вопрос заказчику) | Внимание ревьюерам: бэк — формулы групповых строк и откат FORM_4 (Цыганков); фронт — проброс `formType` в `RealtimeTable.jsx`/`tableColumns.jsx` (Потапова). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
aep added 2 commits 2026-11-12 15:11:53 +03:00
Миграция 0063: v_form2_sheet_sections считает q*.transfer_econ по шаблону Excel
((cp-aq) минус подколонки переноса минус переносы через квартал), total = остаток
после факта, групповые строки тем же; _apply_form_cell запрещает запись
q*.transfer_econ для FORM_2; v_form4_sheet_sections возвращена к версии 0033.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
isComputedColumn/isCellEditable принимают formType; transfer_econ вычисляемый
только на FORM_2, на FORM_4 остаётся редактируемым.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aep requested review from tsygankoviva 2026-11-12 15:12:07 +03:00
aep requested review from PotapovaA 2026-11-12 15:12:07 +03:00
aep added 1 commit 2026-11-12 15:42:36 +03:00
v_svod2_rf: q1..q4.transfer_to_economy вычисляется по формулам листа, сырое поле
budget_line_quarter.transfer_to_economy игнорируется. Эталон RF обновлён: фонд
экономии строк теперь расчётный (GO без изменений).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tsygankoviva approved these changes 2026-11-12 17:25:03 +03:00
PotapovaA approved these changes 2026-11-12 17:25:13 +03:00
aep added 2 commits 2026-11-12 17:45:43 +03:00
Иначе после мержа у alembic две головы (0062 и 0063) и upgrade head
падает. Функции 0063 (_apply_form_cell, v_form2/4_sheet_sections,
v_svod2_rf) в 0060–0062 не переопределяются.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aep merged commit fa3d7adad0 into test 2026-11-12 17:45:55 +03:00
Sign in to join this conversation.
3 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RSHB/DFiP_Budget_planing#336
No description provided.