Номер 191 занят PR #2984 (backfill act_date), который уходит в main
раньше. Обе ветки прошли CI со своим 191 — проверка идёт по голове
ветки и о занятости номера соседом узнать не может.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`UNIQUE (doc_group, doc_num)` вводился, чтобы склеивать ОДИН документ,
пришедший из двух схем портала. Замер 20.08.2026 показал, что задача,
ради которой ключ введён, почти отсутствует, а побочный эффект огромен:
docNum у ГИСОГД НЕ уникален — разрешение и изменения к нему носят один
номер.
группа документов различных key различных docNum схлопывается
DocRS 6098 6096 4305 1793
DocRV 5419 5415 4969 450
DocIZ 548 547 393 155
общих docNum между схемами (DocRS): 2 ← ради этого ключ и вводился
общих key между схемами (DocRS): 2 ← те же два
На проде 9182 строки против 12 065 документов на портале — нет 23.9 %
реестра. Пример 66-06-06-2026: портал отдаёт два документа (key …719586 —
само разрешение, key …752293 — изменения к нему), а UPSERT с
предпочтением позднего date_reg оставлял только изменение. Так вытеснено
598 из 4320 строк РНС (13.8 %) — в §6 на месте разрешения показывается
изменение к нему, без признака подмены.
Ключ стал `UNIQUE (source_key)`: разделяет разрешение и изменения (разные
key) и по-прежнему склеивает настоящие межсхемные дубли (у них key
ОБЩИЙ — ровно 7 записей по всем группам). Дедуп перед сменой не нужен:
source_key на проде уже уникален (9182 из 9182, NOT NULL).
Заодно группа DocIZ добавлена в GROUP_CODE — её не было вовсе, 548
документов не грузились. CHECK расширен значением 'IZ'.
§6 сужена до РНС/РВЭ ЯВНО: агрегат обещает total_count = rs_count +
rv_count, а строки 'IZ' попадали бы в total и ни в один счётчик.
Показывать ли изменения отдельной строкой — вопрос продуктовый (#2986);
до его решения сужение стоит в запросе, а не держится на том, что таких
строк «пока нет».
Проверки:
- два гейта на лоадер (GROUP_CODE и цель ON CONFLICT) — БЕЗ базы,
двусторонние: на origin/main дают конкретные неверные значения
({'DocRS','DocRV'} и старый ON CONFLICT в тексте запроса);
- гейт на §6 и контроль инварианта total = rs + rv на данных — красные
на origin/main;
- герметичная репетиция миграции на временной копии: со старым ключом
разрешение и изменение схлопываются в одну строку (и остаётся именно
изменение — как на проде), после миграции живут раздельно; межсхемный
дубль по-прежнему склеивается; CHECK принимает 'IZ' и отвергает мусор.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>