143 Commits

Author SHA1 Message Date
aep
f459819109 Merge pull request 'AURORA-1886: снятие или перенос даты закрытия возвращает ВСП в действующие (поверх #328, мерж после #323)' (#331) from feat/329-aurora-1886-vsp-reopen into test 2026-11-12 17:03:52 +03:00
aep
2b780f5267 Merge pull request 'feat: формулы ячеек на сервере, маркер fx для всех пользователей (AURORA-1896)' (#323) from feat/320-aurora-1896-cell-formulas into test 2026-11-12 17:03:41 +03:00
aep
ea69099540 Merge pull request 'AURORA-1879: одноимённые этапы «Поддержки» и «Развития» — раздельно в списке, правке, удалении и аудите' (#315) from feat/312-aurora-1879-form-phase-direction into test 2026-11-12 17:02:34 +03:00
Andrey Epifancev
72b57a0c53 test(vsp): красные тесты возврата ВСП в действующие (AURORA-1886, #329)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 11:23:21 +04:00
Andrey Epifancev
744b71fbe7 fix(vsp): админ получает ВСП по id включая удалённые; прошедшая дата закрытия сразу закрывает ВСП (AURORA-1885, #327)
- VSPRepository.get: with_deleted=True означает «включая удалённые», а не «только удалённые»
- VSPService.update: ключ closed_at (имя поля модели) вместо close_date (входной alias)
- тесты: integration test_vsp.py, unit test_vsp_service_close_date.py

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 11:11:50 +04:00
Andrey Epifancev
38036b31af chore(formulas): миграция 0060 → 0061 поверх 0060_form_phase_direction_fix (#315) (AURORA-1896)
Порядок мержа фиксирован: #315 → #317 → #319 → #323. design.md #22.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 01:08:21 +04:00
Andrey Epifancev
551ef0ec14 fix(form2): открытый АХР пересчитывает итоги после удаления записи аренды/коммуналки/охраны (AURORA-1887, #324)
notify_ahr_about_satellite_change рассылал на АХР row_deleted по скрытой
(AURORA-1887) строке сателлита с пустым result: фронт не находил строку
и не получал пересчитанных заголовков — итоги статьи, раздела и сметы
оставались прежними до перезагрузки.

Теперь в result — заголовки ROOT/GROUP/ITEM/SUB_ITEM/SUB_SUB_ITEM по пути
статьи удалённой строки (как del_budget_line для обычных листов). Поиск
строки по аудиту и выборка заголовков вынесены в
SheetRepository/SheetService.get_form2_ahr_satellite_delete_delta.
Протокол WS и фронт не меняются.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 23:51:48 +04:00
Andrey Epifancev
54e60dcf8e test(formulas): GET formulas без доступа, спека приведена к коду (AURORA-1896, M-5)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 21:06:53 +04:00
Andrey Epifancev
e107fa418d perf(formulas): равенство по владельцу вместо IS NOT DISTINCT FROM, отказ на Infinity (AURORA-1896, M-1, M-2, M-3)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 21:06:53 +04:00
Andrey Epifancev
ecef6eb247 fix(formulas): рассылка WS не несёт формулу клиента при отказе в доступе (AURORA-1896, I-1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 21:06:53 +04:00
Andrey Epifancev
683e12c52f chore(formulas): номер миграции 0060 после rebase на test (AURORA-1896)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 20:10:55 +04:00
Andrey Epifancev
18573d6dc4 test(formulas): правки WS-тестов T5.1–T5.3 (AURORA-1896)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 20:07:42 +04:00
Andrey Epifancev
af687a7e22 feat(formulas): formula и formula_meta в cell_updated по WebSocket (AURORA-1896)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 20:07:04 +04:00
Andrey Epifancev
84dbaaf361 test(formulas): правки minor-находок T1.1–T4.2 (AURORA-1896)
T1.1 каскад hard_delete проверяется по AHR_LIMIT; T1.2 тесты триггеров
rent/utility/security/fixed_asset_report; T1.3 NaN в set_cell_formulas
отклоняется (0059 правится на месте); T3.1 unit-кейсы asyncpg-обёртки;
T3.2 предусловие SAVEPOINT-теста и комментарий к 403; T4.1 проверка
незаписи значения при 422 отчёта проекта; T4.2 убрана мёртвая логика.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 20:07:04 +04:00
Andrey Epifancev
187988bd76 feat(formulas): формулы в отчётах проектов — запись и GET formulas (AURORA-1896)
PATCH cell/cells отчёта проекта пишут формулу в той же транзакции, GET
.../report/{year}/{report_type}/formulas возвращает формулы отчёта.
Тесты: roundtrip, снятие формулы, каскад удаления проекта, триггер
rf_project_report_line (del_form3_line и прямой DELETE).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 20:07:04 +04:00
Andrey Epifancev
5bc6a755bc feat(formulas): запись формулы при правке ячейки формы и GET formulas листа (AURORA-1896)
SheetService.update_cell_with_formula/update_cells пишут формулу после значения в одной
транзакции, GET /form/{id}/sheet/{sheet}/formulas. Ошибки БД с обёрткой asyncpg
"<class ...>: invalid_formula: ..." теперь корректно мапятся в 422.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 20:07:04 +04:00
Andrey Epifancev
a29207f814 feat(formulas): таблица cell_formula, set/v_cell_formulas, триггеры очистки, миграция 0059 (AURORA-1896)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 20:07:04 +04:00
Andrey Epifancev
525f801187 Merge remote-tracking branch 'origin/test' into feat/312-aurora-1879-form-phase-direction 2026-11-11 19:35:11 +04:00
Andrey Epifancev
8798f092c4 fix(stages): именованный dollar-тег в DO-блоке 0059, правка интеграционных тестов этапов (AURORA-1879)
- sql_migration._split_statements узнаёт только $tag$, пустой $$ ломал разбиение:
  DO $$ … $$ → DO $do$ … $do$.
- test_form_phases_delete_removes_only_named_phase: ?sheet= без direction
  фильтрует direction IS NULL — читаем весь список и отбираем AHR в тесте.
- test_form_phases_duplicate_without_direction_rejected: после ошибки
  сессия клиента откатывается, число строк не проверяем; защиту БД
  проверяет новый test_form_phase_nodir_unique_index_blocks_duplicate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 16:53:42 +04:00
Andrey Epifancev
92f6049a73 fix(stages): FormPhaseService.create отклоняет дубль этапа на листе и направлении (AURORA-1879)
Интеграционные тесты одноимённых этапов, PATCH/DELETE одного этапа, дубль без направления, direction в аудите.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 16:39:24 +04:00
Andrey Epifancev
69c4a8f9c9 AURORA-1984: событие project_added без программы
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 22:27:16 +04:00
Andrey Epifancev
209d36e832 AURORA-1984: создание, переименование и удаление проекта без программы в SQL
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-08 22:23:28 +04:00
Andrey Epifancev
836e812bad AURORA-1984: самостоятельный проект в модели и листе формы 4
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 22:18:22 +04:00
aep
bf449c5754 Merge pull request 'fix(form2): дельта АХР пуста для статей глубины 4 после правки лимита (AURORA-1850, часть #296)' (#301) from feat/296-ahr-delta-depth4 into test 2026-11-08 17:11:12 +03:00
Andrey Epifancev
d341d21ec6 fix(form2): дельта АХР после правки лимита пуста для статей глубины 4 (AURORA-1850, #296)
0053 пересоздала v3.get_form2_ahr_satellite_delta по телу из 0031 с
сопоставлением лимитного шаблона «ei.depth = 3 AND (item_id OR
num_group_id)» и откатила правку 0037. Лимиты с кодом num_group_id статьи
глубины 4 (принтеры / МФУ / копиры) не попадали в target_lines, дельта
была пустой, и открытый АХР не обновлял сумму до перезагрузки.

Миграция 0058 пересоздаёт функцию с матчером 0037
((depth = 3 AND item_id = code) OR num_group_id = code); остальное тело —
как в 0053.

Тест-защита 0037 ждал в дельте INPUT-строку, которую AURORA-1887 скрыл на
листе AHR, — теперь проверяет заголовок SUB_SUB_ITEM статьи глубины 4.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 17:24:28 +04:00
Andrey Epifancev
8ba26427dd fix(tests): test_form2_ahr_limit — чтение plan.qN без KeyError после null-strip (AURORA-1897, #296)
После AURORA-1848 GET листа вырезает null-поля, поэтому у заголовка статьи
без плана в квартале ключа plan.qN нет вовсе, и чтение «до» падало
KeyError до проверки самой логики. Заменено на plan.get("qN") or 0.
Продуктовый код не меняется: с правкой все 7 тестов зелёные на test
(после PR #295).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 16:04:33 +04:00
Andrey Epifancev
77bfdf69fd perf(svod2): v_svod2_facets с SET jit TO off (O-1)
JIT добавлял ~1,4 с к вызову с буквальными параметрами (стенд масштаба 1: 1500 мс против 43 мс).
Тест: функции svod2 имеют jit=off. Убран тест формы плана: функция с SET не разворачивается.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 11:58:31 +04:00
Andrey Epifancev
5db0bd4cee fix(svod2): серверный поиск совпадает с экраном — пустое поле contract_detail не затирает contract_summary (R-30, решение пользователя 08.11)
В v3.svod2_lines counterparty/reference/deadline/comment берутся как COALESCE(detail, summary).
Оракулы (Python, JS, векторы) отбрасывают null при слиянии, legacy_full() снова читает
ответ без параметров. Тесты: пустое поле detail, отсутствие строки detail, перекрытие непустым detail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 11:45:37 +04:00
Andrey Epifancev
737ff55b42 test(api): схема OpenAPI свода 2 допускает Svod2PageResponse рядом с BaseListResponse (AURORA-1843)
Контрольный тест тяжёлых GET (AURORA-1848) требовал одну ссылку на BaseListResponse;
режим страниц добавляет второй вариант ответа.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 11:31:51 +04:00
Andrey Epifancev
c69a8e586b Merge remote-tracking branch 'origin/feat/220-aurora-1842-svod2-column-virtual' into feat/236-aurora-1843-svod2-server-paging
# Conflicts:
#	api/tests/integration/conftest.py
2026-11-08 11:02:38 +04:00
Andrey Epifancev
79c841dcaf Merge origin/feat/220 в feat/236 (сервер): свод 2 постранично поверх test (AURORA-1843)
Конфликты summary.py, summary_repository.py, summary_service.py,
test_summary2_related_records_sql.py: сохранены новые методы страниц и фасетов,
режим без параметров идёт по быстрому JSON-пути test (AURORA-1848).
Миграция переименована в 0057 (down_revision 0056); в svod2_lines добавлена
поправка 0050 (СПОД аренды, только ГО). Эталон svod2_legacy_golden перезаписан
под ответ без null-полей; legacy_full оракулов строится прямым вызовом функции.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 11:02:30 +04:00
Andrey Epifancev
36d19f1e2f fix(forms): add_budget_line проставляет created_by, NULL-автор удаляется только ADMIN (O-1)
R-4 (решение пользователя 08.11). В миграцию 0056 добавлен v3.add_budget_line:
тело = 0051_form2_ahr_satellite_new_line + только created_by = current_user_id() в
двух INSERT (обычная строка и заготовка записи сателлита). Авто-зеркальные строки
sync (_ensure_form2_ahr_*_sync_line) остаются с NULL. Backfill не делается.
del_budget_line: NULL-автор -> удаляет только ADMIN (комментарий в SQL + тесты).
xfail-тест владельца снят; добавлены тесты NULL-автора (исполнитель 403, ADMIN 200).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 10:59:55 +04:00
Andrey Epifancev
3fb1a3b162 Merge remote-tracking branch 'origin/test' into feat/249-aurora-1936-row-delete-confirm 2026-11-08 09:56:16 +04:00
Andrey Epifancev
d1922c9354 fix(forms): перенумеровать миграцию 1936 в 0056, пересобрать del_budget_line поверх 0053, починить тесты
Миграция 0050_budget_line_delete_owner_guard -> 0056 (down 0055, стек поверх 0055 AURORA-1938).
Тело v3.del_budget_line = актуальное тело из 0053_form2_ahr_source_sheet (AURORA-1907:
запрет удаления АХР-строк с source_sheet IS NOT NULL, ручные удаляются) + только owner-guard;
раньше копия опиралась на 0040 и откатывала 1907.

Тесты: доступ к форме id=1 даёт отдельная пара исполнителей isp2/isp3 (isp1 больше не
добавляется в org 1 — это ломало тесты «исполнитель из чужой организации»); окно фазы
DFIP в фикстуре продлено (истекло 2026-06-06, add_line возвращал 403); маркер
internal_order не приходит в INPUT-строке add_line — берём единственную INPUT-строку;
добавлен тест 1907 (строка из сателлита не удаляется напрямую). Тест «владелец удаляет свою
строку» помечен xfail(strict): add_budget_line не заполняет budget_line.created_by (O-1).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 09:56:16 +04:00
Andrey Epifancev
1f885866c4 Merge remote-tracking branch 'origin/test' into feat/255-aurora-1938-transfer-econ-calc 2026-11-08 09:45:37 +04:00
Andrey Epifancev
83372f7aef Merge origin/test в feat/250-aurora-1888-stages-role-filter
Конфликт в api/tests/integration/test_form_phases_api_smoke.py: оставлены
оба набора тестов (тесты фильтра по роли и 404 из этого PR и тест
aware-дат из test).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 09:38:56 +04:00
Andrey Epifancev
7b3a4ae6ae Merge remote-tracking branch 'origin/feat/255-aurora-1938-transfer-econ-calc' into feat/249-aurora-1936-row-delete-confirm 2026-11-08 09:37:02 +04:00
Andrey Epifancev
6e8942f66f Merge remote-tracking branch 'origin/test' into feat/249-aurora-1936-row-delete-confirm
# Conflicts:
#	web/src/components/RealtimeTable/RealtimeTable.jsx
2026-11-08 09:37:02 +04:00
Andrey Epifancev
e75ed6d44f fix(form4): перенумеровать миграцию 1938 в 0055 и пересобрать _apply_form_cell поверх 0050 (СПОД, AURORA-1906)
Миграция 0050_form4_transfer_econ_calc -> 0055 (down 0054): номер 0050 занят
на test. Тело v3._apply_form_cell = актуальное тело из 0050_form2_ahr_spod_column
+ только дельта AURORA-1938 (запрет ручной записи FORM_4 q*.transfer_econ);
раньше копия опиралась на 0023 и откатывала СПОД. v_form4_sheet_sections
после 0033 на test не менялась — тело без изменений. Добавлен тест на сохранение
обеих правок в итоговом определении функции.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 09:36:25 +04:00
Andrey Epifancev
37c2b96d61 Merge remote-tracking branch 'origin/test' into feat/255-aurora-1938-transfer-econ-calc 2026-11-08 09:21:45 +04:00
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
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
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
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
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
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
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
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