openspec: архив osv-other-systems (#81)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Andrey Epifancev 2026-10-28 21:33:30 +04:00
parent 56af97cdb9
commit a1997f5d90
5 changed files with 72 additions and 5 deletions

View File

@ -9,11 +9,19 @@
### Requirement: Листы ОСВ находятся по содержимому
Парсер SHALL считать листом ОСВ любой лист, где ячейка в первых 30 строках листа (`SHEET_MARKER_ROWS`: шапка ведомости
всегда над таблицей) матчит признак ОСВ из `rules/osv_headers.yaml` (без учёта регистра, «ё/е», переносов строк и
дефисов). Лист с признаками формы ББ/ОФР или её продолжения уходит в конвейер форм (спека `statement-parsing`); прочие листы
SHALL пропускаться с предупреждением файла `SHEET_OTHER` (`severity = info`, `locator = sheet:<имя>`) в
`metrics.warnings`. Книга без единого листа ОСВ и без форм → `status = error`, `error.code = INVALID_DOCUMENT`
(«в книге нет листов ОСВ или форм»). Несколько листов ОСВ → несколько `documents` с `locator = sheet:<имя>`.
Имя листа MUST NOT использоваться для поиска.
дефисов). Признаки ОСВ — названия ведомости разных учётных систем («Оборотно-сальдовая ведомость», «Оборотная
ведомость», «ОСВ по сч.», «Оборотный баланс», «Фин. Обороты», «Отчет по Главной книге»). Лист с признаками формы ББ/ОФР
или её продолжения уходит в конвейер форм (спека `statement-parsing`). Лист, не опознанный ни как ОСВ по признаку, ни
как форма или её продолжение по признакам форм, SHALL считаться листом ОСВ по запасному признаку, если в первых
`SHEET_MARKER_ROWS` строках есть строка групп сумм со всеми тремя группами («начало», «обороты», «конец»), у каждой
группы найдены обе стороны — «Дебет» и «Кредит», и между колонками «Дебет» и «Кредит» группы в строках заголовка нет
других подписей; свёрнутое сальдо (одна колонка в группе) запасного признака не даёт. Запасной признак MUST
проверяться только после классификации форм и MUST NOT отнимать у конвейера форм лист формы, её продолжения или
расшифровки; слабое продолжение (лист из 1–2 кодов сразу после формы) признаком формы не считается — лист с полной
таблицей ОСВ после формы — ОСВ. Прочие листы SHALL пропускаться с предупреждением файла `SHEET_OTHER` (`severity = info`,
`locator = sheet:<имя>`) в `metrics.warnings`. Книга без единого листа ОСВ и без форм → `status = error`,
`error.code = INVALID_DOCUMENT` («в книге нет листов ОСВ или форм»). Несколько листов ОСВ → несколько `documents` с
`locator = sheet:<имя>`. Имя листа MUST NOT использоваться для поиска.
#### Scenario: Один лист — одна ОСВ (все реальные фикстуры)
- **WHEN** разбирается любой файл из `fixtures/osv/**`
@ -27,6 +35,38 @@ SHALL пропускаться с предупреждением файла `SHE
- **WHEN** разбирается книга с одним листом произвольной таблицы
- **THEN** `status = error`, `error.code = INVALID_DOCUMENT`, сообщение называет число просмотренных листов
#### Scenario: Название ведомости другой учётной системы
- **WHEN** разбирается синтетическая ОСВ, у которой в шапке вместо «Оборотно-сальдовая ведомость» стоит одно из
названий «Оборотная ведомость по счету 009», «ОСВ по сч. 41 за 3 кв.», «Оборотный баланс», «Фин. Обороты Листок»,
«Отчет по Главной книге»
- **THEN** лист разобран как ОСВ (`osvDocument`), `SHEET_OTHER` для него нет
#### Scenario: Лист без названия ведомости — по заголовку таблицы
- **WHEN** разбирается синтетический лист без названия ведомости, таблица начинается в первых строках с групп
«НачалоДт | НачалоКт | ОборотДт | ОборотКт | КонецДт | КонецКт» (Navision)
- **THEN** лист разобран как ОСВ по запасному признаку
#### Scenario: Расшифровка формы не становится ОСВ
- **WHEN** разбирается книга с формой ББ и листом расшифровки с колонками «Остаток на начало | Поступило | Выбыло |
Остаток на конец»
- **THEN** вид листа расшифровки тот же, что без запасного признака (форма или продолжение конвейера форм либо
`SHEET_OTHER`), документа ОСВ из него нет
#### Scenario: Лист ОСВ без названия после формы — не слабое продолжение
- **WHEN** разбирается книга: форма ББ, за ней лист Navision без названия ведомости с полным заголовком таблицы, за ним
посторонний лист
- **THEN** форма — свой документ, лист Navision — `osvDocument`, посторонний лист — `SHEET_OTHER`
#### Scenario: Отчёт «Обороты счета» не ОСВ
- **WHEN** лист без названия ведомости содержит все три группы со сторонами, но между «Оборот Дт» и «Оборот Кт» стоят
колонки корреспондирующих счетов
- **THEN** лист пропускается с `SHEET_OTHER`
#### Scenario: Неполная таблица не даёт запасного признака
- **WHEN** лист без названия ведомости содержит группы «обороты» и «конец», но без группы «начало» или со свёрнутым
сальдо (одна колонка в группе)
- **THEN** лист пропускается с `SHEET_OTHER`
### Requirement: Заголовок таблицы и колонки сумм определяются по тексту
Парсер SHALL найти блок заголовка таблицы: 1–4 подряд идущих строки, в которых (с учётом объединённых ячеек) встречаются
группы «сальдо на начало», «обороты за период», «сальдо на конец» по синонимам словаря, и под каждой группой подзаголовки
@ -651,3 +691,30 @@ design #14).
#### Scenario: Строки «Вал.»/«Кол.» в колонке текста не меняются
- **WHEN** разбираются s04, s30 и все реальные фикстуры `../fixtures/osv/**`
- **THEN** golden-снимки совпадают с прежними (родитель показателя — строка над ним, как и было)
### Requirement: Написания групп и сторон других учётных систем
Словари `groups`, `debit`, `credit` SHALL знать написания групп и сторон выгрузок SAP, Navision и других систем: «Остаток
на начало/конец (периода)», «Начальное/Конечное сальдо», «Сальдо начальное/конечное», «Сальдо вх/исх», «НачалоДт/Кт»,
«КонецДт/Кт». Сторона SHALL находиться и в отдельной ячейке под группой, и в самой ячейке группы после её названия — в
том числе в форме «по дебету»/«по кредиту» («Оборот по дебету») и приклеенной к названию без пробела («Сальдо
НачальноеДТВВ», «НачалоДт»). Сторона без границы слова SHALL искаться только в остатке ячейки группы после совпадения
группы. Итоговая строка «ВСЕГО» SHALL распознаваться как итог листа наравне с «Итого» и «ИТОГ».
#### Scenario: Остаток и оборот по дебету
- **WHEN** разбирается синтетическая ОСВ с группами «Остаток на начало периода | Оборот по дебету | Оборот по кредиту |
Остаток на конец периода» и подзаголовками «Дебет | Кредит» под остатками
- **THEN** найдены все шесть колонок сумм; обороты — из ячеек «Оборот по дебету» и «Оборот по кредиту»
#### Scenario: Сторона приклеена к названию
- **WHEN** разбирается синтетическая ОСВ с заголовком «Сальдо НачальноеДТВВ | Сальдо НачальноеКТВВ | Оборот ДТ | Оборот
КТ | Сальдо КонечноеДТВВ | Сальдо КонечноеКТВВ»
- **THEN** найдены все шесть колонок сумм с верными сторонами
#### Scenario: SAP «Сальдо вх/исх»
- **WHEN** разбирается синтетическая ОСВ с группами «Сальдо вх Дт | Сальдо вх Кт | Оборот Дт | Оборот Кт | Сальдо исх Дт
| Сальдо исх Кт»
- **THEN** найдены все шесть колонок сумм
#### Scenario: Итог «ВСЕГО»
- **WHEN** разбирается синтетическая ОСВ, итоговая строка которой подписана «ВСЕГО»
- **THEN** строка — `TOTAL`, предупреждения «строка «Итого» не найдена» нет