da12a9ec1c
- bj_exchange и «кран» Fancy убраны: данные модуля ЛК в PostgreSQL (схема lk) - трансферные таблицы FTV_M2M: создание при установке, события, справочник участников - сверка с DEPO: счёт, ФИО, дата рождения, ИИС по договору, квал-инвестор из опции DEPO - боевой ЛК ЕСИА Финанс при тестовом ИШ: журнал, отказ через DEPO, статусы в ЛК - онлайн-лицензирование в bj, план тестирования M2M для контрагента (интерактивный HTML) - модули QUIK МНП, экспорт QUIK, НПР/УДС; документы и тестовые материалы Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
128 lines
4.6 KiB
Go
128 lines
4.6 KiB
Go
package lkgateway
|
|
|
|
// depo_sim.go — песочница сверки с DEPO («имитация ответа Fancy»).
|
|
// Два режима: «зачисление» (входящий) и «списание» (исходящий). Оператор берёт
|
|
// реального клиента и бумагу из DEPO, меняет любые поля и нажимает «Проверить» —
|
|
// отрабатывают те же runDepoCheck / runDepoCheckOut, что и по настоящим
|
|
// переводам. В НРД и контрагенту ничего не отправляется.
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type depoSimClient struct{ Name, Ser, Num, Account string }
|
|
type depoSimSec struct{ ISIN, Name string }
|
|
|
|
// depoSimLists — реальные клиенты с открытым торговым счётом и бумаги на
|
|
// обслуживании из DEPO (для выпадающих списков). Ошибки глушим — списки
|
|
// вспомогательные, форму можно заполнить руками.
|
|
func depoSimLists() (clients []depoSimClient, secs []depoSimSec) {
|
|
if globalRC == nil {
|
|
return
|
|
}
|
|
fs := globalRC.Snapshot().Fancy
|
|
if strings.TrimSpace(fs.Server) == "" {
|
|
return
|
|
}
|
|
db, err := fancyOpen(fs, fs.DepoDB())
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer db.Close()
|
|
ctx, cancel := context.WithTimeout(context.Background(), 8*time.Second)
|
|
defer cancel()
|
|
|
|
rows, err := db.QueryContext(ctx,
|
|
`SELECT TOP 25 ISNULL(f.NAME,''), ISNULL(f.DOC_SER,''), ISNULL(f.DOC_NUM,''), ISNULL(c.NUMBER,'')
|
|
FROM OD_FACES f JOIN OD_CLIENTS c ON c.FACE=f.ID
|
|
WHERE c.NUMBER LIKE N'ВТНКЦ%' AND c.STATE=0 AND c.D_CLOSE IS NULL
|
|
AND LEN(ISNULL(f.DOC_SER,''))>0 AND LEN(ISNULL(f.DOC_NUM,''))>0
|
|
ORDER BY f.NAME`)
|
|
if err == nil {
|
|
defer rows.Close()
|
|
seen := map[string]bool{}
|
|
for rows.Next() {
|
|
var c depoSimClient
|
|
if rows.Scan(&c.Name, &c.Ser, &c.Num, &c.Account) == nil && !seen[c.Name] {
|
|
seen[c.Name] = true
|
|
c.Ser = strings.ReplaceAll(c.Ser, " ", "")
|
|
clients = append(clients, c)
|
|
}
|
|
}
|
|
}
|
|
rows2, err := db.QueryContext(ctx,
|
|
`SELECT TOP 20 ISNULL(ISIN,''), ISNULL(NAME,'') FROM OD_VALUES
|
|
WHERE V_TYPE=2 AND IS_IN=1 AND ISIN LIKE 'RU%' ORDER BY NAME`)
|
|
if err == nil {
|
|
defer rows2.Close()
|
|
for rows2.Next() {
|
|
var s depoSimSec
|
|
if rows2.Scan(&s.ISIN, &s.Name) == nil && s.ISIN != "" {
|
|
secs = append(secs, s)
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// registerDepoSim вешает /admin/m2m-testing/depo-sim (GET — форма, POST — проверка).
|
|
func registerDepoSim(mux *http.ServeMux, a *admin) {
|
|
mux.HandleFunc("/admin/m2m-testing/depo-sim", func(w http.ResponseWriter, r *http.Request) {
|
|
_ = r.ParseForm()
|
|
v := func(k, def string) string {
|
|
if s := strings.TrimSpace(r.FormValue(k)); s != "" {
|
|
return s
|
|
}
|
|
return def
|
|
}
|
|
defAcc, defSec := "HL171004001C", "36MC0413600000F00"
|
|
if globalRC != nil {
|
|
nsd := globalRC.Snapshot().NSD
|
|
defAcc, defSec = pick(nsd.AccountID, defAcc), pick(nsd.SectionID, defSec)
|
|
}
|
|
form := struct {
|
|
Mode, Last, First, Middle, Ser, Num, ISIN, Code, Qty, Account, Section string
|
|
}{
|
|
Mode: v("mode", "in"),
|
|
Last: v("last", "Силаев"), First: v("first", "Михаил"), Middle: v("middle", "Иванович"),
|
|
Ser: v("ser", "4505"), Num: v("num", "620343"),
|
|
ISIN: strings.ToUpper(v("isin", "RU0009029540")), Code: v("code", ""), Qty: v("qty", "10"),
|
|
Account: v("account", defAcc), Section: v("section", defSec),
|
|
}
|
|
if form.Mode != "out" {
|
|
form.Mode = "in"
|
|
}
|
|
var res *depoResult
|
|
if r.Method == http.MethodPost {
|
|
var rr depoResult
|
|
if form.Mode == "out" {
|
|
rr = runDepoCheckOut(form.Last, form.First, form.Middle, form.Ser, form.Num,
|
|
[]depoOutSec{{ReferenceID: "sim-1", ISIN: form.ISIN, Code: pick(form.Code, form.ISIN), Qty: form.Qty}},
|
|
form.Account, form.Section)
|
|
} else {
|
|
it := &IncomingTransfer{
|
|
GUID: "SIMULATION", SenderCode: "SIM", ReceivedAt: time.Now(),
|
|
InvestorLast: form.Last, InvestorFirst: form.First, InvestorMiddle: form.Middle,
|
|
DocType: "21", DocSeries: form.Ser, DocNumber: form.Num,
|
|
Securities: []IncomingSecurity{{ReferenceID: "sim-1", ISIN: form.ISIN, SecurityCode: pick(form.Code, form.ISIN), Quantity: form.Qty}},
|
|
}
|
|
rr = runDepoCheck(it)
|
|
}
|
|
res = &rr
|
|
}
|
|
clients, secs := depoSimLists()
|
|
data := struct {
|
|
page
|
|
Form any
|
|
Result *depoResult
|
|
Clients []depoSimClient
|
|
Secs []depoSimSec
|
|
Posted bool
|
|
}{nowPage("Имитация сверки с DEPO", "m2mtest"), form, res, clients, secs, r.Method == http.MethodPost}
|
|
render(w, a.depoSim, data)
|
|
})
|
|
}
|