gendesign/data/sql/191_gisogd_permits_key_by_source_key.sql
bot-backend 7d5ca247ca fix(ptica): ключ gisogd_permits — id документа на портале, а не (группа, номер) (#2986)
`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>
2026-08-20 22:41:27 +05:00

57 lines
3.6 KiB
PL/PgSQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- 191: бизнес-ключ gisogd_permits — идентификатор документа на портале (#2986).
--
-- Было: UNIQUE (doc_group, doc_num). Ключ выбирался, чтобы склеивать ОДИН документ,
-- пришедший из двух схем портала. Замер 20.08.2026 показал, что задача, ради которой
-- он введён, почти отсутствует, а побочный эффект огромен:
--
-- общих docNum между схемами (DocRS): 2
-- общих key между схемами (DocRS): 2 ← те же два
--
-- группа документов различных key различных docNum схлопывается
-- DocRS 6098 6096 4305 1793
-- DocRV 5419 5415 4969 450
-- DocIZ 548 547 393 155
--
-- Причина: docNum у ГИСОГД не уникален. Разрешение и изменения к нему носят ОДИН
-- номер. Пример 66-06-06-2026: портал отдаёт два документа (key 1000130002719586 —
-- само разрешение, key 1000130002752293 — изменения к нему), а UPSERT с
-- предпочтением позднего date_reg оставлял только изменение. Самого разрешения в
-- данных не оставалось. На проде так вытеснено 598 из 4320 строк РНС (13.8%).
--
-- Стало: UNIQUE (source_key) — идентификатор документа на портале. Он разделяет
-- разрешение и изменения (разные key) и по-прежнему склеивает настоящие межсхемные
-- дубли (у них key ОБЩИЙ — те самые 7 записей по всем трём группам).
--
-- Дедуп перед сменой ключа не нужен: на проде 20.08.2026 source_key уже уникален —
-- 9182 различных на 9182 строки, NOT NULL. Констрейнт встаёт как есть.
--
-- CHECK расширен значением 'IZ': группа DocIZ (изменения) есть на портале с самого
-- начала, но в GROUP_CODE лоадера её не было, и 548 документов не грузились вовсе.
BEGIN;
SET LOCAL lock_timeout = '5s';
ALTER TABLE gisogd_permits
DROP CONSTRAINT IF EXISTS gisogd_permits_doc_group_doc_num_key;
ALTER TABLE gisogd_permits
DROP CONSTRAINT IF EXISTS chk_gisogd_permits_doc_group;
ALTER TABLE gisogd_permits
ADD CONSTRAINT chk_gisogd_permits_doc_group
CHECK (doc_group IN ('RS', 'RV', 'IZ'));
ALTER TABLE gisogd_permits
ADD CONSTRAINT uq_gisogd_permits_source_key UNIQUE (source_key);
-- (doc_group, doc_num) перестаёт быть уникальным, но остаётся рабочим фильтром
-- («все документы по номеру разрешения») — оставляем как обычный индекс.
CREATE INDEX IF NOT EXISTS idx_gisogd_permits_group_num
ON gisogd_permits (doc_group, doc_num);
COMMENT ON CONSTRAINT uq_gisogd_permits_source_key ON gisogd_permits IS
'Бизнес-ключ = key документа на портале ГИСОГД-СО. docNum НЕ уникален: '
'разрешение и изменения к нему носят один номер (#2986).';
COMMIT;