feat(fansy-store): DDL принимающей БД + контракт данных для команды Fansy
- docs/fansy-contract/v1/ddl/000__roles.sql: роли fansy_etl, bj_reader, bj_migrator - docs/fansy-contract/v1/ddl/001__schemas.sql: схемы fansy_staging и fansy с грантами - docs/fansy-contract/v1/ddl/002__working.sql: рабочая схема (participants, securities, clients, client_documents, iia_contracts, settlement_requisites, depo_accounts, portfolios, etl_errors) - docs/fansy-contract/v1/ddl/003__staging.sql: staging-зеркало с loaded_at и сниженными ограничениями - docs/fansy-contract/v1/ddl/004__seed_participants.sql: предзаполнение справочника (НРД, БКС 5406121446, Ренессанс 7709258228, Альфа-Банк 7728168971) - docs/fansy-contract/v1/data-dictionary.md: семантика каждого поля - docs/fansy-contract/v1/etl-requirements.md: требования к ETL (UPSERT в staging, SLA свежести по таблицам, обработка ошибок) - docs/fansy-contract/v1/examples/example-claim.md: SQL-запросы для формирования M2MTransferRequest - docs/fansy-contract/v1/examples/seed-data.sql: 5 тестовых клиентов + портфели + договоры - migrations/fansy-store/: рабочие копии миграций Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
# Пример заявки M2M end-to-end
|
||||
|
||||
Типовой сценарий: инвестор Иванов И.И. подаёт через ЛК заявку на
|
||||
перевод 3 ценных бумаг с депо-счёта у БКС в депо-счёт у Ренессанс
|
||||
Брокера. Один из переводов — паи ПИФ с дробным количеством. ИИС
|
||||
тип T03.
|
||||
|
||||
## Какие данные нужны m2m-core для формирования M2MTransferRequest
|
||||
|
||||
Сервис `m2m-core` достаёт следующее из `fansy-store` (рабочая схема
|
||||
`fansy`) по идентификатору клиента и набору ЦБ:
|
||||
|
||||
### 1. Анкета клиента (для `InvestorInformation`)
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
c.last_name,
|
||||
c.first_name,
|
||||
c.middle_name,
|
||||
d.document_type,
|
||||
d.series AS document_series,
|
||||
d.number AS document_number
|
||||
FROM fansy.clients c
|
||||
JOIN fansy.client_documents d ON d.client_id = c.id
|
||||
WHERE c.id = :client_id
|
||||
ORDER BY d.created_at DESC
|
||||
LIMIT 1;
|
||||
```
|
||||
|
||||
### 2. ИИС-договор (для `IIAAgreementDetails`)
|
||||
|
||||
```sql
|
||||
SELECT agreement_type, agreement_number, agreement_date, broker_inn
|
||||
FROM fansy.iia_contracts
|
||||
WHERE client_id = :client_id
|
||||
ORDER BY agreement_date DESC
|
||||
LIMIT 1;
|
||||
```
|
||||
|
||||
### 3. Реквизиты передающего/принимающего депозитариев
|
||||
|
||||
```sql
|
||||
SELECT inn
|
||||
FROM fansy.settlement_requisites
|
||||
WHERE inn IN (:transferring_inn, :receiving_inn);
|
||||
```
|
||||
|
||||
### 4. Депо-счета и разделы инвестора (для `SettlementAccount`)
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
da.deponent_code,
|
||||
da.account_id,
|
||||
da.section_id,
|
||||
da.depository_inn
|
||||
FROM fansy.depo_accounts da
|
||||
WHERE da.client_id = :client_id
|
||||
AND da.depository_inn = :depository_inn
|
||||
AND da.is_active = true;
|
||||
```
|
||||
|
||||
### 5. Информация о ценных бумагах и их остатках
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
p.security_code,
|
||||
s.isin,
|
||||
s.classification,
|
||||
s.category,
|
||||
s.security_type,
|
||||
s.reg_number,
|
||||
s.fund_class,
|
||||
p.quantity_whole,
|
||||
p.quantity_fractional,
|
||||
p.isolation_status
|
||||
FROM fansy.portfolios p
|
||||
JOIN fansy.securities s USING (security_code)
|
||||
WHERE p.client_id = :client_id
|
||||
AND p.security_code = ANY(:requested_codes)
|
||||
AND p.valued_at >= now() - interval '5 minutes';
|
||||
```
|
||||
|
||||
### 6. Проверка достаточности остатков
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
p.security_code,
|
||||
COALESCE(p.quantity_whole, 0) + COALESCE(p.quantity_fractional, 0) AS available
|
||||
FROM fansy.portfolios p
|
||||
WHERE p.client_id = :client_id
|
||||
AND p.security_code = ANY(:requested_codes);
|
||||
```
|
||||
|
||||
Сравниваем `available` с запрошенным количеством. Если меньше — отказ
|
||||
от формирования M2MTransferRequest, ошибка в ЛК.
|
||||
|
||||
## Какие данные команда Fansy обязана положить в staging
|
||||
|
||||
Из примера выше:
|
||||
|
||||
- `clients`: запись на инвестора Иванова И.И.
|
||||
- `client_documents`: документ с DocumentType `21`.
|
||||
- `iia_contracts`: договор T03 с брокером (БКС, ИНН 5406121446).
|
||||
- `depo_accounts`: счёт у БКС с разделом для перевода и счёт у
|
||||
Ренессанс Брокера.
|
||||
- `securities`: 3 записи (SHAR/ORDN, SHAR/PREF, MFUN/UKWN с
|
||||
fund_class='A').
|
||||
- `portfolios`: остатки по этим 3 ЦБ на 1500 / 300 / 2500.75
|
||||
соответственно.
|
||||
- `participants`: НРД, БКС (5406121446), Ренессанс (7709258228) — из
|
||||
начального seed.
|
||||
|
||||
## Результат
|
||||
|
||||
`m2m-core` собирает данные → формирует `M2MTransferRequest` →
|
||||
валидирует → подписывает (через `crypto-service`) → отправляет в НРД
|
||||
через `nsd-adapter`. Получает `M2MTransferDecision` от принимающей
|
||||
стороны, обновляет статус сделки и шлёт callback в ЛК.
|
||||
Reference in New Issue
Block a user