9.5 KiB
Raw Blame History

Proposal: Срез 1 — справочники (API), импорт из ЕЦП CRM, политика видимости, администрирование пользователей

Срез: 1 «Справочники» (../docs/context/09-delivery-plan.md), в сокращённом объёме по решению владельца 04.10.2026: без UI справочника, экран администратора — минимальный. Цель — быстрее дойти до Среза 2 (tabular-parser). Репозиторий: arm-core. Issue: RSHB/arm-core#5. Родительский change: ../docs/openspec/changes/slice-1-directories (DBML v5.14, §13 импорт, §10.1 видимость, OQ-86…91). Фикстура: ../fixtures/directories/ecp-export-russkiy-biskvit.xlsx (RSHB/arm-ka-fixtures#2).

Why

Срез 2 (загрузка файлов и парсер) требует, чтобы в ядре уже были ЮЛ-владельцы файлов, их ГК и состав ГСК, а также пользователи с ролями, под которыми загружают. В Срезе 0 есть только схема, seed ролей и /api/v1/me: ни одной записи справочника создать нельзя, пользователей заводит только seed. Срез 1 даёт API справочников, импорт реальной выгрузки ЕЦП CRM (8400 строк, 345 ГК — включая группу «Русский Бисквит» для тестов), правило видимости по филиалу и администрирование пользователей.

What Changes

  • DBML v5.14 (../docs/model/data-model-v5.14.dbml): related_group_member.kind + частичный уникальный индекс (legal_entity_id, kind) WHERE is_current (ЮЛ одновременно в одной ГСК и одной ГСЗ), audit_action + LEGAL_ENTITY_CHANGE, USER_CHANGE. ORM, миграция 0002_dbml_v5_14, DBML_VERSION, Makefile, dbml_parity.DBML_FILE_NAME, тесты миграций и паритета — на v5.14. Таблиц 43, enum'ов 27 — без изменений.
  • Инфраструктура запросов (общая для всех мутаций): зависимость сессии с commit при успехе и rollback при ошибке; зависимость AuditService с ip_address/user_agent из запроса и user_id из Principal; доменные исключения NotFoundError → 404, ConflictError → 409 (с осмысленным текстом вместо шаблонного «нарушение целостности»), DomainValidationError → 422; единый формат списков {items, total, limit, offset}.
  • Policy-слой src/domain/policy.py (чистые функции, без ролей): видимость ГК/ЮЛ по филиалу — ГО видит всё, филиал — ГК своего РФ и своих монозаёмщиков (§10.1); применение — фильтр в репозиториях и проверка на объекте (404 вне видимости).
  • API справочников (/api/v1/directories/…, права DIRECTORY_VIEW / DIRECTORY_EDIT / DIRECTORY_DELETE):
    • филиалы: список;
    • ГК: список (поиск по имени/crm_id, архив), карточка, создание (code генерируется GK-NNNNNN), изменение (имя, РФ — снимок в company_group_history, GROUP_CHANGE/ASSIGNMENT_CHANGE), архив/разархив, история;
    • ЮЛ/ИП: список (фильтры: ГК, «вне ГК», ИНН, имя), карточка, создание (ИНН 10/12 по типу), изменение, перевод в другую ГК (MOVE_TO_GROUP, effective_date), вывод из состава (CLOSE / REMOVE_FROM_GROUP), история, алиасы (добавить/удалить, normalized_alias по §3, конфликт с чужим алиасом → 409);
    • ГСК/ГСЗ: список по ГК, создание (code GSK-/GSZ-NNNNNN), изменение, удаление пустой (ASSUMPTION(OQ-34)), состав: добавить/исключить (SCD2; одна группа каждого вида на ЮЛ; ЮЛ только из той же ГК).
  • Импорт из ЕЦП CRM (POST /api/v1/directories/import, право DIRECTORY_ADMIN): xlsx/csv по §13 (openpyxl добавляется в requirements.txt), dry_run, on_existing = skip | update, одна транзакция, построчные коды §13.2, отчёт в ответе и в audit_event(DIRECTORY_IMPORT), файл в S3 uploads/imports/{audit_event_id}/{name} + s3_object. Допущения ASSUMPTION(OQ-87…OQ-91) в коде. Тесты: срез по «Русскому Бисквиту» из fixtures и dry_run всей выгрузки (маркер fixtures, ARM_KA_DOCS).
  • Администрирование (/api/v1/admin/…, право USERS_ADMIN): пользователи (список, создание с обязательным email, изменение, деактивация; USER_CHANGE), роли (список), назначение ролей пользователю (USER_ROLE_CHANGE), матрица role_permission (чтение, замена набора прав роли; ROLE_PERMISSION_CHANGE); нельзя оставить систему без активного обладателя USERS_ADMIN (в т.ч. снять его с себя, будучи последним).
  • Минимальный экран администратора (web/): API-клиент с Authorization: Bearer (dev-токен по email в режиме разработки), страница /admin: таблица пользователей с назначением ролей и форма создания, матрица «роль × право» с чекбоксами. Без справочника ГК/ЮЛ (решение владельца).
  • Фикстуры тестов: фабрики make_company_group, make_legal_entity, make_user; общая фикстура auth_client.
  • Документы: README.md (API, импорт, права), CLAUDE.md, спеки.

Capabilities

New Capabilities

  • directories-api: ГК, ЮЛ/ИП, алиасы, ГСК/ГСЗ и состав, филиалы — поведение API, истории и аудита.
  • directory-import: импорт выгрузки ЕЦП CRM по §13 с отчётом, dry_run, стратегией дублей и следом в аудите/S3.
  • directory-policy: видимость справочников по филиалу без проверки кода роли.
  • users-admin: администрирование пользователей, назначения ролей и матрицы прав; минимальный экран администратора.

Modified Capabilities

  • data-model: схема равна DBML v5.14 (требования «Схема БД равна DBML», «Версия DBML зафиксирована в коде»); миграции 0001 → 0002 применяются с нуля и откатываются.
  • audit-trail: добавляется требование, какие события пишут справочники, импорт и администрирование (новые значения LEGAL_ENTITY_CHANGE, USER_CHANGE).

Impact

  • Таблицы DBML v5.14: regional_office (чтение, создание при импорте), company_group, company_group_history, legal_entity, legal_entity_history, legal_entity_alias, related_group, related_group_member (новая колонка kind), app_user, user_role, role_permission, audit_event, s3_object (файл импорта). Полей вне DBML нет.
  • Правила: §3 (нормализация алиаса), §10/§10.1 (права и видимость), §13 (импорт, ручные операции).
  • Зависимости: openpyxl (чтение xlsx, в requirements.txt); фронт — без новых пакетов (antd, RTK уже есть).
  • Seed: права и матрица не меняются (16 кодов); test_me_and_dev_token/test_seed_roles не трогаются.
  • Внешние системы: S3 (файл импорта), PostgreSQL 16 (миграция 0002).

Non-goals

  • UI справочника ГК/ЮЛ/ГСК по макету (экраны 50, 51, 61, 77–80) — отдельный срез.
  • Нерезиденты и физлица в справочнике, контрольные разряды ИНН, маппинг «ЦКБ»/«Головная организация» на ГО, несколько ГСК в одной ГК из выгрузки — после ответов OQ-87…OQ-91.
  • Фильтр видимости по ЗО (business_segment) — поля у ГК нет (OQ-86).
  • Онлайн-интеграция с ЕЦП CRM; удаление ГК и ЮЛ (только архив/закрытие); восстановление истории назад.
  • Проверка JWT РАИСА, аудит входа (LOGIN) — остаются как в Срезе 0.