package lkgateway import ( "strings" "testing" "time" ) func TestAutoDecisions(t *testing.T) { it := &IncomingTransfer{Securities: []IncomingSecurity{{ReferenceID: "A"}, {ReferenceID: "B"}}} // Всё прошло — согласие по всем. r := depoResult{Summary: "принять", Secs: []depoSecResult{{ReferenceID: "A", Recommend: "confirm"}, {ReferenceID: "B", Recommend: "confirm"}}} dec, _ := autoDecisions(it, r) if !dec[0].Confirm || !dec[1].Confirm { t.Fatalf("согласие: %+v", dec) } // Отказ по одной — отказ всем пакетом с её кодом. r = depoResult{Summary: "отказ пакетом M2M05", Secs: []depoSecResult{{ReferenceID: "A", Recommend: "confirm"}, {ReferenceID: "B", Recommend: "reject", RejectCode: "M2M05"}}} dec, _ = autoDecisions(it, r) for _, d := range dec { if d.Confirm || d.RejectCode != "M2M05" { t.Fatalf("пакет целиком: %+v", dec) } } // Бумага для квал. инвесторов при неполной квалификации — отказ M2M08 всем. r = depoResult{Summary: "принять", Secs: []depoSecResult{ {ReferenceID: "A", Security: "RU000A10F5K6", Recommend: "confirm", Checks: []depoCheck{{Name: "Бумага только для квал. инвесторов", OK: true, Warn: true, Strict: true, Code: "M2M08"}}}, {ReferenceID: "B", Recommend: "confirm", Checks: []depoCheck{{Name: "Квал-инвестор (если бумага только для квал.)", OK: true, Warn: true, Code: "M2M08"}}}, }} dec, why := autoDecisions(it, r) for _, d := range dec { if d.Confirm || d.RejectCode != "M2M08" { t.Fatalf("строгое предупреждение: %+v", dec) } } if !strings.Contains(why, "RU000A10F5K6") { t.Fatalf("пояснение: %q", why) } // Обычное предупреждение (клиент не квал, бумага без ограничений) отказа не даёт. r = depoResult{Secs: []depoSecResult{ {ReferenceID: "A", Recommend: "confirm", Checks: []depoCheck{{OK: true, Warn: true, Code: "M2M08"}}}, {ReferenceID: "B", Recommend: "confirm"}, }} if dec, _ = autoDecisions(it, r); !dec[0].Confirm || !dec[1].Confirm { t.Fatalf("информационное предупреждение не должно отказывать: %+v", dec) } // Бумага без результата сверки — не принимаем. r = depoResult{Secs: []depoSecResult{{ReferenceID: "A", Recommend: "confirm"}}} if dec, _ = autoDecisions(it, r); dec[0].Confirm || dec[1].Confirm { t.Fatalf("без сверки по бумаге: %+v", dec) } } func TestM2MAutoState(t *testing.T) { st := &m2mAutoState{next: map[string]time.Time{}, alerted: map[string]time.Time{}} now := time.Now() if !st.due("k", now) { t.Fatal("новый шаг должен выполняться сразу") } st.retry("k", now) if st.due("k", now.Add(time.Minute)) || !st.due("k", now.Add(m2mAutoRetry)) { t.Fatal("повтор через m2mAutoRetry") } st.done("k") if !st.due("k", now) { t.Fatal("после выполнения ключ сбрасывается") } } // Выключенный режим ничего не делает (и не трогает сторы). func TestM2MAutoDisabled(t *testing.T) { rc, err := NewRuntimeConfig(t.TempDir() + "/setup.json") if err != nil { t.Fatal(err) } saved := globalIncomingDeps globalIncomingDeps = nil defer func() { globalIncomingDeps = saved }() m2mAutoTickOnce(t.Context(), rc, time.Now()) }