AURORA-1984: проекты ПД без программы (+1979, 1980, 1989) #306

Merged
aep merged 13 commits from feat/305-aurora-1984-pd-standalone-projects into test 2026-11-11 18:12:24 +03:00
Owner

Refs #305. Jira: AURORA-1984, AURORA-1979, AURORA-1980, AURORA-1989.

Порядок мержа: ветка стоит поверх PR #304 (AURORA-1978), он не влит, поэтому его коммит виден и здесь. Сначала #304, затем этот PR. Номер миграции 0059 актуален на test 244c03a.

Что сделано

  • AURORA-1984. На форме 4 проект создаётся прямо в разделе, без программы: form4_project с level='project', parent_id IS NULL, своими section_code и form_id. Стоит строкой ITEM под ROOT, вперемешку с программами в порядке создания. Суммы входят в ROOT один раз, GROUP с пустой программой нет. Расходы, переименование, удаление пустого, выгрузка — как у проекта в программе.
  • AURORA-1980. Кнопка «Переименовать» для программы и проекта. При ошибке окно остаётся открытым с введённым текстом.
  • AURORA-1979. В третьем столбце подпись «программа» / «проект», на экране и в Excel. Данные (header.section_code) не меняются.
  • AURORA-1989. Окно выбора расхода: «номер — название», сортировка с учётом числовых частей, поиск по номеру и названию.
  • Миграция 0059_form4_standalone_project, downgrade — pass. Спека: openspec/changes/aurora-1984-pd-standalone-projects/.

Перед деплоем (T1.3): SELECT count(*) FROM v3.form4_project WHERE parent_id IS NULL AND form_id IS NULL. Ожидается 0, иначе миграция упадёт на проверке.

Проверка

  • Frontend node --test на HEAD e5660ad: 188 passed, 0 failed.
  • pytest tests/unit на HEAD e5660ad: 172 passed, 2 failed (test_export_service_query_params.py, падают и на базе).
  • Весь backend (pytest --init_db) на b87b12f: 889 passed, 10 failed, 4 skipped. Те же 10 падают на базе 1aec5d2, новых нет. Весь набор на базе не зелёный (O-6):
    • test_db_functions_integration.py::test_backend_calls_form3_add_project_and_add_line_functions
    • test_form2_ahr_satellite_spod_integration.py::test_satellite_spod_written_and_included_in_q4_total (3 варианта)
    • test_upd_form_cells_subtree.py: test_edit_path_does_not_call_v_form_view[delta], test_ahr_delta_matches_get_after_rent_edit, test_jit_off_on_builders_and_edit_path
    • test_upd_form_cells_subtree_0037_guard.py::test_v_form2_view_keeps_0037_limit_formula
    • test_export_service_query_params.py: 2 теста
  • Интеграционные тесты после b87b12f заново не гонялись. Позже изменились фронт, export_writers.py, тесты, комментарий в SQL-миграции и design.md; тело миграции не менялось.
  • Biome: 62 ошибки и 54 предупреждения, те же итоги на базе, новых нет.
  • Живая проверка на стенде, форма 4, две вкладки: все сцена��ии пройдены, кроме частично проверенного окна выбора расхода. В БД там только R-коды, поэтому примеры «3.2. раньше 3.10.» и «3.01» проверены только unit-тестами (M-3).

Rulings I made

Рулинги из design.md

