Files
Bridge-and-Join-s/internal/lkgateway/workhours_test.go
T
zuevav bf7c7b53bd Рабочее время организации: запросы M2M вне него — отказ M2M06 (в любом режиме)
Настройка в шаге «Время и сеть» и Настройка → Сервер: дни недели, часы (по поясу сервера), включение
правила. Запрос, полученный вне рабочего времени (и после включения правила), bj сразу отклоняет по всем
бумагам кодом M2M06 «Приостановление операций по счёту депо зачисления» — кода «вне рабочего времени» в
перечне НРД (инструкция по обмену M2M, раздел 7.4) нет, решение депозитария. Строка «Рабочее время» в
проверке готовности; сквозной тест отказа через ИШ. Файл входящих — переменная (тесты не трогают сервер).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
2026-10-06 23:35:50 +03:00

113 lines
5.0 KiB
Go
Raw 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.
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)
}
}
}