1d0f904010
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
161 lines
6.8 KiB
Go
161 lines
6.8 KiB
Go
package lkgateway
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func manualTestOrder() *ManualOrder {
|
|
return &ManualOrder{
|
|
Status: "draft", PaperNo: "15", PaperDate: "2026-09-17", ReceivedVia: "лично в офисе",
|
|
LastName: "Иванов", FirstName: "Иван", MiddleName: "Иванович", BirthDate: "1980-01-02",
|
|
DocType: "21", DocSeries: "0000", DocNumber: "000000", Account: "СЧЁТ-1",
|
|
RecvINN: "7702165310", RecvName: "Депозитарий", SettlePlace: "nrd",
|
|
Securities: []ManualSec{{ISIN: "RU0009029540", Qty: "10"}},
|
|
}
|
|
}
|
|
|
|
func TestManualSendBlockers(t *testing.T) {
|
|
rc, err := NewRuntimeConfig(t.TempDir() + "/setup.json")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
o := manualTestOrder()
|
|
b := manualSendBlockers(rc, o)
|
|
if len(b) != len(manualPreChecks)+1 { // все отметки + способ блокировки в QUIK
|
|
t.Fatalf("без отметок: %v", b)
|
|
}
|
|
o.Checks = map[string]ManualMark{}
|
|
for _, c := range manualPreChecks {
|
|
o.Checks[c.Key] = ManualMark{Done: true}
|
|
}
|
|
o.QuikMode = "manual"
|
|
if b = manualSendBlockers(rc, o); len(b) != 1 || !strings.Contains(b[0], "номер поручения") {
|
|
t.Fatalf("ручная блокировка без номера: %v", b)
|
|
}
|
|
o.QuikInstr = "123"
|
|
if b = manualSendBlockers(rc, o); len(b) != 0 {
|
|
t.Fatalf("всё заполнено: %v", b)
|
|
}
|
|
o.QuikMode = "auto" // цикл QUIK не включён
|
|
if b = manualSendBlockers(rc, o); len(b) != 1 {
|
|
t.Fatalf("автоблокировка недоступна: %v", b)
|
|
}
|
|
o.QuikMode = "none"
|
|
o.Securities = []ManualSec{{ISIN: "US0378331005", Qty: "0"}}
|
|
if b = manualSendBlockers(rc, o); len(b) != 2 {
|
|
t.Fatalf("иностранная бумага и нулевое количество: %v", b)
|
|
}
|
|
o.Securities = []ManualSec{{ISIN: "RU0009029540", Qty: "1"}, {ISIN: "RU000A0JUR61", Qty: "1"}}
|
|
if b = manualSendBlockers(rc, o); len(b) != 1 || !strings.Contains(b[0], "одна бумага") {
|
|
t.Fatalf("одно поручение — одна бумага: %v", b)
|
|
}
|
|
}
|
|
|
|
func TestManualQtyAndClaim(t *testing.T) {
|
|
if q, ok := manualQty("1,5"); !ok || q.Fractional != "1.5" {
|
|
t.Fatalf("дробное: %+v", q)
|
|
}
|
|
if q, ok := manualQty("7"); !ok || q.Whole != 7 {
|
|
t.Fatalf("целое: %+v", q)
|
|
}
|
|
if _, ok := manualQty("-1"); ok {
|
|
t.Fatal("отрицательное")
|
|
}
|
|
rc, _ := NewRuntimeConfig(t.TempDir() + "/setup.json")
|
|
c, err := manualClaim(rc, manualTestOrder())
|
|
if err != nil || c.ClientAccount != "СЧЁТ-1" || c.Investor.BirthDate != "1980-01-02" || c.Securities[0].SecurityCode != "RU0009029540" || c.CostInfo.No == nil {
|
|
t.Fatalf("заявка: %+v %v", c, err)
|
|
}
|
|
}
|
|
|
|
// Страницы раздела: список, форма, карточка черновика, отметки, отказ, печать.
|
|
func TestManualPages(t *testing.T) {
|
|
saved := globalManual
|
|
globalManual = loadManualStore(t.TempDir() + "/manual.json")
|
|
defer func() { globalManual = saved }()
|
|
rc, err := NewRuntimeConfig(t.TempDir() + "/setup.json")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
mux := http.NewServeMux()
|
|
registerManual(mux, rc, nil)
|
|
do := func(method, path string, form url.Values) *httptest.ResponseRecorder {
|
|
var req *http.Request
|
|
if form != nil {
|
|
req = httptest.NewRequest(method, path, strings.NewReader(form.Encode()))
|
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
|
} else {
|
|
req = httptest.NewRequest(method, path, nil)
|
|
}
|
|
rec := httptest.NewRecorder()
|
|
mux.ServeHTTP(rec, req)
|
|
return rec
|
|
}
|
|
if rec := do("GET", "/admin/help/manual", nil); rec.Code != 200 || !strings.Contains(rec.Body.String(), "Порядок работы") {
|
|
t.Fatalf("инструкция: %d", rec.Code)
|
|
}
|
|
if rec := do("GET", "/admin/manual/new", nil); rec.Code != 200 || !strings.Contains(rec.Body.String(), "Новое поручение") {
|
|
t.Fatalf("форма: %d %s", rec.Code, rec.Body.String())
|
|
}
|
|
form := url.Values{"paper_no": {"15"}, "paper_date": {"2026-09-17"}, "last_name": {"Иванов"}, "first_name": {"Иван"},
|
|
"birth_date": {"1980-01-02"}, "doc_type": {"21"}, "doc_series": {"00 00"}, "doc_number": {"000000"}, "account": {"счёт-1"},
|
|
"recv_inn": {"7702165310"}, "sec_isin": {"ru0009029540", ""}, "sec_qty": {"10", ""}, "sec_code": {"", ""}, "sec_name": {"", ""}, "do": {"save"}}
|
|
rec := do("POST", "/admin/manual/save", form)
|
|
if rec.Code != http.StatusSeeOther || !strings.HasPrefix(rec.Header().Get("Location"), "/admin/manual/1") {
|
|
t.Fatalf("сохранение: %d %s", rec.Code, rec.Header().Get("Location"))
|
|
}
|
|
o, _ := globalManual.Get(1)
|
|
if o.DocSeries != "0000" || o.Account != "СЧЁТ-1" || len(o.Securities) != 1 || o.Securities[0].ISIN != "RU0009029540" {
|
|
t.Fatalf("данные: %+v", o)
|
|
}
|
|
if rec = do("GET", "/admin/manual/1", nil); rec.Code != 200 || !strings.Contains(rec.Body.String(), "Отправить пока нельзя") {
|
|
t.Fatalf("карточка: %d %s", rec.Code, rec.Body.String())
|
|
}
|
|
chk := url.Values{"quik_mode": {"none"}}
|
|
for _, c := range manualPreChecks {
|
|
chk.Set("check_"+c.Key, "1")
|
|
}
|
|
do("POST", "/admin/manual/1/checks", chk)
|
|
o, _ = globalManual.Get(1)
|
|
if len(manualSendBlockers(rc, o)) != 0 || o.Checks["paper"].At.IsZero() {
|
|
t.Fatalf("отметки: %+v %v", o.Checks, manualSendBlockers(rc, o))
|
|
}
|
|
if rec = do("GET", "/admin/manual/1", nil); !strings.Contains(rec.Body.String(), "Все проверки и отметки пройдены") {
|
|
t.Fatalf("готово к отправке: %s", rec.Body.String())
|
|
}
|
|
// Изменение данных сбрасывает отметки.
|
|
form.Set("id", "1")
|
|
form.Set("sec_qty", "11")
|
|
do("POST", "/admin/manual/save", form)
|
|
if o, _ = globalManual.Get(1); len(o.Checks) != 0 {
|
|
t.Fatalf("отметки должны сброситься: %+v", o.Checks)
|
|
}
|
|
do("POST", "/admin/manual/1/decline", url.Values{"reason": {"нет подписи клиента"}})
|
|
o, _ = globalManual.Get(1)
|
|
if o.Status != "declined" || o.DeclinedAt.Before(time.Now().Add(-time.Minute)) {
|
|
t.Fatalf("отказ: %+v", o)
|
|
}
|
|
for _, p := range []string{"/admin/manual", "/admin/manual/1", "/admin/manual/1/print"} {
|
|
if rec = do("GET", p, nil); rec.Code != 200 || !strings.Contains(rec.Body.String(), "нет подписи клиента") && p != "/admin/manual" {
|
|
t.Fatalf("%s: %d %s", p, rec.Code, rec.Body.String())
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestOrgIdentity(t *testing.T) {
|
|
var s Settings
|
|
s.NSD.DeponentCode = "MC0000000001"
|
|
if orgCode(s) != "MC0000000001" {
|
|
t.Fatalf("код по депозитарному коду: %q", orgCode(s))
|
|
}
|
|
s.NSD.OrgCode, s.NSD.OrgINN, s.NSD.OrgName = "mc0000000002", "7700000000", "Депозитарий"
|
|
if orgCode(s) != "MC0000000002" || orgINN(s) != "7700000000" || transferringINN(s) != "7700000000" || orgName(s) != "Депозитарий" {
|
|
t.Fatalf("организация из настроек: %q %q %q", orgCode(s), orgINN(s), orgName(s))
|
|
}
|
|
}
|