Files
Bridge-and-Join-s/docs/fancy-events-partial-m2m.md
zuevav 0c081a7857 DEPO: строчные события по депо-поручениям (частичное исполнение пакета)
По ответам программиста Fancy (В. Кокин, 21.09.2026) на 8 вопросов из
docs/fancy-events-partial-m2m.md. Одно депо-поручение (MF010) = одна бумага
пакета, поэтому подача и исход теперь пишутся в DEPO ПО СТРОКАМ с REFERENCE и
сразу по MS010 этой строки, не дожидаясь остальных: пакет может исполниться
частично (Сбер — да, Т-Технологии — отказ). События на весь GUID (пустой
REFERENCE) больше не пишем — переход одновременно с bj2depo.

- BJ_ORDER_SENT / BJ_ORDER_ACCEPTED / BJ_EXECUTED / BJ_ORDER_REJECTED /
  BJ_ORDER_LATE / BJ_CANCELLED — по строке (depoOnOrderLineSent/Result);
  contr_d_id кладём в COMMENT (джобе связка не нужна — по REFERENCE найдёт).
- OrderWatch.Lines — состояние по строкам (contr_d_id → REFERENCE/ISIN/MS010/
  отказ/истечение); объект закрыт, когда MS010 по всем строкам; 30 дней —
  BJ_CANCELLED по каждой незакрытой строке, QUIK-блок снимается по её ISIN.
- Входящий 16/1 хранит ВСЕ contr_d_id (OrderLines) — раньше только первый
  (дефект «входящие отслеживают только первый contr_d_id»). Исходящий 16:
  REFERENCE по ISIN из бумаг M2MTR (outgoingLineRefs, кэш по GUID; svc в deps).
- Карточка: «исполнено частично: N из M» (StatusRu), бейдж warn — как статус
  «частично» в DEPO. Backfill и эмуляция — тоже по строкам.
- Попутно: EXEC процедуры обработчика DEPO — через execProc с проверкой имени
  (sqlident.go), чтобы значение из настроек не стало произвольным T-SQL.

Тесты: TestOrderWatchLinesPartial, TestIncomingOrderLines,
TestOutgoingLineRefsNoRepo; весь пакет зелёный.

РАЗВЁРТЫВАНИЕ — только одновременно с bj2depo (п. 8 ответов Fancy).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4YVo4UMopqT5DzicqpPjL
2026-09-22 16:27:52 +03:00

