Andrey Epifancev d564d4998d План: номера синтетики s33–s36 вместо s40–s43 (R-1, #58)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 11:29:53 +04:00

12 KiB
Raw Blame History

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 Синтетика s33–s36 (R-1: s40–s44 заняты треком B #59, s37–s39 резерв) Рулинг владельца R-1: параллельные треки не конфликтуют по именам файлов набора Пропуск номеров в наборе
19.10.2026 Новый модуль indicators.py вместо правки hierarchy.resolve_levels Трек B меняет каскад иерархии параллельно Ещё один модуль конвейера

Решения владельца 19.10.2026 (чат): п. 1 колонка «Показатели» как метки §1.3, НУ без своих проверок; п. 2 «В валюте» → CURRENCY, «Валюта <код>» — строка OTHER в рублях, код валюты не хранится; п. 3 BU по умолчанию с предупреждением — по рекомендации агента, владелец принял без возражений («ошибки давай исправлять сейчас»).