# PR-2: DDL принимающей БД для команды Fansy ## Цель Спроектировать DDL принимающей БД `fansy-store` под требования документации НРД к данным M2M и передать его команде Fansy как контракт для их ETL. ETL **делает команда Fansy** в автоматизированном режиме. Наша ответственность — схема таблиц, индексы, миграции, типизированный Go-репозиторий чтения и контракт данных. ## Источники правды - `DOC/M2MSchemas_260408/*.xsd` — какие поля и типы нужны для формирования M2M-сообщений. - `DOC/Справочник пользователей.pdf` — перечень контрагентов (БКС 5406121446, Ренессанс Брокер 7709258228, Альфа-банк 7728168971). - `docs/architecture/plan.md` — контракт с командой Fansy (раздел «Контракт с командой Fansy — что мы передаём»). ## Состав PR ### 1. `docs/fansy-contract/v1/ddl/` — SQL-миграции PostgreSQL 16 / PostgreSQL Pro Certified. Используй `goose` или просто пронумерованные файлы `001__init.sql`, `002__staging.sql` и т. д. Схема разделена на две: - `fansy_staging` — куда пишет команда Fansy (только их роль может делать INSERT/UPDATE); - `fansy` — рабочая, куда переливаются актуальные данные триггерами или процедурами после валидации. Минимальный набор таблиц (повторяй структуру и в staging, и в рабочей): - `clients` — депоненты/инвесторы: - `id` (uuid), `inn` (для юрлиц), `last_name`, `first_name`, `middle_name`, `birth_date`, `created_at`, `updated_at`. - `client_documents` — документы инвестора: - `id`, `client_id (FK)`, `document_type` (enum по `IdentityDocumentCode`), `series`, `number`, `issued_at`, `issuer`. - `iia_contracts` — ИИС-договоры: - `id`, `client_id (FK)`, `agreement_type` (`T12` | `T03`), `agreement_number`, `agreement_date`, `broker_inn`. - `depo_accounts` — депо-счета и разделы: - `id`, `client_id (FK)`, `deponent_code`, `account_id`, `section_id`, `depository_inn`, `is_active`, `is_trading`. - `settlement_requisites` — реквизиты расчётов: - `id`, `inn`, `display_name`, `created_at`. - `portfolios` — портфели/остатки ЦБ: - `id`, `client_id (FK)`, `depo_account_id (FK)`, `security_code`, `isin`, `quantity_whole` (numeric), `quantity_fractional` (numeric(38,16)), `isolation_status` (`SGDN`), `valued_at`. - `securities` — справочник ЦБ: - `id`, `security_code` (PK), `isin`, `classification` (`BOND`|`SHAR`|`MFUN`), `category` (`ORDN`|`PREF`|`UKWN`), `security_type`, `security_series`, `reg_number`, `fund_class`, `display_name`. - `participants` — контрагенты-участники сервиса MOST: - `id`, `inn` (PK), `ogrn`, `full_name_rus`, `short_name_rus`, `display_name_rus`, `full_name_eng`, `short_name_eng`, `display_name_eng`, `depository_participant_code`, `broker_participant_code`, `is_available_for_m2m`, `comment`. - Предзаполни записями из `Справочник пользователей.pdf`. Дополнительно: - `etl_errors` — таблица для ошибок выгрузки Fansy (id, source_table, source_pk, payload jsonb, error_message, created_at). - В `_staging`-таблицах поле `loaded_at timestamptz default now()`. **Индексы.** Минимум: PK, FK, индекс по `inn` и `deponent_code` в основных таблицах, индекс по `valued_at` в `portfolios`. **Роль `fansy_etl`.** В отдельном `000__roles.sql`: - роль `fansy_etl` с правами INSERT/UPDATE/SELECT на схему `fansy_staging`; - роль `bj_reader` с SELECT на схему `fansy` — для нашего `m2m-core`/`lk-gateway`; - DDL-права (CREATE/ALTER/DROP) — только у миграционной роли, не у Fansy-ETL. ### 2. `docs/fansy-contract/v1/data-dictionary.md` Таблица: «поле → семантика → источник в Fansy (если известен) → nullable → пример». На каждую колонку каждой таблицы. ### 3. `docs/fansy-contract/v1/etl-requirements.md` Технические требования к процессу выгрузки от команды Fansy: - Подключение: PostgreSQL, роль `fansy_etl`, отдельная учётная запись. - Тип load: **инкрементный UPSERT в staging-таблицы** по бизнес-ключу; полная перезаливка — только для справочников (`securities`, `participants`), не чаще раза в сутки. - SLA свежести данных: - `portfolios` — не позднее 1 минуты после изменения в Fansy; - `clients`, `depo_accounts`, `client_documents`, `iia_contracts` — не позднее 5 минут; - `securities`, `participants` — раз в сутки или по событию. - Формат timestamp — UTC с явной зоной (`timestamptz`). - Обработка ошибок: запись в `etl_errors`. - Окно простоя для регламентных работ — согласовать. ### 4. `docs/fansy-contract/v1/examples/` - `example-claim.md` — какие поля из БД нужны `m2m-core` для одной типовой M2M-заявки (с конкретными SQL-запросами). - `seed-data.sql` — 5–10 тестовых клиентов, портфелей, заявок для совместного приёмочного теста. ### 5. `migrations/fansy-store/` Скопировать `*.sql` из `docs/fansy-contract/v1/ddl/` — отсюда будут исполняться миграциями в нашем сервисе. ### 6. Обновить `docs/fansy-contract/v1/README.md` Описать состав каталога и порядок согласования с командой Fansy. ## Требования к коду - Все DDL-файлы — на одной кодировке UTF-8. - Имена таблиц и колонок — `snake_case` английский. - Комментарии в DDL (`COMMENT ON COLUMN ... IS '...'`) — на русском. - Без эмодзи. ## Коммит ``` feat(fansy-store): DDL принимающей БД + контракт данных для команды Fansy - docs/fansy-contract/v1/ddl/ — миграции PostgreSQL - docs/fansy-contract/v1/data-dictionary.md — словарь данных - docs/fansy-contract/v1/etl-requirements.md — требования к ETL - docs/fansy-contract/v1/examples/ — пример заявки + seed-data - migrations/fansy-store/ — рабочие копии миграций - предзаполнен справочник контрагентов из DOC/Справочник пользователей.pdf Co-Authored-By: Claude Opus 4.7 (1M context) ``` ## После коммита 1. Обновить `docs/tasks/README.md`: PR-2 — «выполнено». 2. Сообщить заказчику, что DDL готов и можно отправлять команде Fansy.