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

4.6 KiB
Raw Blame History

rules/ — словари синонимов парсера

Словари rules/*.yaml, по которым tabular-parser ищет структуру файла по содержимому: заголовки колонок, группировки, периоды, типы данных. Словари — данные, а не код: новый синоним добавляется строкой в YAML без правки парсера. Парсер не привязан к координатам (буквы колонок, номера строк, имена листов); это проверяет AST-линтер tests/unit/parser/test_no_coordinates.py.

Путь указан относительно api/ (рабочего каталога команд сервиса): api/rules/. Загрузчик — src/parser/rules.py (load_rules()), источник содержимого — docs/context/05-domain-rules.md §1.0–§1.5.

Файл Что описывает
osv_headers.yaml маркер листа ОСВ и листов форм ББ/ОФР; группы сумм (начало / обороты / конец); «Дебет»/«Кредит»; служебные колонки (ИНН, КПП, код, количество, валюта); строка «Итого»; метки шапки (счёт, период, выводимые данные, валюта, параметры, субконто)
osv_groups.yaml название группировки из шапки -> ACCOUNT / DEPARTMENT / COUNTERPARTY / CONTRACT / OTHER (default — для всего прочего)
periods.yaml текст периода -> period_quarter и is_cumulative (§1.5); year — паттерн года, end — конец текста периода в строке шапки («г.», «год»)
data_types.yaml «Выводимые данные» -> BU / NU / SUM; строки «Вал.» / «Кол.»; коды валют ISO 4217; синонимы валюты (руб. -> RUB)

Как писать паттерны

  • Паттерн — регулярное выражение Python. Он ищется (search) в нормализованном тексте ячейки и применяется без учёта регистра.
  • Нормализация текста (normalize_text): нижний регистр, «ё» -> «е», дефисы, тире, неразрывные пробелы и переносы строк -> один пробел, пробелы схлопываются. Пример: Оборотно-сальдовая\nведомость -> оборотно сальдовая ведомость.
  • Поэтому в паттернах нет «ё», дефисов, тире и диапазонов [а-я]: пишите оборотно\s*сальдовая, д т (для «Д-т»), \w вместо диапазона. Загрузчик отвергает такой паттерн с указанием файла и ключа.
  • Порядок записей в списках mapping, rules (периоды), header, row — приоритет: побеждает первое совпадение, от специфичных правил к общим.
  • В osv_groups.yaml известные группировки OTHER («Основные средства», «Номенклатура», «Статьи затрат», …) перечислены в mapping явно, хотя default и так даёт OTHER: детектор заголовка таблицы (src/parser/detect.py) считает строку под «Дебет/Кредит» частью блока заголовка, только если её текст совпал с записью mapping, с ИНН или с «субконто». Новая группировка в отдельной строке заголовка = новая строка в mapping.
  • Ошибка в словаре (нет обязательного ключа, неизвестный ключ, неверный регэксп или тип) — RuntimeError при загрузке с именем файла и ключом.

Что намеренно не в штатном словаре

Синоним «нач. остаток» / «начальный остаток» для группы opening не включён: он нужен, чтобы показать, что новый формат подключается строкой в YAML (тест сценария «Новый синоним»).