Полный состав строк ББ/ОФР на экране проверки (#80) #81

Merged
aep merged 11 commits from feat/80-statement-template-lines into main 2026-10-09 11:53:42 +03:00
Owner

Closes #80

Что сделано

  • Task 1 (438752f): справочник строк форм ББ/ОФР по редакциям 66n/fsbu4 (api/rules/statement_lines.yaml, domain/statement_lines.py).
  • Task 2 (3a543b5): GET …/statement достраивает строки справочника и недостающие ячейки (id = null, origin = template), в БД не пишет.
  • Task 3 (37e7f40): PATCH …/statement адресует ячейку line_id или line_code, создаёт строку и ячейку при первой непустой правке; вся валидация до первой вставки.
  • Task 4 (2d21a41): созданные правкой строки с пустыми суммами не участвуют в проверках §7.
  • Task 5 (5c330eb): README, CLAUDE.md, design.md.
  • Fix wave по финальному ревью: d5118ba (перенос правки фронта во встроенный web/), 753c10a (design/proposal/README).
    Связанные PR: arm-web #20 (в test), arm-ka-docs #82.

Проверки

make check-full (после Task 5): exit 0 — lint + mypy, test 1279 passed, integration 865 passed, e2e 1 passed (не skip), dbml-check, check-infra, docker-build, web-check. После fix wave прогнаны make web-check (exit 0) и vitest в web/ (121 тест, зелёные); бэкенд после Task 5 не менялся.

Rulings I made

  • R-1…R-8 — в openspec/changes/statement-template-lines/design.md, раздел «Decisions made without discussion».
  • R-9: достройка реализована функцией _lines_out в schemas/statements.py, а не domain/statement_lines.complete_form. Цена ошибки: рефакторинг в domain позже.
  • R-10: ключ достроенной строки на фронте code-<code>, а не code:<code> (':' разделяет rowKey и columnId в cellKey). Цена: нет.
  • R-11: адресация ячеек PATCH вынесена из _apply_cells в _resolve_cells (ruff PLR0912/PLW2901); поведение сохранено. Цена: нет.
  • R-12: правка фронта перенесена и во встроенный arm-core/web в этой же ветке (иначе после слияния он шлёт line_id: "null" и дублирует ключи). Цена: дифф PR вырос; если arm-core/web не поддерживается — откатить d5118ba.
  • R-13: M-2…M-6 финального ревью отложены в follow-up. Цена: M-2 — форма без сумм может стать RECOGNIZED после ручного создания и очистки строки.

Находки ревью

Маркер Описание Статус
I-1 встроенный фронт arm-core/web ломается на id = null fixed d5118ba
M-2 пустая созданная строка учитывается в has_lines (D-5) deferred
M-3 аудит не пишет создание строки (только value:<id>) deferred
M-4 редакция берётся по дате до правки шапки в том же PATCH deferred
M-5 arm-web: 422 при параллельном создании — технический текст, черновик code-… залипает deferred
M-6 данные: 66n 2411 с префиксом «в т.ч.»; нет 2530 в 66n ОФР (уточнить у владельца) deferred
M-7 docs §11: вставка разорвала предложение fixed 2b3ead4 (docs #82)
M-8 сигнатуры в api-contract-slice-3b и README fixed 753c10a, 2b3ead4
M-9 design/proposal расходились с кодом fixed 753c10a
T1.1 повтор id редакции в yaml молча перезаписывается deferred
T1.2 LineCatalog.editions — изменяемый dict в frozen dataclass deferred
T1.3 null-имя строки превращается в "None" deferred
T1.4 составы проверены выборочно (финальное ревью сверило полностью — совпадает) rejected: полная сверка с шаблонами выполнена финальным ревью
T2.1 дубль line_code в БД не схлопывается достройкой rejected: уникальный индекс (meta_id, line_code) делает дубль невозможным
T2.2 точное сравнение кодов без нормализации deferred
T2.3 O(строки×колонки) в _lines_out rejected: ≈40×3, несущественно
T2.4 тест «GET не пишет» сверяет только число строк deferred
T2.5 тест правит reporting_date через общую сессию deferred
T3.1 недостижимая ветка if target is None в _apply_cells deferred
T3.2 цепочка присваивания created[...] deferred
T3.3 тест Focus 1 не проверяет пустоту аудита deferred
T3.4 тест Focus 2 не проверяет аудит с двумя ключами deferred
T3.5 нет теста line_id чужой формы deferred
T4.1 нет теста «0 = заполнено» deferred
T4.2 тест Task 4 зависит от хелперов Task 2/3 deferred
T5.1 README: UNKNOWN_CELL без обратных кавычек fixed 753c10a
T5.2 абзац формы в CLAUDE.md слишком длинный deferred
T5.3 слабые обоснования R-9/R-10 deferred
T5.4 complete_form в D-3 fixed 753c10a
T6.1 draftToPatch вне try/catch (arm-web) deferred
T6.2 line_code '' в draftToPatch (arm-web) deferred
T6.3 не рисуется ячейка без значения (arm-web) rejected: сервер всегда отдаёт ячейки по всем колонкам
T7.1 docs qa-guide F8a: пример 1105 неверен fixed b55db42 (docs #82)
T7.2 docs qa-guide F8b: формулировки fixed b55db42
T7.3 docs: пояснение «нет редакции» fixed b55db42

🤖 Generated with Claude Code

Closes #80 ## Что сделано - Task 1 (438752f): справочник строк форм ББ/ОФР по редакциям `66n`/`fsbu4` (`api/rules/statement_lines.yaml`, `domain/statement_lines.py`). - Task 2 (3a543b5): `GET …/statement` достраивает строки справочника и недостающие ячейки (`id = null`, `origin = template`), в БД не пишет. - Task 3 (37e7f40): `PATCH …/statement` адресует ячейку `line_id` или `line_code`, создаёт строку и ячейку при первой непустой правке; вся валидация до первой вставки. - Task 4 (2d21a41): созданные правкой строки с пустыми суммами не участвуют в проверках §7. - Task 5 (5c330eb): README, CLAUDE.md, design.md. - Fix wave по финальному ревью: d5118ba (перенос правки фронта во встроенный `web/`), 753c10a (design/proposal/README). Связанные PR: arm-web #20 (в `test`), arm-ka-docs #82. ## Проверки `make check-full` (после Task 5): exit 0 — lint + mypy, test 1279 passed, integration 865 passed, e2e 1 passed (не skip), dbml-check, check-infra, docker-build, web-check. После fix wave прогнаны `make web-check` (exit 0) и vitest в `web/` (121 тест, зелёные); бэкенд после Task 5 не менялся. ## Rulings I made - R-1…R-8 — в `openspec/changes/statement-template-lines/design.md`, раздел «Decisions made without discussion». - R-9: достройка реализована функцией `_lines_out` в `schemas/statements.py`, а не `domain/statement_lines.complete_form`. Цена ошибки: рефакторинг в domain позже. - R-10: ключ достроенной строки на фронте `code-<code>`, а не `code:<code>` (':' разделяет rowKey и columnId в cellKey). Цена: нет. - R-11: адресация ячеек PATCH вынесена из `_apply_cells` в `_resolve_cells` (ruff PLR0912/PLW2901); поведение сохранено. Цена: нет. - R-12: правка фронта перенесена и во встроенный `arm-core/web` в этой же ветке (иначе после слияния он шлёт `line_id: "null"` и дублирует ключи). Цена: дифф PR вырос; если `arm-core/web` не поддерживается — откатить d5118ba. - R-13: M-2…M-6 финального ревью отложены в follow-up. Цена: M-2 — форма без сумм может стать `RECOGNIZED` после ручного создания и очистки строки. ## Находки ревью | Маркер | Описание | Статус | |---|---|---| | I-1 | встроенный фронт `arm-core/web` ломается на `id = null` | fixed d5118ba | | M-2 | пустая созданная строка учитывается в `has_lines` (D-5) | deferred | | M-3 | аудит не пишет создание строки (только `value:<id>`) | deferred | | M-4 | редакция берётся по дате до правки шапки в том же PATCH | deferred | | M-5 | arm-web: 422 при параллельном создании — технический текст, черновик `code-…` залипает | deferred | | M-6 | данные: 66n 2411 с префиксом «в т.ч.»; нет 2530 в 66n ОФР (уточнить у владельца) | deferred | | M-7 | docs §11: вставка разорвала предложение | fixed 2b3ead4 (docs #82) | | M-8 | сигнатуры в api-contract-slice-3b и README | fixed 753c10a, 2b3ead4 | | M-9 | design/proposal расходились с кодом | fixed 753c10a | | T1.1 | повтор id редакции в yaml молча перезаписывается | deferred | | T1.2 | `LineCatalog.editions` — изменяемый dict в frozen dataclass | deferred | | T1.3 | null-имя строки превращается в "None" | deferred | | T1.4 | составы проверены выборочно (финальное ревью сверило полностью — совпадает) | rejected: полная сверка с шаблонами выполнена финальным ревью | | T2.1 | дубль `line_code` в БД не схлопывается достройкой | rejected: уникальный индекс `(meta_id, line_code)` делает дубль невозможным | | T2.2 | точное сравнение кодов без нормализации | deferred | | T2.3 | O(строки×колонки) в `_lines_out` | rejected: ≈40×3, несущественно | | T2.4 | тест «GET не пишет» сверяет только число строк | deferred | | T2.5 | тест правит `reporting_date` через общую сессию | deferred | | T3.1 | недостижимая ветка `if target is None` в `_apply_cells` | deferred | | T3.2 | цепочка присваивания `created[...]` | deferred | | T3.3 | тест Focus 1 не проверяет пустоту аудита | deferred | | T3.4 | тест Focus 2 не проверяет аудит с двумя ключами | deferred | | T3.5 | нет теста `line_id` чужой формы | deferred | | T4.1 | нет теста «0 = заполнено» | deferred | | T4.2 | тест Task 4 зависит от хелперов Task 2/3 | deferred | | T5.1 | README: `UNKNOWN_CELL` без обратных кавычек | fixed 753c10a | | T5.2 | абзац формы в CLAUDE.md слишком длинный | deferred | | T5.3 | слабые обоснования R-9/R-10 | deferred | | T5.4 | `complete_form` в D-3 | fixed 753c10a | | T6.1 | `draftToPatch` вне try/catch (arm-web) | deferred | | T6.2 | `line_code ''` в `draftToPatch` (arm-web) | deferred | | T6.3 | не рисуется ячейка без значения (arm-web) | rejected: сервер всегда отдаёт ячейки по всем колонкам | | T7.1 | docs qa-guide F8a: пример 1105 неверен | fixed b55db42 (docs #82) | | T7.2 | docs qa-guide F8b: формулировки | fixed b55db42 | | T7.3 | docs: пояснение «нет редакции» | fixed b55db42 | 🤖 Generated with [Claude Code](https://claude.com/claude-code)
aep added 9 commits 2026-10-09 11:15:13 +03:00
Спека: достройка формы по справочнику строк редакции в GET …/statement,
создание строки и ячейки при первой правке по line_code, пустые шаблонные
строки вне проверок §7 и статуса.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019qoydUVv8g1qHxc123u2RR
Просьба владельца: 1600/1700 сливаются с обычными строками. R-7 в design.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019qoydUVv8g1qHxc123u2RR
Спека: «1600 = 1700» проверяется при потерянной 1700 (цель 1600 есть);
цвет строк «БАЛАНС» — #f9f0ff (синий занят «исправлено»); R-8 has_lines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019qoydUVv8g1qHxc123u2RR
Относительный `git -C arm-core` из корня workspace указывал на main-checkout
(O-1 первого запуска контроллера).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019qoydUVv8g1qHxc123u2RR
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
GET …/statement добавляет строки справочника редакции, которых нет в форме
(id = null, origin = template), и недостающие ячейки существующих строк
(id = null, все значения пусты). В БД ничего не пишется. Добавлено поле
LineOut.origin (source | template).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
CellPatch адресует ячейку ровно одним из line_id / line_code. Строка справочника
редакции, которой нет в форме, создаётся при первой непустой правке
(line_code_original_value = NULL — признак «не из источника»); отсутствующая
ячейка существующей строки тоже создаётся. Адресация (колонка, строка, код)
проверяется целиком до первой вставки, две ячейки новой строки делят одну
строку, повтор line_code после создания даёт 422 UNKNOWN_CELL. Аудит — одно
RECOGNIZED_DATA_EDIT на запрос, у созданной ячейки before = null.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
statement_amounts не отдаёт проверкам строки с line_code_original_value IS NULL,
у которых все суммы пустые; заполненная хотя бы в одной колонке строка
проверяется по всем колонкам.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
README: достройка GET, адресация PATCH по line_code, строка UNKNOWN_CELL.
CLAUDE.md: абзац про справочник строк. design.md: рулинги R-9…R-11.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
aep added 2 commits 2026-10-09 11:33:18 +03:00
Правка arm-web 9e89b9f перенесена в arm-core/web: id и origin у строк и ячеек
формы, ключ достроенной строки code-<код>, отправка line_code, раскладка
formLayout. Без неё встроенный фронт отправлял бы line_id "null" (I-1, R-12).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
M-9: design.md и proposal.md приведены к коду (достройка - _lines_out в
schemas/statements.py, справочник без valid_from/valid_until, ленивая
загрузка с ручными проверками); добавлены R-12 и R-13. T5.1/M-8: сигнатура
PATCH values и обратные кавычки в таблице ошибок README.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
aep merged commit 5534b8effd into main 2026-10-09 11:53:42 +03:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RSHB/arm-core#81
No description provided.