osv/synthetic — синтетические ОСВ
Синтетика для форматов шапки, иерархии и колонок, которых нет в реальных файлах osv/{rb,schastl}/. Данных реальных
организаций здесь нет: организация «ООО "Тестовая организация"», контрагенты «ООО Альфа», «ООО Бета» и т. п., ИНН
вымышленные. Файлы — вход парсера ОСВ (tabular-parser), а не эталон: ожидания по каждому файлу выведены из спеки
(openspec/changes/slice-2a-osv-parser/specs/osv-parsing/spec.md) и лежат в тесте
tabular-parser/api/tests/synthetic/test_synthetic_files.py.
Суммы согласованы арифметически (сальдо на конец = начало + обороты, родитель = сумма детей по колонкам), поэтому все
файлы, кроме s10, сходятся по контрольным суммам §1.4 и дают статус done.
Генерация
Файлы собирает детерминированный генератор (openpyxl + минимальный писатель BIFF12 для xlsb); повторный запуск даёт те же байты (метки времени книги и zip зафиксированы):
cd tabular-parser/api
.venv/bin/python -m tests.synthetic.generate ../../fixtures/osv/synthetic
Правка набора — в tabular-parser/api/tests/synthetic/generate.py, затем перегенерация и коммит файлов здесь.
Набор
| Файл | Что проверяет | Ожидание |
|---|---|---|
s01_variant2_header.xlsx |
шапка варианта 2: «Период: …», «Детализация по субсчетам, субконто: Контрагенты, Договоры», заголовок «Субконто»; данные «Сумма» | header_variant=2, group_schema=[ACCOUNT, COUNTERPARTY, CONTRACT], Q1/2026, data_type=SUM, hierarchy=outline |
s02_no_outline_indent.xlsx |
уровни только отступами ячеек (без outline level); Валюта БУ, НУ: руб.; период «2 квартал 2025 г.» |
hierarchy=indent, дерево 0/1/2 |
s03_no_outline_no_indent.xlsx |
ни outline, ни отступов: уровни по кодам счетов и жирности; период «I кв. 2025 г.» (римский квартал) | hierarchy=account_pattern, дерево как у s02 |
s04_currency_quantity_rows.xlsx |
под контрагентом строки «USD», «Кол.» (и «Вал.» у другого) | data_type CURRENCY/QUANTITY, в проверку суммы детей не входят, done |
s05_text_numbers.xlsx |
суммы текстом: «1 234 567,89», «(1 234,00)», «—»; неразрывные и узкие пробелы, прочерки «–», «-»; период «полугодие 2025 г.» | 1234567.89, -1234.00, null |
s06_two_osv_and_other_sheet.xlsx |
листы «ОСВ 60», «Справка», «ОСВ 62» | два документа в порядке листов, предупреждение о пропуске «Справка» |
s07_no_opening_collapsed_closing.xlsx |
нет группы «Сальдо на начало»; сальдо на конец — одна колонка со знаком; период «9 месяцев 2025 г.» | opening_* = null, отрицательное сальдо — в closing_credit, предупреждение о свёрнутом сальдо |
s08_extra_kpp_column.xlsx |
колонка «КПП» между «ИНН» и суммами; период «с 01.01.2025 по 31.03.2025» | extra["КПП"] у контрагентов, суммы не сдвинуты |
s09_subaccount_names.xlsx |
«60.01, Расчеты с поставщиками и подрядчиками», буквенный субсчёт «60.АВ, …» | ACCOUNT, account_code_raw без названия, row_value — исходный текст |
s10_broken_sum.xlsx |
у «ООО Бета» closing_debit увеличен на 1 |
needs_check, нарушение тождества — строка контрагента, суммы родителя — строка «60.01» |
s11_header_repeat.xlsx |
заголовок таблицы повторяется внутри данных (печать по страницам); период «12 месяцев 2025 г.» | строки заголовка пропущены, дерево и суммы не нарушены |
s12_statement_and_osv.xlsx |
лист ББ («Бухгалтерский баланс», 0710001) и лист «ОСВ 60»; данные «НУ», период «январь - сентябрь 2025 г.» | один документ, предупреждение «skipped: statement» |
s13_no_outline_indent.xlsb |
та же ведомость, что s02, в формате xlsb; отступ — ведущими пробелами текста |
результат равен s02 кроме предупреждения «xlsb: outline level недоступен» |
s14_statement_forms.xlsx |
три листа форм, каждый опознаётся одним признаком: «Форма по ОКУД 0710001», «Отчет о финансовых результатах», «Форма по ОКУД 0710002»; лист «ОСВ 60» | один документ, три предупреждения «skipped: statement» |
s15_group_title_synonyms.xlsx |
названия групп сумм: лист «ОСВ 60» — «Входящее сальдо»/«Конечное сальдо», лист «ОСВ 62» — «Начальное сальдо»/«Исходящее сальдо» | два документа, все шесть колонок сумм найдены, done |
s16_header_synonyms.xlsx |
лист «ОСВ 60»: нет названия организации, период «2024», валюта «RUB (код 643)», «Счет» и «Контрагенты» отдельными строками под «Дебет/Кредит»; лист «ОСВ 62» (вариант 2): «Детализация по субсчетам: Номенклатура, Статьи затрат, Нематериальные активы, Валюта» | organization_name="" + предупреждение, Q4/2024, currency=RUB, схема листа 62 — ACCOUNT + четыре OTHER |
s17_inn_in_name.xlsx |
колонки ИНН нет, ИНН записан в текст названия контрагента: «ООО Альфа, 7701234567», «ООО Бета (ИНН 7707654321)», «ООО Гамма ИНН: 5001234567», «ИП Сидоров 500100732259» (OQ-100) | counterparty_inn — цифры, counterparty_name — без ИНН и разделителя, row_value не меняется; физлицо без ИНН — null; done |
s18_inn_row_above.xlsx |
у «ООО Альфа» и «ООО Гамма» ИНН с верной контрольной суммой (7701234560, 5001234561) стоит отдельной строкой над названием (без сумм, тот же уровень), колонки ИНН нет (OQ-130); без подсказки в шапке строка с неверной контрольной суммой не склеивается (#35) |
строка с ИНН в rows не попадает и не уходит в OTHER; ИНН — у контрагента, предупреждение «строка N: ИНН … отнесён к контрагенту в строке M»; done |
s19_inn_kpp_cell.xlsx |
колонка «ИНН/КПП»: в ячейках склеенное «7701234567/770101001» (OQ-100) | counterparty_inn — только ИНН; колонка распознана как колонка ИНН; done |
s20_inn_above_sibling_blank.xlsx |
ИНН строкой над наименованием, сосед того же уровня, без сумм (#35) | ИНН — у своего контрагента, строк ИНН в rows нет, done |
s21_inn_above_sibling_sums.xlsx |
ИНН строкой над наименованием, сосед, с теми же суммами | то же; пара — по равенству сумм |
s22_inn_above_parent_blank.xlsx |
строка ИНН — родитель наименования (уровень выше), без сумм | наименование поднимается на её место, ИНН — ему, done |
s23_inn_above_parent_sums.xlsx |
строка ИНН — родитель наименования, с суммами | то же |
s24_inn_below_child_blank.xlsx |
строка ИНН — ребёнок наименования (уровень ниже), без сумм | ИНН — родителю, строка из rows уходит, done |
s25_inn_below_child_sums.xlsx |
строка ИНН — ребёнок наименования, с суммами (как «Контрагенты.ИНН» в 1С, но без подсказки в шапке) | то же |
s26_inn_below_sibling_sums.xlsx |
ИНН строкой под наименованием, сосед, с суммами | ИНН — своему контрагенту, done |
s27_inn_below_sibling_blank.xlsx |
ИНН строкой под наименованием, сосед, без сумм (дефект main: ИНН уходил следующему контрагенту) | ИНН — своему контрагенту; направление — по блоку 60.02, кончающемуся строкой ИНН; done |
s28_inn_bad_checksum.xlsx |
раскладка s20 («над, не в дереве, без сумм»), но у ООО Альфа строка ИНН 7701234567 с неверной контрольной суммой (#35) |
строка остаётся обычной, у Альфы ИНН нет, предупреждение «похожа на ИНН … контрольная сумма не сходится», needs_check; остальные контрагенты — со своими ИНН (направление «над» — по блоку 60.02) |
s29_xls_no_codepage.xls |
xls BIFF5 без записи CODEPAGE, строки в cp1251 (собран tests/synthetic/xls_writer.py); отступ — ведущими пробелами (AURORA-1662) |
кириллица читается как cp1251, предупреждение «xls без кодовой страницы — строки прочитаны как cp1251», done |
s30_val_kol_vo_materials.xlsx |
счёт 10 (вариант 2, номенклатура): материал «Вал» без точки, под материалами строки «Кол-во» (AURORA-1663) | «Вал» — обычная строка (data_type шапки, OTHER), «Кол-во» — QUANTITY, done |
s31_rows_below_total.xlsx |
под «Итого» дописаны «Ответственный:», блок «ООО Альфа (ГК)» с числами и строка «Итого по ГК» (AURORA-1664) | таблица кончается на первой «Итого», хвост вне документа, предупреждение «ниже таблицы … есть числа», done |
s32_total_with_suffix.xlsx |
итоговая строка подписана «Итого по счету 60», точного «Итого» нет (I-1: правило total_row — запасное после total_row_exact) |
TOTAL — последняя строка, done |
s40_flat_header_account.xlsx |
плоская форма 1С (#59, AURORA-1661): «по счету: 76.Н.1» с двоеточием, вид аналитики «Контрагенты» строкой между названием и периодом, организация ниже периода; строк-счетов нет, без outline и отступов; «Итого развернутое» перед «Итого» | account_code_raw=76.Н.1, hierarchy=header_account, строки COUNTERPARTY, «Итого развернутое» и «Итого» — TOTAL, done |
s41_flat_chart_of_accounts.xlsx |
плоская форма: вид аналитики «Организации», период «за 2 Квартал 2026 г. План счетов ООО Хреновская Нива» одной строкой, «Итого развернутое» перед «Итого» | организация из хвоста «План счетов», account_code_raw=60, Q2/2026, hierarchy=header_account, строки COUNTERPARTY без предупреждения о виде субконто, done |
s42_subaccounts_totals_reversed.xlsx |
под счётом 76 в шапке идут строки-субсчета «76.2», «76.5», «76.Н», «76.Н.1» (корня «76» нет), «Итого развернутое» перед «Итого» | account_code_raw=76, «Итого развернутое» — TOTAL, сверка по основной «Итого», done |
s43_subkonto_unnamed_60.xlsx |
счёт 60: корень «60.01» и два элемента аналитики с отступом, вид субконто в шапке не назван; «Итого» перед «Итого развернутое» | hierarchy=indent, подстроки — COUNTERPARTY по плану счетов с предупреждением OSV_ROWS, done |
s44_subkonto_unnamed_10.xlsx |
то же, что s43, но счёт 10 (материалы «Мука пшеничная», «Сахар-песок») |
счёт 10 не расчётный: подстроки остаются OTHER без имени, предупреждения нет, done |
s45_account_label_value_cells.xlsx |
выгрузка 1С «ОСВ по счёту 60 по контрагентам» (tabular-parser#71, AURORA-1714): слов «по счету» нет, счёт — «Счет Поставщика» | «60*» в соседних ячейках, «Счет Клиента» без значения; в первой колонке голые числовые коды 441, 431, 199; период «За период» | «01.01.25..30.06.25» | account_code_raw=60, 2025 Q2 нарастающий, голые коды не счета, строки COUNTERPARTY, done |
s46_counterparty_code_blocks.xlsx |
та же выгрузка целиком: вид субконто «Поставщики» в колонке суммы первой строки данных; блоки субсчетов 60.111, 60.112 (сумм в строке нет); в блоке — код контрагента с суммами, строка названия без сумм, договоры (в том числе «441»); «ИТОГ по 60.111» с суммами блока; в конце «ИТОГ» | hierarchy=code_blocks, субсчета ACCOUNT с суммами из «ИТОГ по …», коды — COUNTERPARTY с названием, договоры — CONTRACT, строки «ИТОГ по …», названий и «Поставщики» в rows нет, «ИТОГ» — TOTAL, done |
s47_indent_hierarchy_code_sums.xlsx |
три листа «Субконто» без вида аналитики в шапке, иерархия по отступам (AURORA-1858, tabular-parser#78): «68 сч.» — подуровень 68.01.1 на том же отступе, что 68.01; «90 сч.» — безымянная строка закрытия сразу за счётом 90.09 (пустая ячейка отступа не хранится); «91 сч.» — аналитика на одном отступе, вложенность видна только по суммам (100 = 60 + 40, 30 = 20 + 10, 40 ⊃ 40) |
hierarchy=indent, 68.01.1 — ребёнок 68.01, строка закрытия — ребёнок 90.09/91.09, аналитика 91 вложена по суммам, три листа done |
s17–s19 — регрессия извлечения ИНН из текста (issue #9). s14–s16 добавлены тестом покрытия словарей tabular-parser (rules/*.yaml, решение R-22): каждая запись словаря
должна сработать на реальных или синтетических файлах; эти файлы закрывают записи, которых нет в реальных ОСВ.
s29–s32 — tabular-parser#47 (кодировка xls без CODEPAGE, «Вал»/«Кол-во», строки ниже «Итого», итог «Итого по счету»).
s20–s27 — восемь раскладок строки ИНН рядом с контрагентом (issue tabular-parser#35); ИНН с верной контрольной суммой — без подсказки в шапке другие не склеиваются.
О файле xlsb
s13_no_outline_indent.xlsb собран не Excel и не LibreOffice (их на машине разработки нет), а минимальным
писателем BIFF12 tabular-parser/api/tests/synthetic/xlsb_writer.py: он пишет только то, что читает pyxlsb
(workbook, таблица общих строк, лист; без стилей и объединений). Файл читается pyxlsb и парсером, но совместимость с
Excel не проверялась и этот файл не доказывает чтение xlsb, сохранённого Excel (другая раскладка записей, стили,
BrtCellSt и т. д.). Когда появится возможность — заменить s13 настоящим: открыть s02_no_outline_indent.xlsx в
Excel или LibreOffice, «Сохранить как» → Книга Excel двоичная (.xlsb), имя s13_no_outline_indent.xlsb; в xlsb нет
outline level и форматирования ячеек, отступ нужно продублировать ведущими пробелами в колонке текста до сохранения.