Входящие M2M: частичный приём — каждая бумага решается сама по себе (НРД допускает: по каждой принятой свой черновик 16/1); переводы на ИИС не принимаем — отказ M2M07 по всем бумагам

- finishResult: итог confirm / reject / partial, без отказа всем пакетом;
- autoDecisions и ручной ответ: без правила «целиком», квал-предупреждение — отказ только по своей бумаге;
- признак ИИС из заголовка запроса (IIAAgreementDetails), у сохранённых раньше — по исходному XML;
- форма оператора: без автоматического «отказ всем», подсказка про ИИС; тексты и тесты.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
This commit is contained in:
zuevav
2026-09-25 15:36:58 +03:00
parent 76b97b0755
commit 92afdd2868
12 changed files with 90 additions and 103 deletions
+13 -8
View File
@@ -3,8 +3,9 @@ package lkgateway
// Автоматический режим M2M (решение 16.09.2026): ручные шаги оператора выполняются без участия
// человека, чтобы соблюдать сроки и убрать человеческий фактор.
//
// - Входящий перевод ждёт решения → свежая сверка с DEPO → решение по её рекомендации: пакет
// принимается только целиком; предупреждение со Strict (бумага для квалифицированных инвесторов
// - Входящий перевод ждёт решения → свежая сверка с DEPO → решение по её рекомендации: каждая
// бумага решается сама по себе (частичный приём), переводы на ИИС — отказ M2M07 по всем бумагам;
// предупреждение со Strict (бумага для квалифицированных инвесторов
// при неполной квалификации клиента) — отказ M2M08. Без сверки ничего не принимается: если DEPO
// или ИШ недоступны, bj повторяет каждые m2mAutoRetry и шлёт оповещение.
// - После нашего согласия НРД присылает черновик 16/1 (MF010) → поручение подаётся автоматически.
@@ -144,15 +145,19 @@ func incomingHasConfirmed(it *IncomingTransfer) bool {
}
// autoDecisions — решение по результату сверки: рекомендация по каждой бумаге, Strict-предупреждение
// даёт отказ M2M08, пакет только целиком. why — пояснение для карточки.
// даёт отказ M2M08 по этой бумаге, остальные решаются сами по себе; перевод на ИИС — отказ всем. why — пояснение для карточки.
func autoDecisions(it *IncomingTransfer, r depoResult) (decisions []SecurityDecision, why string) {
bySec := map[string]depoSecResult{}
strictSec := map[string]bool{} // бумаги для квал. инвесторов при неполной квалификации — отказ M2M08 именно по ним
strict := ""
for _, sr := range r.Secs {
bySec[sr.ReferenceID] = sr
for _, c := range sr.Checks {
if c.Strict && c.Warn && strict == "" {
strict = sr.Security
if c.Strict && c.Warn {
strictSec[sr.ReferenceID] = true
if strict == "" {
strict = sr.Security
}
}
}
}
@@ -162,7 +167,7 @@ func autoDecisions(it *IncomingTransfer, r depoResult) (decisions []SecurityDeci
switch {
case !ok:
d.RejectCode = "M2M05"
case strict != "":
case strictSec[sec.ReferenceID]:
d.RejectCode = "M2M08"
case sr.Recommend == "confirm":
d.Confirm = true
@@ -174,10 +179,10 @@ func autoDecisions(it *IncomingTransfer, r depoResult) (decisions []SecurityDeci
}
decisions = append(decisions, d)
}
decisions = packageDecisions(decisions)
decisions = iisDecisions(it, decisions)
why = r.Summary
if strict != "" {
why = "отказ M2M08: бумага " + strict + " для квалифицированных инвесторов, квалификация клиента неполная"
why += "; отказ M2M08 по " + strict + ": бумага для квалифицированных инвесторов, квалификация клиента неполная"
}
return decisions, why
}