17 Commits

Author SHA1 Message Date
Andrey Epifancev
133b31a1f3 fix(osv): нетто-признак только цепочкой нетто-строк, непрерывность периодов, спека и CLAUDE.md (AURORA-1863, AURORA-1823, #78, ревью)
I-2: в netted попадает только строка, сама сошедшаяся с детьми лишь по нетто; сошедшаяся по колонкам признак не
передаёт. I-3: сальдо конца периода = сальдо начала следующего (по колонкам либо по нетто), разрыв — нарушение.
M-6: сценарии спеки (защиты вложения по суммам, цепочка нетто-строк, непрерывность периодов); CLAUDE.md и докстринг
checks.py ссылаются на решения владельца 28.10.2026.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 10:56:18 +04:00
Andrey Epifancev
e01f218138 fix(osv): строки «Период» сверяются цепочкой сальдо, а не суммой (AURORA-1823, #78)
period_groups в osv_groups.yaml, признак is_period у ClassifiedRow; родитель, все дети которого
периоды: обороты = Σ, начало = начало первого, конец = конец последнего. НКЗ лист 58 убран
из манифеста ожидаемых needs_check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 00:44:24 +04:00
Andrey Epifancev
6117201b49 fix(osv): развёрнутый родитель над свёрнутым в нетто ребёнком сверяется по нетто (AURORA-1863, #78)
Узкий вариант: нетто сальдо допустимо, если среди прямых детей есть нетто-ребёнок
(прошёл сверку только по нетто либо имеет такого потомка); обороты — по колонкам.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 00:33:20 +04:00
Andrey Epifancev
99114508f7 ОСВ: «Итого» свёрнута при развёрнутом корне сверяется по нетто (AURORA-1708, #73)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 01:18:26 +04:00
Andrey Epifancev
a6cd375306 fix(osv): «Организация» не вид субконто, валюта не контрагент, тождество вторых итогов (#59)
I-1 (R-17): синоним COUNTERPARTY только «Организации» (^организации\b).
I-2 (R-18): правило расчётных счетов не применяется к строкам, известным словарю как не-контрагенты (валюта, «В валюте»).
I-4 (R-19): тождество у второй итоговой строки пропускается только без оборотов и при наличии другой «Итого».
M-1, M-5, M-6, M-7 (вымышленное ФИО ИП в синтетике), M-9.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 13:19:39 +04:00
Andrey Epifancev
835083ca4d fix(osv): вторые итоговые строки («Итого развернутое») вне тождества строки, R-11 отменён R-16 (#59)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 13:19:18 +04:00
Andrey Epifancev
71c4c93db2 feat(osv): стратегия header_account — плоский список под счётом шапки (#59)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 13:18:23 +04:00
Andrey Epifancev
774141588e fix(osv): «Итого развернутое» перед «Итого» — итоговая строка, сверка по основной «Итого» (#59)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 13:18:06 +04:00
Andrey Epifancev
1d2a46f3e7 Счёт 90 в списке счетов без сальдо по аналитике (OQ-132, O-1, #58)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 12:52:03 +04:00
Andrey Epifancev
d6dd341003 Правки итогового ревью: спека, предупреждение, README, design (#58)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 12:47:49 +04:00
Andrey Epifancev
8924dd13a6 Классификация и проверки по признаку строки-показателя, BU по умолчанию (#58)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 12:09:05 +04:00
Andrey Epifancev
702ea1dff9 refactor(osv): предупреждения листа ОСВ с кодами OSV_* (вывод 1.x прежний) (#54)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
2026-10-18 20:35:29 +04:00
Andrey Epifancev
49400682bc feat(osv): счета без сальдо по аналитике (91, 99) вне тождества строки (OQ-132, #11 п. 2)
У 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
2026-10-08 00:18:36 +04:00
Andrey Epifancev
af8ec918c5 feat(osv): шапка ОСВ без меток и «Счет: Код / Наименование» (ОСВ 63 Новоросметалл), «Итого» ↔ Σ уровня 0 по нетто
- header: период отдельной ячейкой (periods.yaml: standalone), тип данных отдельной ячейкой («Бухгалтерский»,
  data_types.yaml: standalone_header), организация — хвост названия ведомости; код счёта — из первой строки-счёта
  таблицы (с предупреждением), если «по счету» в шапке нет.
- classify/detect: текст строки может стоять правее колонки текста (колонка задаёт уровень), подписи «Код»/
  «Наименование» (osv_headers.yaml: column_captions) — не группировки, строка сумм без подписи в конце таблицы —
  «Итого» (с предупреждением).
- checks: сумма уровня 0 сверяется с «Итого» по правилу R-21 (свёрнутое сальдо «Итого» — по нетто), как у родителя.
- tests: osv_dkb_files, покрытие словарей включает osv-dkb/**; README.

Refs #11

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
2026-10-06 13:04:31 +04:00
Andrey Epifancev
6fd7adde22 feat(osv): «Итого» сверяется с суммой строк уровня 0; «Итого развернутое» — вторая итоговая строка
- checks: «Итого» = первый корень ACCOUNT либо сумма всех строк уровня 0 (лист без строки корневого счёта,
  верхний уровень 58.01/58.03; OQ-106, OQ-133). Прежнее правило «= первому корню» остаётся достаточным;
  строки-показатели в сумму не входят; основная «Итого» — первая TOTAL листа.
- classify/hierarchy: вторые итоговые строки сразу за «Итого» (osv_headers.yaml: total_row_secondary) остаются
  в таблице как TOTAL уровня 0, а не уходят в OTHER; без обычной «Итого» вторая служит единственной итоговой.

Refs #11

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
2026-10-06 12:50:35 +04:00
Andrey Epifancev
9b8b8ea727 fix: финальное ревью — лимиты чтения xlsx (I-1), лог traceback (I-2), ACCOUNT_RE (M-1), ИНН/КПП (M-3)
- I-1 (R-23): readers/_limits.py — сумма ZipInfo.file_size ≤ 10 × PARSE_MAX_BYTES (параметр read_book от
  OsvParser), потоковый скан <mergeCell ref> до openpyxl и площадь merged после чтения любого формата
  (MERGED_AREA_LIMIT = 200 000; реальный максимум 10 090) → UNSUPPORTED_FORMAT; дедлайн в циклах detect
  (поиск строки групп, дополнительные колонки); README «Лимиты» исправлен, «Известные ограничения» (defusedxml).
- I-2: OsvParser логирует стек непредвиденной ошибки (loguru ERROR), UNREADABLE — WARNING без стека.
- M-1: ACCOUNT_RE с re.ASCII | re.DOTALL (многострочное название после запятой, только цифры 0–9).
- M-3 (R-24): правило детектора ИНН не дополняет 9/11 цифр нулём; дополнение — только при извлечении
  (numbers.inn_digits) из колонки, выбранной по заголовку или по строгому правилу.
- T9.1: тесты R-21 (свёрнутый родитель на противоположной стороне; (0,0) при детях (X, X)).
- T1.1: хелперы фикстур пропускают скрытые файлы/каталоги и lock-файлы Excel (~$…).
- T12.3: golden-update не удаляет снимки части без исходного каталога (osv/synthetic или реальные файлы).

Golden-снимки не изменились (82/82).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 16:29:53 +04:00
Andrey Epifancev
e705d75520 feat(parser): контрольные суммы §1.4, статусы, OsvParser как парсер по умолчанию, лимиты
checks.py: тождество сальдо по каждой строке, суммы родителя = Σ детей того же data_type
(CURRENCY/QUANTITY исключены; обороты — по колонкам, сальдо — по колонкам или по нетто при
свёрнутом сальдо родителя), «Итого» = корневой счёт (R-13: нет корня — «Итого» пусто/0;
R-20: нет «Итого» — false и предупреждение).
osv.py: OsvParser — лимит размера, чтение по сигнатуре, листы по содержимому (формы ББ/ОФР и
прочие — пропуск с предупреждением), карта исходов D-6, кооперативный дедлайн, metrics
(rows без TOTAL, warnings с «sheet=<имя> hierarchy=<стратегия>» первой записью по листу).
get_parser(settings, rules_dir=…) → OsvParser (словари грузятся при создании: битый словарь —
падение старта); PARSE_MAX_BYTES / PARSE_TIMEOUT_SECONDS в Settings и .env.*; app.py передаёт
настройки. test_null_parser.py → test_parser_factory.py.
Тесты: юнит-карта статусов, «Испорченная сумма», «Пустая ОСВ», два листа ОСВ, новый синоним
без релиза кода (R-8); property-тест на 66 реальных файлах (все done, < 5 с, схема v1.1).
test_app и интеграционный round-trip ждут ошибку реального парсера вместо NOT_IMPLEMENTED.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 14:37:21 +04:00