Счета без сальдо по аналитике (91, 99) вне тождества строк — OQ-132 (#11 п. 2) #26

Merged
aep merged 1 commits from feat/11-osv-91-no-saldo into main 2026-10-07 23:24:56 +03:00
Owner

Closes #11

Пункты 1, 3–6 issue закрыты PR #13 (слит; коммиты 30f78c4, 6fd7add, af8ec91 — см. комментарий в #11 от 06.10.2026, пункт 6 — «дефекта разноса нет»); этот PR закрывает последний открытый пункт 2 (счёт 91) по решению владельца от 07.10.2026 (OQ-132, вариант Б, правило — 05-domain-rules.md §1.4, RSHB/arm-ka-docs#62).

Что сделано

  • Новый словарь api/rules/osv_checks.yaml, ключ accounts_without_analytic_balance: 91, 99 (90 не включён). Модель OsvCheckRules в rules.py (валидация кодов, метод has_no_analytic_balance), Rules.checks.
  • checks.py: balance_identity, parent_sums, run_checks принимают необязательный exempt: OsvCheckRules; osv.py передаёт rules.checks. Без exempt поведение прежнее.
  • Тождество строки на счетах списка не проверяется. «Сумма детей = родитель» и «Итого» сохраняются (детали — R-3).
  • Тесты: unit test_checks.py (дерево 91 с аналитикой только по оборотам; оборотная сверка и сальдо субсчетов под корнем остаются нарушениями; «Итого» проверяется; 910/90.01 не освобождаются), test_rules.py (состав списка, сопоставление, правка данных без кода, валидация); манифест tests/osv_dkb_expectations.yaml — убраны две записи по 91.
  • Документация: README.md, CLAUDE.md сервиса, api/rules/README.md, openspec/specs/osv-parsing/spec.md (правка напрямую, без change).

Статусы двух ОСВ 91 (CLI парсера)

Файл До После
osv-dkb/tsimlyansky/2025-Q3/91_ 9мес.2025.xls needs_check: тождество — 39 строк, родители — строки 10, 28, 50 done, оба списка пусты, total_row_matches_root = true
osv-dkb/primanych/2025-Q3/Оборотно-сальдовая ведомость по счету 91 за 9 месяцев 2025 г. ООО Приманыческий.xls needs_check: тождество — 34 строки, родители — строки 10, 23, 45 done, оба списка пусты, total_row_matches_root = true

Golden-снимки

Лежат в репозитории fixtures: RSHB/arm-ka-fixtures#14 (ветка feat/11-golden-91-no-saldo). make golden-update изменил ровно два снимка из 113 — эти два файла 91; в каждом только status (needs_check -> done), пустые balance_identity_violations/parent_sum_violations и исчезнувшие два предупреждения §1.4. Суммы строк, прочие снимки, total_row_matches_root не менялись. Golden-тесты (make test) зелёные только при снимках из #14: сливать оба PR вместе.

Проверки

  • make check: ruff check, ruff format --check, mypy src (50 файлов) — чисто; pytest 2251 passed, 1 skipped, 10 deselected (156 с), при ../fixtures = ветка feat/11-golden-91-no-saldo. До правки снимков на main-фикстурах падали ровно два golden-теста 91 (845 passed, 2 failed в tests/fixtures) — ожидаемо.
  • make check-full: check (выше) + make test-integration (compose-стенд postgres/nats/minio поднят, 10 passed) + make docker-build (образ собран).

Rulings I made

  • R-1 Список счетов — отдельный файл osv_checks.yaml, а не ключ в существующем: в соседних словарях записи — Pattern, а здесь коды счетов; смешивание сломало бы тест покрытия словарей (R-22) и смысл файлов. Файл внесён в PATTERNLESS покрытия (как statement_checks.yaml). Счёт 90 не включён (решение владельца).
  • R-2 Сопоставление со списком — по коду ближайшего счёта ветки строки (account_code_raw, «как в файле»): код совпадает с записью списка либо начинается с <запись>. (91, 91.01, 91.09; не 910, не 9). Не по коду из шапки документа: работает и для листа без «по счету …» в шапке (код берётся из таблицы), и для листа с несколькими корнями. Следствие: у строки «Итого» кода нет, поэтому её тождество проверяется как обычно (на 91 оно выполняется, корень = «Итого»).
  • R-3 Как «сумма детей = родитель» сохраняется на этих счетах. Буквальная сверка всех шести колонок не проходит на 91 по самой природе счёта: у 91.01 сальдо на конец = обороты, а у его аналитики сальдо пусто (parent_sum на строках 10/28/50 остаётся). Поэтому: обороты сверяются всегда; сальдо — только у родителя, у которого есть дочерние субсчета (строки ACCOUNT: корень 91 -> 91.01/91.02/91.09, по правилам R-21); у родителя с одной аналитикой сальдо не сверяется. Это моя трактовка слов владельца «иерархия сохраняется». Прошу подтвердить (риск: если владелец имел в виду полную сверку шести колонок, обе ОСВ 91 остались бы needs_check по parent_sum — задача п. 2 не достигалась бы).
  • R-4 Эталоны (golden) вынесены в отдельный PR fixtures #14 по правилам репозитория (снимки правятся только make golden-update отдельным коммитом в fixtures).
  • R-5 Ожидания пакета ДКБ (osv_dkb_expectations.yaml): две записи 91 удалены (теперь done); записи agrokompleks 62/76 (аналитика магазинов без сальдо, «тот же класс») не тронуты — решение владельца касается только 91 и 99.
  • Bounded-задача: OpenSpec change и design.md нет; решения R-1…R-5 зафиксированы здесь и в openspec/specs/osv-parsing/spec.md.

Находки

Маркер Находка Статус
O-1 Дефект п. 4/5 из комментария #11 от 07.10.2026 (ОСВ 63 Новоросметалл) на текущем main не воспроизводится на fixtures/osv-dkb/nm/2025-Q3/НМ_ОСВ_63_Контрагенты_2025.09-01_24498.xlsx: done, организация «НОВОРОСМЕТАЛЛ ООО», счёт 63 (из первой строки таблицы, предупреждение), период «9 месяцев 2025 г.» -> 2025 Q3, тип данных BU, строка 58 принята за «Итого» с предупреждением и не входит в сумму детей, нару��ений нет. Файла тестировщика («…-требуется проверка.xlsx») в fixtures нет; вероятно, тестировщик гонял сборку до PR #13 или иную копию файла. Код не менялся. deferred: запросить у тестировщика сам файл и хеш/версию сборки
O-2 Тот же класс (аналитика без сальдо на конец) в agrokompleks 62 (2025-Q3) и 76 (2025-Q3, 2024-10_2025-09): остаются needs_check по тождеству строки; в список не включены (решение владельца: только 91 и 99). deferred: решение владельца, нужно ли расширять список
O-3 05-domain-rules.md §1.4 говорит «проверки «сумма детей = родитель» на этих счетах сохраняются» без уточнения, что сальдо аналитики не сверяется (R-3). deferred: уточнить формулировку в arm-ka-docs после подтверждения R-3
O-4 Golden-снимки 91 вынесены в RSHB/arm-ka-fixtures#14 (R-4). fixed 4940068 (парсер), fixtures: коммит ветки feat/11-golden-91-no-saldo
O-5 docker-build и test-integration выполнены на локальном compose-стенде (параллельный make check-full arm-core конфликтов не вызвал). fixed (проверено)

🤖 Generated with Claude Code

https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2

Closes #11 Пункты 1, 3–6 issue закрыты PR #13 (слит; коммиты 30f78c4, 6fd7add, af8ec91 — см. комментарий в #11 от 06.10.2026, пункт 6 — «дефекта разноса нет»); этот PR закрывает последний открытый пункт 2 (счёт 91) по решению владельца от 07.10.2026 (OQ-132, вариант Б, правило — `05-domain-rules.md` §1.4, RSHB/arm-ka-docs#62). ## Что сделано - Новый словарь `api/rules/osv_checks.yaml`, ключ `accounts_without_analytic_balance`: `91`, `99` (90 не включён). Модель `OsvCheckRules` в `rules.py` (валидация кодов, метод `has_no_analytic_balance`), `Rules.checks`. - `checks.py`: `balance_identity`, `parent_sums`, `run_checks` принимают необязательный `exempt: OsvCheckRules`; `osv.py` передаёт `rules.checks`. Без `exempt` поведение прежнее. - Тождество строки на счетах списка не проверяется. «Сумма детей = родитель» и «Итого» сохраняются (детали — R-3). - Тесты: unit `test_checks.py` (дерево 91 с аналитикой только по оборотам; оборотная сверка и сальдо субсчетов под корнем остаются нарушениями; «Итого» проверяется; `910`/`90.01` не освобождаются), `test_rules.py` (состав списка, сопоставление, правка данных без кода, валидация); манифест `tests/osv_dkb_expectations.yaml` — убраны две записи по 91. - Документация: `README.md`, `CLAUDE.md` сервиса, `api/rules/README.md`, `openspec/specs/osv-parsing/spec.md` (правка напрямую, без change). ## Статусы двух ОСВ 91 (CLI парсера) | Файл | До | После | |---|---|---| | `osv-dkb/tsimlyansky/2025-Q3/91_ 9мес.2025.xls` | `needs_check`: тождество — 39 строк, родители — строки 10, 28, 50 | `done`, оба списка пусты, `total_row_matches_root = true` | | `osv-dkb/primanych/2025-Q3/Оборотно-сальдовая ведомость по счету 91 за 9 месяцев 2025 г. ООО Приманыческий.xls` | `needs_check`: тождество — 34 строки, родители — строки 10, 23, 45 | `done`, оба списка пусты, `total_row_matches_root = true` | ## Golden-снимки Лежат в репозитории fixtures: **RSHB/arm-ka-fixtures#14** (ветка `feat/11-golden-91-no-saldo`). `make golden-update` изменил ровно два снимка из 113 — эти два файла 91; в каждом только `status` (`needs_check` -> `done`), пустые `balance_identity_violations`/`parent_sum_violations` и исчезнувшие два предупреждения §1.4. Суммы строк, прочие снимки, `total_row_matches_root` не менялись. Golden-тесты (`make test`) зелёные только при снимках из #14: сливать оба PR вместе. ## Проверки - `make check`: ruff check, ruff format --check, mypy src (50 файлов) — чисто; pytest 2251 passed, 1 skipped, 10 deselected (156 с), при `../fixtures` = ветка `feat/11-golden-91-no-saldo`. До правки снимков на main-фикстурах падали ровно два golden-теста 91 (845 passed, 2 failed в `tests/fixtures`) — ожидаемо. - `make check-full`: `check` (выше) + `make test-integration` (compose-стенд postgres/nats/minio поднят, 10 passed) + `make docker-build` (образ собран). ## Rulings I made - **R-1** Список счетов — отдельный файл `osv_checks.yaml`, а не ключ в существующем: в соседних словарях записи — `Pattern`, а здесь коды счетов; смешивание сломало бы тест покрытия словарей (R-22) и смысл файлов. Файл внесён в `PATTERNLESS` покрытия (как `statement_checks.yaml`). Счёт 90 не включён (решение владельца). - **R-2** Сопоставление со списком — по коду **ближайшего счёта ветки строки** (`account_code_raw`, «как в файле»): код совпадает с записью списка либо начинается с `<запись>.` (`91`, `91.01`, `91.09`; не `910`, не `9`). Не по коду из шапки документа: работает и для листа без «по счету …» в шапке (код берётся из таблицы), и для листа с несколькими корнями. Следствие: у строки «Итого» кода нет, поэтому её тождество проверяется как обычно (на 91 оно выполняется, корень = «Итого»). - **R-3** Как «сумма детей = родитель» сохраняется на этих счетах. Буквальная сверка всех шести колонок не проходит на 91 по самой природе счёта: у 91.01 сальдо на конец = обороты, а у его аналитики сальдо пусто (parent_sum на строках 10/28/50 остаётся). Поэтому: **обороты** сверяются всегда; **сальдо** — только у родителя, у которого есть дочерние субсчета (строки ACCOUNT: корень 91 -> 91.01/91.02/91.09, по правилам R-21); у родителя с одной аналитикой сальдо не сверяется. Это моя трактовка слов владельца «иерархия сохраняется». **Прошу подтвердить** (риск: если владелец имел в виду полную сверку шести колонок, обе ОСВ 91 остались бы `needs_check` по parent_sum — задача п. 2 не достигалась бы). - **R-4** Эталоны (`golden`) вынесены в отдельный PR fixtures #14 по правилам репозитория (снимки правятся только `make golden-update` отдельным коммитом в fixtures). - **R-5** Ожидания пакета ДКБ (`osv_dkb_expectations.yaml`): две записи 91 удалены (теперь `done`); записи agrokompleks 62/76 (аналитика магазинов без сальдо, «тот же класс») **не тронуты** — решение владельца касается только 91 и 99. - Bounded-задача: OpenSpec change и `design.md` нет; решения R-1…R-5 зафиксированы здесь и в `openspec/specs/osv-parsing/spec.md`. ## Находки | Маркер | Находка | Статус | |---|---|---| | O-1 | Дефект п. 4/5 из комментария #11 от 07.10.2026 (ОСВ 63 Новоросметалл) на текущем main **не воспроизводится** на `fixtures/osv-dkb/nm/2025-Q3/НМ_ОСВ_63_Контрагенты_2025.09-01_24498.xlsx`: `done`, организация «НОВОРОСМЕТАЛЛ ООО», счёт 63 (из первой строки таблицы, предупреждение), период «9 месяцев 2025 г.» -> 2025 Q3, тип данных BU, строка 58 принята за «Итого» с предупреждением и не входит в сумму детей, нару��ений нет. Файла тестировщика («…-требуется проверка.xlsx») в fixtures нет; вероятно, тестировщик гонял сборку до PR #13 или иную копию файла. Код не менялся. | deferred: запросить у тестировщика сам файл и хеш/версию сборки | | O-2 | Тот же класс (аналитика без сальдо на конец) в agrokompleks 62 (2025-Q3) и 76 (2025-Q3, 2024-10_2025-09): остаются `needs_check` по тождеству строки; в список не включены (решение владельца: только 91 и 99). | deferred: решение владельца, нужно ли расширять список | | O-3 | `05-domain-rules.md` §1.4 говорит «проверки «сумма детей = родитель» на этих счетах сохраняются» без уточнения, что сальдо аналитики не сверяется (R-3). | deferred: уточнить формулировку в arm-ka-docs после подтверждения R-3 | | O-4 | Golden-снимки 91 вынесены в RSHB/arm-ka-fixtures#14 (R-4). | fixed 4940068 (парсер), fixtures: коммит ветки `feat/11-golden-91-no-saldo` | | O-5 | `docker-build` и `test-integration` выполнены на локальном compose-стенде (параллельный `make check-full` arm-core конфликтов не вызвал). | fixed (проверено) | 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
aep added 1 commit 2026-10-07 23:19:43 +03:00
У 91 и 99 строки аналитики несут только обороты, сальдо закрыто на субсчёт закрытия
(91.09), поэтому каждая ОСВ 91 получала needs_check. Список счетов — данные
api/rules/osv_checks.yaml (accounts_without_analytic_balance: 91, 99; 90 не входит).

- тождество строки на таких счетах не проверяется;
- «сумма детей = родитель» сохраняется: обороты всегда, сальдо — только у родителя
  с дочерними субсчетами (корень -> субсчета); у родителя с одной аналитикой сальдо
  не сверяется;
- «Итого» сверяется как обычно;
- строка относится к счёту списка по коду ближайшего счёта ветки (91, 91.01; не 910).

Тесты: unit checks/rules, манифест osv_dkb_expectations (две ОСВ 91 теперь done).
README, CLAUDE.md, openspec/specs/osv-parsing, api/rules/README.md обновлены.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
Author
Owner

Уточнение к находке O-4: коммит снимков в arm-ka-fixtures#14 — 0f04cce.

Уточнение к находке O-4: коммит снимков в arm-ka-fixtures#14 — 0f04cce.
aep merged commit 49f725d238 into main 2026-10-07 23:24:56 +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-tabular-parser#26
No description provided.