Merge pull request 'docs(context): §11.1 очистка OCR-текста из модуля старого ядра для нормализатора scan-gateway' (#43) from feat/42-ocr-cleanup-rules into main
Reviewed-on: #43
This commit is contained in:
commit
3ef8ed19b7
@ -730,6 +730,64 @@ OQ-92 (пустые «Организация»/«Группа компаний»
|
|||||||
только строки с кодом) + `financial_statement_value` (число: убрать пробелы/`-`, скобки → минус; `confidence`; `is_recognized`).
|
только строки с кодом) + `financial_statement_value` (число: убрать пробелы/`-`, скобки → минус; `confidence`; `is_recognized`).
|
||||||
Сверки: ИНН/имя vs `legal_entity` → `document.counterparty_check`; дата vs период версии → `period_check`.
|
Сверки: ИНН/имя vs `legal_entity` → `document.counterparty_check`; дата vs период версии → `period_check`.
|
||||||
|
|
||||||
|
### §11.1 Очистка OCR-текста (перенос из старого ядра, Срез 3)
|
||||||
|
|
||||||
|
Источник — модуль старого ядра `DKB_ARMKA` `api/src/services/ofr_result_conversion/` (`utils.py`, `date_utils.py`,
|
||||||
|
`consts.py`; в локальном `reference-old-arm` тот же код лежит в `api/src/core/PDFWorker/`). Решение владельца
|
||||||
|
06.10.2026: модуль **проверен на реальном стенде ИС Сканирование, его код можно переносить** в нормализатор `scan-gateway`.
|
||||||
|
Это **единственное исключение** из правила «доменный код из `reference-old-arm` не переносить» (CLAUDE.md workspace).
|
||||||
|
Переносятся чистые функции очистки и разбора; обвязка старого ядра (`json_to_db_rows`, dataclass'ы `Meta/DbRow/DbValue`,
|
||||||
|
прямая запись в `financial_statement_*`) не переносится — результат ложится в `statementDocument` контракта v1.2
|
||||||
|
(`string_value`, `confidence`, `is_recognized`, `period_date`, `period_text`, `line_code_confidence`). Перенос — с тестами
|
||||||
|
на `fixtures/ocr/aep_*.json`; изменения правил ниже — только через этот параграф.
|
||||||
|
|
||||||
|
1. **Буквы-двойники рядом с цифрами** (`date_utils._normalize`, `_LOOKALIKES`): `О/о/O/o → 0`, `З/з → 3`,
|
||||||
|
`l/I/|/і → 1`, `б → 6`, `S/s → 5`, `Ч → 4` — заменяются **только если символ стоит вплотную к цифре**, в несколько
|
||||||
|
проходов («2ОО5» → «2005»); слова («Общество») не портятся. Если первая строка значения состоит только из цифр,
|
||||||
|
пробелов, `|`, точек и двоеточий — `|` считается разделителем клеток формы («2|0|2|4|» → «2 0 2 4»), а не единицей.
|
||||||
|
2. **Даты из OCR-текста** (`date_utils._parse_date`): сначала текстовые формы по всей строке в порядке приоритета —
|
||||||
|
диапазон «с 01.01.2025 по 30.09.2025» (берётся конец), «30 сентября 2025 г./r./года» (латинская `r` вместо `г`),
|
||||||
|
«I квартал 2026» / «1-й кв.» / «первый квартал», «1 полугодие» / «1 п/г», «9 месяцев 2025», «январь – сентябрь 2025»
|
||||||
|
(последний месяц), «за 2025 г.» / «2025 год» (31.12); затем числовые — три группы цифр («30.09.2025», «2025 03 31»,
|
||||||
|
«30/09/25»), иначе цифры склеиваются: 8 цифр → ДДММГГГГ / ГГГГММДД / ГГГГДДММ (первый валидный вариант), 4 → год
|
||||||
|
(31.12, только 1990–2100), 6 → ДДММГГ; хвост «0:00:00» отбрасывается. Двузначный год → 20YY. Период квартала/полугодия/
|
||||||
|
N месяцев → последний день последнего месяца. Не дата (название организации) → `None`. Разборщик общий с §12 п. 4
|
||||||
|
(Excel), там на вход приходят чистые строки.
|
||||||
|
3. **Раскладка колонок** (`_build_layout`, `_infer_layout`): шапка — строка с ячейкой, начинающейся на «код» (после
|
||||||
|
нормализации: нижний регистр, всё не-буквенно-цифровое → пробел); наименование — ячейка с «наименование», иначе ближайшая
|
||||||
|
заполненная слева от кода; колонки значений — правее кода, где в тексте есть четыре цифры года или текст начинается на
|
||||||
|
«на » / «за ». Повторная шапка внутри таблицы **перезаписывает** раскладку. **Без шапки** раскладка выводится по данным:
|
||||||
|
код — столбец с наибольшим числом значений из справочника кодов строк; наименование — столбец левее кода с наибольшим
|
||||||
|
числом текстовых ячеек; значения — столбцы правее кода, где суммы не реже мусора (полоса скана) или столбец пуст
|
||||||
|
(период без данных); шапка синтезируется (`Код` / `Наименование показателя`, тексты периодов пустые). Строки до первой
|
||||||
|
настоящей шапки разбираются по выведенной раскладке. Ни шапки, ни столбца кода — таблица пропускается с warning.
|
||||||
|
**Рулинг 06.10.2026 (вместо прежнего «без шапки → колонки без дат, `NEEDS_CHECK`»):** раскладку выводить, как в старом
|
||||||
|
ядре, но документ без шапки всё равно отдавать `needs_check` с причиной в `metrics.warnings` — колонки без `period_date`
|
||||||
|
аналитик подтверждает руками.
|
||||||
|
4. **Классы строк** (`_classify_row`): пустой код → строка пропускается; нечисловой код → заголовок (не данные);
|
||||||
|
наименование «Баланс» → `BALANCE`, начинается с «итого» → `TOTAL`, иначе обычная строка. Берутся только строки с кодом
|
||||||
|
(как в §11 выше); расшифровки без кода — OQ-36.
|
||||||
|
5. **Тип таблицы** (`_resolve_table_type`): по первой цифре кодов строк данных — больше `1xxx` → BALANCE, больше `2xxx` →
|
||||||
|
INCOME; это запасной путь, когда `label.form_name` зашумлён; при расхождении с `label` — `needs_check`.
|
||||||
|
6. **Код и наименование строки**: код очищается до букв, цифр, пробела и точки (`_clear_value`: переносы строк и
|
||||||
|
табуляции → пробел, остальное выбрасывается); наименование берётся **из справочника по коду** (`consts.codes_mapping`,
|
||||||
|
у нас — `rules/statement_lines.yaml` из §12 п. 2), а из OCR — только если код не найден в справочнике (`line_code_confidence
|
||||||
|
< 100`). Код считается распознанным (`line_code_recognized`), если `confidence == 100`, очищенный текст равен сырому и код
|
||||||
|
есть в справочнике.
|
||||||
|
7. **Суммы** (`_parse_amount`): запятая → точка, пробелы убираются; содержимое скобок — отрицательное; из строки
|
||||||
|
удаляется всё, кроме цифр, `+`, `-`, `.`; несколько точек — разделители тысяч, остаётся последняя; `Decimal`, иначе
|
||||||
|
`None`. Прочерк, «–», «—», пусто — пустое значение (NULL, не 0). `string_value` — очищенный текст (`_clear_value`).
|
||||||
|
**`is_recognized`** значения = `confidence == 100` **и** разбор суммы не потребовал выбрасывать символы (сырой текст без
|
||||||
|
скобок равен очищенному). Для ячеек шапки: `is_recognized` = `confidence == 100` и в тексте не было мусора; если дата
|
||||||
|
разобралась — `period_text` нормализуется в «На ДД.ММ.ГГГГ», `period_date` — результат п. 2. Ячейки под колонкой
|
||||||
|
заголовка нет — пустое значение с `is_recognized = false`, чтобы не сдвигать столбцы.
|
||||||
|
8. **Шапка документа**: ИНН — только цифры из `inn.form_name`, «распознан», если `confidence == 100` и в сыром тексте не
|
||||||
|
было ничего, кроме цифр; единицы — `_clear_value`, тот же критерий; дата отчёта — п. 2, «распознана», если
|
||||||
|
`confidence == 100` и дата разобралась. Нераспознанное → `needs_check` (как в §11).
|
||||||
|
9. **Ошибка разбора одного документа** (исключение в разборе `data_ocr`) не роняет файл: документ помечается ошибкой
|
||||||
|
(`BACKEND_PARSING_ERROR` + текст исключения), остальные документы файла обрабатываются; хотя бы один документ есть —
|
||||||
|
конверт `needs_check`, ни одного — `error` (в терминах `recognition-result-message`).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## §12. ББ и ОФР из Excel (tabular-parser, второй тип документа)
|
## §12. ББ и ОФР из Excel (tabular-parser, второй тип документа)
|
||||||
|
|||||||
@ -160,7 +160,9 @@ Change'и: `arm-core/openspec/changes/slice-2c-osv-ingest` (issue arm-core#14,
|
|||||||
## Срез 3 — ББ/ОФР: scan-gateway, маппинг форм, логические проверки, подтверждение документа
|
## Срез 3 — ББ/ОФР: scan-gateway, маппинг форм, логические проверки, подтверждение документа
|
||||||
|
|
||||||
- `scan-gateway`: горячие папки (по FNR02) с заглушкой-эмулятором ИС Сканирование для dev (возвращает `aep_*.json`
|
- `scan-gateway`: горячие папки (по FNR02) с заглушкой-эмулятором ИС Сканирование для dev (возвращает `aep_*.json`
|
||||||
по имени файла); сырой ответ → S3 `raw/`; нормализация в контракт результата; таймаут 5 мин.
|
по имени файла); сырой ответ → S3 `raw/`; нормализация в контракт результата по §11 и **§11.1** (очистка OCR-текста:
|
||||||
|
перенос проверенного на стенде модуля `ofr_result_conversion` старого ядра — единственное разрешённое исключение для
|
||||||
|
`reference-old-arm`, решение владельца 06.10.2026); таймаут 5 мин.
|
||||||
- Маппинг: `financial_statement_meta/column/line/value` из JSON; числа, скобки, confidence; ИНН/имя сверка.
|
- Маппинг: `financial_statement_meta/column/line/value` из JSON; числа, скобки, confidence; ИНН/имя сверка.
|
||||||
- Логические проверки §7 (чистые функции `domain/checks.py`), акцепт КА, «Подтвердить данные» → `CONFIRMED`,
|
- Логические проверки §7 (чистые функции `domain/checks.py`), акцепт КА, «Подтвердить данные» → `CONFIRMED`,
|
||||||
`RECOGNIZED_DATA_EDIT` с before/after.
|
`RECOGNIZED_DATA_EDIT` с before/after.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user