2026-11-07 09:01:31 +04:00

9.0 KiB
Raw Blame History

Context

Решения владельца 06.11.2026 (выбраны рекомендованные варианты): 1734 — резать по смене формы у себя; 1735 — отсеивать редкую колонку с неразобранной подписью. Разбор на JSON из задач (прогон нормализатора scan-gateway на пакете 0.1.3):

  • АК-ЮЛ: один документ BALANCE, 54 кода (ББ + ОФР), SEGMENT_COLUMNS_MISMATCH у сегмента строки 19, десять жёстких нарушений ББ. Строка 41 — шапка с «Коды» (столбец кодов сдвинут в столбец 2), сегмент открывается, но остаётся в ББ.
  • Калтан, ОФР: колонки 4 / 5 («31») / 6, COLUMN_WITHOUT_DATE по столбцу 5; в столбце 5 разбирается одно число — «$301 .» (тире «—», «——-» числами не считаются).

Decisions

  • Разрез — отдельная функция до раскладки. normalize_candidate возвращает один документ, хосты вызывают его на каждый кандидат с изоляцией ошибок. Менять CandidateResult на список ломает API у трёх потребителей; разрез на кандидаты сохраняет шаги 2–8 нетронутыми — каждая часть проходит их как обычный кандидат (свои колонки, периоды, §7). Сегменты для разреза ищутся тем же кодом шага 2 (_split_and_analyse), что и для раскладки.
  • Условие разреза: своя шапка + первые min_codes (3) кодов сегмента — одной формы, отличной от формы текущей части. Шапка нужна, чтобы не резать по случайным строкам; порог — чтобы пара строк другой формы (OCR-мусор, «пояснения» в хвосте) не создавала документ. Тип части — по первому сегменту части с определённым типом.
  • Часть k ≥ 1: type_hint = null, пустые evidence и warnings — метка таблицы ИС относится к первой форме, а предупреждения адаптера (единицы, шапка) уже есть у первой части; повторять их в каждой части — дубли.
  • Редкий столбец: «между» — есть колонка периода левее и правее; «редкий» — число не более чем в одной строке с кодом при ≥ 3 у каждой колонки периода сегмента. Правило применяется в segment_columns (у каждого сегмента со своей шапкой), адреса идут в общее NUMBERS_OUTSIDE_TABLE формы.

Decisions made without discussion

Дата Решение Обоснование Цена ошибки
2026-11-06 locator части — <locator>;form:<k> (k с 1); первая часть — прежний locator Locator нигде не разбирается (ядро и UI показывают как строку); формат читаемый, у первой части ничего не меняется — golden и уже сохранённые документы не съезжают Низкая: строка в карточке документа; поменять формат — одна строка кода
2026-11-06 Порог разреза — существующий min_codes словаря диапазонов (3), не новый ключ Тот же смысл «достаточно кодов, чтобы считать это формой» уже есть в словаре Низкая: порог — данные
2026-11-06 Разрез — общий для OCR и Excel Правила шага 2 общие (как Р-44); у Excel формы обычно на разных листах — разрез почти не срабатывает, но лист «ББ + ОФР» с повторной шапкой тоже станет двумя документами Средняя: golden tabular-parser может измениться — проверяется при подъёме пина, при сюрпризе — флаг источника
2026-11-06 Текст NUMBERS_OUTSIDE_TABLE: «числа вне колонок формы не учитываются», если есть адрес редкого столбца, иначе прежний Прежний текст «правее таблицы» неверен для столбца посередине; прежние случаи и их golden не меняются Нулевая: текст предупреждения
2026-11-06 «Редкий»: ≤ 1 число в столбце и ≥ 3 у каждой колонки периода Калтан: 1 против 10+; столбец с двумя числами уже может быть данными — оставляем аналитику Низкая: порог — константа пакета
2026-11-06 Реальные JSON АК-ЮЛ и Калтана в fixtures не кладём; тесты пакета — на синтетических кандидатах (tests/builders.py), прогон реальных файлов — вручную через нормализатор scan-gateway Файлы заказчика с контура; синтетика воспроизводит обе раскладки строка в строку Низкая
2026-11-07 Тип сегмента для разреза — по первым min_codes кодам (все одной формы), а не по большинству всех кодов сегмента (исполнение, Task 2) Строки ОФР без своей шапки прилипают к сегменту пассива ББ с повторной шапкой; по большинству такой сегмент — «ОФР», и разрез по шапке ББ унёс бы пассив в ОФР Низкая: сегмент, который открывается 1–2 кодами своей формы и дальше идёт чужой, не режется — как до изменения
2026-11-07 Для разреза — помощник segments.split_segments (первая строка, своя шапка, коды сегмента) вместо прямого импорта приватных функций модуля split.py не зависит от приватных имён Нулевая

Risks / Trade-offs

  • Правило редкого столбца срабатывает и на ББ АК-ЮЛ (прогон 07.11): в сегменте пассива столбец 5 с обрывком «На 2» и одним числом 46922 (итог 1700 за 31.12.2024, OCR сдвинул его из столбца 6) уходит в NUMBERS_OUTSIDE_TABLE (row:40). До изменения этот сегмент сопоставлялся по порядку (SEGMENT_COLUMNS_MISMATCH, значения столбца 5 уезжали в колонку 6, настоящие значения столбца 6 терялись); теперь столбец 6 сопоставлен по дате, потеряно одно число, адрес виден аналитику, жёсткая проверка 1600 = 1700 ловит пустой 1700.

  • АК-ЮЛ после разреза: ОФР — отдельный документ, но подписи его колонок 5 («За I п / 20:») и 6 («юлугодие / 25 года») ИС тоже разорвала, и ни одна не разбирается как период — столбец 5 не «между периодами», правило редкого столбца не срабатывает: обе колонки с COLUMN_WITHOUT_DATE, документ needs_check, аналитик ставит дату. Это честный результат на испорченной шапке; ББ после разреза теряет 2xxx-строки и жёсткие нарушения, вызванные ими.

  • Саракташагротехремонт — JSON в задаче нет (только PDF); ожидаем ту же раскладку, проверим после выкладки.

  • Хостам нужен один вызов split_by_form; без него поведение прежнее — подъём пина без правки хоста ничего не ломает.