Колонка «Показатели», строки-показатели, «В валюте», BU по умолчанию (AURORA-1613, AURORA-1661 — валютная часть). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
108 lines
12 KiB
Markdown
108 lines
12 KiB
Markdown
# Design: колонка «Показатели» и валютные строки ОСВ
|
||
|
||
Правило — `05-domain-rules.md` §1.3 (абзацы «строки-показатели», «Колонка «Показатели»»), §1.4 (сверка родителя),
|
||
ветка docs `feat/58-osv-indicators`.
|
||
|
||
## Как выглядит файл (реальный образец контура, в git не кладётся)
|
||
|
||
`result_dir.zip`, `files/3da66219-….xlsx` — ОСВ по счёту 02, шапка без «Выводимые данные» («Параметры: Валюта БУ, НУ:
|
||
Руб»):
|
||
|
||
```
|
||
r7 Счет | Показа-\nтели | Сальдо на начало | Обороты за период | Сальдо на конец
|
||
r8 Основные средства | | Дебет | Кредит | Дебет | Кредит | Дебет | Кредит
|
||
r10 02 | БУ | | 480896,82 | 45754,41 | 46336,70 | | 481479,11 outline 0
|
||
r11 | НУ | | 480896,82 | 45754,41 | 46336,71 | | 481479,12 outline 0
|
||
r12 Интерактивная … | БУ | … outline 1
|
||
r13 | НУ | … outline 1
|
||
r16 Машина … (A16:D17 объединены) | БУ | … outline 1
|
||
r17 (продолжение объединения) | НУ | … outline 1
|
||
r30 Итого (A30:D31 объединены) | БУ | … outline 0
|
||
r31 (продолжение) | НУ | … outline 0
|
||
```
|
||
|
||
`files/270b41da-….xlsx` (плоская форма, трек B) — пары строк «Валюта CNY» (рубли) / «В валюте» (сумма в валюте) под
|
||
субсчётом 76.55.
|
||
|
||
Сейчас: колонка «Показа-тели» попадает в `extra_cols` и в `_label_cols` (r11, r13 — пустой текст → текст «НУ» из
|
||
колонки E, отступ +1000 → ребёнок строки БУ); r17 — текст объединённой ячейки (повтор названия), `data_type` всех строк
|
||
`null` (шапка молчит); r31 — не «Итого развернутое», `_trailing_totals` обрывается, строка уходит в подвал с
|
||
предупреждением «ниже таблицы есть числа».
|
||
|
||
## Решения
|
||
|
||
### Признак строки-показателя — поле строки, не значение `data_type`
|
||
|
||
Сейчас «показатель» = `data_type ∈ {CURRENCY, QUANTITY}` (`checks._INDICATOR_DATA_TYPES`). NU в этот набор добавить
|
||
нельзя: документ с «Выводимые данные: НУ» (s12) целиком состоит из строк NU, и все его проверки пропали бы. Поэтому
|
||
вводится признак `indicator: bool` у `BodyRow` (вычисляется при сборе строк) и у `ClassifiedRow`; `checks._is_indicator`
|
||
читает признак. Строка-показатель — если:
|
||
|
||
1. в листе есть колонка «Показатели», ячейка строки в ней непуста и метка ≠ «БУ» (словарь
|
||
`data_types.indicator_column`); `data_type` — из словаря; «ПР», «ВР» — `null` (словарь `indicator_column_untyped`);
|
||
метка не из обоих словарей — `null` + предупреждение `OSV_ROWS` «строка N: метка «X» в колонке «Показатели» не
|
||
распознана — строка не участвует в проверках»;
|
||
2. иначе — текст строки матчит `data_types.row` («Вал.», «Кол.», «Кол-во», **«В валюте»**) или равен коду валюты
|
||
(как сейчас, `row_data_type`).
|
||
|
||
Метка «БУ» в колонке даёт строке `data_type = BU` явно (даже если шапка молчит или называет НУ — колонка точнее шапки).
|
||
|
||
### Текст строки с меткой колонки — метка
|
||
|
||
У строки-показателя из колонки текст в колонке текста либо пуст, либо повторяет объединённую ячейку строки БУ (r17).
|
||
`BodyRow.text` = метка («НУ»), `is_account = False`. Так `row_value` не дублирует название объекта, а ИНН-логика и
|
||
классификатор не принимают строку за счёт или контрагента. Колонка «Показатели» исключается из `_label_cols` (как колонка
|
||
ИНН) и остаётся в `extra` под своим заголовком.
|
||
|
||
### Иерархия: показатели вне каскада, родитель — предыдущая строка данных
|
||
|
||
Новый модуль `src/parser/indicators.py` (чтобы не пересекаться с треком B в `hierarchy.py`):
|
||
`attach_indicators(rows, levels, total_row) -> Levels`. В `OsvParser.parse_sheet` каскад `resolve_levels` получает
|
||
строки без показателей; затем каждому показателю (до «Итого») назначается родитель — ближайшая строка выше, которая не
|
||
показатель, — и уровень `level(родителя) + 1`; показатель в начале таблицы без строки данных выше — уровень 0 без
|
||
родителя. Итоговые строки-показатели — уровень 0 без родителя (как «Итого»). Стратегия иерархии (`Levels.strategy`) —
|
||
стратегия каскада.
|
||
|
||
Для строк «Вал.»/«Кол.» под контрагентом (s04, s30, реальные файлы) результат совпадает с прежним: 1С печатает
|
||
показатель сразу под строкой, к которой он относится. Golden-проверка это подтверждает; любое расхождение golden на
|
||
реальных файлах — стоп и вопрос владельцу (не перегенерировать молча).
|
||
|
||
### Итоговые строки-показатели
|
||
|
||
`_trailing_totals` продолжает серию итоговых строк и через строки с меткой показателя в колонке «Показатели»
|
||
(r31 после r30): они остаются в таблице, классифицируются TOTAL с `data_type` метки и `indicator = True`;
|
||
`checks._total` берёт первую итоговую строку **не показатель**. Трек B меняет `_trailing_totals`/`_total` под
|
||
«Итого развернутое» перед «Итого» — при слиянии второй трек добавляет своё условие к версии первого.
|
||
|
||
### Вид данных по умолчанию
|
||
|
||
Если шапка не называет вид данных (`doc.data_type is None`), строки без собственного вида (не показатели и без метки
|
||
«БУ») получают `BU`; один раз на лист — предупреждение `OSV_HEADER` «вид данных в шапке не указан — строки без метки
|
||
приняты как БУ». Если все строки данных размечены колонкой «Показатели», предупреждения нет (умолчание не
|
||
применялось). `header.data_type` остаётся `null`; существующее предупреждение шапки «тип выводимых данных … не найден»
|
||
сохраняется.
|
||
|
||
### Что не меняется
|
||
|
||
- `balance_identity` проверяет все строки, включая показатели (как сейчас у «Вал.»/«Кол.»): у НУ/количества тождество
|
||
«начало + обороты = конец» тоже выполняется.
|
||
- «Валюта <код>» — обычная строка OTHER (рубли): `row_data_type("Валюта USD")` = `None` уже сейчас; закрепляется тестом.
|
||
- Контракт, DBML, arm-core.
|
||
|
||
## Decisions made without discussion
|
||
|
||
| Дата | Решение | Обоснование | Что стоит ошибка |
|
||
|---|---|---|---|
|
||
| 19.10.2026 | «ПР», «ВР» и метка не из словаря — `data_type = null`, строка-показатель | В контракте нет значения для разниц; `null` ядро не берёт в свод, проверки строку не видят | Разницы не видны как отдельный вид данных до AURORA-1669; переразметка — правка словаря |
|
||
| 19.10.2026 | Признак показателя — поле `indicator`, а не набор значений `data_type` | Документ «Выводимые данные: НУ» не должен терять проверки | Лишнее поле в двух dataclass; контракт не меняется |
|
||
| 19.10.2026 | `row_value` строки с меткой колонки — метка, а не текст колонки текста | Текст там пуст или повтор объединённой ячейки строки БУ | Если 1С когда-то печатает в строке НУ своё название — оно теряется (не встречалось в 31 файле контура) |
|
||
| 19.10.2026 | Колонка «Показатели» остаётся в `extra` | Первичка не теряется, ядро `extra` хранит как есть | Дублирование метки в `extra` и `data_type` |
|
||
| 19.10.2026 | Родитель показателя — предыдущая строка данных для всех показателей, включая «Вал.»/«Кол.» в колонке текста | Один механизм для колонки, «В валюте» и старых меток; каскад не видит строк, которые ломают дерево | Если показатель стоит не сразу под своей строкой, родитель будет неверным; ловит golden |
|
||
| 19.10.2026 | Умолчание BU — только строкам без собственного вида; `header.data_type` остаётся `null` | Шапка действительно молчит; ядру нужен вид строки, не шапки | Предупреждение на листах без «Выводимые данные» (были без него) |
|
||
| 19.10.2026 | Синтетика s40–s43 (s33–s39 оставлены треку B) | Параллельные треки не должны конфликтовать по именам файлов набора | Пропуск номеров в наборе |
|
||
| 19.10.2026 | Новый модуль `indicators.py` вместо правки `hierarchy.resolve_levels` | Трек B меняет каскад иерархии параллельно | Ещё один модуль конвейера |
|
||
|
||
Решения владельца 19.10.2026 (чат): п. 1 колонка «Показатели» как метки §1.3, НУ без своих проверок; п. 2 «В валюте» →
|
||
CURRENCY, «Валюта <код>» — строка OTHER в рублях, код валюты не хранится; п. 3 BU по умолчанию с предупреждением — по
|
||
рекомендации агента, владелец принял без возражений («ошибки давай исправлять сейчас»).
|