Firebird: автоопределение из DEPO как на MSSQL — реквизиты организации и поиск без учёта регистра
Проверено по шагам мастера, что bj берёт из DEPO сам: подготовка базы, префикс счетов (шаг 3), реквизиты (шаг 4), готовность (шаг 10), ручной ввод, подбор клиента для портфеля ЛК. - Реквизиты (Det01): счёт НРД ссылается на исходную версию лица, а ИНН НРД бывает только в новых (в исходной — ИНН НДЦ) — лицо по любой версии (ID или SELF_ID; ИНН НРД или MNEM «НДЦ»); номер счёта — и «счёт/раздел», не только «счёт/LEI/код/раздел». Счёт НРД — тот, с которым записан выбранный раздел (пара «раздел + счёт» — по ней процедуры находят место хранения), а не самый частый. Для MSSQL — только шире: прежнее находится. - Поиск по ФИО, договору и счёту — без учёта регистра, как в MSSQL (Cyrillic_General_CI_AS): в базе Fancy с кодировкой NONE регистр кириллицы различается — Firebird-варианты сравнивают в WIN1251 (подбор клиента для портфеля ЛК — запросы вынесены в fsql/lkportfolio.go, поиск и список договоров). - На копии базы: шаг 4 — счёт, код, разделы, ИНН и наименования организации; поиск «бр-1147», «бубликов» находит; FBLivePrepare — 103 из 103. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
This commit is contained in:
@@ -75,14 +75,15 @@ func depoDetectRequisites(ctx context.Context, fs FancyMSSQLSettings) (*DepoRequ
|
|||||||
accounts := map[string]int{}
|
accounts := map[string]int{}
|
||||||
codes := map[string]int{}
|
codes := map[string]int{}
|
||||||
sections := map[string]bool{}
|
sections := map[string]bool{}
|
||||||
|
pairs := map[string]map[string]int{} // открытый раздел → счета, с которыми он записан в DEPO
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var number, name string
|
var number, name string
|
||||||
var state int
|
var state int
|
||||||
if rows.Scan(&number, &state, &name) != nil {
|
if rows.Scan(&number, &state, &name) != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
parts := strings.Split(strings.TrimSpace(number), "/")
|
parts := strings.Split(strings.TrimSpace(number), "/") // счёт/LEI/код/раздел или счёт/раздел
|
||||||
if len(parts) < 4 {
|
if len(parts) < 2 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
acc, sec := strings.TrimSpace(parts[0]), strings.TrimSpace(parts[len(parts)-1])
|
acc, sec := strings.TrimSpace(parts[0]), strings.TrimSpace(parts[len(parts)-1])
|
||||||
@@ -93,6 +94,12 @@ func depoDetectRequisites(ctx context.Context, fs FancyMSSQLSettings) (*DepoRequ
|
|||||||
codes[m[2]]++
|
codes[m[2]]++
|
||||||
if state == 0 {
|
if state == 0 {
|
||||||
sections[sec] = true
|
sections[sec] = true
|
||||||
|
if depoAccountRe.MatchString(acc) {
|
||||||
|
if pairs[sec] == nil {
|
||||||
|
pairs[sec] = map[string]int{}
|
||||||
|
}
|
||||||
|
pairs[sec][acc]++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,7 +131,21 @@ func depoDetectRequisites(ctx context.Context, fs FancyMSSQLSettings) (*DepoRequ
|
|||||||
}
|
}
|
||||||
res.Notes = append(res.Notes, "раздела "+want+" нет среди открытых — проверьте выбранный раздел")
|
res.Notes = append(res.Notes, "раздела "+want+" нет среди открытых — проверьте выбранный раздел")
|
||||||
}
|
}
|
||||||
if len(accounts) > 1 {
|
// счёт — тот, с которым выбранный раздел записан в DEPO: по паре «раздел + счёт» процедуры обработки
|
||||||
|
// находят место хранения (у организации бывает несколько счетов в НРД с торговым разделом)
|
||||||
|
if p := pairs[res.SectionID]; len(p) > 0 {
|
||||||
|
res.AccountID = mostCommon(p)
|
||||||
|
if len(p) > 1 {
|
||||||
|
var other []string
|
||||||
|
for a := range p {
|
||||||
|
if a != res.AccountID {
|
||||||
|
other = append(other, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(other)
|
||||||
|
res.Notes = append(res.Notes, fmt.Sprintf("раздел %s записан в DEPO с несколькими счетами в НРД — выбран %s, есть ещё %s: проверьте по договору с НРД", res.SectionID, res.AccountID, strings.Join(other, ", ")))
|
||||||
|
}
|
||||||
|
} else if len(accounts) > 1 {
|
||||||
res.Notes = append(res.Notes, fmt.Sprintf("в DEPO несколько депозитарных счетов в НРД (%d) — выбран самый частый %s", len(accounts), res.AccountID))
|
res.Notes = append(res.Notes, fmt.Sprintf("в DEPO несколько депозитарных счетов в НРД (%d) — выбран самый частый %s", len(accounts), res.AccountID))
|
||||||
}
|
}
|
||||||
// организация по коду участника
|
// организация по коду участника
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ func depoListContracts(ctx context.Context, s FancyMSSQLSettings, search string,
|
|||||||
if limit <= 0 || limit > 500 {
|
if limit <= 0 || limit > 500 {
|
||||||
limit = 100
|
limit = 100
|
||||||
}
|
}
|
||||||
q := fmt.Sprintf(fsql.Dp02, limit)
|
q := fmt.Sprintf(depoSQL(s, fsql.Dp02), limit)
|
||||||
rows, err := conn.QueryContext(cctx, q, search, "%"+likeEscape(search)+"%")
|
rows, err := conn.QueryContext(cctx, q, search, "%"+likeEscape(search)+"%")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -221,7 +221,7 @@ func depoFindContracts(ctx context.Context, s FancyMSSQLSettings, like string, l
|
|||||||
limit = 50
|
limit = 50
|
||||||
}
|
}
|
||||||
rows, err := conn.QueryContext(cctx, fmt.Sprintf(
|
rows, err := conn.QueryContext(cctx, fmt.Sprintf(
|
||||||
fsql.QDb02, limit),
|
depoSQL(s, fsql.QDb02), limit),
|
||||||
"%"+like+"%")
|
"%"+like+"%")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ var (
|
|||||||
fbDatePartRe = regexp.MustCompile(`(?i)\b(YEAR|MONTH|DAY)\s*\(\s*([A-Za-z_][A-Za-z0-9_.]*)\s*\)`)
|
fbDatePartRe = regexp.MustCompile(`(?i)\b(YEAR|MONTH|DAY)\s*\(\s*([A-Za-z_][A-Za-z0-9_.]*)\s*\)`)
|
||||||
fbFloatRe = regexp.MustCompile(`(?i)\bAS\s+float\b`)
|
fbFloatRe = regexp.MustCompile(`(?i)\bAS\s+float\b`)
|
||||||
fbTopRe = regexp.MustCompile(`(?i)\bSELECT(\s+DISTINCT)?\s+TOP\s*(\(\s*@?\w+\s*\)|\d+)`)
|
fbTopRe = regexp.MustCompile(`(?i)\bSELECT(\s+DISTINCT)?\s+TOP\s*(\(\s*@?\w+\s*\)|\d+)`)
|
||||||
fbGUIDRe = regexp.MustCompile(`^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$`)
|
fbGUIDRe = regexp.MustCompile(`^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$`)
|
||||||
fbISOTimeRe = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d+)?)?$`)
|
fbISOTimeRe = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d+)?)?$`)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ var fbLiveFmtRe = regexp.MustCompile(`%(\[\d\])?s`)
|
|||||||
var fbLiveSkip = map[string]bool{
|
var fbLiveSkip = map[string]bool{
|
||||||
"Doc02": true, "Doc03": true, "Doc04": true, "Sn01": true, "Sn02": true, "Sn03": true, "Sn04": true, "Sn05": true,
|
"Doc02": true, "Doc03": true, "Doc04": true, "Sn01": true, "Sn02": true, "Sn03": true, "Sn04": true, "Sn05": true,
|
||||||
"On01": true, "On02": true, "On03": true, "Pr01": true, "Qk01": true, "Cl01": true, "Tbl01": true, "Tbl02": true, "QTb01": true,
|
"On01": true, "On02": true, "On03": true, "Pr01": true, "Qk01": true, "Cl01": true, "Tbl01": true, "Tbl02": true, "QTb01": true,
|
||||||
"Ev05": true, // DEPONENT_ID — пишется, только если колонка есть (depoHasColumn)
|
"Ev05": true, // DEPONENT_ID — пишется, только если колонка есть (depoHasColumn)
|
||||||
"Que04": true, "Que05": true,
|
"Que04": true, "Que05": true,
|
||||||
"Ev06": true, "Ev07": true, "Ev08": true, "Ev09": true, "Que01": true, "Que02": true, "Que03": true, "Flow01": true, "Flow02": true,
|
"Ev06": true, "Ev07": true, "Ev08": true, "Ev09": true, "Que01": true, "Que02": true, "Que03": true, "Flow01": true, "Flow02": true,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ package lkgateway
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -31,6 +32,15 @@ func fbLiveSettings(t *testing.T) FancyMSSQLSettings {
|
|||||||
DepoDatabase: strings.TrimPrefix(u.Path, "/"), AccountPrefix: os.Getenv("BJ_FB_TEST_ACC")}
|
DepoDatabase: strings.TrimPrefix(u.Path, "/"), AccountPrefix: os.Getenv("BJ_FB_TEST_ACC")}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fbLiveDB(t *testing.T, s FancyMSSQLSettings) *sql.DB {
|
||||||
|
db, err := fancyOpen(s, s.DepoDB())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Cleanup(func() { db.Close() })
|
||||||
|
return db
|
||||||
|
}
|
||||||
|
|
||||||
func TestFBLiveLK(t *testing.T) {
|
func TestFBLiveLK(t *testing.T) {
|
||||||
s := fbLiveSettings(t)
|
s := fbLiveSettings(t)
|
||||||
rc, err := NewRuntimeConfig(t.TempDir() + "/setup.json")
|
rc, err := NewRuntimeConfig(t.TempDir() + "/setup.json")
|
||||||
@@ -78,6 +88,15 @@ func TestFBLiveLK(t *testing.T) {
|
|||||||
check("depoListContracts", err, len(lst), first(len(lst), lst))
|
check("depoListContracts", err, len(lst), first(len(lst), lst))
|
||||||
fnd, err := depoFindContracts(ctx, s, contract[:2], 5)
|
fnd, err := depoFindContracts(ctx, s, contract[:2], 5)
|
||||||
check("depoFindContracts", err, len(fnd), fnd)
|
check("depoFindContracts", err, len(fnd), fnd)
|
||||||
|
// поиск без учёта регистра, как в MSSQL: строчными буквами
|
||||||
|
low := strings.ToLower(contract)
|
||||||
|
fnd, err = depoFindContracts(ctx, s, low, 5)
|
||||||
|
check("depoFindContracts("+low+")", err, len(fnd), fnd)
|
||||||
|
lst, err = depoListContracts(ctx, s, low, 5)
|
||||||
|
check("depoListContracts("+low+")", err, len(lst), lst)
|
||||||
|
if len(fnd) == 0 || len(lst) == 0 {
|
||||||
|
t.Errorf("поиск договора строчными (%s) не нашёл", low)
|
||||||
|
}
|
||||||
t.Logf("depoSuggestContracts: %v", depoSuggestContracts(ctx, s))
|
t.Logf("depoSuggestContracts: %v", depoSuggestContracts(ctx, s))
|
||||||
|
|
||||||
ids, face, accs, err := depoClientIDs(ctx, s, contract)
|
ids, face, accs, err := depoClientIDs(ctx, s, contract)
|
||||||
@@ -130,10 +149,23 @@ func TestFBLiveLK(t *testing.T) {
|
|||||||
}
|
}
|
||||||
ver, upd, err := depoVersion(ctx, s)
|
ver, upd, err := depoVersion(ctx, s)
|
||||||
t.Logf("depoVersion: %q %q %v", ver, upd, err)
|
t.Logf("depoVersion: %q %q %v", ver, upd, err)
|
||||||
|
rd := readyDepo(ctx, rc)
|
||||||
|
t.Logf("readyDepo (шаг 10): %s — %s", rd.State, rd.Detail)
|
||||||
|
|
||||||
fio := strings.Fields(os.Getenv("BJ_FB_TEST_FIO"))
|
fio := strings.Fields(os.Getenv("BJ_FB_TEST_FIO"))
|
||||||
pp := strings.Fields(os.Getenv("BJ_FB_TEST_PASSPORT"))
|
pp := strings.Fields(os.Getenv("BJ_FB_TEST_PASSPORT"))
|
||||||
if len(fio) == 3 && len(pp) == 2 {
|
if len(fio) == 3 && len(pp) == 2 {
|
||||||
|
cl, err := lkPortfolioClients(ctx, rc, strings.ToLower(fio[0]))
|
||||||
|
check("lkPortfolioClients("+strings.ToLower(fio[0])+")", err, len(cl), cl)
|
||||||
|
if len(cl) == 0 {
|
||||||
|
t.Errorf("подбор клиента для портфеля ЛК строчными (%s) не нашёл", strings.ToLower(fio[0]))
|
||||||
|
}
|
||||||
|
pairs, err := lkPortfolioAllPairs(ctx, rc, fbLiveDB(t, s))
|
||||||
|
check("lkPortfolioAllPairs", err, len(pairs), pairs)
|
||||||
|
low, _ := manualDepoSearch(rc, strings.ToLower(fio[0]))
|
||||||
|
if len(low) == 0 {
|
||||||
|
t.Errorf("ручной поиск клиента строчными (%s) не нашёл", strings.ToLower(fio[0]))
|
||||||
|
}
|
||||||
faces, msg := manualDepoSearch(rc, fio[0])
|
faces, msg := manualDepoSearch(rc, fio[0])
|
||||||
t.Logf("manualDepoSearch(%s): %d %s — %+v", fio[0], len(faces), msg, first(len(faces), faces))
|
t.Logf("manualDepoSearch(%s): %d %s — %+v", fio[0], len(faces), msg, first(len(faces), faces))
|
||||||
if len(faces) == 0 {
|
if len(faces) == 0 {
|
||||||
|
|||||||
@@ -3,9 +3,13 @@ package fsql
|
|||||||
// Автоопределение реквизитов депозитария в DEPO (Fancy) для первичной настройки.
|
// Автоопределение реквизитов депозитария в DEPO (Fancy) для первичной настройки.
|
||||||
|
|
||||||
// Det01 — счета депозитария в НРД: в DEPO это счета «лица НКО АО НРД» (ИНН 7702165310 одинаков у всех
|
// Det01 — счета депозитария в НРД: в DEPO это счета «лица НКО АО НРД» (ИНН 7702165310 одинаков у всех
|
||||||
// клиентов Fancy). NUMBER = <депозитарный счёт>/<LEI>/<код>/<раздел>.
|
// клиентов Fancy; кодировщик НРД — MNEM «НДЦ»). Счёт ссылается на исходную версию лица (SELF_ID), а ИНН НРД
|
||||||
var Det01 = `SELECT c.NUMBER, ISNULL(c.STATE,0), ISNULL(c.NAME,'') FROM OD_CLIENTS c JOIN OD_FACES f ON f.ID=c.FACE
|
// бывает только в новых (в исходной — прежний ИНН НДЦ), поэтому лицо — по любой версии. NUMBER —
|
||||||
WHERE f.INN='7702165310' AND c.NUMBER LIKE '%/%/%/%' ORDER BY c.STATE, c.NUMBER`
|
// <депозитарный счёт>/<LEI>/<код>/<раздел> или <депозитарный счёт>/<раздел> (обезличенная база Fancy на Firebird).
|
||||||
|
var Det01 = `SELECT c.NUMBER, ISNULL(c.STATE,0), ISNULL(c.NAME,'') FROM OD_CLIENTS c
|
||||||
|
WHERE c.NUMBER LIKE '%/%' AND EXISTS (SELECT 1 FROM OD_FACES f WHERE (f.ID = c.FACE OR f.SELF_ID = c.FACE)
|
||||||
|
AND (f.INN = '7702165310' OR f.MNEM = N'НДЦ'))
|
||||||
|
ORDER BY c.STATE, c.NUMBER`
|
||||||
|
|
||||||
// Det03 — карточка организации по коду участника НРД: действующая версия лица (кодер ссылается на исходную
|
// Det03 — карточка организации по коду участника НРД: действующая версия лица (кодер ссылается на исходную
|
||||||
// запись SELF_ID, действующая — LAST_FLAG=1) и юридические наименования из OD_U_FACES. NAME в OD_FACES —
|
// запись SELF_ID, действующая — LAST_FLAG=1) и юридические наименования из OD_U_FACES. NAME в OD_FACES —
|
||||||
|
|||||||
@@ -94,6 +94,26 @@ var FB = map[string]string{
|
|||||||
(SELECT FIRST 1 CAST(x.RATE AS DOUBLE PRECISION) FROM OD_VALUES_RATES x WHERE x.VALUE_ID = v.ID AND x.MARKET = 0 AND x.RATE > 0 ORDER BY x.OFICDATE DESC)
|
(SELECT FIRST 1 CAST(x.RATE AS DOUBLE PRECISION) FROM OD_VALUES_RATES x WHERE x.VALUE_ID = v.ID AND x.MARKET = 0 AND x.RATE > 0 ORDER BY x.OFICDATE DESC)
|
||||||
FROM OD_VALUES v WHERE v.V_TYPE = 1`,
|
FROM OD_VALUES v WHERE v.V_TYPE = 1`,
|
||||||
|
|
||||||
|
// Поиск по ФИО, договору и счёту без учёта регистра, как в MSSQL (Cyrillic_General_CI_AS): в базе Fancy с
|
||||||
|
// кодировкой NONE сравнение и UPPER различают регистр кириллицы — сравниваем в WIN1251.
|
||||||
|
Lkp01: `SELECT FIRST 50 COALESCE(p.PORT_NUM,''), COALESCE(f.NAME,''), c.NUMBER
|
||||||
|
FROM OD_CLIENTS c JOIN OD_FACES f ON f.ID=c.FACE LEFT JOIN OD_CLIENTS_PORTS p ON p.CLIENT=c.ID
|
||||||
|
WHERE c.NUMBER LIKE @pre AND c.STATE=0 AND c.D_CLOSE IS NULL
|
||||||
|
AND (UPPER(CAST(f.NAME AS VARCHAR(255) CHARACTER SET WIN1251)) LIKE UPPER(CAST(@q AS VARCHAR(260) CHARACTER SET WIN1251))
|
||||||
|
OR UPPER(CAST(p.PORT_NUM AS VARCHAR(255) CHARACTER SET WIN1251)) LIKE UPPER(CAST(@q AS VARCHAR(260) CHARACTER SET WIN1251))
|
||||||
|
OR UPPER(CAST(c.NUMBER AS VARCHAR(255) CHARACTER SET WIN1251)) LIKE UPPER(CAST(@q AS VARCHAR(260) CHARACTER SET WIN1251)))
|
||||||
|
ORDER BY f.NAME`,
|
||||||
|
QDb02: `SELECT FIRST (%d) DISTINCT PORT_NUM FROM OD_CLIENTS_PORTS
|
||||||
|
WHERE UPPER(CAST(PORT_NUM AS VARCHAR(255) CHARACTER SET WIN1251)) LIKE UPPER(CAST(@p1 AS VARCHAR(260) CHARACTER SET WIN1251)) ORDER BY PORT_NUM`,
|
||||||
|
Dp02: `SELECT FIRST (%d) p.PORT_NUM, COUNT(DISTINCT rst.VALUE_ID)
|
||||||
|
FROM OD_CLIENTS_PORTS p
|
||||||
|
JOIN OD_CLIENTS c ON c.ID = p.CLIENT
|
||||||
|
JOIN OD_RESTS rst ON rst.REG_1 = c.ID
|
||||||
|
JOIN OD_VALUES v ON v.ID = rst.VALUE_ID AND v.V_TYPE = 2
|
||||||
|
WHERE CAST(rst.K AS DOUBLE PRECISION) <> 0 AND (CAST(@p1 AS VARCHAR(255)) = ''
|
||||||
|
OR UPPER(CAST(p.PORT_NUM AS VARCHAR(255) CHARACTER SET WIN1251)) LIKE UPPER(CAST(@p2 AS VARCHAR(260) CHARACTER SET WIN1251)))
|
||||||
|
GROUP BY p.PORT_NUM ORDER BY p.PORT_NUM`,
|
||||||
|
|
||||||
// SELECT без FROM в Firebird нет
|
// SELECT без FROM в Firebird нет
|
||||||
QEvPosted: `SELECT (SELECT COUNT(*) FROM FTV_M2M WHERE GUID=@g),
|
QEvPosted: `SELECT (SELECT COUNT(*) FROM FTV_M2M WHERE GUID=@g),
|
||||||
(SELECT COUNT(*) FROM FTV_M2M_EVENTS WHERE GUID=@g AND EVENT_TYPE='BJ_ORDER_ACCEPTED' AND STATE='SUCCESS'),
|
(SELECT COUNT(*) FROM FTV_M2M_EVENTS WHERE GUID=@g AND EVENT_TYPE='BJ_ORDER_ACCEPTED' AND STATE='SUCCESS'),
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package fsql
|
||||||
|
|
||||||
|
// Lkp01 — поиск клиента для синхронизации портфеля ЛК: по ФИО, договору или счёту (до 50).
|
||||||
|
var Lkp01 = `SELECT TOP 50 ISNULL(p.PORT_NUM,''), ISNULL(f.NAME,''), c.NUMBER
|
||||||
|
FROM OD_CLIENTS c JOIN OD_FACES f ON f.ID=c.FACE LEFT JOIN OD_CLIENTS_PORTS p ON p.CLIENT=c.ID
|
||||||
|
WHERE c.NUMBER LIKE @pre AND c.STATE=0 AND c.D_CLOSE IS NULL AND (f.NAME LIKE @q OR p.PORT_NUM LIKE @q OR c.NUMBER LIKE @q)
|
||||||
|
ORDER BY f.NAME`
|
||||||
|
|
||||||
|
// Lkp02 — все открытые торговые счета с портфелем (режим «для всех клиентов»).
|
||||||
|
var Lkp02 = `SELECT ISNULL(p.PORT_NUM,''), c.NUMBER
|
||||||
|
FROM OD_CLIENTS c LEFT JOIN OD_CLIENTS_PORTS p ON p.CLIENT=c.ID
|
||||||
|
WHERE c.NUMBER LIKE @pre AND c.STATE=0 AND c.D_CLOSE IS NULL AND p.PORT_NUM IS NOT NULL`
|
||||||
@@ -24,6 +24,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -629,10 +631,7 @@ func lkPortfolioClients(ctx context.Context, rc *RuntimeConfig, q string) ([]LKP
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
cctx, cancel := context.WithTimeout(ctx, 15*time.Second)
|
cctx, cancel := context.WithTimeout(ctx, 15*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
rows, err := db.QueryContext(cctx, `SELECT TOP 50 ISNULL(p.PORT_NUM,''), ISNULL(f.NAME,''), c.NUMBER
|
rows, err := db.QueryContext(cctx, fsql.Lkp01, sql.Named("q", "%"+likeEscape(q)+"%"), sql.Named("pre", likeEscape(ps.accountPrefix())+"%"))
|
||||||
FROM OD_CLIENTS c JOIN OD_FACES f ON f.ID=c.FACE LEFT JOIN OD_CLIENTS_PORTS p ON p.CLIENT=c.ID
|
|
||||||
WHERE c.NUMBER LIKE @pre AND c.STATE=0 AND c.D_CLOSE IS NULL AND (f.NAME LIKE @q OR p.PORT_NUM LIKE @q OR c.NUMBER LIKE @q)
|
|
||||||
ORDER BY f.NAME`, sql.Named("q", "%"+likeEscape(q)+"%"), sql.Named("pre", likeEscape(ps.accountPrefix())+"%"))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -650,15 +649,12 @@ func lkPortfolioClients(ctx context.Context, rc *RuntimeConfig, q string) ([]LKP
|
|||||||
|
|
||||||
// lkPortfolioAllPairs — все открытые торговые счета DEPO с портфелем (режим «для всех
|
// lkPortfolioAllPairs — все открытые торговые счета DEPO с портфелем (режим «для всех
|
||||||
// клиентов»): фильтр по префиксу счёта, договор ЛК выводится из счёта по шаблону,
|
// клиентов»): фильтр по префиксу счёта, договор ЛК выводится из счёта по шаблону,
|
||||||
// портфель — PORT_NUM. Только MSSQL-база DEPO (как и поиск одного клиента).
|
// портфель — PORT_NUM.
|
||||||
func lkPortfolioAllPairs(ctx context.Context, rc *RuntimeConfig, db *sql.DB) ([]lkPortfolioPair, error) {
|
func lkPortfolioAllPairs(ctx context.Context, rc *RuntimeConfig, db *sql.DB) ([]lkPortfolioPair, error) {
|
||||||
ps := rc.Snapshot().LK.PortfolioSync
|
ps := rc.Snapshot().LK.PortfolioSync
|
||||||
cctx, cancel := context.WithTimeout(ctx, 30*time.Second)
|
cctx, cancel := context.WithTimeout(ctx, 30*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
rows, err := db.QueryContext(cctx, `SELECT ISNULL(p.PORT_NUM,''), c.NUMBER
|
rows, err := db.QueryContext(cctx, fsql.Lkp02, sql.Named("pre", likeEscape(ps.accountPrefix())+"%"))
|
||||||
FROM OD_CLIENTS c LEFT JOIN OD_CLIENTS_PORTS p ON p.CLIENT=c.ID
|
|
||||||
WHERE c.NUMBER LIKE @pre AND c.STATE=0 AND c.D_CLOSE IS NULL AND p.PORT_NUM IS NOT NULL`,
|
|
||||||
sql.Named("pre", likeEscape(ps.accountPrefix())+"%"))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user