Andrey Epifancev 0826be0cad Срез 1: DBML v5.14, §13 импорт из ЕЦП CRM, §10.1 видимость, OQ-86…91, change slice-1-directories
- data-model-v5.14.dbml: related_group_member.kind + partial unique (legal_entity_id, kind) WHERE is_current
  (ЮЛ одновременно в одной ГСК и одной ГСЗ — решение владельца 04.10.2026), audit_action + LEGAL_ENTITY_CHANGE,
  USER_CHANGE; КПП не вводится.
- 05-domain-rules.md: §13 правила импорта выгрузки ЕЦП (формат, построчные коды, транзакция, след, ручные операции),
  §10.1 видимость справочников по филиалу без кода роли.
- 07-open-questions.md: OQ-31/32 закрыты, OQ-25 уточнён по выгрузке, добавлены OQ-86…OQ-91.
- source/biq/ecp-export-lagal-entity.xlsx — первоисточник формата (добавлен владельцем).
- openspec/changes/slice-1-directories: proposal, design, tasks (skip_specs).

Issue: RSHB/arm-ka-docs#6

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-04 20:22:26 +04:00

8.6 KiB
Raw Blame History

Design: Срез 1 (сквозное) — DBML v5.14, импорт ЕЦП, видимость

Context

См. proposal.md. Факты, на которых стоит дизайн:

  • Выгрузка ЕЦП (docs/source/biq/ecp-export-lagal-entity.xlsx, лист «Выписки_01.04.26»): 8400 строк, колонки ИНН, iD ГК, Базовый РФ ГК в CRM, Группа компаний, Организация, ГСК, ГСЗ, Тип; 345 ГК; 53 значения РФ (51 «… РФ», плюс «ЦКБ» 1370 строк и «Головная организация»); типы ЮЛ 7395, ИП 469, нерез. 354, ФЛ 180, нет инн 2; ИНН: 10 цифр у ЮЛ, 12 у ИП, 279 нечисловых; 215 ИНН встречаются в нескольких ГК; флаги ГСК/ГСЗ — строки «входит в ГСК» / «входит в ГСЗ» (плюс мусор: 0, ИНН в колонке флага); идентификатора ГСК/ГСЗ нет; у 213 ГК есть члены ГСК (до 83).
  • Решения владельца 04.10.2026: без UI справочника; КПП не нужен; ЮЛ в одной ГК, одновременно в одной ГСК и одной ГСЗ; экран администратора минимальный.
  • Инварианты: права — данные, код роли в логике не проверяется; первичка не мутируется; append-only аудит; поля вне DBML не вводить.

Goals / Non-Goals

Goals: одна версия DBML, которую реализует миграция 0002; правила импорта, по которым можно написать тесты на реальной выгрузке; правило видимости без кода роли. Non-Goals: см. proposal.

Decisions

Уникальность «одна группа каждого вида на ЮЛ» нельзя выразить индексом через join; варианты — триггер или денормализация. Выбрана денормализация (kind = related_group.kind, равенство проверяет ядро при вставке, тест на рассинхрон), индекс (legal_entity_id, kind) WHERE is_current. Альтернатива — триггер: сложнее переносить, невидим в ORM. Цена ошибки: убрать колонку и индекс миграцией.

D-2. Версия DBML — новый файл, старый остаётся

data-model-v5.14.dbml рядом с v5.13 (история версий — файлы, changelog в шапке); entities-v5.14.md — копия с таблицей изменений наверху; ссылки в CLAUDE.md репозиториев и Makefile/DBML_VERSION arm-core переводятся на v5.14 в дочернем change.

D-3. Импорт — правила §13 как данные для тестов, строки не блокируют файл

Построчные коды (UNSUPPORTED_TYPE, INVALID_INN, DUPLICATE_IN_FILE, RF_CREATED, GK_*, LE_*, GSK_CREATED, MEMBER_ADDED, UNKNOWN_FLAG) фиксируются в §13.2 и становятся контрактом отчёта и тестов arm-core; файл отвергается только при отсутствии обязательных колонок или нечитаемости. Одна транзакция, dry_run, стратегия on_existing ∈ {skip, update}.

