docs(2b): 06-test-data (подраздел 4б, синтетика st01–st06, golden форм), 03-architecture (BookParser, контракт v1.2), 09-delivery-plan (Срез 2b)
Refs #26 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
This commit is contained in:
parent
4272ba8061
commit
00d171564e
@ -27,8 +27,12 @@
|
||||
- **arm-core** — монолитное ядро: справочники, файлы/документы, маппинг результатов распознавания, консолидация
|
||||
(вычисления), согласование, ЕХ, аудит, права. Один Alembic, одна схема.
|
||||
- **tabular-parser** — читает файл из S3 `uploads/`, находит на листах ОСВ (§1) и формы ББ/ОФР (§12) **по содержимому**,
|
||||
пишет нормализованный JSON в S3 `results/`, публикует `recognition.result`. Контракт результата —
|
||||
`docs/contracts/recognition-result.schema.json` (контракт v1.0). Правила распознавания
|
||||
пишет нормализованный JSON в S3 `results/`, публикует `recognition.result`. Внутри — `BookParser` (оркестратор книги:
|
||||
лимиты, чтение, дедлайн, вид каждого листа): листы ОСВ идут в конвейер `osv.py`, листы форм — в конвейер форм
|
||||
`statements/` (блоки форм, колонки, шапка, строки, соотношения §7, склейка продолжений); документы результата — сначала
|
||||
ОСВ, затем формы. Контракт результата —
|
||||
`docs/contracts/recognition-result.schema.json` (контракт v1.2: `DISCLOSURE` в `document_type`, `statementDocument.checks`,
|
||||
границы периода ОСВ `period_start/period_end/is_from_year_start`). Правила распознавания
|
||||
заголовков/группировок — `rules/*.yaml`.
|
||||
- **scan-gateway** — адаптер ИС Сканирование: переименовать файл `UUID_имя.pdf`, положить в «Входящие», опросить
|
||||
«Исходящие/UUID/UUID.json», сохранить сырой ответ в S3 `raw/{job_id}.json` (в БД не регистрируется), нормализовать
|
||||
@ -82,7 +86,7 @@
|
||||
работе или обработанного, он не публикуется (его `Nats-Msg-Id` совпал бы с настоящим результатом). Нечитаемый запрос
|
||||
(не JSON, нет `job_id`) остаётся без ответа: сервис пишет лог и отбрасывает его, ядро не получает ack, повторяет
|
||||
публикацию `OUTBOX_MAX_REPUBLISH` раз и закрывает задание в `dlq` с `error_code = NO_ACK`. Новый MINOR раскатывается сначала на потребителей
|
||||
(ядро и сервисы обновляют копии схем раньше, чем производитель начнёт слать 1.1), потому что закрытые enum отвергают
|
||||
(ядро и сервисы обновляют копии схем раньше, чем производитель начнёт слать новый MINOR, например 1.2), потому что закрытые enum отвергают
|
||||
незнакомые значения.
|
||||
- Сервисы не знают про БД и про бизнес-смысл: они возвращают структуру файла; нормализация счетов, резолв
|
||||
контрагентов, проверки — в ядре.
|
||||
|
||||
@ -139,7 +139,7 @@ JSON `aep_*.json` — реальные ответы Content AI: структур
|
||||
|---|---|---|
|
||||
| ОСВ шести организаций (29 файлов, 34 МБ) | `osv-dkb/<org>/<период>/` | АО «Цимлянский» (7 ОСВ за 9 мес. 2025), ООО «Новороссийский Кислородный завод» (2 книги по 3 листа), ООО «Новоросметалл» (2 книги по 3 листа + ОСВ 63; вариант 2, «сумма»), ООО «Новороссийский прокатный завод» (2 книги; одна за окт. 2024 – сент. 2025), ООО «Приманыческий» (7 ОСВ), АО фирма «Агрокомплекс» им. Ткачева (4 ОСВ по 50 тыс. строк, 9–14 МБ) |
|
||||
| «Анализ счета» (3 книги) | `analysis-reports/<org>/2025-Q3/` | отчёт 1С по корреспонденции счетов с отбором по контрагентам группы; не ОСВ, парсер отвечает `INVALID_DOCUMENT` |
|
||||
| ББ/ОФР в Excel (15 файлов) | `statements-xlsx/<org>/<период>/` | АО «Унагранде Ко» и «Унагранде Групп» (постраничные xls из 1С, 2024 г. и 9 мес. 2025), ООО НПЗ (одна книга ФСБУ 4/2023 с подстроками «в том числе»), ООО «Агрофирма Межениновская» (TDSheet, 66н); `templates/` — пустые формы 66н и ФСБУ 4/2023 |
|
||||
| ББ/ОФР в Excel (18 файлов: 14 форм и 4 шаблона) | `statements-xlsx/<org>/<период>/` | АО «Унагранде Ко» и «Унагранде Групп» (постраничные xls из 1С, 2024 г. и 9 мес. 2025), ООО НПЗ (одна книга ФСБУ 4/2023 с подстроками «в том числе»), ООО «Агрофирма Межениновская» (TDSheet, 66н); `templates/` — пустые формы 66н и ФСБУ 4/2023 |
|
||||
| План счетов 1С заказчика | `directories/chart-of-accounts-1c.xlsx` | 488 строк: код, наименование, субконто 1–3, вид; в seed 122 кода, все есть в выгрузке; 366 кодов выгрузки в seed нет (OQ-113, arm-core#23) |
|
||||
|
||||
`osv-dkb/` намеренно вне `osv/`: fixtures-тесты парсера и ядра требуют один лист `Лист_1`, `done`, период = каталогу и
|
||||
@ -149,6 +149,40 @@ golden-снимок на каждый файл, а здесь многолист
|
||||
«Итого развернутое», листы с именем кода счёта, нет валюты в шапке, объём) — `fixtures/osv-dkb/README.md`,
|
||||
arm-tabular-parser#11, OQ-131…OQ-135. ИНН организаций в шапках ОСВ нет (OQ-136).
|
||||
|
||||
## 4б. Формы ББ/ОФР в Excel: манифест, golden, синтетика (Срез 2b)
|
||||
|
||||
**Раскладки реальных файлов** (`fixtures/statements-xlsx/`, README там же; 18 файлов: 14 форм и 4 шаблона):
|
||||
|
||||
| Раскладка | Где | Особенности |
|
||||
|---|---|---|
|
||||
| 1С-xls постранично | `unagrande-co/2024-FY/`, `unagrande-group/{2024-FY,2025-Q3}/` | один файл = одна страница формы; на странице 1 титул (организация, ИНН, ОКПО, единица «в тыс. рублей», ОКЕИ, аудитор со **своим** ИНН), на странице 2 только «Форма 0710001 с.2»; пятизначные подстроки (11101…), значения в рублях с копейками при «тыс. руб.»; страниц 1 ББ в пакете нет (только актив) и ОФР Групп 2024 — только стр. 2 |
|
||||
| Многолистовая xlsx ФСБУ 4/2023 | `npz/2025-Q3/` | ББ на 5 листах, ОФР на 3; заголовок формы после титула; листы 2–5 без заголовка и маркера; строка 1105 «Гудвил», подстроки 12301…, строка без кода с суммами; лист ОФР с одной строкой 2400 (OQ-142) |
|
||||
| `TDSheet` 66н | `mezheninovskaya/2025-Q3/` | вся форма на одном листе, дата тройкой «30 \| 9 \| 2025» числами, двухстрочные заголовки, строка нумерации колонок, значения — тысячи с дробной частью |
|
||||
| Шаблоны | `templates/` | 66н и ФСБУ 4/2023: коды есть, сумм и шапки нет; заголовок на две строки; в шаблоне ФСБУ «АКТИВ» и код 1110 в одной строке (OQ-141) |
|
||||
|
||||
**Манифест** `tabular-parser/api/tests/statements_manifest.yaml`: для каждого из 18 файлов — организация, ИНН, документы по
|
||||
порядку (`type`, `status`, `complete`, причина `needs_check`, `failed_relations`). Статусы сверены прогоном: `done` только
|
||||
у Межениновской (ББ и ОФР); остальные — `needs_check` по данным файла (рубли с копейками при шапке «тыс. руб.», только
|
||||
актив, страница 2 без шапки, шаблон без сумм), НПЗ — `1600 = 1700` расходится на 1.94 / 9.02 / 2.48 руб. (OQ-137).
|
||||
Таблица «файл → статус» — README `tabular-parser`, «Парсер форм».
|
||||
|
||||
**Golden** `fixtures/golden/expected_statement_parse/<тот же путь без расширения>.json` — 24 снимка (18 реальных файлов +
|
||||
6 синтетических); регрессия, не оракул; обновление — `make golden-update` (один для ОСВ и форм), просмотр diff, отдельный
|
||||
коммит в `fixtures`. Оракулы корректности — манифест и property-тест `tests/fixtures/test_statements_property.py` (манифест покрывает
|
||||
каждый файл; тип, статус и видимая причина `needs_check` каждого документа совпадают с ожиданиями).
|
||||
|
||||
**Синтетика** `fixtures/statements-xlsx/synthetic/st01…st06` (генератор `tabular-parser/api/tests/synthetic/generate_statements.py`,
|
||||
ожидания — `tests/synthetic/test_statement_synthetic_files.py`, описание — README каталога):
|
||||
|
||||
| Файл | Что проверяет |
|
||||
|---|---|
|
||||
| `st01_both_forms_one_sheet` | ББ и ОФР на одном листе, два документа с одним `locator` (§12 п. 1) |
|
||||
| `st02_csv_like` | csv-подобный лист: двухстрочный заголовок, коды без подписи «Код», отрицательное значение, единиц нет |
|
||||
| `st03_no_codes` | форма без колонки кодов → `needs_check`, «колонка кодов не найдена» (OQ-138) |
|
||||
| `st04_mixed_book` | книга: лист ОСВ + лист баланса, порядок документов ОСВ → форма |
|
||||
| `st05_continuation_only` | одинокая страница 2 → `needs_check`, предупреждение о продолжении (OQ-139) |
|
||||
| `st06_header_variants` | варианты, которых нет в реальных файлах: старое название ОФР, расшифровки/ОДДС/ОИК, форма только с ОКУД 0710xxx, организация в «», «Адрес», «Пояснения», числовая дата (покрытие словарей `statement_*.yaml`) |
|
||||
|
||||
## 5. Прочее
|
||||
|
||||
- `Форма расшифровки к отчетности 01 10 24 / 01 04 25 / 01 07 25.xlsx` — расшифровки АО РБ (кредиты и займы, дебиторы и
|
||||
@ -224,8 +258,8 @@ fixtures/
|
||||
## 7. Синтетика, golden-снимки и xlsb парсера ОСВ (Срез 2a)
|
||||
|
||||
Реальные файлы покрывают один вариант шапки и один формат файла (xls/xlsx из 1С 8.3). Остальное — синтетика
|
||||
`fixtures/osv/synthetic/` (вымышленные организации и ИНН; суммы согласованы арифметически, поэтому все файлы, кроме
|
||||
`s10`, дают `done`). Файлы собирает детерминированный генератор `tabular-parser/api/tests/synthetic/generate.py`
|
||||
`fixtures/osv/synthetic/` (вымышленные организации и ИНН; суммы согласованы арифметически, поэтому листы ОСВ, кроме
|
||||
`s10`, дают `done`; книги `s12`/`s14` с формами — `needs_check` по формам). Файлы собирает детерминированный генератор `tabular-parser/api/tests/synthetic/generate.py`
|
||||
(повторный запуск даёт те же байты), ожидания по каждому файлу — в `tests/synthetic/test_synthetic_files.py`, описание —
|
||||
в `fixtures/osv/synthetic/README.md`.
|
||||
|
||||
@ -242,13 +276,14 @@ fixtures/
|
||||
| `s09_subaccount_names` | названия субсчетов в строке счёта, буквенный субсчёт |
|
||||
| `s10_broken_sum` | испорченная сумма → `needs_check` с номерами строк |
|
||||
| `s11_header_repeat` | заголовок таблицы повторяется внутри данных (печать по страницам) |
|
||||
| `s12_statement_and_osv` | лист ББ и лист ОСВ в одной книге: форма пропускается с предупреждением |
|
||||
| `s12_statement_and_osv` | лист ББ и лист ОСВ в одной книге: с Среза 2b — два документа (ОСВ, затем ББ без колонки кодов → `needs_check`) |
|
||||
| `s13_no_outline_indent` (`.xlsb`) | та же ведомость, что `s02`, в xlsb |
|
||||
| `s14_statement_forms` | три формы ББ/ОФР, каждая опознаётся своим признаком |
|
||||
| `s14_statement_forms` | три формы ББ/ОФР, каждая опознаётся своим признаком (с 2b — документы `BALANCE`/`INCOME` без колонки кодов, `needs_check`) |
|
||||
| `s15_group_title_synonyms` | названия групп сумм «Входящее/Начальное/Конечное/Исходящее сальдо» |
|
||||
| `s16_header_synonyms` | шапка без организации, период «2024», группировки `OTHER`, «Детализация: …» |
|
||||
|
||||
`s14`–`s16` добавлены тестом покрытия словарей: каждая запись `rules/*.yaml` обязана сработать на реальных или
|
||||
`s17`–`s19` — извлечение ИНН (из текста названия, из строки над названием, «ИНН/КПП» в одной ячейке; OQ-100, OQ-130).
|
||||
Формы ББ/ОФР из Excel — подраздел 4б. `s14`–`s16` добавлены тестом покрытия словарей: каждая запись `rules/*.yaml` обязана сработать на реальных или
|
||||
синтетических файлах.
|
||||
|
||||
**xlsb рукописный.** `s13` собран **не Excel и не LibreOffice** (их нет на машине разработки), а минимальным писателем
|
||||
@ -257,7 +292,7 @@ BIFF12 `tabular-parser/api/tests/synthetic/xlsb_writer.py`: он пишет то
|
||||
файл из Excel (OQ-102). Инструкция замены — в README `fixtures/osv/synthetic/`.
|
||||
|
||||
**Golden-снимки.** Для каждого файла `fixtures/osv/**` (включая синтетику) в `fixtures/golden/expected_osv_parse/` лежит
|
||||
результат разбора (88 файлов = 72 реальных + 16 синтетических): файл результата контракта v1.1 без `job_id`, `file_id`,
|
||||
результат разбора (113 файлов, из них 19 синтетических `s01`–`s19`): файл результата контракта v1.2 (v1.1 — до Среза 2b) без `job_id`, `file_id`,
|
||||
`service.version`, `metrics.duration_ms`. Снимок — **регрессия, не оракул**: он фиксирует, что парсер выдаёт сейчас.
|
||||
Обновление — только `make golden-update` в `tabular-parser` с просмотром diff и отдельным коммитом в `fixtures`;
|
||||
`make golden-check` (код возврата 1 при расхождении) — без записи. Оракулы корректности — property-тест
|
||||
|
||||
@ -104,15 +104,26 @@ Change'и: `tabular-parser/openspec/changes/slice-2a-osv-parser` (issue arm-tabu
|
||||
- **Документы:** `05-domain-rules.md` §1 приведён к факту (§1.6 — результат парсера), `06-test-data.md` §7 (синтетика,
|
||||
golden, рукописный xlsb), OQ-98…OQ-105 открыты (финальное ревью добавило OQ-106…OQ-109), OQ-81 частично закрыт (в `tabular-parser` `ARM_KA_FIXTURES` поддержан; `scan-gateway` — follow-up).
|
||||
- **Не сделано / риски:** xlsb проверен только рукописным синтетическим файлом (OQ-102); ИНН из текста строки не
|
||||
извлекается (OQ-100); счета с буквой в первом сегменте не распознаются (OQ-103).
|
||||
извлекался (OQ-100; реализовано позже в tabular-parser PR #15); счета с буквой в первом сегменте не распознаются (OQ-103).
|
||||
|
||||
### Срез 2b — ББ/ОФР из Excel (`tabular-parser`)
|
||||
### Срез 2b — ББ/ОФР из Excel (`tabular-parser`) — реализован, ожидает ревью и merge
|
||||
|
||||
- `tabular-parser`: ББ/ОФР из Excel по §12 в тот же `statementDocument`; поиск листов с формами по содержимому
|
||||
(в 2a такие листы пропускаются с предупреждением `skipped: statement (slice 2b)`); словари синонимов `rules/*.yaml`;
|
||||
контрольные формулы §7 для форм.
|
||||
- Тесты: property-тесты инвариантов на **всех** файлах `fixtures/statements-xlsx/**` (формулы §7) + синтетика (ББ+ОФР на
|
||||
одном листе, csv-подобный лист); снимки результата — рядом с golden ОСВ.
|
||||
- **Реализовано (ветка `feat/14-slice-2b-statement-parser`, tabular-parser PR #16; docs — PR #27, ветка
|
||||
`feat/26-slice-2b-statement-parser`):** `BookParser` + конвейер форм `statements/`, словари `statement_*.yaml`, контракт
|
||||
v1.2 (`DISCLOSURE`, `checks`, границы периода ОСВ; копии схемы в arm-core PR #27 и scan-gateway PR #5), `§12`/`§7` по
|
||||
решениям владельца. Тесты: манифест `api/tests/statements_manifest.yaml` (18 реальных файлов), синтетика `st01`–`st06`,
|
||||
golden `expected_statement_parse/` (18 + 6 снимков), интеграционный тест воркера на книге НПЗ.
|
||||
- **Объём:** парсер + контракт v1.2; **маппинг форм в ядре (`statementDocument → document + financial_statement_*`) —
|
||||
Срез 3**. По факту `done` только у форм Межениновской; остальные `needs_check` по данным файлов (рубли с копейками при
|
||||
«тыс. руб.», страницы без шапки, шаблоны) — OQ-137, OQ-139.
|
||||
- **Не сделано / риски:** единицы не нормализуются (OQ-137); форма без колонки кодов не разбирается (OQ-138); страницы
|
||||
в разных файлах не склеиваются (OQ-139); строки без кода не хранятся (OQ-140); лист ОФР НПЗ с единственной строкой 2400
|
||||
теряется (OQ-142); после контракта v1.2 `docs/contracts/**` заморожены (копии схемы в arm-core и scan-gateway равны им байт в байт); косметика T1.1/T2.x уходит в следующий MINOR.
|
||||
|
||||
### Срез 2c — Загрузка файлов и маппинг результата в ядре (`arm-core`) — реализован, ожидает ревью и merge
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user