Маркер Решение Цена ошибки
R-1 (design #13) Подпись третьего столбца — строковый признак в конфиге и accessorFn в processColumns: structuredClone конфига падает на функциях правка одной ветки в processColumns
R-2 (design #14) Отдельный Form4DepthRowNormalizer для AHR/CAP/OPER: Form1DepthRowNormalizer общий для всех форм лишний класс из нескольких строк
R-3 (design #15) Отдельное окно RenameNodeModal, закрытие по is_self + событие + id, отдельный канал ошибок лишний компонент; поздний ответ может закрыть повторно открытое окно того же узла
R-4 (design #16) Downgrade 0059 — pass, как у SQL-миграций репозитория откат только вручную
R-5 (design #17) Эталон «как до миграции» — pg_temp-копия функции из 0053 тест привязан к файлу 0053
R-6 (design #18) Права на переименование и удаление — членство в форме, без v3.can_edit, как у программ прямой запрос по WS может переименовать или удалить узел при закрытом окне ввода
R-7 (design #19) Путь «проект в программу» тоже через alignNodeRows + updateCells строки ответа, которых нет локально, отбрасываются до program_added или перезагрузки
R-8 (design #20) Самостоятельный проект опознаётся явно (ITEM с project_id без program_id) и получает уровень программы в дереве и в Excel: иначе проект после программы вкладывался в неё если у ITEM другой формы появится project_id без program_id, он станет верхним уровнем
R-9 (design #21) Устаревшие имена строк после добавления расхода (O-7) в этой ветке не чинятся: воспроизводится на базе, путь row_added общий для всех форм неверные названия до перезагрузки, вынесено в follow-up

Решения по находкам и допущения

  • T2.3 / T2.4: section_code в аудите создания проекта и новый текст ошибки «Укажите либо программу, либо форму и раздел» оставлены. Цена: изменение аудита и текста ошибки для существующего пути.
  • T5.2: принята цена R-3. Цена: редкая гонка, пока у WS нет идентификатора запроса.
  • O-2: коммит 209d36e с трейлером Sonnet 5.5 оставлен, правка переписала бы 9 SHA. Цена: расхождение в одном коммите.
  • O-3 / O-5: у Task 2 не было настоящего RED, исполнители Tasks 2, 4, 5, 6 не вызывали codegraph. Цена: правила процесса соблюдены не полностью, вреда ревью не нашло.
  • O-4: падение form3-теста признано не связанным с веткой после проверки на базе.
  • Решения исполнителей: в миграции именованные теги долларовых кавычек ($do$, $function$), разделитель sql_migration.py не понимает $$; в test_cell_patch_response сравнение через strip_nulls; проверка «Только FORM_4» и в ветке без программы; unit-тесты сервера на @pytest.mark.asyncio; пробельный item_id считается отсутствием кода.

Находки

Маркер Суть Статус
T1.1 test_cell_patch_response не проверял значение 20 fixed 209d36e
T1.2 заглушка-комментарий Task 2 в 0059.sql fixed 209d36e
T1.3 новый CHECK требует form_id; проверка в миграции падает при NULL в проде deferred
T2.1 нет SQL-теста отказа чужому исполнителю на создании deferred
T2.2 нет тестов rename/delete с ROOT, AHR/OPER, «Только FORM_4», аудита ROOT fixed 69c4a8f, остальное deferred
T2.3 section_code в аудите PROJECT_CREATE rejected: требование D2, поле аддитивное
T2.4 заменено сообщение об обязательной программе rejected: так задумано
T3.1 дублирование проверки членства из add_program deferred
T3.2 стиль тестов rejected: по конвенциям репозитория
T4.1 путь «в программу» через alignNodeRows rejected: предписано планом, R-7
T4.2 нет теста сдвига вложенных subRows deferred
T4.3 subscribeToProjectAdds без unit-теста deferred
T5.1 пустой result без error оставляет окно в saving deferred
T5.2 поздний ответ закрытого окна rejected: принятая цена R-3
T5.3 Enter не отправляет форму; пустое значение на один рендер deferred
T5.4 нет тоста при renameNode=false deferred
T6.1 правила подписи на бэке и фронте эквивалентны условно deferred
T7.1 тест поиска проверяет только подпись deferred
T7.2 нет теста на item_id из пробелов deferred
T7.3 фильтр MUI может совпасть с тире rejected: косметика
O-2 трейлер коммита 209d36e deferred
O-3 у Task 2 не было настоящего RED rejected: тесты проверены ревьюером
O-4 падение form3 add_line rejected: падает и на базе
O-5 не все исполнители вызывали codegraph rejected: вреда не обнаружено
O-6 10 падений всего набора, все и на базе deferred
O-7 после добавления расхода у строк ниже имена предыдущих строк до F5 deferred (R-9)
O-8 вторая вкладка не переподключает WS после рестарта API; 410 на повторной загрузке экспорта deferred
O-9 отказ по правам при переименовании приходит как «Проект не найден» deferred
O-10 агент перепроверки удалил *.yml/*.log в общем .playwright-mcp rejected: только отладочные логи
I-1 самостоятельный проект после программы вкладывался в неё fixed f5ce14f (R-8)
M-1 исторический расход без проекта после самостоятельного проекта вкладывается в него после F5 и блокирует удаление; то же в Excel deferred
M-2 фикс f5ce14f не проверялся вживую fixed: перепроверка пройдена
M-3 в окне выбора только R-коды, неясно, какой «номер статьи» нужен deferred
M-4 при закрытом сокете переименование без тоста deferred
M-5 устаревшие записи design.md fixed e5660ad
M-6 слабые тесты fixed e5660ad
M-7 комментарий «Часть 1» в 0059.sql fixed e5660ad

🤖 Generated with Claude Code

Refs #305. Jira: AURORA-1984, AURORA-1979, AURORA-1980, AURORA-1989. **Порядок мержа:** ветка стоит поверх PR #304 (AURORA-1978), он не влит, поэтому его коммит виден и здесь. Сначала #304, затем этот PR. Номер миграции 0059 актуален на `test` 244c03a. ## Что сделано - **AURORA-1984.** На форме 4 проект создаётся прямо в разделе, без программы: `form4_project` с `level='project'`, `parent_id IS NULL`, своими `section_code` и `form_id`. Стоит строкой ITEM под ROOT, вперемешку с программами в порядке создания. Суммы входят в ROOT один раз, GROUP с пустой программой нет. Расходы, переименование, удаление пустого, выгрузка — как у проекта в программе. - **AURORA-1980.** Кнопка «Переименовать» для программы и проекта. При ошибке окно остаётся открытым с введённым текстом. - **AURORA-1979.** В третьем столбце подпись «программа» / «проект», на экране и в Excel. Данные (`header.section_code`) не меняются. - **AURORA-1989.** Окно выбора расхода: «номер — название», сортировка с учётом числовых частей, поиск по номеру и названию. - Миграция `0059_form4_standalone_project`, downgrade — `pass`. Спека: `openspec/changes/aurora-1984-pd-standalone-projects/`. **Перед деплоем (T1.3):** `SELECT count(*) FROM v3.form4_project WHERE parent_id IS NULL AND form_id IS NULL`. Ожидается 0, иначе миграция упадёт на проверке. ## Проверка - Frontend `node --test` на HEAD e5660ad: 188 passed, 0 failed. - `pytest tests/unit` на HEAD e5660ad: 172 passed, 2 failed (`test_export_service_query_params.py`, падают и на базе). - Весь backend (`pytest --init_db`) на b87b12f: **889 passed, 10 failed, 4 skipped**. Те же 10 падают на базе 1aec5d2, новых нет. Весь набор на базе не зелёный (O-6): - `test_db_functions_integration.py::test_backend_calls_form3_add_project_and_add_line_functions` - `test_form2_ahr_satellite_spod_integration.py::test_satellite_spod_written_and_included_in_q4_total` (3 варианта) - `test_upd_form_cells_subtree.py`: `test_edit_path_does_not_call_v_form_view[delta]`, `test_ahr_delta_matches_get_after_rent_edit`, `test_jit_off_on_builders_and_edit_path` - `test_upd_form_cells_subtree_0037_guard.py::test_v_form2_view_keeps_0037_limit_formula` - `test_export_service_query_params.py`: 2 теста - Интеграционные тесты после b87b12f заново не гонялись. Позже изменились фронт, `export_writers.py`, тесты, комментарий в SQL-миграции и `design.md`; тело миграции не менялось. - Biome: 62 ошибки и 54 предупреждения, те же итоги на базе, новых нет. - Живая проверка на стенде, форма 4, две вкладки: все сцена��ии пройдены, кроме частично проверенного окна выбора расхода. В БД там только R-коды, поэтому примеры «3.2. раньше 3.10.» и «3.01» проверены только unit-тестами (M-3). ## Rulings I made **Рулинги из `design.md`** | Маркер | Решение | Цена ошибки | |---|---|---| | R-1 (design #13) | Подпись третьего столбца — строковый признак в конфиге и `accessorFn` в `processColumns`: `structuredClone` конфига падает на функциях | правка одной ветки в `processColumns` | | R-2 (design #14) | Отдельный `Form4DepthRowNormalizer` для AHR/CAP/OPER: `Form1DepthRowNormalizer` общий для всех форм | лишний класс из нескольких строк | | R-3 (design #15) | Отдельное окно `RenameNodeModal`, закрытие по `is_self` + событие + id, отдельный канал ошибок | лишний компонент; поздний ответ может закрыть повторно открытое окно того же узла | | R-4 (design #16) | Downgrade 0059 — `pass`, как у SQL-миграций репозитория | откат только вручную | | R-5 (design #17) | Эталон «как до миграции» — `pg_temp`-копия функции из 0053 | тест привязан к файлу 0053 | | R-6 (design #18) | Права на переименование и удаление — членство в форме, без `v3.can_edit`, как у программ | прямой запрос по WS может переименовать или удалить узел при закрытом окне ввода | | R-7 (design #19) | Путь «проект в программу» тоже через `alignNodeRows` + `updateCells` | строки ответа, которых нет локально, отбрасываются до `program_added` или перезагрузки | | R-8 (design #20) | Самостоятельный проект опознаётся явно (ITEM с `project_id` без `program_id`) и получает уровень программы в дереве и в Excel: иначе проект после программы вкладывался в неё | если у ITEM другой формы появится `project_id` без `program_id`, он станет верхним уровнем | | R-9 (design #21) | Устаревшие имена строк после добавления расхода (O-7) в этой ветке не чинятся: воспроизводится на базе, путь `row_added` общий для всех форм | неверные названия до перезагрузки, вынесено в follow-up | **Решения по находкам и допущения** - T2.3 / T2.4: `section_code` в аудите создания проекта и новый текст ошибки «Укажите либо программу, либо форму и раздел» оставлены. Цена: изменение аудита и текста ошибки для существующего пути. - T5.2: принята цена R-3. Цена: редкая гонка, пока у WS нет идентификатора запроса. - O-2: коммит 209d36e с трейлером `Sonnet 5.5` оставлен, правка переписала бы 9 SHA. Цена: расхождение в одном коммите. - O-3 / O-5: у Task 2 не было настоящего RED, исполнители Tasks 2, 4, 5, 6 не вызывали codegraph. Цена: правила процесса соблюдены не полностью, вреда ревью не нашло. - O-4: падение form3-теста признано не связанным с веткой после проверки на базе. - Решения исполнителей: в миграции именованные теги долларовых кавычек (`$do$`, `$function$`), разделитель `sql_migration.py` не понимает `$$`; в `test_cell_patch_response` сравнение через `strip_nulls`; проверка «Только FORM_4» и в ветке без программы; unit-тесты сервера на `@pytest.mark.asyncio`; пробельный `item_id` считается отсутствием кода. ## Находки | Маркер | Суть | Статус | |---|---|---| | T1.1 | test_cell_patch_response не проверял значение 20 | fixed 209d36e | | T1.2 | заглушка-комментарий Task 2 в 0059.sql | fixed 209d36e | | T1.3 | новый CHECK требует `form_id`; проверка в миграции падает при NULL в проде | deferred | | T2.1 | нет SQL-теста отказа чужому исполнителю на создании | deferred | | T2.2 | нет тестов rename/delete с ROOT, AHR/OPER, «Только FORM_4», аудита | ROOT fixed 69c4a8f, остальное deferred | | T2.3 | `section_code` в аудите PROJECT_CREATE | rejected: требование D2, поле аддитивное | | T2.4 | заменено сообщение об обязательной программе | rejected: так задумано | | T3.1 | дублирование проверки членства из `add_program` | deferred | | T3.2 | стиль тестов | rejected: по конвенциям репозитория | | T4.1 | путь «в программу» через `alignNodeRows` | rejected: предписано планом, R-7 | | T4.2 | нет теста сдвига вложенных `subRows` | deferred | | T4.3 | `subscribeToProjectAdds` без unit-теста | deferred | | T5.1 | пустой result без error оставляет окно в saving | deferred | | T5.2 | поздний ответ закрытого окна | rejected: принятая цена R-3 | | T5.3 | Enter не отправляет форму; пустое значение на один рендер | deferred | | T5.4 | нет тоста при `renameNode=false` | deferred | | T6.1 | правила подписи на бэке и фронте эквивалентны условно | deferred | | T7.1 | тест поиска проверяет только подпись | deferred | | T7.2 | нет теста на `item_id` из пробелов | deferred | | T7.3 | фильтр MUI может совпасть с тире | rejected: косметика | | O-2 | трейлер коммита 209d36e | deferred | | O-3 | у Task 2 не было настоящего RED | rejected: тесты проверены ревьюером | | O-4 | падение form3 add_line | rejected: падает и на базе | | O-5 | не все исполнители вызывали codegraph | rejected: вреда не обнаружено | | O-6 | 10 падений всего набора, все и на базе | deferred | | O-7 | после добавления расхода у строк ниже имена предыдущих строк до F5 | deferred (R-9) | | O-8 | вторая вкладка не переподключает WS после рестарта API; 410 на повторной загрузке экспорта | deferred | | O-9 | отказ по правам при переименовании приходит как «Проект не найден» | deferred | | O-10 | агент перепроверки удалил `*.yml`/`*.log` в общем `.playwright-mcp` | rejected: только отладочные логи | | I-1 | самостоятельный проект после программы вкладывался в неё | fixed f5ce14f (R-8) | | M-1 | исторический расход без проекта после самостоятельного проекта вкладывается в него после F5 и блокирует удаление; то же в Excel | deferred | | M-2 | фикс f5ce14f не проверялся вживую | fixed: перепроверка пройдена | | M-3 | в окне выбора только R-коды, неясно, какой «номер статьи» нужен | deferred | | M-4 | при закрытом сокете переименование без тоста | deferred | | M-5 | устаревшие записи `design.md` | fixed e5660ad | | M-6 | слабые тесты | fixed e5660ad | | M-7 | комментарий «Часть 1» в 0059.sql | fixed e5660ad | 🤖 Generated with [Claude Code](https://claude.com/claude-code)
aep added 14 commits 2026-11-08 22:23:16 +03:00
«Удалить строку» на строке программы (GROUP) или проекта (ITEM) ничего не
делала: у этих строк нет line_id, окно подтверждения не открывалось, а
события program_deleted / project_deleted, которые сервер уже поддерживает,
фронт не отправлял.

- getDeleteTarget: по выделенной строке выбирает программу, проект или
  строку бюджета; для непустых программы/проекта сразу показывает причину.
- RealtimeContext: deleteProgram / deleteProject и обработка ответов.
- useRealtimeData: строка убирается из дерева, пересчёт ROOT/GROUP из
  ответа сопоставляется по section_code / program_id / project_id
  (alignNodeRows), а не по sort_order — сервер нумерует строки заново, и у
  листа без строк бюджета нет ROOT (найдено при проверке на стенде).
- Окно подтверждения называет удаляемую программу/проект.
- getWsErrorMessage срезает префикс "<class 'asyncpg...'>: " — иначе отказ
  сервера (программа с проектами у устаревшего клиента) показывался с ним.

Refs #303

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #305

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aep requested review from PotapovaA 2026-11-09 08:12:53 +03:00
aep requested review from tsygankoviva 2026-11-09 08:12:55 +03:00
tsygankoviva approved these changes 2026-11-09 09:58:46 +03:00
PotapovaA approved these changes 2026-11-09 14:36:15 +03:00
aep merged commit 4dc111a0ce into test 2026-11-11 18:12:24 +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#306
No description provided.