From a1997f5d90e757a237412d3d82a9c36cac07ae15 Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Wed, 28 Oct 2026 21:33:30 +0400 Subject: [PATCH] =?UTF-8?q?openspec:=20=D0=B0=D1=80=D1=85=D0=B8=D0=B2=20os?= =?UTF-8?q?v-other-systems=20(#81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- .../.openspec.yaml | 0 .../2026-10-28-osv-other-systems}/design.md | 0 .../2026-10-28-osv-other-systems}/proposal.md | 0 .../specs/osv-parsing/spec.md | 0 openspec/specs/osv-parsing/spec.md | 77 +++++++++++++++++-- 5 files changed, 72 insertions(+), 5 deletions(-) rename openspec/changes/{osv-other-systems => archive/2026-10-28-osv-other-systems}/.openspec.yaml (100%) rename openspec/changes/{osv-other-systems => archive/2026-10-28-osv-other-systems}/design.md (100%) rename openspec/changes/{osv-other-systems => archive/2026-10-28-osv-other-systems}/proposal.md (100%) rename openspec/changes/{osv-other-systems => archive/2026-10-28-osv-other-systems}/specs/osv-parsing/spec.md (100%) diff --git a/openspec/changes/osv-other-systems/.openspec.yaml b/openspec/changes/archive/2026-10-28-osv-other-systems/.openspec.yaml similarity index 100% rename from openspec/changes/osv-other-systems/.openspec.yaml rename to openspec/changes/archive/2026-10-28-osv-other-systems/.openspec.yaml diff --git a/openspec/changes/osv-other-systems/design.md b/openspec/changes/archive/2026-10-28-osv-other-systems/design.md similarity index 100% rename from openspec/changes/osv-other-systems/design.md rename to openspec/changes/archive/2026-10-28-osv-other-systems/design.md diff --git a/openspec/changes/osv-other-systems/proposal.md b/openspec/changes/archive/2026-10-28-osv-other-systems/proposal.md similarity index 100% rename from openspec/changes/osv-other-systems/proposal.md rename to openspec/changes/archive/2026-10-28-osv-other-systems/proposal.md diff --git a/openspec/changes/osv-other-systems/specs/osv-parsing/spec.md b/openspec/changes/archive/2026-10-28-osv-other-systems/specs/osv-parsing/spec.md similarity index 100% rename from openspec/changes/osv-other-systems/specs/osv-parsing/spec.md rename to openspec/changes/archive/2026-10-28-osv-other-systems/specs/osv-parsing/spec.md diff --git a/openspec/specs/osv-parsing/spec.md b/openspec/specs/osv-parsing/spec.md index bfc1ce0..1f80982 100644 --- a/openspec/specs/osv-parsing/spec.md +++ b/openspec/specs/osv-parsing/spec.md @@ -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`, предупреждения «строка «Итого» не найдена» нет