# scan-gateway Specification ## Purpose Требования к scan-gateway в единой нормализации ББ/ОФР: адаптер json-ответов ИС Сканирование (шаг 1) в общую сетку ячеек и выдача результата распознавания контракта 2.0, нормализованного общим кодом `arm_statements`. ## Requirements ### Requirement: Адаптер json ИС шага 1 scan-gateway SHALL оставить у себя обмен с ИС Сканирование (горячие папки, опрос, срок, склейку набора json в `raw/{job_id}.json` до нормализации, очистку папки) и адаптер «таблица `table_structure[i]` json → `FormCandidate`»; шаги 2–8 SHALL выполняться копией пакета `arm_statements`. Адаптер SHALL: создавать кандидата на каждую таблицу каждого успешного json; копировать шапку json (`organization`, `inn`, `units`, `date`) в шапку каждой своей таблицы как `Cell` (`text = form_name`, `confidence` ИС); передавать `label.form_name` таблицы как заголовок в `evidence` (тип — общим правилом шага 1 по словарю заголовков, `statement_labels.yaml` уходит в словарь пакета); строить плотную сетку по `row_index` и `column_index` ИС (пустые позиции — `null`), `Cell.ref = row:`; `locator = file:<имя json>;table:`. `value` у OCR-ячеек всегда `null`. #### Scenario: Один json — ББ и ОФР - **WHEN** json `aep_3.json` содержит две таблицы — «Бухгалтерский баланс» и «Отчет о финансовых результатах» — под общей шапкой - **THEN** два кандидата с `locator` `file:aep_3.json;table:0` и `…;table:1`, у каждого копия шапки json ### Requirement: Ошибки набора json Ошибочный json набора (`parse_error`, непустой `error.code`, корень не объект) при хотя бы одном успешном соседе SHALL давать предупреждение файла `JSON_FAILED` (`error`, `locator = file:<имя json>`, в `message` — код и сообщение ИС); все json ошибочны — конверт `error` с кодом первого. Исключение при разборе таблицы — предупреждение **файла** `TABLE_PARSE_ERROR` (`error`, `locator = file:<имя json>;table:`; документа у таблицы нет), остальные таблицы разбираются; ни одной таблицы не разобрано — `error RECOGNITION_FAILED`. #### Scenario: Таблица упала при разборе - **WHEN** разбор `table:1` json `aep_3.json` бросил исключение, `table:0` разобрана - **THEN** документ `BALANCE` из `table:0`; в `metrics.warnings` — `TABLE_PARSE_ERROR` уровня `error` с `locator = "file:aep_3.json;table:1"`; конверт `needs_check`; ядро не автоподтверждает документы файла #### Scenario: Потерянный ОФР (решение № 28 среза 3a) - **WHEN** `.json` успешен (ББ), а `_ofr.json` вернул `INVALID_DOCUMENT` - **THEN** документ ББ получает свой статус; в `metrics.warnings` — `JSON_FAILED` уровня `error`; конверт `needs_check`; ядро не автоподтверждает документы файла ### Requirement: Что уходит из шлюза scan-gateway SHALL удалить `api/rules/statement_lines.yaml` и подстановку наименований по справочнику, срезание уверенности кода до 99 по справочнику, выбор редакции для имён (`_choose_edition`), пропуск строк с нечисловым и пустым кодом со счётчиками, правило «оставлена первая строка» при повторе кода, синтез шапки, правило «ячейки под колонкой нет → `confidence = 0`, не распознано», привязку `is_recognized` к `confidence` и правило «любое предупреждение → `needs_check`». Модули `normalizer/ocr/text|dates|amounts` переезжают в общие разборы пакета, `layout|rows|header| document` — в шаги 2–6 пакета; `ocr_lookalikes.yaml` — в словарь пакета. #### Scenario: Строки без кода в aep_3 - **WHEN** в `aep_3.json` строки «БАЛАНС» и «Выручка» имеют пустой код, а в колонке значения мусор `211(1 |` - **THEN** строки попадают в результат со статусами (`detail` под строкой с кодом, `missing` в начале таблицы) и сырым текстом; значение `211(1 |` — `amount = null`, `string_value = "211(1 |"`, `is_recognized = false` (скобка внутри цифр, правило шага 4), а не 2111; счётчиков «строк без кода с суммами пропущено» нет #### Scenario: Таблица ИС только с текстом - **WHEN** в json есть таблица без столбца кодов и без распознанного типа, в ячейках только текст подписей - **THEN** документа нет, в `metrics.warnings` — `TABLE_SKIPPED` уровня `info` с `locator` таблицы; конверт из-за неё не `needs_check`