9 Commits

Author SHA1 Message Date
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
30f78c42e7 feat(osv): период-диапазон месяцев «Октябрь 2024 г. – Сентябрь 2025 г.» (скользящий, не с начала года)
Раньше первый месяц диапазона давал «2024 Q4, нарастающий». Теперь словарь periods.yaml (months, range)
разбирает диапазон: период режется по году конца, январь–конец квартала — нарастающий, ровно квартал — квартальный,
остальное (скользящие 12 месяцев) — год конца, квартал и is_cumulative = null + предупреждение «не с начала года».
Контракт v1.1 не менялся.

Refs #11

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
2026-10-06 12:49:11 +04:00
Andrey Epifancev
7738221b5a docs: README/CLAUDE.md Среза 2a, tasks.md, спека-дельты
- README: парсер по модулям, статусы и коды, словари и добавление синонима, лимиты, golden-процесс, настройки PARSE_*
- CLAUDE.md: раздел «Добавлено в Срезе 2a» (модули, правила расширения, линтер, R-21); api/rules/README.md: ключи словарей
- openspec: tasks.md (5.1), design.md (D-1…D-7, O-7/O-8), спека-дельты osv-parsing (R-12…R-22) и tabular-recognition-service («Результат по контракту»)
- tests: check_snapshot в golden_helpers + тесты «нет снимка»/«регрессия»; locator в property-тесте; пример needs_check синхронизирован с docs

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 15:53:11 +04:00
Andrey Epifancev
bc143ef140 test: golden-снимки, линтер координат, покрытие словарей; make golden-update
- golden_helpers, scripts/golden_update.py (--check), test_golden на 66 ОСВ и синтетике; make golden-update/golden-check/test-fixtures
- тест покрытия словарей (R-22): счётчик срабатываний Pattern; из osv_headers.yaml удалены неиспользуемые service_columns kpp/code/quantity/currency
- синтетика s14–s16 в генераторе и таблице ожиданий; skip вместо падения при отсутствии osv/synthetic (T11.1); комментарий R-21 в s07 (T11.2)
- линтер: предел адреса 10 вместо 4 (T3.1), обращение cell(3, 4) (T3.8); реальные файлы не фиксируют BU/RUB (T3.9)
- README: golden-процесс; отмечены Task 12 и пункты 4.2, 4.3

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 15:28:41 +04:00
Andrey Epifancev
83dd241a00 feat(parser): шапка ОСВ и схема группировок (§1.1, §1.5)
- header.py: parse_doc_header (организация, счёт, период, data_type, валюта, вариант шапки,
  предупреждения на русском) и build_group_schema (вариант 1 — метки в text_col, вариант 2 —
  «субконто: …»); has_inn по ячейке ИНН в строке метки (отдельной или в тексте метки)
- periods.yaml: end — конец текста периода («г.», «год»); PeriodRules.end
- линтер координат: Literal[1, 2] не считается индексацией ячейки
- fixtures-тест на 66 файлах: счёт по имени файла одним правилом без исключений

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 13:12:20 +04:00
Andrey Epifancev
a833945669 feat(parser): детекторы листов ОСВ, заголовка таблицы и колонок по содержимому
detect.py: classify_sheet (ОСВ / форма ББ-ОФР / прочее по словарю), find_table_header
(строка с ≥ 2 группами сумм, «Дебет/Кредит» под группой в пределах merged-диапазона
или до следующей группы, заголовок в 1–4 строки, в т.ч. «Нач. сальдо Дт» в одной
ячейке; без «начала»; свёрнутое сальдо в *_debit + collapsed; свёрнутые «Обороты» и
половинчатая пара Дт/Кт — InvalidFormatError с названием группы), text_col, inn_col
(заголовок «ИНН» или ≥ 80 % значений из 10/12 цифр), right_edge, extra_cols,
group_label_rows, first_data_row, is_header_repeat (две группы или копия строки блока).

Pattern.search_normalized — ячейка нормализуется один раз (T3.6). osv_groups: известные
группировки OTHER перечислены явно, чтобы строка-метка «Основные средства» в
неслитом заголовке была частью блока. Хелпер тестов gridbuilder (Sheet из «картинки»).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 12:54:11 +04:00
Andrey Epifancev
fcd609c633 feat(rules): словари ОСВ (заголовки, группировки, периоды, типы данных) и загрузчик
Словари api/rules/{osv_headers,osv_groups,periods,data_types}.yaml и src/parser/rules.py
(normalize_text, Pattern, load_rules, pydantic-валидация с RuntimeError по файлу и ключу,
currency_aliases по R-6). AST-линтер координат tests/unit/parser/test_no_coordinates.py
перенесён из Task 12 (R-7, правила R-4/R-5). Тест формулировок реальных ОСВ.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 12:28:46 +04:00
Andrey Epifancev
b7af0d1824 docs: README каталога api/rules (словари синонимов парсера)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 02:41:02 +04:00