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) } } }