83 lines
8.7 KiB
Markdown
Raw Permalink 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.
# Вопросы программисту Fancy: частичное исполнение пакета M2M
Контекст. По входящему переводу M2M на несколько бумаг НРД после нашего согласия формирует
отдельное депо-поручение 16/1 на каждую бумагу (черновики MF010 приходят по одному на бумагу).
Дальше каждое поручение исполняется независимо: по одному может прийти MS010 «исполнено», по
другому — MS010 с отказом (не сквитовалось со встречным 16 контрагента, GS116 «не сквитовано»,
истёк срок 30 дней). Пример: пакет «10 Сбер + 10 Т-Технологии», Сбер зачислен, Т-Технологии — нет.
То же возможно по исходящим (поручения 16 по каждой бумаге).
Сейчас bj пишет в FTV_M2M_EVENTS события на весь перевод (REFERENCE пустой):
BJ_ORDER_ACCEPTED + BJ_EXECUTED либо BJ_ORDER_REJECTED. При частичном исполнении это неверно.
bj готов писать события **по строке пакета** (REFERENCE = Security/ReferenceId из FTV_M2M_LINES).
## Вопросы
1. **События по строке.** Умеет ли bj2depo обрабатывать событие с заполненным `REFERENCE`
(одна бумага пакета): создать проводку зачисления/списания только по ней и не трогать другие
строки? Или джоба работает только с событием на весь GUID?
2. **Набор событий для частичного исхода.** Какой вариант удобен джобе:
- (а) по каждой строке своё событие: `BJ_EXECUTED` (REFERENCE=Сбер) и `BJ_ORDER_REJECTED`
(REFERENCE=Т-Технологии, PARAMETERS — текст отказа НРД); события на весь GUID при этом
не пишутся;
- (б) одно событие на GUID `BJ_EXECUTED_PARTIAL` с перечнем в PARAMETERS
(`executed: ISIN…; rejected: ISIN… — причина`), проводки делает оператор Fancy вручную;
- (в) оба: строчные события для проводок и сводное на GUID для статуса документа.
3. **Порядок во времени.** MS010 по разным бумагам приходят в разное время (минуты — дни).
Можно ли писать событие по строке сразу при получении её MS010, не дожидаясь остальных
(документ в DEPO будет какое-то время «частично исполнен»)? Или ждать, пока ответят по всем,
и писать пакетом?
4. **Состояние документа DEPO.** Какое STATE/COMMENT bj2depo поставит документу, у которого
часть строк исполнена, часть отказана? Есть ли в DEPO статус «исполнено частично», или
документ разделяется на два?
5. **Отказ после исполнения.** Если по бумаге сначала пришло REORD/принятие, а затем отказ
(MS010 с отказом) — нужно ли отдельное событие отмены ранее созданной проводки, или
`BJ_ORDER_REJECTED` по строке этого достаточно?
6. **Срок 30 дней.** Поручение без MS010 через 30 дней считается отменённым. Сейчас bj пишет
`BJ_CANCELLED` на весь GUID. По строке — тем же событием с REFERENCE?
7. **Поручения без строки.** `BJ_ORDER_SENT` сейчас несёт номера всех поданных поручений
(contr_d_id) в PARAMETERS. Нужно ли джобе соответствие contr_d_id ↔ REFERENCE (в каком поле)?
8. **Обратная совместимость.** Пока джоба не умеет строки — можем ли мы продолжать писать события
на GUID при полном исполнении/полном отказе и переходить на строчные только при частичном
исходе? Или переключаться целиком?
## Что сделает bj после ответа
- хранить по каждому поручению 16/16-1 связку `contr_d_id ↔ ISIN ↔ REFERENCE`;
- вердикт по каждому поручению; статус перевода «исполнен» только когда исполнены все,
«отказ» — когда отказ по всем, иначе «исполнен частично» с ожиданием остальных;
- события в FTV_M2M_EVENTS в согласованном формате (п. 2);
- в карточке перевода — статус по каждой бумаге, оповещение оператору о частичном исполнении.
---
## Ответы Fancy (В. Кокин, письмо 21.09.2026) и что реализовано в bj
| # | Вопрос | Ответ | В bj |
|---|--------|-------|------|
| 1 | Событие с REFERENCE по одной бумаге — провести только её | **Да** | события исходов пишутся по строкам с REFERENCE |
| 2 | Формат при частичном исходе | **(а) отдельные события по строкам** — они приходят в разное время | `BJ_EXECUTED`/`BJ_ORDER_REJECTED` по каждой строке |
| 3 | Писать по строке сразу при её MS010 или ждать все | **Сразу** | `orderWatchCheck` пишет исход строки в момент её MS010 |
| 4 | Состояние документа DEPO при частичном исполнении | **есть статус «частично»**, документ не делится | карточка bj: «исполнено частично: N из M» (`StatusRu`/`Kind`=warn) |
| 5 | Отказ после принятия (REORD) — событие отмены проводки? | **Такого не может быть**; экстремальный казус — руками | отдельного события отмены нет |
| 6 | 30 дней по одной бумаге → `BJ_CANCELLED` с REFERENCE | **Да** | истечение по строке → `BJ_CANCELLED` с REFERENCE, QUIK-блок снимается по ISIN |
| 7 | Связка contr_d_id ↔ REFERENCE джобе | **Не нужна** — по REFERENCE найдёт всё | contr_d_id кладём в COMMENT для разбора |
| 8 | Совместимость: строчные только при частичном? | **Сразу везде**, но **одновременно** на bj и bj2depo | все `BJ_ORDER_*`/`BJ_EXECUTED`/`BJ_CANCELLED` — строчные; события на весь GUID больше не пишем |
**Реализация в bj** (`orderwatch.go`, `depoevents.go`, `incoming*.go`, `outgoing_order.go`):
- одно депо-поручение (MF010) = одна бумага; входящий 16/1 теперь хранит **все** `contr_d_id` (`OrderLines`: contr_d_id ↔ ISIN ↔ REFERENCE) — раньше только первый;
- исходящий 16: REFERENCE берётся из бумаг M2MTR по ISIN (`outgoingLineRefs`, кэш по GUID);
- `OrderWatch.Lines` — состояние по строкам; объект закрыт, когда MS010 по всем строкам;
- `BJ_ORDER_SENT` — по строке (COMMENT = contr_d_id); `BJ_ORDER_LATE` — по каждой незакрытой строке при просрочке 5 мин.
**Развёртывание — только одновременно с bj2depo** (п. 8): до подтверждения Вадима, что джоба читает строчные события, bj на стенд/бой не выкатывается.
Предложение Вадима: прогнать тесты с реальным контрагентом на функционале вендора (есть компания с потребностью тестировать).