Andrey Epifancev d6dd341003 Правки итогового ревью: спека, предупреждение, README, design (#58)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 12:47:49 +04:00

14 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): levels_with_indicators(rows, total_row, deadline) -> Levels: функция сама запускает каскад resolve_levels на строках без показателей (в OsvParser.parse_sheet вызывается она одна); затем каждому показателю (до «Итого») назначается родитель — ближайшая строка выше, которая не показатель, — и уровень level(родителя) + 1; показатель в начале таблицы без строки данных выше — уровень 0 без родителя. Итоговые строки-показатели — уровень 0 без родителя (как «Итого»). Стратегия иерархии (Levels.strategy) — стратегия каскада.

Для строк «Вал.»/«Кол.» под контрагентом (s04, s30, реальные файлы) результат совпадает с прежним: 1С печатает показатель сразу под строкой, к которой он относится. Golden-проверка это подтверждает; любое расхождение golden на реальных файлах — стоп и вопрос владельцу (не перегенерировать молча).

Итоговые строки-показатели

_trailing_totals продолжает серию итоговых строк и через строки с меткой показателя в колонке «Показатели» (r31 после r30): они остаются в таблице, классифицируются TOTAL с data_type метки и indicator = True; checks._total берёт первую итоговую строку не показатель. Трек B добавляет _leading_totals и меняет _total под «Итого развернутое» перед «Итого» (_trailing_totals не трогает) — при слиянии второй трек добавляет своё условие к версии первого.

Вид данных по умолчанию

Если шапка не называет вид данных (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 T1.1: в колонке «Показатели» метка «Вал» без точки = CURRENCY (^вал\.?$), хотя в тексте строки (row) «Вал» без точки — не метка (материал, AURORA-1663) В колонке меток закрытый набор Ложный показатель для метки «Вал» вместо БУ
19.10.2026 T4.1: любая метка колонки «Показатели», кроме «БУ», у строки сразу после «Итого» делает её итоговой строкой-показателем (включая неизвестную метку) Показатели не должны превращаться в «хвост ниже таблицы»; предупреждение о неизвестной метке выдаёт read_label Неизвестная метка у реальной строки ниже таблицы будет втянута в таблицу
19.10.2026 R-2: трейлер коммитов «Claude Sonnet 5.5» вместо «Claude Opus 5.5» из плана Атрибуция сессии Правка трейлеров
19.10.2026 R-3: Task 3 плана (haiku) исполнен sonnet Проза с рефакторингом Стоимость
19.10.2026 R-4: мелкие находки T6.1/T6.3 исправлены до записи golden, а не отложены Golden пишется один раз на исправленном коде Лишний коммит
19.10.2026 R-5: golden s34 обновлён владельцем вручную после отказа классификатора в make golden-update Снимок s34 — собственный новый снимок ветки; изменилась одна строка (текст предупреждения о неизвестной метке по I-2) Ручное обновление без агентского ревью diff; diff проверен контроллером: одна строка

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