Документация: регистр имён частей xlsx и метки количества (#66)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
2a6a49811e
commit
1ad100b79d
@ -119,7 +119,7 @@ ParseOutcome`. Структура ОСВ ищется **по содержимо
|
||||
| Модуль | Что делает |
|
||||
|---|---|
|
||||
| `grid.py` | модель листа: `Cell`, `Sheet`, `MergedRange`, `column_letter` (буква колонки — только для диагностики) |
|
||||
| `readers/` | чтение книги в `Sheet`: `read_book(data, file_type) -> (листы, предупреждения)`; формат определяется по сигнатуре байтов (xlsx — openpyxl, xls — xlrd с `formatting_info`, xlsb — pyxlsb, без outline level); несовпадение с `file_type` — предупреждение; до библиотеки чтения — лимиты чтения (`_limits.py`, см. «Лимиты») |
|
||||
| `readers/` | чтение книги в `Sheet`: `read_book(data, file_type) -> (листы, предупреждения)`; формат определяется по сигнатуре байтов (xlsx — openpyxl; части архива, отличающиеся от ссылок `[Content_Types].xml`/`*.rels` только регистром (`xl/SharedStrings.xml`), до openpyxl переименовываются по ссылкам, как их находит Excel — AURORA-1707; xls — xlrd с `formatting_info`, xlsb — pyxlsb, без outline level); несовпадение с `file_type` — предупреждение; до библиотеки чтения — лимиты чтения (`_limits.py`, см. «Лимиты») |
|
||||
| `rules.py` | загрузчик словарей `rules/*.yaml` в frozen-модели (pydantic), `normalize_text`, `Pattern`; ошибка словаря — `RuntimeError` с файлом и ключом при старте |
|
||||
| `detect.py` | вид листа (`classify_sheet`: ОСВ / форма ББ-ОФР / прочее), блок заголовка таблицы (`find_table_header`: 1–4 строки, шесть колонок сумм, колонка текста, ИНН, дополнительные колонки, правая граница, повтор заголовка внутри данных) |
|
||||
| `header.py` | шапка документа (организация, счёт, период, тип данных, валюта) и схема группировок `group_schema` (варианты шапки 1 и 2) |
|
||||
@ -163,7 +163,7 @@ ParseOutcome`. Структура ОСВ ищется **по содержимо
|
||||
### Строки-показатели и колонка «Показатели» (§1.3, AURORA-1613, AURORA-1661)
|
||||
|
||||
Колонка «Показатели» (`service_columns.indicator`; заголовок часто «Показа-тели») несёт вид суммы строки: «БУ» — обычная
|
||||
строка данных (`data_type = BU`), «НУ», «Вал.», «Кол.» — показатели (`NU`/`CURRENCY`/`QUANTITY` по словарю
|
||||
строка данных (`data_type = BU`), «НУ», «Вал.», «Кол.», «Кол. доп.» — показатели (`NU`/`CURRENCY`/`QUANTITY` по словарю
|
||||
`data_types.yaml`: `indicator_column`), «ПР», «ВР» (`indicator_column_untyped`, `data_type = null`) и неизвестная метка — показатель с
|
||||
`data_type = null` (неизвестная — ещё и предупреждение `OSV_ROWS`). Показатель — строка с признаком `indicator`: он
|
||||
не входит в суммирование «сумма детей = родитель» и не проверяется как родитель, его родитель в дереве — предыдущая строка
|
||||
@ -226,7 +226,7 @@ ParseOutcome`. Структура ОСВ ищется **по содержимо
|
||||
|
||||
Словари — данные: `osv_headers.yaml` (признаки листов, группы сумм, «Дебет/Кредит», колонка ИНН, «Итого», метки шапки),
|
||||
`osv_groups.yaml` (группировки → `ACCOUNT/DEPARTMENT/COUNTERPARTY/CONTRACT/OTHER`), `periods.yaml` (период → квартал и
|
||||
нарастающий итог), `data_types.yaml` (БУ/НУ/сумма, строки «Вал.»/«Кол.», коды и написания валют), `osv_checks.yaml` (счета без сальдо
|
||||
нарастающий итог), `data_types.yaml` (БУ/НУ/сумма, строки «Вал.»/«Кол.»/«Кол-во, <единица>», коды и написания валют), `osv_checks.yaml` (счета без сальдо
|
||||
по аналитике — вне тождества строки). Формат и правила
|
||||
записи паттернов — [`api/rules/README.md`](api/rules/README.md).
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ AST-линтер `tests/unit/parser/test_no_coordinates.py`.
|
||||
| `osv_groups.yaml` | `mapping`, `default` | название группировки из шапки -> `ACCOUNT` / `DEPARTMENT` / `COUNTERPARTY` / `CONTRACT` / `OTHER` (`default` — для всего прочего) |
|
||||
| `osv_checks.yaml` | `accounts_without_analytic_balance` | коды счетов верхнего уровня без сальдо по аналитике (состав `90`, `91`, `99`; OQ-132, 90 добавлен 19.10.2026): тождество строки «начало + обороты = конец» на них не проверяется (субсчета включены, `910` — нет); сверки «сумма детей = родитель» по оборотам и «Итого» сохраняются. Не `Pattern`: записи — коды счетов, а не регулярные выражения |
|
||||
| `periods.yaml` | `rules` (`pattern`, `quarter`, `is_cumulative`), `year`, `end`, `months` (названия месяцев, группы `m01…m12`), `not_single_month` (тексты, где один месяц не задаёт границы периода: дата на число, квартал, «N месяцев»), `range` (диапазон месяцев с годами, группы `m1`, `y1`, `m2`, `y2`), `standalone` (период отдельной ячейкой без метки) | текст периода -> `period_quarter` и `is_cumulative` (§1.5, `ASSUMPTION(OQ-02)`); `year` — паттерн года, `end` — конец текста периода в строке шапки («г.», «год») |
|
||||
| `data_types.yaml` | `header`, `standalone_header` (тип данных отдельной ячейкой без метки), `row`, `currency_codes`, `currency_aliases` | «Выводимые данные» -> `BU` / `NU` / `SUM`; строки «Вал.» / «Кол.» -> `CURRENCY` / `QUANTITY`; коды валют ISO 4217 (строка, равная коду, — валютная); написания валюты в шапке (`руб.` -> `RUB`; ключ алиаса обязан быть в `currency_codes`) |
|
||||
| `data_types.yaml` | `header`, `standalone_header` (тип данных отдельной ячейкой без метки), `row`, `currency_codes`, `currency_aliases` | «Выводимые данные» -> `BU` / `NU` / `SUM`; строки «Вал.» / «Кол.», «Кол-во», «Кол-во, <единица>» -> `CURRENCY` / `QUANTITY`; метки колонки «Показатели» (`indicator_column`: «Кол.», «Кол. доп.» -> `QUANTITY`); коды валют ISO 4217 (строка, равная коду, — валютная); написания валюты в шапке (`руб.` -> `RUB`; ключ алиаса обязан быть в `currency_codes`) |
|
||||
|
||||
Словари форм ББ/ОФР (`statement_*.yaml` в прежней версии) удалены из сервиса: их держит пакет `arm_statements`
|
||||
(`api/arm_statements/rules/`), сервис их не читает.
|
||||
|
||||
@ -336,7 +336,9 @@ balance_identity_violations, parent_sum_violations}`. Результат про
|
||||
|
||||
### Requirement: Форматы, лимиты, время
|
||||
Парсер SHALL читать XLSX (openpyxl, полное чтение), XLS (xlrd, `formatting_info`), XLSB (pyxlsb; outline level недоступен —
|
||||
каскад начинается с отступа). Несоответствие `file_type` сигнатуре файла → попытка по сигнатуре и предупреждение файла `FILE_TYPE_MISMATCH` (`severity = info`) в `metrics.warnings`.
|
||||
каскад начинается с отступа). Имена частей xlsx SHALL сравниваться без учёта регистра, как в Excel (AURORA-1707): часть,
|
||||
отличающаяся от ссылки `[Content_Types].xml` (`Override PartName`) или `*.rels` (`Target` внутренней связи) только
|
||||
регистром, читается под именем из ссылки; две части под одну ссылку не угадываются. Несоответствие `file_type` сигнатуре файла → попытка по сигнатуре и предупреждение файла `FILE_TYPE_MISMATCH` (`severity = info`) в `metrics.warnings`.
|
||||
Файл больше `PARSE_MAX_BYTES` (по умолчанию 50 МиБ) → `error UNSUPPORTED_FORMAT` с текстом про лимит. До вызова
|
||||
библиотеки чтения SHALL действовать лимиты чтения (R-23) → `error UNSUPPORTED_FORMAT` с текстом про лимит: сумма
|
||||
объявленных несжатых размеров записей zip (xlsx/xlsb) не больше `ZIP_UNCOMPRESSED_LIMIT_FACTOR × PARSE_MAX_BYTES` (10 ×);
|
||||
@ -364,6 +366,11 @@ balance_identity_violations, parent_sum_violations}`. Результат про
|
||||
- **WHEN** запрос говорит `XLSX`, а байты — BIFF8
|
||||
- **THEN** файл прочитан как xls, в `metrics.warnings` — `FILE_TYPE_MISMATCH` (`info`), статус по содержимому
|
||||
|
||||
#### Scenario: Имя части xlsx в другом регистре
|
||||
- **WHEN** таблица строк лежит в архиве как `xl/SharedStrings.xml`, а ссылки ведут на `xl/sharedStrings.xml` (или лист
|
||||
`Sheet1.xml` при ссылке на `sheet1.xml`)
|
||||
- **THEN** книга читается так же, как с именами из ссылок; не `UNREADABLE` и без потери листа
|
||||
|
||||
#### Scenario: xls без кодовой страницы
|
||||
- **WHEN** разбирается xls без записи CODEPAGE (синтетика, `codepage=None`)
|
||||
- **THEN** строки прочитаны как cp1251, в `metrics.warnings` — предупреждение файла `XLS_NO_CODEPAGE` (`info`, без
|
||||
@ -538,11 +545,11 @@ design #14).
|
||||
Строка-показатель — строка, которая несёт вид сумм предыдущей строки данных, а не уровень аналитики. Парсер SHALL считать
|
||||
строку показателем, если:
|
||||
1. в таблице есть колонка «Показатели» (заголовок блока по словарю `osv_headers.yaml` — `service_columns.indicator`,
|
||||
«Показатели», «Показа-тели»), ячейка строки в ней непуста и метка не «БУ»: «НУ» → `data_type = NU`, «Кол.» →
|
||||
«Показатели», «Показа-тели»), ячейка строки в ней непуста и метка не «БУ»: «НУ» → `data_type = NU`, «Кол.», «Кол. доп.» →
|
||||
QUANTITY, «Вал.» → CURRENCY (словарь `data_types.yaml` — `indicator_column`); «ПР», «ВР» (`indicator_column_untyped`)
|
||||
→ `data_type = null`; метка не из словарей → `data_type = null` и предупреждение `OSV_ROWS` «строка N: метка «X» в
|
||||
колонке «Показатели» не распознана — строка не участвует в проверках»;
|
||||
2. иначе — текст строки матчит `data_types.yaml` — `row` («Вал.», «Кол.», «Кол-во», «В валюте» → CURRENCY/QUANTITY) или
|
||||
2. иначе — текст строки матчит `data_types.yaml` — `row` («Вал.», «Кол.», «Кол-во», «Кол-во, <единица>», «В валюте» → CURRENCY/QUANTITY) или
|
||||
равен коду валюты из `currency_codes`.
|
||||
|
||||
Строка «Валюта <код>» («Валюта USD») MUST NOT считаться показателем: это строка аналитики с рублёвыми суммами; код валюты
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user