bf7c7b53bd
Настройка в шаге «Время и сеть» и Настройка → Сервер: дни недели, часы (по поясу сервера), включение правила. Запрос, полученный вне рабочего времени (и после включения правила), bj сразу отклоняет по всем бумагам кодом M2M06 «Приостановление операций по счёту депо зачисления» — кода «вне рабочего времени» в перечне НРД (инструкция по обмену M2M, раздел 7.4) нет, решение депозитария. Строка «Рабочее время» в проверке готовности; сквозной тест отказа через ИШ. Файл входящих — переменная (тесты не трогают сервер). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
113 lines
5.0 KiB
Go
113 lines
5.0 KiB
Go
package lkgateway
|
||
|
||
import (
|
||
"context"
|
||
"io"
|
||
"net/http"
|
||
"net/http/httptest"
|
||
"path/filepath"
|
||
"strings"
|
||
"testing"
|
||
"time"
|
||
|
||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/nsdadapter/igw"
|
||
)
|
||
|
||
func TestWorkHoursOpen(t *testing.T) {
|
||
at := func(s string) time.Time { // 06.10.2026 — вторник
|
||
tm, err := time.ParseInLocation("02.01.2006 15:04", s, time.Local)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
return tm
|
||
}
|
||
w := WorkHoursSettings{Enabled: true, Days: []int{1, 2, 3, 4, 5}, From: "09:00", To: "18:00"}
|
||
cases := map[string]bool{
|
||
"06.10.2026 08:59": false, "06.10.2026 09:00": true, "06.10.2026 17:59": true, "06.10.2026 18:00": false,
|
||
"10.10.2026 12:00": false, // суббота
|
||
"12.10.2026 10:00": true, // понедельник
|
||
}
|
||
for s, want := range cases {
|
||
if got := w.Open(at(s)); got != want {
|
||
t.Errorf("%s: %v, ожидалось %v", s, got, want)
|
||
}
|
||
}
|
||
night := WorkHoursSettings{Enabled: true, Days: []int{5}, From: "20:00", To: "08:00"} // пятница, ночная смена
|
||
if !night.Open(at("09.10.2026 21:00")) || !night.Open(at("10.10.2026 07:00")) || night.Open(at("10.10.2026 21:00")) {
|
||
t.Error("ночная смена")
|
||
}
|
||
if !(WorkHoursSettings{}).Open(at("10.10.2026 03:00")) {
|
||
t.Error("правило выключено — всегда открыто")
|
||
}
|
||
if got := w.Text(); got != "пн–пт 09:00–18:00" {
|
||
t.Errorf("текст: %q", got)
|
||
}
|
||
if got := (WorkHoursSettings{Days: []int{1, 3, 4}}).Text(); got != "пн, ср, чт 09:00–18:00" {
|
||
t.Errorf("текст: %q", got)
|
||
}
|
||
}
|
||
|
||
// Запрос, полученный вне рабочего времени, получает отказ M2M06 по всем бумагам; полученный в рабочее время —
|
||
// ждёт решения как обычно; полученный до включения правила — не трогается.
|
||
func TestWorkHoursRejectsOffHours(t *testing.T) {
|
||
old := incomingStateFile
|
||
incomingStateFile = filepath.Join(t.TempDir(), "incoming.json")
|
||
defer func() { incomingStateFile = old }()
|
||
var sent []string
|
||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
b, _ := io.ReadAll(r.Body)
|
||
sent = append(sent, r.Method+" "+r.URL.Path+" "+string(b))
|
||
_, _ = io.WriteString(w, `{"id":42}`)
|
||
}))
|
||
defer srv.Close()
|
||
rc, _ := NewRuntimeConfig(filepath.Join(t.TempDir(), "setup.json"))
|
||
_ = rc.UpdateNSD(NSDSettings{DeponentCode: "MC0413600000", OrgINN: "7703807489"})
|
||
enabledAt := time.Date(2026, 10, 1, 0, 0, 0, 0, time.Local)
|
||
_ = rc.UpdateWorkHours(WorkHoursSettings{Enabled: true, Days: []int{1, 2, 3, 4, 5}, From: "09:00", To: "18:00", SavedAt: enabledAt})
|
||
store := &IncomingStore{items: map[string]*IncomingTransfer{}}
|
||
mk := func(id string, at time.Time) {
|
||
store.items[id] = &IncomingTransfer{ID: id, GUID: "6f1c2a7e-0d4b-4c8a-9e2f-3b5d7a9c1e0" + id, ReceivedAt: at, Status: "pending",
|
||
SenderCode: "MC0012500000", ReceiverCode: "MC0413600000", InvestorLast: "Бубликов",
|
||
Securities: []IncomingSecurity{{ReferenceID: "M2MREF0000000001", SecurityCode: "RU0009029540", Quantity: "1"}, {ReferenceID: "M2MREF0000000002", SecurityCode: "RU000A0JUR61", Quantity: "2"}}}
|
||
}
|
||
mk("1", time.Date(2026, 10, 10, 20, 0, 0, 0, time.Local)) // суббота вечер
|
||
mk("2", time.Date(2026, 10, 6, 11, 0, 0, 0, time.Local)) // вторник, рабочее время
|
||
mk("3", time.Date(2026, 9, 27, 20, 0, 0, 0, time.Local)) // до включения правила
|
||
saved := globalIncomingDeps
|
||
globalIncomingDeps = &incomingDeps{store: store, igwClient: igw.NewClient(srv.URL), igwChan: "TEST3MC0413600000", rc: rc, ourCode: "MC0413600000"}
|
||
defer func() { globalIncomingDeps = saved }()
|
||
m2mAuto.done("workhours:1")
|
||
|
||
workHoursTick(context.Background(), rc, time.Date(2026, 10, 10, 20, 1, 0, 0, time.Local))
|
||
|
||
posts := 0
|
||
for _, x := range sent { // POST пакета; GET — клиент ИШ сам спрашивает статус доставки
|
||
if strings.HasPrefix(x, "POST /api/package/TEST3MC0413600000/file") {
|
||
posts++
|
||
}
|
||
}
|
||
if posts != 1 {
|
||
for _, n := range rc.Snapshot().News.Items {
|
||
t.Log(n.Title, " — ", n.Body)
|
||
}
|
||
t.Fatalf("в шлюз должен уйти один пакет решения, ушло %d", posts)
|
||
}
|
||
it, _ := store.Get("1")
|
||
if it.Status != "answered" || !strings.Contains(it.AnswerNote, "вне рабочего времени") {
|
||
t.Fatalf("запрос вне рабочего времени: %s / %s", it.Status, it.AnswerNote)
|
||
}
|
||
for _, s := range it.Securities {
|
||
if s.Decision != "rejected" || s.RejectCode != workHoursRejectCode {
|
||
t.Errorf("бумага %s: %s %s, ожидался отказ %s", s.ReferenceID, s.Decision, s.RejectCode, workHoursRejectCode)
|
||
}
|
||
}
|
||
if !strings.Contains(it.DecisionXML, workHoursRejectCode) {
|
||
t.Error("в решении нет кода M2M06")
|
||
}
|
||
for _, id := range []string{"2", "3"} {
|
||
if it, _ := store.Get(id); it.Status != "pending" {
|
||
t.Errorf("запрос %s не должен был получить ответ: %s", id, it.Status)
|
||
}
|
||
}
|
||
}
|