D-4. Неоднозначности выгрузки — осторожные допущения + OQ, не угадывание

нерез./ФЛ — пропуск (OQ-87); ИНН только по длине (OQ-88); «ЦКБ»/«Головная организация» — обычные филиалы (OQ-89); ИНН в нескольких ГК — первая выигрывает, остальные в отчёт (OQ-90); одна неявная ГСК/ГСЗ на ГК с именем ГК (OQ-91). Каждое допущение помечается ASSUMPTION(OQ-nn) в коде импортёра, все обратимы одной командой или повторным импортом с update.

D-5. Видимость — по regional_office.is_head_office, без ролей

ГО видит всё, филиал — ГК своего РФ и своих монозаёмщиков; ЗО не фильтрует (OQ-86). Запись вне видимости — 404.

D-6. Выгрузка хранится в docs/source/biq/, срез — в fixtures

Полная выгрузка — первоисточник формата и прогон «на всём объёме» (помечена как внутренняя: реальные ИНН); для unit-тестов — 21 строка ГК «Русский Бисквит» в fixtures/directories/. fixtures/README и 06-test-data.md §6 обновляются.

Risks / Trade-offs

  • [Импорт всей выгрузки создаст 53 филиала и ~345 ГК в dev-БД] → dry_run первым, отчёт показывает RF_CREATED.
  • [Денормализованный kind разойдётся с группой] → проверка в сервисе + тест; индекс всё равно защищает уникальность.
  • [Допущения D-4 окажутся неверны] → данные исправимы повторным импортом с update или одной миграцией данных; OQ отслеживаются.

Migration Plan

Миграция 0002 (arm-core): ALTER TABLE related_group_member ADD kind (заполнение из related_group.kind для существующих строк — в dev их нет), замена индекса. Откат — обратная замена индекса и DROP COLUMN.

Open Questions

OQ-86…OQ-91 (см. 07-open-questions.md) — ни один не блокирует: приняты допущения D-4/D-5. Вопросы владельцу: «ЦКБ» и «Головная организация» = ГО? нужны ли нерезиденты/ФЛ?

Decisions made without discussion

№ Дата Решение Обоснование Цена ошибки
1 2026-10-04 D-1: kind в related_group_member вместо триггера индекс виден в ORM и сверке с DBML миграция: убрать колонку
2 2026-10-04 D-2: новый файл v5.14, v5.13 остаётся правило «новая версия DBML с changelog» нет
9 2026-10-04 v5.14: два новых значения audit_action — LEGAL_ENTITY_CHANGE, USER_CHANGE без них события ЮЛ/пользователей пришлось бы писать под чужим действием (GROUP_CHANGE) удалить значения enum (миграция)
3 2026-10-04 D-3: коды отчёта импорта фиксированы в §13.2; строки не блокируют файл; on_existing skip/update; dry_run макет [38] «Пропустить существующие»; реальная выгрузка грязная добавить/переименовать коды
4 2026-10-04 D-4: пять допущений по неоднозначностям выгрузки (OQ-87…OQ-91) нельзя угадывать; все обратимы повторный импорт / миграция данных
5 2026-10-04 D-5: видимость по is_head_office, ЗО не фильтрует права — данные; у ГК нет сегмента добавить поле сегмента (DBML v5.15) и фильтр
6 2026-10-04 D-6: полная выгрузка в docs/source/biq, срез в fixtures первоисточник формата vs тестовые данные перенос файла
7 2026-10-04 Срез 1 без UI справочника, экран администратора минимальный решение владельца 04.10.2026 UI — отдельный срез
8 2026-10-04 Записи вне видимости отвечают 404, не 403 не раскрывать существование чужих ГК одна константа