Входящие 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
+26 -23
View File
@@ -5,47 +5,50 @@ import (
"testing"
)
// Пакет принимается только целиком: отказ по одной бумаге — отказ по всем с тем же кодом.
func TestFinishResultWholePackage(t *testing.T) {
// Частичный приём (решение 25.09.2026): каждая бумага решается сама по себе.
func TestFinishResultPartial(t *testing.T) {
res := depoResult{Secs: []depoSecResult{
{Security: "RU0009029540", Recommend: "confirm"},
{Security: "RU0007661625", Recommend: "reject", RejectCode: "M2M05"},
{Security: "RU000A0JUR61", Recommend: "confirm"},
}}
finishResult(&res)
if res.Recommend != "reject" || !strings.Contains(res.Summary, "отказ пакетом M2M05") {
if res.Recommend != "partial" || !strings.Contains(res.Summary, "принять 2, отказ 1") {
t.Fatalf("итог: %s %q", res.Recommend, res.Summary)
}
for _, s := range res.Secs {
if s.Recommend != "reject" || s.RejectCode != "M2M05" {
t.Fatalf("бумага %s: %s %s", s.Security, s.Recommend, s.RejectCode)
}
if res.Secs[0].Recommend != "confirm" || res.Secs[2].Recommend != "confirm" || res.Secs[1].RejectCode != "M2M05" {
t.Fatalf("бумаги решаются отдельно: %+v", res.Secs)
}
if last := res.Secs[0].Checks[len(res.Secs[0].Checks)-1]; last.OK || !strings.Contains(last.Detail, "RU0007661625") {
t.Fatalf("пояснение отказа пакетом: %+v", last)
}
ok := depoResult{Secs: []depoSecResult{{Recommend: "confirm"}, {Recommend: "confirm"}}}
finishResult(&ok)
if ok.Recommend != "confirm" {
t.Fatalf("все бумаги прошли: %s", ok.Recommend)
}
no := depoResult{Secs: []depoSecResult{{Recommend: "reject", RejectCode: "M2M01"}, {Recommend: "reject", RejectCode: "M2M05"}}}
finishResult(&no)
if no.Recommend != "reject" || no.Summary != "отказ M2M01" {
t.Fatalf("все отклонены: %s %q", no.Recommend, no.Summary)
}
}
func TestPackageDecisions(t *testing.T) {
in := []SecurityDecision{{ReferenceID: "A", Confirm: true}, {ReferenceID: "B", RejectCode: "M2M08"}, {ReferenceID: "C", Confirm: true}}
out := packageDecisions(in)
for _, d := range out {
if d.Confirm || d.RejectCode != "M2M08" {
t.Fatalf("частичное согласие не должно уходить: %+v", out)
// Автоответ: частичное согласие уходит как есть; перевод на ИИС — отказ M2M07 по всем бумагам.
func TestAutoDecisionsPartialAndIIS(t *testing.T) {
it := &IncomingTransfer{Securities: []IncomingSecurity{{ReferenceID: "A"}, {ReferenceID: "B"}}}
r := depoResult{Secs: []depoSecResult{{ReferenceID: "A", Recommend: "confirm"}, {ReferenceID: "B", Recommend: "reject", RejectCode: "M2M05"}}}
d, _ := autoDecisions(it, r)
if !d[0].Confirm || d[1].Confirm || d[1].RejectCode != "M2M05" {
t.Fatalf("частичное согласие: %+v", d)
}
it.IIS = true
d, _ = autoDecisions(it, r)
for _, x := range d {
if x.Confirm || x.RejectCode != "M2M07" {
t.Fatalf("ИИС не принимаем: %+v", d)
}
}
if !in[0].Confirm {
t.Fatal("исходный срез не должен меняться")
}
all := []SecurityDecision{{ReferenceID: "A", Confirm: true}, {ReferenceID: "B", Confirm: true}}
if got := packageDecisions(all); !got[0].Confirm || !got[1].Confirm {
t.Fatalf("согласие по всем: %+v", got)
legacy := &IncomingTransfer{RawXML: "<x><IIAAgreementDetails/></x>"}
if !incomingIsIIS(legacy) {
t.Fatal("ИИС у сохранённого раньше перевода — по исходному XML")
}
}