Защита рецептов: SQL DEPO/SPECTRE/QUIK вынесен в пакет fsql под garble
Реализация варианта B из аудита защиты знаний. Прямой garble всего bj-server ломает html/template (он обращается к полям структур по имени, garble их переименовывает). Решение — селективная обфускация: GOGARBLE обфусцирует ТОЛЬКО пакет с секретами, шаблоны и обработчики не затрагиваются. 95 SQL-запросов к DEPO/SPECTRE/QUIK и трансферным таблицам FTV_M2M вынесены из lkgateway в отдельный пакет internal/lkgateway/fsql как переменные (именно var, не const: const компилятор вставил бы обратно в необфусцируемый пакет, и шифрование бы не сработало — проверено). Сами обработчики, типы и параметры sql.Named остались на месте; пакет держит только строки запросов. build-release.sh собирает bj-server с `GOGARBLE=.../fsql garble -literals` (нужен отдельный SDK go1.26 — модуль-кэшный тулчейн garble не подходит); если garble/go1.26 не найдены — обычная сборка с предупреждением. Проверено на реальном garble-бинаре (запускается, /admin и страницы на структурах работают): рецепт чтения чужих систем из бинаря исчез — OD_RESTS 13→0, OD_WIRING 5→0, OD_TURNS 1→0, OD_BALANCES 3→0, D_B_CONTRACTS 1→0, OD_CLIENTS_PORTS 10→0, DepoLimits/MoneyLimits →0. Остаток FTV_M2M — упоминания имён таблиц в операторских embed-шаблонах и логах, не сам рецепт. Стенд собран обычной сборкой (без garble) — трассировки остаются читаемыми. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q4YVo4UMopqT5DzicqpPjL
This commit is contained in:
@@ -25,6 +25,7 @@ import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -113,8 +114,7 @@ func depoResolveParty(ctx context.Context, db *sql.DB, fs FancyMSSQLSettings, se
|
||||
e := db.QueryRowContext(ctx,
|
||||
// Карточка лица в DEPO версионная: действующая версия (LAST_FLAG=1) даёт ФИО и дату рождения,
|
||||
// а счета и опции привязаны к исходной записи (SELF_ID).
|
||||
`SELECT TOP 1 ISNULL(NULLIF(SELF_ID,0),ID), ISNULL(NAME,''), DATE_BIRTH FROM OD_FACES WHERE REPLACE(ISNULL(DOC_SER,''),' ','')=@p1 AND DOC_NUM=@p2
|
||||
ORDER BY ISNULL(LAST_FLAG,0) DESC, ID DESC`,
|
||||
fsql.Chk01,
|
||||
sql.Named("p1", ser), sql.Named("p2", num)).Scan(&p.faceID, &p.faceName, &p.birth)
|
||||
p.faceOK = e == nil
|
||||
}
|
||||
@@ -122,7 +122,7 @@ func depoResolveParty(ctx context.Context, db *sql.DB, fs FancyMSSQLSettings, se
|
||||
|
||||
if p.faceOK {
|
||||
rows, e := db.QueryContext(ctx,
|
||||
`SELECT ID, ISNULL(NUMBER,''), ISNULL(STATE,-1), D_CLOSE FROM OD_CLIENTS WHERE FACE=@p1 AND NUMBER LIKE N'ВТНКЦ%' ORDER BY ID`,
|
||||
fsql.Chk02,
|
||||
sql.Named("p1", p.faceID))
|
||||
if e == nil {
|
||||
for rows.Next() {
|
||||
@@ -177,10 +177,7 @@ var depoQualKinds = []string{
|
||||
// маска видов бумаг (511 и -1 — все виды, 0 — ни одного). Возвращает (предупреждение, по всем видам, пояснение).
|
||||
func depoFaceQualified(ctx context.Context, db *sql.DB, faceID int64) (warn, all bool, det string) {
|
||||
var val sql.NullString
|
||||
err := db.QueryRowContext(ctx, `SELECT TOP 1 CAST(o.VAL AS varchar(20)) FROM OD_OPTIONS o
|
||||
JOIN OP_FIELDS f ON f.ID = o.DESCR AND f.AS_NAME = 'IS_QUAL'
|
||||
WHERE o.OBJECT = @p1 AND o.B_DATE <= GETDATE() AND (o.E_DATE IS NULL OR o.E_DATE > GETDATE())
|
||||
ORDER BY o.B_DATE DESC`, sql.Named("p1", faceID)).Scan(&val)
|
||||
err := db.QueryRowContext(ctx, fsql.Chk03, sql.Named("p1", faceID)).Scan(&val)
|
||||
const notQual = " — если бумага только для квал., нужен отказ M2M08; решает оператор"
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return true, false, "инвестор НЕ квалифицированный (нет опции «Вхождение в реестр квалифицированных инвесторов» в DEPO)" + notQual
|
||||
@@ -214,7 +211,7 @@ func depoAccountIIS(ctx context.Context, db *sql.DB, fs FancyMSSQLSettings, clie
|
||||
if clientID == 0 {
|
||||
return true, "не проверяется — нет открытого счёта клиента"
|
||||
}
|
||||
rows, err := db.QueryContext(ctx, `SELECT ISNULL(PORT_NUM,'') FROM OD_CLIENTS_PORTS WHERE CLIENT=@p1`, sql.Named("p1", clientID))
|
||||
rows, err := db.QueryContext(ctx, fsql.Chk04, sql.Named("p1", clientID))
|
||||
if err != nil {
|
||||
return true, "договор счёта не прочитан: " + quikErrorDetail(err)
|
||||
}
|
||||
@@ -245,7 +242,7 @@ func depoAccountIIS(ctx context.Context, db *sql.DB, fs FancyMSSQLSettings, clie
|
||||
// depoSecurity — бумага в справочнике DEPO.
|
||||
func depoSecurity(ctx context.Context, db *sql.DB, isin string) (id int64, name string, found, accepted bool) {
|
||||
var isIn sql.NullInt64
|
||||
e := db.QueryRowContext(ctx, `SELECT TOP 1 ID, ISNULL(NAME,''), IS_IN FROM OD_VALUES WHERE ISIN=@p1`,
|
||||
e := db.QueryRowContext(ctx, fsql.Chk05,
|
||||
sql.Named("p1", isin)).Scan(&id, &name, &isIn)
|
||||
found = e == nil
|
||||
accepted = found && isIn.Valid && isIn.Int64 == 1
|
||||
@@ -256,10 +253,7 @@ func depoSecurity(ctx context.Context, db *sql.DB, isin string) (id int64, name
|
||||
// опция бумаги RESTRICTED («Ограничение ценной бумаги по обращению», 1 — для квал. инвесторов).
|
||||
func depoSecurityQualOnly(ctx context.Context, db *sql.DB, valID int64) (bool, string) {
|
||||
var val sql.NullString
|
||||
err := db.QueryRowContext(ctx, `SELECT TOP 1 CAST(o.VAL AS varchar(20)) FROM OD_OPTIONS o
|
||||
JOIN OP_FIELDS f ON f.ID = o.DESCR AND f.AS_NAME = 'RESTRICTED'
|
||||
WHERE o.OBJECT = @p1 AND o.B_DATE <= GETDATE() AND (o.E_DATE IS NULL OR o.E_DATE > GETDATE())
|
||||
ORDER BY o.B_DATE DESC`, sql.Named("p1", valID)).Scan(&val)
|
||||
err := db.QueryRowContext(ctx, fsql.Chk06, sql.Named("p1", valID)).Scan(&val)
|
||||
switch {
|
||||
case errors.Is(err, sql.ErrNoRows):
|
||||
return false, "ограничений по обращению нет (опция DEPO)"
|
||||
@@ -321,9 +315,7 @@ func depoBlocking(ctx context.Context, db *sql.DB, valID, clientID int64) (ok bo
|
||||
var balAcc sql.NullInt64
|
||||
var k sql.NullFloat64
|
||||
er := db.QueryRowContext(ctx,
|
||||
`SELECT TOP 1 r.BLOCK_DATE, r.BLOCK_REASON, r.BAL_ACC, CAST(r.K AS float)
|
||||
FROM OD_RESTS r WHERE r.VALUE_ID=@p1 AND r.REG_1=@p2
|
||||
ORDER BY CASE WHEN r.BLOCK_DATE IS NOT NULL THEN 0 WHEN r.BAL_ACC IN (837,3410,4342,5647) AND CAST(r.K AS float)<>0 THEN 1 ELSE 2 END`,
|
||||
fsql.Chk07,
|
||||
sql.Named("p1", valID), sql.Named("p2", clientID)).Scan(&blockDate, &blockReason, &balAcc, &k)
|
||||
if er != nil {
|
||||
return true, "регистра бумаги на счёте нет — блокировок нет"
|
||||
@@ -500,7 +492,7 @@ func runDepoCheckOutAccount(last, first, middle, ser, num, birth string, secs []
|
||||
default:
|
||||
var id, state int64
|
||||
var dclose sql.NullTime
|
||||
err := db.QueryRowContext(ctx, `SELECT TOP 1 ID, ISNULL(STATE,-1), D_CLOSE FROM OD_CLIENTS WHERE FACE=@p1 AND UPPER(NUMBER)=@p2 ORDER BY ID`,
|
||||
err := db.QueryRowContext(ctx, fsql.Chk08,
|
||||
sql.Named("p1", p.faceID), sql.Named("p2", want)).Scan(&id, &state, &dclose)
|
||||
switch {
|
||||
case err != nil:
|
||||
@@ -578,7 +570,7 @@ func runDepoCheckOutAccount(last, first, middle, ser, num, birth string, secs []
|
||||
if p.accOpen != "" && found {
|
||||
var have float64
|
||||
_ = db.QueryRowContext(ctx,
|
||||
`SELECT ISNULL(SUM(CAST(K AS float)),0) FROM OD_RESTS WHERE VALUE_ID=@p1 AND REG_1=@p2 AND BAL_ACC=@p3`,
|
||||
fsql.Chk09,
|
||||
sql.Named("p1", valID), sql.Named("p2", p.clientID), sql.Named("p3", depoTradeBalAcc)).Scan(&have)
|
||||
qtyOK = have >= need && need > 0
|
||||
qtyDet = fmt.Sprintf("на торговом счёте %s: %.0f шт., списываем %.0f", p.accOpen, have, need)
|
||||
|
||||
@@ -8,6 +8,7 @@ package lkgateway
|
||||
|
||||
import (
|
||||
"context"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -36,11 +37,7 @@ func depoSimLists() (clients []depoSimClient, secs []depoSimSec) {
|
||||
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`)
|
||||
fsql.Sim01)
|
||||
if err == nil {
|
||||
defer rows.Close()
|
||||
seen := map[string]bool{}
|
||||
@@ -54,8 +51,7 @@ func depoSimLists() (clients []depoSimClient, secs []depoSimSec) {
|
||||
}
|
||||
}
|
||||
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`)
|
||||
fsql.Sim02)
|
||||
if err == nil {
|
||||
defer rows2.Close()
|
||||
for rows2.Next() {
|
||||
|
||||
@@ -3,6 +3,7 @@ package lkgateway
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -48,7 +49,7 @@ func depoContractExists(ctx context.Context, s FancyMSSQLSettings, contract stri
|
||||
defer cancel()
|
||||
var full string
|
||||
err = conn.QueryRowContext(cctx,
|
||||
"SELECT TOP 1 PORT_NUM FROM OD_CLIENTS_PORTS WHERE PORT_NUM=@p1 OR PORT_NUM LIKE @p2",
|
||||
fsql.QDb01,
|
||||
contract, likeEscape(contract)+" %").Scan(&full)
|
||||
if err != nil {
|
||||
return "", false
|
||||
@@ -67,15 +68,7 @@ func depoClientPositions(ctx context.Context, s FancyMSSQLSettings, contract str
|
||||
cctx, cancel := context.WithTimeout(ctx, 25*time.Second)
|
||||
defer cancel()
|
||||
|
||||
q := `SELECT p.PORT_NUM, ISNULL(c.NUMBER,''), ISNULL(v.ISIN,''), ISNULL(v.NAME,''),
|
||||
CAST(rst.K AS float), ISNULL(rst.BLOCK_REASON,''), ISNULL(rst.BAL_ACC,0)
|
||||
FROM OD_RESTS rst
|
||||
JOIN OD_CLIENTS c ON c.ID = rst.REG_1
|
||||
JOIN OD_CLIENTS_PORTS p ON p.CLIENT = c.ID
|
||||
JOIN OD_VALUES v ON v.ID = rst.VALUE_ID AND v.V_TYPE = 2
|
||||
WHERE (p.PORT_NUM = @p1 OR p.PORT_NUM LIKE @p2)
|
||||
AND CAST(rst.K AS float) <> 0
|
||||
ORDER BY v.NAME`
|
||||
q := fsql.Dp01
|
||||
rows, err := conn.QueryContext(cctx, q, contract, likeEscape(contract)+" %")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -164,13 +157,7 @@ func depoListContracts(ctx context.Context, s FancyMSSQLSettings, search string,
|
||||
if limit <= 0 || limit > 500 {
|
||||
limit = 100
|
||||
}
|
||||
q := fmt.Sprintf(`SELECT TOP (%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 float) <> 0 AND (@p1 = '' OR p.PORT_NUM LIKE @p2)
|
||||
GROUP BY p.PORT_NUM ORDER BY p.PORT_NUM`, limit)
|
||||
q := fmt.Sprintf(fsql.Dp02, limit)
|
||||
rows, err := conn.QueryContext(cctx, q, search, "%"+likeEscape(search)+"%")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -203,7 +190,7 @@ func depoFindContracts(ctx context.Context, s FancyMSSQLSettings, like string, l
|
||||
limit = 50
|
||||
}
|
||||
rows, err := conn.QueryContext(cctx, fmt.Sprintf(
|
||||
"SELECT DISTINCT TOP (%d) PORT_NUM FROM OD_CLIENTS_PORTS WHERE PORT_NUM LIKE @p1 ORDER BY PORT_NUM", limit),
|
||||
fsql.QDb02, limit),
|
||||
"%"+like+"%")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -259,7 +246,7 @@ func depoSuggestContracts(ctx context.Context, s FancyMSSQLSettings) []string {
|
||||
cctx, cancel := context.WithTimeout(ctx, 20*time.Second)
|
||||
defer cancel()
|
||||
rows, err := conn.QueryContext(cctx,
|
||||
"SELECT DISTINCT TOP (5000) PORT_NUM FROM OD_CLIENTS_PORTS WHERE PORT_NUM <> '' ORDER BY PORT_NUM")
|
||||
fsql.QDb03)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -159,14 +160,14 @@ func depoEventAt(rc *RuntimeConfig, at time.Time, guid, ref, typ, codes, params
|
||||
params = string([]rune(params)[:4000])
|
||||
}
|
||||
var n int
|
||||
_ = db.QueryRowContext(ctx, "SELECT COUNT(*) FROM dbo.FTV_M2M_EVENTS WHERE GUID=@g AND ISNULL(REFERENCE,'')=@r AND EVENT_TYPE=@t",
|
||||
_ = db.QueryRowContext(ctx, fsql.QEv01,
|
||||
sql.Named("g", guid), sql.Named("r", ref), sql.Named("t", typ)).Scan(&n)
|
||||
if n > 0 {
|
||||
return
|
||||
}
|
||||
q := `INSERT INTO dbo.FTV_M2M_EVENTS (GUID, REFERENCE, EVENT_TYPE, EVENT_DATE, M2M_REJECT_CODE) VALUES (@g, @r, @t, @at, @c)`
|
||||
q := fsql.Ev01
|
||||
if depoHasColumn(ctx, db, "FTV_M2M_EVENTS", "PARAMETERS") {
|
||||
q = `INSERT INTO dbo.FTV_M2M_EVENTS (GUID, REFERENCE, EVENT_TYPE, EVENT_DATE, M2M_REJECT_CODE, PARAMETERS) VALUES (@g, @r, @t, @at, @c, @p)`
|
||||
q = fsql.Ev02
|
||||
}
|
||||
_, err = db.ExecContext(ctx, q,
|
||||
sql.Named("g", guid), sql.Named("r", nullStr(ref)), sql.Named("t", typ), sql.Named("at", at.In(time.FixedZone("МСК", 3*3600)).Format("2006-01-02T15:04:05.000")),
|
||||
@@ -203,7 +204,7 @@ func depoUpsertOrder(rc *RuntimeConfig, guid, direction, cpCode, deponentName, d
|
||||
return false
|
||||
}
|
||||
var n int
|
||||
_ = db.QueryRowContext(ctx, "SELECT COUNT(*) FROM dbo.FTV_M2M WHERE GUID=@g", sql.Named("g", guid)).Scan(&n)
|
||||
_ = db.QueryRowContext(ctx, fsql.QEv02, sql.Named("g", guid)).Scan(&n)
|
||||
if n > 0 {
|
||||
return true
|
||||
}
|
||||
@@ -211,16 +212,13 @@ func depoUpsertOrder(rc *RuntimeConfig, guid, direction, cpCode, deponentName, d
|
||||
var deponentID sql.NullInt64
|
||||
serN := strings.ReplaceAll(strings.TrimSpace(ser), " ", "")
|
||||
if serN != "" && strings.TrimSpace(num) != "" {
|
||||
_ = db.QueryRowContext(ctx, "SELECT TOP 1 SELF_ID FROM OD_FACES WHERE REPLACE(DOC_SER,' ','')=@s AND DOC_NUM=@n ORDER BY ID", sql.Named("s", serN), sql.Named("n", strings.TrimSpace(num))).Scan(&deponentID)
|
||||
_ = db.QueryRowContext(ctx, fsql.QEv03, sql.Named("s", serN), sql.Named("n", strings.TrimSpace(num))).Scan(&deponentID)
|
||||
}
|
||||
// счёт клиента для DEPO_NUMBER строк: открытый торговый ВТНКЦ…, при нескольких договорах — самый
|
||||
// ранний (то же правило, что при зачислении в QUIK); джоба по номеру находит OD_CLIENTS.ID (DEPO).
|
||||
var clientAcc sql.NullString
|
||||
if serN != "" && strings.TrimSpace(num) != "" {
|
||||
_ = db.QueryRowContext(ctx, `SELECT TOP 1 c.NUMBER FROM OD_FACES f
|
||||
JOIN OD_CLIENTS c ON c.FACE=f.ID LEFT JOIN OD_CLIENTS_PORTS p ON p.CLIENT=c.ID
|
||||
WHERE REPLACE(f.DOC_SER,' ','')=@s AND f.DOC_NUM=@n AND c.NUMBER LIKE N'ВТНКЦ%' AND c.STATE=0 AND c.D_CLOSE IS NULL
|
||||
ORDER BY ISNULL(p.PORT_DATE,'2099-01-01'), ISNULL(c.D_OPEN,'2099-01-01'), c.NUMBER`,
|
||||
_ = db.QueryRowContext(ctx, fsql.Ev03,
|
||||
sql.Named("s", serN), sql.Named("n", strings.TrimSpace(num))).Scan(&clientAcc)
|
||||
}
|
||||
hasDepoNumber := depoHasColumn(ctx, db, "FTV_M2M_LINES", "DEPO_NUMBER")
|
||||
@@ -231,9 +229,9 @@ func depoUpsertOrder(rc *RuntimeConfig, guid, direction, cpCode, deponentName, d
|
||||
return false
|
||||
}
|
||||
// COMMENT не пишем — его заполняет bj2depo (17.09.2026); comment остаётся только для журнала bj.
|
||||
head := `INSERT INTO dbo.FTV_M2M (GUID, DIRECTION, CONTRAGENT_M2M_CODE, DEPONENT_NAME, DEPONENT_DOC) VALUES (@g, @d, @cp, @nm, @doc)`
|
||||
head := fsql.Ev04
|
||||
if hasDeponentID {
|
||||
head = `INSERT INTO dbo.FTV_M2M (GUID, DIRECTION, CONTRAGENT_M2M_CODE, DEPONENT_NAME, DEPONENT_DOC, DEPONENT_ID) VALUES (@g, @d, @cp, @nm, @doc, @did)`
|
||||
head = fsql.Ev05
|
||||
}
|
||||
if _, err := tx.ExecContext(ctx, head,
|
||||
sql.Named("g", guid), sql.Named("d", direction), sql.Named("cp", nullStr(cpCode)), sql.Named("nm", nullStr(deponentName)), sql.Named("doc", nullStr(deponentDoc)),
|
||||
@@ -247,7 +245,7 @@ func depoUpsertOrder(rc *RuntimeConfig, guid, direction, cpCode, deponentName, d
|
||||
for _, ln := range lines {
|
||||
var share sql.NullInt64
|
||||
if ln.ISIN != "" && hasShare {
|
||||
_ = db.QueryRowContext(ctx, "SELECT TOP 1 ID FROM OD_VALUES WHERE ISIN=@i ORDER BY ID", sql.Named("i", ln.ISIN)).Scan(&share)
|
||||
_ = db.QueryRowContext(ctx, fsql.QEv04, sql.Named("i", ln.ISIN)).Scan(&share)
|
||||
}
|
||||
cols, vals := "GUID, REFERENCE, ISIN, SEC_CODE, AMOUNT, PLACE_NUMBER, LINK_NUMBER", "@g, @r, @i, @c, @a, @p, ''"
|
||||
if hasShare {
|
||||
@@ -256,7 +254,7 @@ func depoUpsertOrder(rc *RuntimeConfig, guid, direction, cpCode, deponentName, d
|
||||
if hasDepoNumber {
|
||||
cols, vals = cols+", DEPO_NUMBER", vals+", @acc"
|
||||
}
|
||||
q := `INSERT INTO dbo.FTV_M2M_LINES (` + cols + `) VALUES (` + vals + `)`
|
||||
q := fsql.Ev06 + cols + `) VALUES (` + vals + `)`
|
||||
if _, err := tx.ExecContext(ctx, q,
|
||||
sql.Named("g", guid), sql.Named("r", ln.Ref), sql.Named("i", nullStr(ln.ISIN)), sql.Named("c", nullStr(ln.Code)), sql.Named("sh", share), sql.Named("a", ln.Amount), sql.Named("p", nullStr(ln.Place)), sql.Named("acc", clientAcc)); err != nil {
|
||||
tx.Rollback()
|
||||
@@ -440,10 +438,7 @@ func depoPollOrders(ctx context.Context, db *sql.DB, rc *RuntimeConfig) {
|
||||
} else if depoHasColumn(ctx, db, "FTV_M2M", "FANSY_DOC") {
|
||||
docCol = "CAST(m.FANSY_DOC AS varchar(32))"
|
||||
}
|
||||
rows, err := db.QueryContext(ctx, `SELECT TOP 200 CAST(m.GUID AS varchar(36)), ISNULL(m.STATE,''), ISNULL(`+docCol+`,''), ISNULL(m.COMMENT,''),
|
||||
ISNULL((SELECT TOP 1 ISNULL(l.COMMENT,'') FROM dbo.FTV_M2M_LINES l WHERE l.GUID=m.GUID AND ISNULL(l.STATE,'')='ERROR'),''),
|
||||
ISNULL((SELECT TOP 1 ISNULL(st.NAME,'') FROM OD_DOCS d LEFT JOIN OD_DOC_STATES st ON st.ID=d.STATE AND st.D_CAT=0 WHERE CAST(d.ID AS varchar(32))=`+docCol+`),''),
|
||||
(SELECT TOP 1 d.PROC_DATE FROM OD_DOCS d WHERE CAST(d.ID AS varchar(32))=`+docCol+`)
|
||||
rows, err := db.QueryContext(ctx, fsql.Ev07+docCol+fsql.Ev08+docCol+fsql.Ev09+docCol+`)
|
||||
FROM dbo.FTV_M2M m WHERE m.TimeNew > DATEADD(day,-45,GETDATE()) ORDER BY m.ID DESC`)
|
||||
if err != nil {
|
||||
log.Printf("depo-events: чтение FTV_M2M: %v", err)
|
||||
@@ -525,7 +520,7 @@ func depoWriteHandbook(rc *RuntimeConfig) error {
|
||||
return err
|
||||
}
|
||||
// полная перезапись (согласовано с программистом); DELETE — у логина bj нет права на TRUNCATE
|
||||
if _, err := tx.ExecContext(ctx, "DELETE FROM dbo.FTV_M2M_HANDBOOK"); err != nil {
|
||||
if _, err := tx.ExecContext(ctx, fsql.QEv05); err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
@@ -534,8 +529,7 @@ func depoWriteHandbook(rc *RuntimeConfig) error {
|
||||
if short == "" {
|
||||
short = e.DisplayName
|
||||
}
|
||||
_, err := tx.ExecContext(ctx, `INSERT INTO dbo.FTV_M2M_HANDBOOK (INN, PARTICIPANT_CODE, KIND, NAME_FULL, NAME_SHORT, NAME_DISPLAY, NAME_ENG, HANDBOOK_AT, UPDATED_AT, ACTIVE)
|
||||
VALUES (@inn, @code, @kind, @full, @short, @disp, @eng, @at, GETDATE(), 1)`,
|
||||
_, err := tx.ExecContext(ctx, fsql.Ev10,
|
||||
sql.Named("inn", e.INN), sql.Named("code", nullStr(e.Code)), sql.Named("kind", kind), sql.Named("full", nullStr(e.FullName)), sql.Named("short", nullStr(short)),
|
||||
sql.Named("disp", nullStr(e.DisplayName)), sql.Named("eng", nullStr(e.EngName)), sql.Named("at", hbAt))
|
||||
return err
|
||||
@@ -708,14 +702,14 @@ ALTER ROLE SQLAgentOperatorRole ADD MEMBER %[1]s;
|
||||
|
||||
func depoJobPing(ctx context.Context, db *sql.DB, wait time.Duration) (bool, string) {
|
||||
guid := strings.ToUpper(fmt.Sprintf("%08x-0000-4000-8000-%012x", time.Now().Unix()&0xFFFFFFFF, time.Now().UnixNano()&0xFFFFFFFFFFFF))
|
||||
if _, err := db.ExecContext(ctx, "INSERT INTO dbo.FTV_M2M_EVENTS (GUID, REFERENCE, EVENT_TYPE, EVENT_DATE) VALUES (@g, NULL, 'BJ_PING', GETDATE())", sql.Named("g", guid)); err != nil {
|
||||
if _, err := db.ExecContext(ctx, fsql.QEv06, sql.Named("g", guid)); err != nil {
|
||||
return false, "не удалось записать проверочное событие: " + quikErrorDetail(err)
|
||||
}
|
||||
defer db.ExecContext(context.Background(), "DELETE FROM dbo.FTV_M2M_EVENTS WHERE GUID=@g", sql.Named("g", guid))
|
||||
defer db.ExecContext(context.Background(), fsql.QEv07, sql.Named("g", guid))
|
||||
deadline := time.Now().Add(wait)
|
||||
for time.Now().Before(deadline) {
|
||||
var st string
|
||||
if err := db.QueryRowContext(ctx, "SELECT ISNULL(STATE,'') FROM dbo.FTV_M2M_EVENTS WHERE GUID=@g", sql.Named("g", guid)).Scan(&st); err == nil && st != "TODO" && st != "" {
|
||||
if err := db.QueryRowContext(ctx, fsql.QEv08, sql.Named("g", guid)).Scan(&st); err == nil && st != "TODO" && st != "" {
|
||||
return true, fmt.Sprintf("проверочное событие BJ_PING обработано за %s (STATE=%s)", time.Since(deadline.Add(-wait)).Round(time.Second), st)
|
||||
}
|
||||
time.Sleep(3 * time.Second)
|
||||
@@ -976,8 +970,7 @@ func depoSimulateIncoming(ctx context.Context, rc *RuntimeConfig, it *IncomingTr
|
||||
serN := strings.ReplaceAll(strings.TrimSpace(ser), " ", "")
|
||||
numN := strings.TrimSpace(num)
|
||||
var name string
|
||||
if err := db.QueryRowContext(ctx, `SELECT TOP 1 f.NAME FROM OD_FACES f JOIN OD_CLIENTS c ON c.FACE=f.ID
|
||||
WHERE REPLACE(f.DOC_SER,' ','')=@s AND f.DOC_NUM=@n AND c.NUMBER LIKE N'ВТНКЦ%' AND c.STATE=0`, sql.Named("s", serN), sql.Named("n", numN)).Scan(&name); err != nil {
|
||||
if err := db.QueryRowContext(ctx, fsql.Ev11, sql.Named("s", serN), sql.Named("n", numN)).Scan(&name); err != nil {
|
||||
return "", fmt.Errorf("клиент с паспортом %s %s и открытым торговым счётом в DEPO не найден", ser, num)
|
||||
}
|
||||
guid := strings.ToUpper(fmt.Sprintf("%08x-%04x-4000-8000-%012x", time.Now().Unix()&0xFFFFFFFF, time.Now().UnixNano()&0xFFFF, time.Now().UnixNano()&0xFFFFFFFFFFFF))
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"log"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -55,13 +56,7 @@ func (f depoJobFailure) TableRu() string {
|
||||
|
||||
// depoJobFailures — записи с ошибкой обработки за days дней, новые первыми.
|
||||
func depoJobFailures(ctx context.Context, db *sql.DB, days, limit int) ([]depoJobFailure, error) {
|
||||
rows, err := db.QueryContext(ctx, `SELECT TOP (@n) * FROM (
|
||||
SELECT 'FTV_M2M' AS T, ID, CAST(GUID AS varchar(36)) AS G, '' AS R, ISNULL(DIRECTION,'') AS K, ISNULL(TimeEnd, TimeNew) AS A, ISNULL(COMMENT,'') AS C
|
||||
FROM dbo.FTV_M2M WHERE STATE='ERROR' AND ISNULL(TimeEnd, TimeNew) > DATEADD(day, -@d, GETDATE())
|
||||
UNION ALL
|
||||
SELECT 'FTV_M2M_EVENTS', ID, CAST(GUID AS varchar(36)), ISNULL(REFERENCE,''), EVENT_TYPE, ISNULL(TimeEnd, TimeNew), ISNULL(COMMENT,'')
|
||||
FROM dbo.FTV_M2M_EVENTS WHERE STATE='ERROR' AND EVENT_TYPE LIKE 'BJ[_]%' AND ISNULL(TimeEnd, TimeNew) > DATEADD(day, -@d, GETDATE())
|
||||
) x ORDER BY A DESC`, sql.Named("n", limit), sql.Named("d", days))
|
||||
rows, err := db.QueryContext(ctx, fsql.Hlth01, sql.Named("n", limit), sql.Named("d", days))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -95,9 +90,9 @@ func depoRequeueFailures(ctx context.Context, db *sql.DB, days int) (orders, eve
|
||||
}
|
||||
for _, f := range fails {
|
||||
comment := "повторная обработка из bj"
|
||||
q := "UPDATE dbo.FTV_M2M SET STATE='TODO', TimeBeg=NULL, TimeEnd=NULL, COMMENT=@c WHERE ID=@id AND STATE='ERROR'"
|
||||
q := fsql.QHl01
|
||||
if f.Table == "FTV_M2M_EVENTS" {
|
||||
q = "UPDATE dbo.FTV_M2M_EVENTS SET STATE='TODO', TimeBeg=NULL, TimeEnd=NULL, COMMENT=@c WHERE ID=@id AND STATE='ERROR'"
|
||||
q = fsql.QHl02
|
||||
if lf := globalLKFlows.Get(f.GUID); f.Type == "BJ_GATEWAY_REJECT" && lf != nil && lf.Reason != "" {
|
||||
comment = lf.Reason
|
||||
}
|
||||
@@ -111,7 +106,7 @@ func depoRequeueFailures(ctx context.Context, db *sql.DB, days int) (orders, eve
|
||||
if f.Table == "FTV_M2M" {
|
||||
orders += n
|
||||
// строки поручения, помеченные ошибкой, тоже возвращаем
|
||||
if _, e := tx.ExecContext(ctx, "UPDATE dbo.FTV_M2M_LINES SET STATE='TODO', TimeBeg=NULL, TimeEnd=NULL WHERE GUID=@g AND STATE='ERROR'", sql.Named("g", f.GUID)); e != nil {
|
||||
if _, e := tx.ExecContext(ctx, fsql.QHl03, sql.Named("g", f.GUID)); e != nil {
|
||||
tx.Rollback()
|
||||
return 0, 0, e
|
||||
}
|
||||
@@ -133,9 +128,7 @@ func depoAlertEventFailures(ctx context.Context, db *sql.DB, rc *RuntimeConfig)
|
||||
var id sql.NullInt64
|
||||
var typ, guid, comment string
|
||||
var n int
|
||||
err := db.QueryRowContext(ctx, `SELECT COUNT(*) OVER (), ID, EVENT_TYPE, CAST(GUID AS varchar(36)), ISNULL(COMMENT,'')
|
||||
FROM dbo.FTV_M2M_EVENTS WHERE STATE='ERROR' AND EVENT_TYPE LIKE 'BJ[_]%' AND ID > @last AND ISNULL(TimeEnd, TimeNew) > DATEADD(day, -1, GETDATE())
|
||||
ORDER BY ID DESC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY`, sql.Named("last", depoFailAlertedID)).Scan(&n, &id, &typ, &guid, &comment)
|
||||
err := db.QueryRowContext(ctx, fsql.Hlth02, sql.Named("last", depoFailAlertedID)).Scan(&n, &id, &typ, &guid, &comment)
|
||||
if err != nil || !id.Valid {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -111,9 +112,7 @@ func depoQueueLoad(ctx context.Context, rc *RuntimeConfig, limit int) ([]depoQue
|
||||
break
|
||||
}
|
||||
}
|
||||
rows, err := db.QueryContext(ctx, `SELECT TOP (@n) CAST(m.GUID AS varchar(36)), ISNULL(m.STATE,''), ISNULL(m.DIRECTION,''), ISNULL(m.DEPONENT_NAME,''), ISNULL(m.DEPONENT_DOC,''), ISNULL(m.CONTRAGENT_M2M_CODE,''), `+timeCol+`, ISNULL(`+docCol+`,''), ISNULL(m.COMMENT,''),
|
||||
ISNULL((SELECT TOP 1 ISNULL(st.NAME,'') FROM OD_DOCS d LEFT JOIN OD_DOC_STATES st ON st.ID=d.STATE AND st.D_CAT=0 WHERE CAST(d.ID AS varchar(32))=`+docCol+`),''),
|
||||
(SELECT TOP 1 d.PROC_DATE FROM OD_DOCS d WHERE CAST(d.ID AS varchar(32))=`+docCol+`)
|
||||
rows, err := db.QueryContext(ctx, fsql.Que01+timeCol+`, ISNULL(`+docCol+fsql.Que02+docCol+fsql.Que03+docCol+`)
|
||||
FROM dbo.FTV_M2M m ORDER BY `+strings.Replace(timeCol, "NULL", "m.GUID", 1)+` DESC`, sql.Named("n", limit))
|
||||
if err != nil {
|
||||
return nil, sum, err
|
||||
@@ -144,7 +143,7 @@ func depoQueueLoad(ctx context.Context, rc *RuntimeConfig, limit int) ([]depoQue
|
||||
}
|
||||
// строки
|
||||
if depoTableExists(ctx, db, "FTV_M2M_LINES") {
|
||||
lr, err := db.QueryContext(ctx, `SELECT CAST(l.GUID AS varchar(36)), ISNULL(l.ISIN,''), ISNULL(l.SEC_CODE,''), ISNULL(CAST(l.AMOUNT AS varchar(40)),''), ISNULL(l.STATE,''), ISNULL(l.COMMENT,'') FROM dbo.FTV_M2M_LINES l WHERE l.GUID IN (SELECT TOP (@n) GUID FROM dbo.FTV_M2M ORDER BY `+strings.Replace(strings.TrimPrefix(timeCol, "m."), "NULL", "GUID", 1)+` DESC)`, sql.Named("n", limit))
|
||||
lr, err := db.QueryContext(ctx, fsql.Que04+strings.Replace(strings.TrimPrefix(timeCol, "m."), "NULL", "GUID", 1)+` DESC)`, sql.Named("n", limit))
|
||||
if err == nil {
|
||||
for lr.Next() {
|
||||
var g string
|
||||
@@ -164,7 +163,7 @@ func depoQueueLoad(ctx context.Context, rc *RuntimeConfig, limit int) ([]depoQue
|
||||
}
|
||||
// события
|
||||
if depoTableExists(ctx, db, "FTV_M2M_EVENTS") {
|
||||
er, err := db.QueryContext(ctx, `SELECT CAST(e.GUID AS varchar(36)), ISNULL(e.REFERENCE,''), ISNULL(e.STATE,''), ISNULL(e.EVENT_TYPE,''), e.EVENT_DATE, ISNULL(e.M2M_REJECT_CODE,''), ISNULL(e.COMMENT,'') FROM dbo.FTV_M2M_EVENTS e WHERE e.GUID IN (SELECT TOP (@n) GUID FROM dbo.FTV_M2M ORDER BY `+strings.Replace(strings.TrimPrefix(timeCol, "m."), "NULL", "GUID", 1)+` DESC) ORDER BY e.EVENT_DATE`, sql.Named("n", limit))
|
||||
er, err := db.QueryContext(ctx, fsql.Que05+strings.Replace(strings.TrimPrefix(timeCol, "m."), "NULL", "GUID", 1)+` DESC) ORDER BY e.EVENT_DATE`, sql.Named("n", limit))
|
||||
if err == nil {
|
||||
for er.Next() {
|
||||
var g string
|
||||
@@ -196,10 +195,10 @@ func depoQueueLoad(ctx context.Context, rc *RuntimeConfig, limit int) ([]depoQue
|
||||
}
|
||||
if depoTableExists(ctx, db, "FTV_M2M_HANDBOOK") {
|
||||
sum.HasHandbook = true
|
||||
_ = db.QueryRowContext(ctx, "SELECT count(*) FROM dbo.FTV_M2M_HANDBOOK").Scan(&sum.Handbook)
|
||||
_ = db.QueryRowContext(ctx, fsql.QQu01).Scan(&sum.Handbook)
|
||||
if depoHasColumn(ctx, db, "FTV_M2M_HANDBOOK", "HANDBOOK_AT") {
|
||||
var t sql.NullTime
|
||||
if db.QueryRowContext(ctx, "SELECT max(HANDBOOK_AT) FROM dbo.FTV_M2M_HANDBOOK").Scan(&t) == nil && t.Valid {
|
||||
if db.QueryRowContext(ctx, fsql.QQu02).Scan(&t) == nil && t.Valid {
|
||||
sum.HandbookAt = t.Time
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
@@ -225,8 +226,8 @@ func depoTablesGrantSQL(pg bool, user string) []string {
|
||||
if pg {
|
||||
return []string{
|
||||
fmt.Sprintf(`GRANT USAGE ON SCHEMA public TO "%s"`, user),
|
||||
fmt.Sprintf(`GRANT SELECT ON ALL TABLES IN SCHEMA public TO "%s"`, user), // учётные таблицы DEPO (сверка)
|
||||
fmt.Sprintf(`GRANT SELECT, INSERT, UPDATE, DELETE ON %s TO "%s"`, strings.Join(depoTableNames(), ", "), user),
|
||||
fmt.Sprintf(fsql.Tbl01, user), // учётные таблицы DEPO (сверка)
|
||||
fmt.Sprintf(fsql.Tbl02, strings.Join(depoTableNames(), ", "), user),
|
||||
}
|
||||
}
|
||||
out := []string{
|
||||
@@ -274,7 +275,7 @@ func depoTablesScript(f FancyMSSQLSettings) string {
|
||||
} else {
|
||||
b.WriteString("-- Права логину bj: выдайте SELECT, INSERT, UPDATE, DELETE на таблицы выше (логин bj в настройках не указан).\n\n")
|
||||
}
|
||||
b.WriteString("-- Кроме того, логину bj нужно право SELECT на учётные таблицы DEPO (OD_CLIENTS, OD_CLIENTS_PORTS, OD_RESTS, OD_VALUES и др.) для сверки переводов.\n")
|
||||
b.WriteString(fsql.QTb01)
|
||||
return b.String()
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
package fsql
|
||||
|
||||
// fsql — SQL-запросы к учётным системам DEPO и SPECTRE и к экспорту QUIK,
|
||||
// вынесенные из lkgateway отдельным пакетом. В релизной сборке этот пакет
|
||||
// (и только он) обфусцируется garble: строки запросов шифруются и в бинаре
|
||||
// не читаются `strings`. Именно здесь лежит знание о чужих схемах (какие
|
||||
// таблицы, связи и столбцы), которое дороже всего восстанавливать.
|
||||
//
|
||||
// ВАЖНО: только var, не const — константу компилятор вставил бы в
|
||||
// вызывающий (необфусцированный) пакет, и шифрование бы не сработало.
|
||||
// Запросы — data-only: параметры передаются через sql.Named на месте вызова.
|
||||
|
||||
var Arch01 = `SELECT r.ID, b.NUM_S, ISNULL(b.SYS_NAME,''), b.NUM_1, ISNULL(r.REG_2,0), ISNULL(r.VALUE_ID,0),
|
||||
CAST(ISNULL(r.A,0) AS float), CAST(ISNULL(r.D,0) AS float), CAST(ISNULL(r.EQ_D,0) AS float),
|
||||
ISNULL(vs.ISIN,''), ISNULL(vs.NAME,''), ISNULL(vc.SYSNAME,''), ISNULL(sh.CLASS,0), CAST(ISNULL(sh.NOMINAL,0) AS float)
|
||||
FROM OD_RESTS r JOIN OD_BALANCES b ON b.ID = r.BAL_ACC
|
||||
LEFT JOIN OD_VALUES vs ON vs.ID = r.REG_2
|
||||
LEFT JOIN OD_VALUES vc ON vc.ID = r.VALUE_ID
|
||||
LEFT JOIN OD_SHARES sh ON sh.ID = r.REG_2
|
||||
WHERE r.REG_3 = @c AND b.IS_BAL = 1 AND b.PART = 39 AND b.NUM_1 IN (50,51,52,55,58)
|
||||
ORDER BY b.NUM_1, vs.NAME`
|
||||
|
||||
var Arch02 = `SELECT REST,
|
||||
CAST(SUM(CASE WHEN TYPE_ = 1 THEN AMOUNT_ ELSE -AMOUNT_ END) AS float),
|
||||
CAST(SUM(CASE WHEN TYPE_ = 1 THEN VALUE_ ELSE -VALUE_ END) AS float),
|
||||
CAST(SUM(CASE WHEN TYPE_ = 1 THEN EQ_ ELSE -EQ_ END) AS float)
|
||||
FROM OD_TURNS WHERE REST IN (%s) AND WIRDATE >= @d AND IS_PLAN = 'F' AND YEAR(WIRDATE) < 9000
|
||||
GROUP BY REST`
|
||||
|
||||
var Arch03 = `SELECT MAX(R_DATE) FROM OD_DOCS WHERE YEAR(R_DATE) < 9000`
|
||||
|
||||
var Arch04 = `SELECT TOP 1 OFICDATE, CAST(RATE3 AS float), CAST(PFR_PRICE AS float), CAST(CLOSE_ AS float)
|
||||
FROM OD_VALUES_RATES WHERE VALUE_ID = @v AND OFICDATE <= @d AND (RATE3 > 0 OR PFR_PRICE > 0 OR CLOSE_ > 0)
|
||||
ORDER BY OFICDATE DESC`
|
||||
|
||||
var Arch05 = `SELECT TOP 1 CAST(RATE AS float) FROM OD_VALUES_RATES WHERE VALUE_ID = @v AND MARKET = 0 AND OFICDATE <= @d AND RATE > 0 ORDER BY OFICDATE DESC`
|
||||
|
||||
var Arch06 = `SELECT r.ID, b.NUM_1, ISNULL(b.SYS_NAME,'') FROM OD_RESTS r JOIN OD_BALANCES b ON b.ID = r.BAL_ACC
|
||||
WHERE r.REG_3 = @c AND b.PART = 39 AND ((b.NUM_1 = 58 AND b.SYS_NAME LIKE N'ПОРТФЕЛЬ%') OR b.NUM_1 IN (50,51,52,55))`
|
||||
|
||||
var Arch07 = `
|
||||
WITH w AS (
|
||||
SELECT wr.WIRDATE, wr.EQ_, wr.D_REST, wr.K_REST, wr.D_SUMMA, wr.K_SUMMA, wr.D_AMOUNT, wr.K_AMOUNT, wr.NAME,
|
||||
wr.D_REST AS sec_rest, wr.K_REST AS money_rest
|
||||
FROM OD_WIRING wr
|
||||
WHERE wr.D_REST IN (%[1]s) AND wr.IS_PLAN = 'F' AND YEAR(wr.WIRDATE) < 9000
|
||||
AND wr.WIRDATE >= @f AND wr.WIRDATE < @t AND (wr.D_AMOUNT <> 0 OR wr.K_AMOUNT <> 0)
|
||||
UNION ALL
|
||||
SELECT wr.WIRDATE, wr.EQ_, wr.D_REST, wr.K_REST, wr.D_SUMMA, wr.K_SUMMA, wr.D_AMOUNT, wr.K_AMOUNT, wr.NAME,
|
||||
wr.K_REST, wr.D_REST
|
||||
FROM OD_WIRING wr
|
||||
WHERE wr.K_REST IN (%[1]s) AND wr.D_REST NOT IN (%[1]s) AND wr.IS_PLAN = 'F' AND YEAR(wr.WIRDATE) < 9000
|
||||
AND wr.WIRDATE >= @f AND wr.WIRDATE < @t AND (wr.D_AMOUNT <> 0 OR wr.K_AMOUNT <> 0))
|
||||
SELECT w.WIRDATE, CAST(ISNULL(w.EQ_,0) AS float), w.D_REST, w.K_REST,
|
||||
CAST(ISNULL(w.D_SUMMA,0) AS float), CAST(ISNULL(w.K_SUMMA,0) AS float),
|
||||
CAST(ISNULL(w.D_AMOUNT,0) AS float), CAST(ISNULL(w.K_AMOUNT,0) AS float),
|
||||
ISNULL(w.NAME,''), ISNULL(sv.NAME,''), ISNULL(sv.ISIN,''), ISNULL(mv.SYSNAME,'')
|
||||
FROM w
|
||||
LEFT JOIN OD_RESTS sr ON sr.ID = w.sec_rest
|
||||
LEFT JOIN OD_VALUES sv ON sv.ID = sr.REG_2
|
||||
LEFT JOIN OD_RESTS mr ON mr.ID = w.money_rest
|
||||
LEFT JOIN OD_VALUES mv ON mv.ID = mr.VALUE_ID
|
||||
ORDER BY w.WIRDATE`
|
||||
|
||||
var Arch08 = `SELECT w.WIRDATE, CAST(ISNULL(w.EQ_,0) AS float), w.D_REST, w.K_REST,
|
||||
CAST(ISNULL(w.D_SUMMA,0) AS float), CAST(ISNULL(w.K_SUMMA,0) AS float), ISNULL(w.NAME,''), ISNULL(mv.SYSNAME,'')
|
||||
FROM OD_WIRING w
|
||||
JOIN OD_RESTS mr ON mr.ID = CASE WHEN w.D_REST IN (%[1]s) THEN w.D_REST ELSE w.K_REST END
|
||||
LEFT JOIN OD_VALUES mv ON mv.ID = mr.VALUE_ID
|
||||
WHERE (w.D_REST IN (%[1]s) OR w.K_REST IN (%[1]s)) AND w.IS_PLAN = 'F' AND YEAR(w.WIRDATE) < 9000
|
||||
AND w.WIRDATE >= @f AND w.WIRDATE < @t
|
||||
ORDER BY w.WIRDATE`
|
||||
|
||||
var Arch09 = `SELECT r.ID FROM OD_RESTS r JOIN OD_BALANCES b ON b.ID = r.BAL_ACC WHERE r.REG_3 = @c AND b.SYS_NAME = N'ВЫРУЧКА'`
|
||||
|
||||
var Arch10 = `
|
||||
WITH w AS (
|
||||
SELECT wr.WIRDATE, wr.EQ_, wr.D_REST, wr.K_REST, wr.D_SUMMA, wr.K_SUMMA, wr.D_REST AS sec_rest
|
||||
FROM OD_WIRING wr
|
||||
WHERE wr.K_REST IN (%[1]s) AND wr.IS_PLAN = 'F' AND YEAR(wr.WIRDATE) < 9000
|
||||
AND wr.WIRDATE >= @f AND wr.WIRDATE < @t AND wr.EQ_ <> 0
|
||||
UNION ALL
|
||||
SELECT wr.WIRDATE, wr.EQ_, wr.D_REST, wr.K_REST, wr.D_SUMMA, wr.K_SUMMA, wr.K_REST
|
||||
FROM OD_WIRING wr
|
||||
WHERE wr.D_REST IN (%[1]s) AND wr.K_REST NOT IN (%[1]s) AND wr.IS_PLAN = 'F' AND YEAR(wr.WIRDATE) < 9000
|
||||
AND wr.WIRDATE >= @f AND wr.WIRDATE < @t AND wr.EQ_ <> 0)
|
||||
SELECT w.WIRDATE, CAST(ISNULL(w.EQ_,0) AS float), w.D_REST, w.K_REST,
|
||||
CAST(ISNULL(w.D_SUMMA,0) AS float), CAST(ISNULL(w.K_SUMMA,0) AS float), ISNULL(sv.ISIN,'')
|
||||
FROM w
|
||||
LEFT JOIN OD_RESTS sr ON sr.ID = w.sec_rest
|
||||
LEFT JOIN OD_VALUES sv ON sv.ID = sr.REG_2`
|
||||
@@ -0,0 +1,28 @@
|
||||
package fsql
|
||||
|
||||
var Chk01 = `SELECT TOP 1 ISNULL(NULLIF(SELF_ID,0),ID), ISNULL(NAME,''), DATE_BIRTH FROM OD_FACES WHERE REPLACE(ISNULL(DOC_SER,''),' ','')=@p1 AND DOC_NUM=@p2
|
||||
ORDER BY ISNULL(LAST_FLAG,0) DESC, ID DESC`
|
||||
|
||||
var Chk02 = `SELECT ID, ISNULL(NUMBER,''), ISNULL(STATE,-1), D_CLOSE FROM OD_CLIENTS WHERE FACE=@p1 AND NUMBER LIKE N'ВТНКЦ%' ORDER BY ID`
|
||||
|
||||
var Chk03 = `SELECT TOP 1 CAST(o.VAL AS varchar(20)) FROM OD_OPTIONS o
|
||||
JOIN OP_FIELDS f ON f.ID = o.DESCR AND f.AS_NAME = 'IS_QUAL'
|
||||
WHERE o.OBJECT = @p1 AND o.B_DATE <= GETDATE() AND (o.E_DATE IS NULL OR o.E_DATE > GETDATE())
|
||||
ORDER BY o.B_DATE DESC`
|
||||
|
||||
var Chk04 = `SELECT ISNULL(PORT_NUM,'') FROM OD_CLIENTS_PORTS WHERE CLIENT=@p1`
|
||||
|
||||
var Chk05 = `SELECT TOP 1 ID, ISNULL(NAME,''), IS_IN FROM OD_VALUES WHERE ISIN=@p1`
|
||||
|
||||
var Chk06 = `SELECT TOP 1 CAST(o.VAL AS varchar(20)) FROM OD_OPTIONS o
|
||||
JOIN OP_FIELDS f ON f.ID = o.DESCR AND f.AS_NAME = 'RESTRICTED'
|
||||
WHERE o.OBJECT = @p1 AND o.B_DATE <= GETDATE() AND (o.E_DATE IS NULL OR o.E_DATE > GETDATE())
|
||||
ORDER BY o.B_DATE DESC`
|
||||
|
||||
var Chk07 = `SELECT TOP 1 r.BLOCK_DATE, r.BLOCK_REASON, r.BAL_ACC, CAST(r.K AS float)
|
||||
FROM OD_RESTS r WHERE r.VALUE_ID=@p1 AND r.REG_1=@p2
|
||||
ORDER BY CASE WHEN r.BLOCK_DATE IS NOT NULL THEN 0 WHEN r.BAL_ACC IN (837,3410,4342,5647) AND CAST(r.K AS float)<>0 THEN 1 ELSE 2 END`
|
||||
|
||||
var Chk08 = `SELECT TOP 1 ID, ISNULL(STATE,-1), D_CLOSE FROM OD_CLIENTS WHERE FACE=@p1 AND UPPER(NUMBER)=@p2 ORDER BY ID`
|
||||
|
||||
var Chk09 = `SELECT ISNULL(SUM(CAST(K AS float)),0) FROM OD_RESTS WHERE VALUE_ID=@p1 AND REG_1=@p2 AND BAL_ACC=@p3`
|
||||
@@ -0,0 +1,10 @@
|
||||
package fsql
|
||||
|
||||
var Sim01 = `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`
|
||||
|
||||
var Sim02 = `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`
|
||||
@@ -0,0 +1,19 @@
|
||||
package fsql
|
||||
|
||||
var Dp01 = `SELECT p.PORT_NUM, ISNULL(c.NUMBER,''), ISNULL(v.ISIN,''), ISNULL(v.NAME,''),
|
||||
CAST(rst.K AS float), ISNULL(rst.BLOCK_REASON,''), ISNULL(rst.BAL_ACC,0)
|
||||
FROM OD_RESTS rst
|
||||
JOIN OD_CLIENTS c ON c.ID = rst.REG_1
|
||||
JOIN OD_CLIENTS_PORTS p ON p.CLIENT = c.ID
|
||||
JOIN OD_VALUES v ON v.ID = rst.VALUE_ID AND v.V_TYPE = 2
|
||||
WHERE (p.PORT_NUM = @p1 OR p.PORT_NUM LIKE @p2)
|
||||
AND CAST(rst.K AS float) <> 0
|
||||
ORDER BY v.NAME`
|
||||
|
||||
var Dp02 = `SELECT TOP (%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 float) <> 0 AND (@p1 = '' OR p.PORT_NUM LIKE @p2)
|
||||
GROUP BY p.PORT_NUM ORDER BY p.PORT_NUM`
|
||||
@@ -0,0 +1,7 @@
|
||||
package fsql
|
||||
|
||||
var QDb01 = "SELECT TOP 1 PORT_NUM FROM OD_CLIENTS_PORTS WHERE PORT_NUM=@p1 OR PORT_NUM LIKE @p2"
|
||||
|
||||
var QDb02 = "SELECT DISTINCT TOP (%d) PORT_NUM FROM OD_CLIENTS_PORTS WHERE PORT_NUM LIKE @p1 ORDER BY PORT_NUM"
|
||||
|
||||
var QDb03 = "SELECT DISTINCT TOP (5000) PORT_NUM FROM OD_CLIENTS_PORTS WHERE PORT_NUM <> '' ORDER BY PORT_NUM"
|
||||
@@ -0,0 +1,31 @@
|
||||
package fsql
|
||||
|
||||
var Ev01 = `INSERT INTO dbo.FTV_M2M_EVENTS (GUID, REFERENCE, EVENT_TYPE, EVENT_DATE, M2M_REJECT_CODE) VALUES (@g, @r, @t, @at, @c)`
|
||||
|
||||
var Ev02 = `INSERT INTO dbo.FTV_M2M_EVENTS (GUID, REFERENCE, EVENT_TYPE, EVENT_DATE, M2M_REJECT_CODE, PARAMETERS) VALUES (@g, @r, @t, @at, @c, @p)`
|
||||
|
||||
var Ev03 = `SELECT TOP 1 c.NUMBER FROM OD_FACES f
|
||||
JOIN OD_CLIENTS c ON c.FACE=f.ID LEFT JOIN OD_CLIENTS_PORTS p ON p.CLIENT=c.ID
|
||||
WHERE REPLACE(f.DOC_SER,' ','')=@s AND f.DOC_NUM=@n AND c.NUMBER LIKE N'ВТНКЦ%' AND c.STATE=0 AND c.D_CLOSE IS NULL
|
||||
ORDER BY ISNULL(p.PORT_DATE,'2099-01-01'), ISNULL(c.D_OPEN,'2099-01-01'), c.NUMBER`
|
||||
|
||||
var Ev04 = `INSERT INTO dbo.FTV_M2M (GUID, DIRECTION, CONTRAGENT_M2M_CODE, DEPONENT_NAME, DEPONENT_DOC) VALUES (@g, @d, @cp, @nm, @doc)`
|
||||
|
||||
var Ev05 = `INSERT INTO dbo.FTV_M2M (GUID, DIRECTION, CONTRAGENT_M2M_CODE, DEPONENT_NAME, DEPONENT_DOC, DEPONENT_ID) VALUES (@g, @d, @cp, @nm, @doc, @did)`
|
||||
|
||||
var Ev06 = `INSERT INTO dbo.FTV_M2M_LINES (`
|
||||
|
||||
var Ev07 = `SELECT TOP 200 CAST(m.GUID AS varchar(36)), ISNULL(m.STATE,''), ISNULL(`
|
||||
|
||||
var Ev08 = `,''), ISNULL(m.COMMENT,''),
|
||||
ISNULL((SELECT TOP 1 ISNULL(l.COMMENT,'') FROM dbo.FTV_M2M_LINES l WHERE l.GUID=m.GUID AND ISNULL(l.STATE,'')='ERROR'),''),
|
||||
ISNULL((SELECT TOP 1 ISNULL(st.NAME,'') FROM OD_DOCS d LEFT JOIN OD_DOC_STATES st ON st.ID=d.STATE AND st.D_CAT=0 WHERE CAST(d.ID AS varchar(32))=`
|
||||
|
||||
var Ev09 = `),''),
|
||||
(SELECT TOP 1 d.PROC_DATE FROM OD_DOCS d WHERE CAST(d.ID AS varchar(32))=`
|
||||
|
||||
var Ev10 = `INSERT INTO dbo.FTV_M2M_HANDBOOK (INN, PARTICIPANT_CODE, KIND, NAME_FULL, NAME_SHORT, NAME_DISPLAY, NAME_ENG, HANDBOOK_AT, UPDATED_AT, ACTIVE)
|
||||
VALUES (@inn, @code, @kind, @full, @short, @disp, @eng, @at, GETDATE(), 1)`
|
||||
|
||||
var Ev11 = `SELECT TOP 1 f.NAME FROM OD_FACES f JOIN OD_CLIENTS c ON c.FACE=f.ID
|
||||
WHERE REPLACE(f.DOC_SER,' ','')=@s AND f.DOC_NUM=@n AND c.NUMBER LIKE N'ВТНКЦ%' AND c.STATE=0`
|
||||
@@ -0,0 +1,17 @@
|
||||
package fsql
|
||||
|
||||
var QEv01 = "SELECT COUNT(*) FROM dbo.FTV_M2M_EVENTS WHERE GUID=@g AND ISNULL(REFERENCE,'')=@r AND EVENT_TYPE=@t"
|
||||
|
||||
var QEv02 = "SELECT COUNT(*) FROM dbo.FTV_M2M WHERE GUID=@g"
|
||||
|
||||
var QEv03 = "SELECT TOP 1 SELF_ID FROM OD_FACES WHERE REPLACE(DOC_SER,' ','')=@s AND DOC_NUM=@n ORDER BY ID"
|
||||
|
||||
var QEv04 = "SELECT TOP 1 ID FROM OD_VALUES WHERE ISIN=@i ORDER BY ID"
|
||||
|
||||
var QEv05 = "DELETE FROM dbo.FTV_M2M_HANDBOOK"
|
||||
|
||||
var QEv06 = "INSERT INTO dbo.FTV_M2M_EVENTS (GUID, REFERENCE, EVENT_TYPE, EVENT_DATE) VALUES (@g, NULL, 'BJ_PING', GETDATE())"
|
||||
|
||||
var QEv07 = "DELETE FROM dbo.FTV_M2M_EVENTS WHERE GUID=@g"
|
||||
|
||||
var QEv08 = "SELECT ISNULL(STATE,'') FROM dbo.FTV_M2M_EVENTS WHERE GUID=@g"
|
||||
@@ -0,0 +1,13 @@
|
||||
package fsql
|
||||
|
||||
var Hlth01 = `SELECT TOP (@n) * FROM (
|
||||
SELECT 'FTV_M2M' AS T, ID, CAST(GUID AS varchar(36)) AS G, '' AS R, ISNULL(DIRECTION,'') AS K, ISNULL(TimeEnd, TimeNew) AS A, ISNULL(COMMENT,'') AS C
|
||||
FROM dbo.FTV_M2M WHERE STATE='ERROR' AND ISNULL(TimeEnd, TimeNew) > DATEADD(day, -@d, GETDATE())
|
||||
UNION ALL
|
||||
SELECT 'FTV_M2M_EVENTS', ID, CAST(GUID AS varchar(36)), ISNULL(REFERENCE,''), EVENT_TYPE, ISNULL(TimeEnd, TimeNew), ISNULL(COMMENT,'')
|
||||
FROM dbo.FTV_M2M_EVENTS WHERE STATE='ERROR' AND EVENT_TYPE LIKE 'BJ[_]%' AND ISNULL(TimeEnd, TimeNew) > DATEADD(day, -@d, GETDATE())
|
||||
) x ORDER BY A DESC`
|
||||
|
||||
var Hlth02 = `SELECT COUNT(*) OVER (), ID, EVENT_TYPE, CAST(GUID AS varchar(36)), ISNULL(COMMENT,'')
|
||||
FROM dbo.FTV_M2M_EVENTS WHERE STATE='ERROR' AND EVENT_TYPE LIKE 'BJ[_]%' AND ID > @last AND ISNULL(TimeEnd, TimeNew) > DATEADD(day, -1, GETDATE())
|
||||
ORDER BY ID DESC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY`
|
||||
@@ -0,0 +1,7 @@
|
||||
package fsql
|
||||
|
||||
var QHl01 = "UPDATE dbo.FTV_M2M SET STATE='TODO', TimeBeg=NULL, TimeEnd=NULL, COMMENT=@c WHERE ID=@id AND STATE='ERROR'"
|
||||
|
||||
var QHl02 = "UPDATE dbo.FTV_M2M_EVENTS SET STATE='TODO', TimeBeg=NULL, TimeEnd=NULL, COMMENT=@c WHERE ID=@id AND STATE='ERROR'"
|
||||
|
||||
var QHl03 = "UPDATE dbo.FTV_M2M_LINES SET STATE='TODO', TimeBeg=NULL, TimeEnd=NULL WHERE GUID=@g AND STATE='ERROR'"
|
||||
@@ -0,0 +1,13 @@
|
||||
package fsql
|
||||
|
||||
var Que01 = `SELECT TOP (@n) CAST(m.GUID AS varchar(36)), ISNULL(m.STATE,''), ISNULL(m.DIRECTION,''), ISNULL(m.DEPONENT_NAME,''), ISNULL(m.DEPONENT_DOC,''), ISNULL(m.CONTRAGENT_M2M_CODE,''), `
|
||||
|
||||
var Que02 = `,''), ISNULL(m.COMMENT,''),
|
||||
ISNULL((SELECT TOP 1 ISNULL(st.NAME,'') FROM OD_DOCS d LEFT JOIN OD_DOC_STATES st ON st.ID=d.STATE AND st.D_CAT=0 WHERE CAST(d.ID AS varchar(32))=`
|
||||
|
||||
var Que03 = `),''),
|
||||
(SELECT TOP 1 d.PROC_DATE FROM OD_DOCS d WHERE CAST(d.ID AS varchar(32))=`
|
||||
|
||||
var Que04 = `SELECT CAST(l.GUID AS varchar(36)), ISNULL(l.ISIN,''), ISNULL(l.SEC_CODE,''), ISNULL(CAST(l.AMOUNT AS varchar(40)),''), ISNULL(l.STATE,''), ISNULL(l.COMMENT,'') FROM dbo.FTV_M2M_LINES l WHERE l.GUID IN (SELECT TOP (@n) GUID FROM dbo.FTV_M2M ORDER BY `
|
||||
|
||||
var Que05 = `SELECT CAST(e.GUID AS varchar(36)), ISNULL(e.REFERENCE,''), ISNULL(e.STATE,''), ISNULL(e.EVENT_TYPE,''), e.EVENT_DATE, ISNULL(e.M2M_REJECT_CODE,''), ISNULL(e.COMMENT,'') FROM dbo.FTV_M2M_EVENTS e WHERE e.GUID IN (SELECT TOP (@n) GUID FROM dbo.FTV_M2M ORDER BY `
|
||||
@@ -0,0 +1,5 @@
|
||||
package fsql
|
||||
|
||||
var QQu01 = "SELECT count(*) FROM dbo.FTV_M2M_HANDBOOK"
|
||||
|
||||
var QQu02 = "SELECT max(HANDBOOK_AT) FROM dbo.FTV_M2M_HANDBOOK"
|
||||
@@ -0,0 +1,5 @@
|
||||
package fsql
|
||||
|
||||
var Tbl01 = `GRANT SELECT ON ALL TABLES IN SCHEMA public TO "%s"`
|
||||
|
||||
var Tbl02 = `GRANT SELECT, INSERT, UPDATE, DELETE ON %s TO "%s"`
|
||||
@@ -0,0 +1,3 @@
|
||||
package fsql
|
||||
|
||||
var QTb01 = "-- Кроме того, логину bj нужно право SELECT на учётные таблицы DEPO (OD_CLIENTS, OD_CLIENTS_PORTS, OD_RESTS, OD_VALUES и др.) для сверки переводов.\n"
|
||||
@@ -0,0 +1,3 @@
|
||||
package fsql
|
||||
|
||||
var QIn01 = "SELECT CAST(DOC AS varchar(32)) FROM dbo.FTV_M2M WHERE GUID=@g"
|
||||
@@ -0,0 +1,4 @@
|
||||
package fsql
|
||||
|
||||
var Cl01 = `SELECT TOP 1 DOC, INVESTOR, NAME, C_OPEN, C_CLOSE, C_STATE FROM D_B_CONTRACTS
|
||||
WHERE UPPER(NAME) = @n OR UPPER(NAME) LIKE @n + ' %' ORDER BY C_STATE DESC, DOC DESC`
|
||||
@@ -0,0 +1,35 @@
|
||||
package fsql
|
||||
|
||||
var Doc01 = `SELECT TOP 40 ISNULL(a.KD_TYPE,''), ISNULL(v.ISIN,''), ISNULL(v.NAME,''), a.FIX_DATE, a.OPER_DATE, ISNULL(a.OFFER_NAME,'')
|
||||
FROM U_CA_ACTS a JOIN OD_VALUES v ON v.ID = a.SHARE
|
||||
WHERE UPPER(v.ISIN) IN (%s)
|
||||
AND ISNULL(a.FIX_DATE, a.OPER_DATE) >= DATEADD(month, -1, GETDATE())
|
||||
ORDER BY ISNULL(a.FIX_DATE, a.OPER_DATE)`
|
||||
|
||||
var Doc02 = `
|
||||
CREATE TABLE IF NOT EXISTS lk.doc_requests (
|
||||
id bigserial PRIMARY KEY,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
contract_number text NOT NULL,
|
||||
client_name text,
|
||||
kind text NOT NULL,
|
||||
period_from date,
|
||||
period_to date,
|
||||
account text,
|
||||
comment text,
|
||||
status text NOT NULL DEFAULT 'new',
|
||||
staff_note text,
|
||||
done_at timestamptz
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS ix_lk_doc_requests_contract ON lk.doc_requests (contract_number, created_at DESC);
|
||||
`
|
||||
|
||||
var Doc03 = `INSERT INTO lk.doc_requests (contract_number, client_name, kind, period_from, period_to, account, comment)
|
||||
VALUES ($1,$2,$3,$4,$5,$6,$7)`
|
||||
|
||||
var Doc04 = `SELECT id, created_at, kind, period_from, period_to, COALESCE(account,''), status, COALESCE(staff_note,'')
|
||||
FROM lk.doc_requests WHERE contract_number=$1 ORDER BY created_at DESC LIMIT 50`
|
||||
|
||||
var Doc05 = `SELECT TOP 30 d.R_DATE, ISNULL(d.NUM,''), e.B_DATE, e.E_DATE, e.DEPO, d.STATE, ISNULL(e.IS_TURNS,0)
|
||||
FROM U_OP_INF_EXTRACT e JOIN OD_DOCS d ON d.ID = e.DOC
|
||||
WHERE e.DEPO IN (%s) ORDER BY d.R_DATE DESC`
|
||||
@@ -0,0 +1,7 @@
|
||||
package fsql
|
||||
|
||||
var Flow01 = `SELECT ISNULL(`
|
||||
|
||||
var Flow02 = `,''), ISNULL(m.STATE,''), ISNULL(m.COMMENT,''),
|
||||
ISNULL((SELECT TOP 1 ISNULL(l.COMMENT,'') FROM dbo.FTV_M2M_LINES l WHERE l.GUID=m.GUID AND ISNULL(l.STATE,'')='ERROR'),'')
|
||||
FROM dbo.FTV_M2M m WHERE m.GUID=@g`
|
||||
@@ -0,0 +1,3 @@
|
||||
package fsql
|
||||
|
||||
var QFl01 = "SELECT ISNULL(STATE,''), ISNULL(COMMENT,'') FROM dbo.FTV_M2M_EVENTS WHERE GUID=@g AND EVENT_TYPE='BJ_GATEWAY_REJECT'"
|
||||
@@ -0,0 +1,6 @@
|
||||
package fsql
|
||||
|
||||
var Fx01 = `SELECT UPPER(LTRIM(RTRIM(v.SYSNAME))), r.OFICDATE, CAST(r.RATE AS float)
|
||||
FROM OD_VALUES_RATES r JOIN OD_VALUES v ON v.ID = r.VALUE_ID
|
||||
WHERE v.V_TYPE = 1 AND r.MARKET = 0 AND r.RATE > 0
|
||||
AND r.OFICDATE = (SELECT MAX(x.OFICDATE) FROM OD_VALUES_RATES x WHERE x.VALUE_ID = r.VALUE_ID AND x.MARKET = 0 AND x.RATE > 0)`
|
||||
@@ -0,0 +1,47 @@
|
||||
package fsql
|
||||
|
||||
var Hist01 = `SELECT DISTINCT c.ID, ISNULL(c.NUMBER,''), ISNULL(c.FACE,0)
|
||||
FROM OD_CLIENTS c JOIN OD_CLIENTS_PORTS p ON p.CLIENT = c.ID
|
||||
WHERE p.PORT_NUM = @p1 OR p.PORT_NUM LIKE @p2`
|
||||
|
||||
var Hist02 = `SELECT TOP %d * FROM (
|
||||
SELECT d.R_DATE AS RD, d.PROC_DATE AS PD, ISNULL(d.NUM,'') AS NUM, d.STATE AS ST, N'зачисление' AS KIND,
|
||||
z.DEPO AS ACC, ISNULL(v.ISIN,'') AS ISIN, ISNULL(v.NAME,'') AS SEC, CAST(ISNULL(z.AMOUNT,0) AS float) AS QTY,
|
||||
LTRIM(RTRIM(ISNULL(z.COMMENT,'') + ' ' + ISNULL(z.REJECT_REASON,''))) AS NOTE
|
||||
FROM U_OP_INV_ZACH z JOIN OD_DOCS d ON d.ID = z.DOC LEFT JOIN OD_VALUES v ON v.ID = z.SHARE
|
||||
WHERE z.DEPO IN (%s)
|
||||
UNION ALL
|
||||
SELECT d.R_DATE, d.PROC_DATE, ISNULL(d.NUM,''), d.STATE, N'списание',
|
||||
p.DEPO, ISNULL(v.ISIN,''), ISNULL(v.NAME,''), -CAST(ISNULL(p.AMOUNT,0) AS float),
|
||||
LTRIM(RTRIM(ISNULL(p.COMMENT,'') + ' ' + ISNULL(p.REJECT_REASON,'')))
|
||||
FROM U_OP_INV_SPIS p JOIN OD_DOCS d ON d.ID = p.DOC LEFT JOIN OD_VALUES v ON v.ID = p.SHARE
|
||||
WHERE p.DEPO IN (%s)
|
||||
UNION ALL
|
||||
SELECT d.R_DATE, d.PROC_DATE, ISNULL(d.NUM,''), d.STATE, N'перевод: списание',
|
||||
t.D_DEPO, ISNULL(v.ISIN,''), ISNULL(v.NAME,''), -CAST(ISNULL(t.AMOUNT,0) AS float),
|
||||
LTRIM(RTRIM(ISNULL(t.COMMENT,'') + ' ' + ISNULL(t.REJECT_REASON,'')))
|
||||
FROM U_OP_INV_PEREVOD t JOIN OD_DOCS d ON d.ID = t.DOC LEFT JOIN OD_VALUES v ON v.ID = t.SHARE
|
||||
WHERE t.D_DEPO IN (%s)
|
||||
UNION ALL
|
||||
SELECT d.R_DATE, d.PROC_DATE, ISNULL(d.NUM,''), d.STATE, N'перевод: зачисление',
|
||||
t.K_DEPO, ISNULL(v.ISIN,''), ISNULL(v.NAME,''), CAST(ISNULL(t.AMOUNT,0) AS float),
|
||||
LTRIM(RTRIM(ISNULL(t.COMMENT,'') + ' ' + ISNULL(t.REJECT_REASON,'')))
|
||||
FROM U_OP_INV_PEREVOD t JOIN OD_DOCS d ON d.ID = t.DOC LEFT JOIN OD_VALUES v ON v.ID = t.SHARE
|
||||
WHERE t.K_DEPO IN (%s)) x
|
||||
WHERE x.RD >= @p1 AND x.RD < DATEADD(day, 1, @p2)
|
||||
ORDER BY x.RD DESC, x.NUM DESC`
|
||||
|
||||
var Hist03 = `SELECT TOP 200 h.P_DATE, h.INCOME_KIND, ISNULL(v.ISIN,''), ISNULL(v.NAME,''),
|
||||
CAST(ISNULL(l.AMOUNT,0) AS float), CAST(ISNULL(l.SUMMA_TOTAL,0) AS float),
|
||||
CAST(ISNULL(l.TAX_HOLDED,0) AS float), CAST(ISNULL(l.TOTAL_TO_PAY,0) AS float),
|
||||
ISNULL(l.STATUS,''), ISNULL(l.DEPO,0)
|
||||
FROM U_OP_INF_INCOME_DOL l
|
||||
JOIN OD_DOLS o ON o.ID = l.DOL
|
||||
JOIN U_OP_INF_INCOME h ON h.DOC = o.DOC
|
||||
LEFT JOIN OD_VALUES v ON v.ID = h.SHARE
|
||||
WHERE (l.DEPO IN (%s) OR l.INCOME_FACE = @p3)
|
||||
AND h.P_DATE >= @p1 AND h.P_DATE < DATEADD(day, 1, @p2)
|
||||
ORDER BY h.P_DATE DESC`
|
||||
|
||||
var Hist04 = `SELECT CAST(ISNULL(SUM(CAST(SUMMA AS float)),0) AS float) FROM OD_NDFL
|
||||
WHERE FACE = @p1 AND R_DATE >= @p2 AND R_DATE < DATEADD(day, 1, @p3)`
|
||||
@@ -0,0 +1,22 @@
|
||||
package fsql
|
||||
|
||||
var On01 = `
|
||||
WITH d AS (
|
||||
SELECT DISTINCT ON ("ClientCode","SecCode","Trdacc") "SecCode","CurrentBal","AwgPositionPrice","LoadDate"
|
||||
FROM "DepoLimits" WHERE "ClientCode" = ANY($1) AND "LimitKind"='T2'
|
||||
ORDER BY "ClientCode","SecCode","Trdacc","LoadDate" DESC)
|
||||
SELECT "SecCode", SUM("CurrentBal")::float8,
|
||||
COALESCE(SUM("CurrentBal"*"AwgPositionPrice")/NULLIF(SUM("CurrentBal"),0),0)::float8, MAX("LoadDate")
|
||||
FROM d WHERE "CurrentBal" <> 0 GROUP BY "SecCode" ORDER BY "SecCode"`
|
||||
|
||||
var On02 = `
|
||||
SELECT DISTINCT ON ("SecCode") "SecCode", upper(COALESCE("ISINCode",'')), COALESCE("SecShortName","SecName",''), "ClassCode", COALESCE("FaceValue",0)::float8
|
||||
FROM "Securities" WHERE "SecCode" = ANY($1)
|
||||
ORDER BY "SecCode", CASE "ClassCode" WHEN 'TQBR' THEN 1 WHEN 'TQOB' THEN 2 WHEN 'TQCB' THEN 3 WHEN 'TQTF' THEN 4 WHEN 'TQIF' THEN 5 WHEN 'TQRD' THEN 6 ELSE 9 END`
|
||||
|
||||
var On03 = `
|
||||
WITH m AS (
|
||||
SELECT DISTINCT ON ("ClientCode","CurrCode","Tag") "CurrCode","CurrentBal","LoadDate"
|
||||
FROM "MoneyLimits" WHERE "ClientCode" = ANY($1) AND "LimitKind"='T2'
|
||||
ORDER BY "ClientCode","CurrCode","Tag","LoadDate" DESC)
|
||||
SELECT "CurrCode", SUM("CurrentBal")::float8, MAX("LoadDate") FROM m GROUP BY "CurrCode" HAVING SUM("CurrentBal") <> 0 ORDER BY "CurrCode"`
|
||||
@@ -0,0 +1,22 @@
|
||||
package fsql
|
||||
|
||||
var Sn01 = `
|
||||
CREATE TABLE IF NOT EXISTS lk.portfolio_daily (
|
||||
day DATE NOT NULL, contract VARCHAR(64) NOT NULL,
|
||||
value DOUBLE PRECISION NOT NULL DEFAULT 0, cash DOUBLE PRECISION NOT NULL DEFAULT 0,
|
||||
positions INT NOT NULL DEFAULT 0, priced INT NOT NULL DEFAULT 0,
|
||||
source VARCHAR(16) NOT NULL DEFAULT 'quik', created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (day, contract))`
|
||||
|
||||
var Sn02 = `SELECT day, value, cash, positions FROM lk.portfolio_daily
|
||||
WHERE contract = $1 AND day >= current_date - $2::int ORDER BY day`
|
||||
|
||||
var Sn03 = `INSERT INTO lk.portfolio_daily(day, contract, value, cash, positions, priced, source)
|
||||
VALUES ($1,$2,$3,$4,$5,$6,$7)
|
||||
ON CONFLICT (day, contract) DO UPDATE SET value = EXCLUDED.value, cash = EXCLUDED.cash,
|
||||
positions = EXCLUDED.positions, priced = EXCLUDED.priced, source = EXCLUDED.source, created_at = now()`
|
||||
|
||||
var Sn04 = `SELECT DISTINCT "ClientCode" FROM "DepoLimits"
|
||||
WHERE "LimitKind" = 'T2' AND "CurrentBal" <> 0 AND "ClientCode" <> ''`
|
||||
|
||||
var Sn05 = `SELECT count(*) FROM lk.portfolio_daily WHERE day = $1`
|
||||
@@ -0,0 +1,17 @@
|
||||
package fsql
|
||||
|
||||
var Up01 = `SELECT UPPER(v.ISIN), ISNULL(c.P_DATE, c.E_DATE), CAST(ISNULL(c.SUMMA,0) AS float), CAST(ISNULL(c.PERCENT_,0) AS float)
|
||||
FROM OD_COUPONS c JOIN OD_VALUES v ON v.ID = c.SHARE
|
||||
WHERE UPPER(v.ISIN) IN (%s) AND ISNULL(c.P_DATE, c.E_DATE) >= @f AND ISNULL(c.P_DATE, c.E_DATE) <= @t`
|
||||
|
||||
var Up02 = `SELECT UPPER(v.ISIN), o.P_DATE, CAST(ISNULL(o.O_PRICE,0) AS float)
|
||||
FROM OD_OFFERS o JOIN OD_VALUES v ON v.ID = o.SHARE
|
||||
WHERE UPPER(v.ISIN) IN (%s) AND o.CANCEL_DATE IS NULL AND o.P_DATE >= @f AND o.P_DATE <= @t`
|
||||
|
||||
var Up03 = `SELECT UPPER(v.ISIN), sh.DEATHDATE, CAST(ISNULL(sh.NOMINAL,0) AS float)
|
||||
FROM OD_SHARES sh JOIN OD_VALUES v ON v.ID = sh.ID
|
||||
WHERE UPPER(v.ISIN) IN (%s) AND sh.E_DATE > GETDATE() AND sh.DEATHDATE >= @f AND sh.DEATHDATE <= @t`
|
||||
|
||||
var Up04 = `SELECT UPPER(v.ISIN), ISNULL(a.OPER_DATE, a.FIX_DATE)
|
||||
FROM U_CA_ACTS a JOIN OD_VALUES v ON v.ID = a.SHARE
|
||||
WHERE UPPER(v.ISIN) IN (%s) AND UPPER(ISNULL(a.KD_TYPE,'')) = 'DVCA' AND ISNULL(a.OPER_DATE, a.FIX_DATE) >= @f AND ISNULL(a.OPER_DATE, a.FIX_DATE) <= @t`
|
||||
@@ -0,0 +1,19 @@
|
||||
package fsql
|
||||
|
||||
var Man01 = `SELECT TOP 20 ISNULL(NULLIF(f.SELF_ID,0),f.ID), ISNULL(f.NAME,''), f.DATE_BIRTH, ISNULL(f.DOC_TYPE,0), ISNULL(f.DOC_SER,''), ISNULL(f.DOC_NUM,''),
|
||||
f.DOC_DAT, ISNULL(f.DOC_PLACE,''), ISNULL(f.DOC_CODE,''), ISNULL(f.PHONE,'')
|
||||
FROM OD_FACES f
|
||||
WHERE ISNULL(f.LAST_FLAG,1)=1 AND (UPPER(f.NAME) LIKE UPPER(@q) OR f.DOC_NUM=@d OR REPLACE(ISNULL(f.DOC_SER,''),' ','')+f.DOC_NUM=@d)
|
||||
AND EXISTS (SELECT 1 FROM OD_CLIENTS c WHERE c.FACE=ISNULL(NULLIF(f.SELF_ID,0),f.ID) AND c.NUMBER LIKE N'ВТНКЦ%' AND c.STATE=0 AND c.D_CLOSE IS NULL)
|
||||
ORDER BY f.NAME`
|
||||
|
||||
var Man02 = `SELECT c.ID, ISNULL(c.NUMBER,''),
|
||||
ISNULL((SELECT TOP 1 p.PORT_NUM FROM OD_CLIENTS_PORTS p WHERE p.CLIENT=c.ID ORDER BY p.PORT_DATE, p.PORT_NUM),'')
|
||||
FROM OD_CLIENTS c WHERE c.FACE=@f AND c.NUMBER LIKE N'ВТНКЦ%' AND c.STATE=0 AND c.D_CLOSE IS NULL ORDER BY c.ID`
|
||||
|
||||
var Man03 = `SELECT ISNULL(v.ISIN,''), ISNULL(v.NAME,''), SUM(CAST(r.K AS float))
|
||||
FROM OD_RESTS r JOIN OD_VALUES v ON v.ID=r.VALUE_ID
|
||||
WHERE r.REG_1=@c AND r.BAL_ACC=@b
|
||||
GROUP BY v.ISIN, v.NAME HAVING SUM(CAST(r.K AS float)) > 0 ORDER BY v.NAME`
|
||||
|
||||
var Man04 = `SELECT TOP 1 ID FROM OD_CLIENTS WHERE NUMBER=@n AND STATE=0 AND D_CLOSE IS NULL ORDER BY ID`
|
||||
@@ -0,0 +1,13 @@
|
||||
package fsql
|
||||
|
||||
var Pr01 = `
|
||||
SELECT DISTINCT ON (s."ISINCode")
|
||||
upper(s."ISINCode"), s."ClassCode", COALESCE(s."SecShortName", s."SecName", ''),
|
||||
COALESCE(p.last, 0)::float8, COALESCE(p.prevprice, 0)::float8,
|
||||
COALESCE(s."FaceValue", 0)::float8, COALESCE(p.accruedint, 0)::float8, COALESCE(s."FaceUnit", '')
|
||||
FROM "Securities" s JOIN "Params" p ON p."SecCode" = s."SecCode" AND p."ClassCode" = s."ClassCode"
|
||||
WHERE s."ISINCode" <> '' AND (p.last > 0 OR p.prevprice > 0)
|
||||
ORDER BY s."ISINCode",
|
||||
CASE s."ClassCode" WHEN 'TQBR' THEN 1 WHEN 'TQOB' THEN 2 WHEN 'TQCB' THEN 3
|
||||
WHEN 'TQTF' THEN 4 WHEN 'TQIF' THEN 5 WHEN 'TQRD' THEN 6 ELSE 9 END,
|
||||
p.last DESC`
|
||||
@@ -0,0 +1,9 @@
|
||||
package fsql
|
||||
|
||||
var Qk01 = `SELECT ic.ClassCode, sec.SecCode FROM ISecurities sec JOIN IClasses ic ON ic.ClassId=sec.ClassId
|
||||
WHERE sec.Enable=1 AND ic.ClassCode IN ('INSTRINM2M','INSTROUTM2M') ORDER BY sec.SecurityId`
|
||||
|
||||
var Qk02 = `SELECT TOP 5 p.PORT_NUM FROM OD_FACES f
|
||||
JOIN OD_CLIENTS c ON c.FACE=f.ID JOIN OD_CLIENTS_PORTS p ON p.CLIENT=c.ID
|
||||
WHERE REPLACE(f.DOC_SER,' ','')=@p1 AND f.DOC_NUM=@p2 AND c.NUMBER LIKE N'ВТНКЦ%' AND c.STATE=0
|
||||
ORDER BY ISNULL(p.PORT_DATE,'2099-01-01'), ISNULL(c.D_OPEN,'2099-01-01'), c.NUMBER`
|
||||
@@ -0,0 +1,16 @@
|
||||
package fsql
|
||||
|
||||
var Sec01 = `SELECT TOP 1 ID, ISNULL(NAME,''), ISNULL(CFI,''), V_TYPE, IS_IN FROM OD_VALUES WHERE ISIN=@p1 ORDER BY ID`
|
||||
|
||||
var Sec02 = `SELECT TOP 1 ISSUER, CAST(NOMINAL AS float), NUM_REG, DEATHDATE FROM OD_SHARES
|
||||
WHERE ID=@p1 AND E_DATE > GETDATE() ORDER BY B_DATE DESC`
|
||||
|
||||
var Sec03 = `SELECT TOP 1 ISNULL(NAME,'') FROM OD_FACES WHERE ID=@p1 OR SELF_ID=@p1 ORDER BY ISNULL(LAST_FLAG,0) DESC, ID DESC`
|
||||
|
||||
var Sec04 = `SELECT TOP 12 ISNULL(P_DATE, E_DATE) AS PAY_DATE, CAST(ISNULL(SUMMA,0) AS float),
|
||||
CAST(ISNULL(PERCENT_,0) AS float), FIX_DATE, ISNULL(IS_PAY,0)
|
||||
FROM OD_COUPONS WHERE SHARE=@p1 AND ISNULL(P_DATE, E_DATE) >= DATEADD(month,-3,GETDATE())
|
||||
ORDER BY PAY_DATE`
|
||||
|
||||
var Sec05 = `SELECT TOP 3 P_DATE, CAST(ISNULL(O_PRICE,0) AS float) FROM OD_OFFERS
|
||||
WHERE SHARE=@p1 AND CANCEL_DATE IS NULL AND P_DATE >= GETDATE() ORDER BY P_DATE`
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
@@ -72,7 +73,7 @@ func registerIncoming(mux *http.ServeMux, a *admin, deps incomingDeps) {
|
||||
for i := 0; i < 8; i++ {
|
||||
time.Sleep(5 * time.Second)
|
||||
var d sql.NullString
|
||||
_ = db.QueryRowContext(ctx, "SELECT CAST(DOC AS varchar(32)) FROM dbo.FTV_M2M WHERE GUID=@g", sql.Named("g", guid)).Scan(&d)
|
||||
_ = db.QueryRowContext(ctx, fsql.QIn01, sql.Named("g", guid)).Scan(&d)
|
||||
if d.Valid && d.String != "" && d.String != "0" {
|
||||
doc = d.String
|
||||
break
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -63,15 +64,7 @@ func lkArchivePortfolio(ctx context.Context, s FancyMSSQLSettings, contract stri
|
||||
today := time.Now()
|
||||
isPast := day.Before(time.Date(today.Year(), today.Month(), today.Day(), 0, 0, 0, 0, time.UTC))
|
||||
|
||||
rows, err := conn.QueryContext(cctx, `SELECT r.ID, b.NUM_S, ISNULL(b.SYS_NAME,''), b.NUM_1, ISNULL(r.REG_2,0), ISNULL(r.VALUE_ID,0),
|
||||
CAST(ISNULL(r.A,0) AS float), CAST(ISNULL(r.D,0) AS float), CAST(ISNULL(r.EQ_D,0) AS float),
|
||||
ISNULL(vs.ISIN,''), ISNULL(vs.NAME,''), ISNULL(vc.SYSNAME,''), ISNULL(sh.CLASS,0), CAST(ISNULL(sh.NOMINAL,0) AS float)
|
||||
FROM OD_RESTS r JOIN OD_BALANCES b ON b.ID = r.BAL_ACC
|
||||
LEFT JOIN OD_VALUES vs ON vs.ID = r.REG_2
|
||||
LEFT JOIN OD_VALUES vc ON vc.ID = r.VALUE_ID
|
||||
LEFT JOIN OD_SHARES sh ON sh.ID = r.REG_2
|
||||
WHERE r.REG_3 = @c AND b.IS_BAL = 1 AND b.PART = 39 AND b.NUM_1 IN (50,51,52,55,58)
|
||||
ORDER BY b.NUM_1, vs.NAME`, sql.Named("c", c.DOC))
|
||||
rows, err := conn.QueryContext(cctx, fsql.Arch01, sql.Named("c", c.DOC))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("остатки: %v", err)
|
||||
}
|
||||
@@ -91,12 +84,7 @@ func lkArchivePortfolio(ctx context.Context, s FancyMSSQLSettings, contract stri
|
||||
for _, r := range rests {
|
||||
ids = append(ids, fmt.Sprint(r.id))
|
||||
}
|
||||
trows, err := conn.QueryContext(cctx, fmt.Sprintf(`SELECT REST,
|
||||
CAST(SUM(CASE WHEN TYPE_ = 1 THEN AMOUNT_ ELSE -AMOUNT_ END) AS float),
|
||||
CAST(SUM(CASE WHEN TYPE_ = 1 THEN VALUE_ ELSE -VALUE_ END) AS float),
|
||||
CAST(SUM(CASE WHEN TYPE_ = 1 THEN EQ_ ELSE -EQ_ END) AS float)
|
||||
FROM OD_TURNS WHERE REST IN (%s) AND WIRDATE >= @d AND IS_PLAN = 'F' AND YEAR(WIRDATE) < 9000
|
||||
GROUP BY REST`, strings.Join(ids, ",")), sql.Named("d", day.AddDate(0, 0, 1)))
|
||||
trows, err := conn.QueryContext(cctx, fmt.Sprintf(fsql.Arch02, strings.Join(ids, ",")), sql.Named("d", day.AddDate(0, 0, 1)))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("обороты: %v", err)
|
||||
}
|
||||
@@ -209,7 +197,7 @@ func spectreAsOf(ctx context.Context, conn *sql.DB) time.Time {
|
||||
return spectreAsOfCache.v
|
||||
}
|
||||
var d sql.NullTime
|
||||
_ = conn.QueryRowContext(ctx, `SELECT MAX(R_DATE) FROM OD_DOCS WHERE YEAR(R_DATE) < 9000`).Scan(&d)
|
||||
_ = conn.QueryRowContext(ctx, fsql.Arch03).Scan(&d)
|
||||
v := time.Time{}
|
||||
if d.Valid {
|
||||
v = time.Date(d.Time.Year(), d.Time.Month(), d.Time.Day(), 0, 0, 0, 0, time.UTC)
|
||||
@@ -253,9 +241,7 @@ func spectreKind(class int) string {
|
||||
func spectreQuote(ctx context.Context, conn *sql.DB, secID int64, day time.Time) (float64, int) {
|
||||
var ofic sql.NullTime
|
||||
var rate3, pfr, closeP sql.NullFloat64
|
||||
err := conn.QueryRowContext(ctx, `SELECT TOP 1 OFICDATE, CAST(RATE3 AS float), CAST(PFR_PRICE AS float), CAST(CLOSE_ AS float)
|
||||
FROM OD_VALUES_RATES WHERE VALUE_ID = @v AND OFICDATE <= @d AND (RATE3 > 0 OR PFR_PRICE > 0 OR CLOSE_ > 0)
|
||||
ORDER BY OFICDATE DESC`, sql.Named("v", secID), sql.Named("d", day.AddDate(0, 0, 1))).Scan(&ofic, &rate3, &pfr, &closeP)
|
||||
err := conn.QueryRowContext(ctx, fsql.Arch04, sql.Named("v", secID), sql.Named("d", day.AddDate(0, 0, 1))).Scan(&ofic, &rate3, &pfr, &closeP)
|
||||
if err != nil {
|
||||
return 0, 1 << 30
|
||||
}
|
||||
@@ -287,7 +273,7 @@ func spectreFx(ctx context.Context, conn *sql.DB, day time.Time) func(curID int6
|
||||
return v
|
||||
}
|
||||
var rate sql.NullFloat64
|
||||
_ = conn.QueryRowContext(ctx, `SELECT TOP 1 CAST(RATE AS float) FROM OD_VALUES_RATES WHERE VALUE_ID = @v AND MARKET = 0 AND OFICDATE <= @d AND RATE > 0 ORDER BY OFICDATE DESC`,
|
||||
_ = conn.QueryRowContext(ctx, fsql.Arch05,
|
||||
sql.Named("v", curID), sql.Named("d", day.AddDate(0, 0, 1))).Scan(&rate)
|
||||
v := rate.Float64
|
||||
if v <= 0 {
|
||||
@@ -355,8 +341,7 @@ func lkArchiveOperationsLoad(ctx context.Context, s FancyMSSQLSettings, contract
|
||||
cctx, cancel := context.WithTimeout(ctx, 40*time.Second)
|
||||
defer cancel()
|
||||
// Счета бумаг (ПОРТФЕЛЬ) и денег (касса) договора.
|
||||
rows, err := conn.QueryContext(cctx, `SELECT r.ID, b.NUM_1, ISNULL(b.SYS_NAME,'') FROM OD_RESTS r JOIN OD_BALANCES b ON b.ID = r.BAL_ACC
|
||||
WHERE r.REG_3 = @c AND b.PART = 39 AND ((b.NUM_1 = 58 AND b.SYS_NAME LIKE N'ПОРТФЕЛЬ%') OR b.NUM_1 IN (50,51,52,55))`, sql.Named("c", c.DOC))
|
||||
rows, err := conn.QueryContext(cctx, fsql.Arch06, sql.Named("c", c.DOC))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -404,29 +389,7 @@ func lkArchiveOperationsLoad(ctx context.Context, s FancyMSSQLSettings, contract
|
||||
// разбирать список счетов на каждой строке журнала — год данных читался
|
||||
// 6–7 секунд, сейчас — десятки миллисекунд (оба индекса по D_REST/K_REST
|
||||
// с WIRDATE отрабатывают поиском).
|
||||
wrows, err := conn.QueryContext(cctx, fmt.Sprintf(`
|
||||
WITH w AS (
|
||||
SELECT wr.WIRDATE, wr.EQ_, wr.D_REST, wr.K_REST, wr.D_SUMMA, wr.K_SUMMA, wr.D_AMOUNT, wr.K_AMOUNT, wr.NAME,
|
||||
wr.D_REST AS sec_rest, wr.K_REST AS money_rest
|
||||
FROM OD_WIRING wr
|
||||
WHERE wr.D_REST IN (%[1]s) AND wr.IS_PLAN = 'F' AND YEAR(wr.WIRDATE) < 9000
|
||||
AND wr.WIRDATE >= @f AND wr.WIRDATE < @t AND (wr.D_AMOUNT <> 0 OR wr.K_AMOUNT <> 0)
|
||||
UNION ALL
|
||||
SELECT wr.WIRDATE, wr.EQ_, wr.D_REST, wr.K_REST, wr.D_SUMMA, wr.K_SUMMA, wr.D_AMOUNT, wr.K_AMOUNT, wr.NAME,
|
||||
wr.K_REST, wr.D_REST
|
||||
FROM OD_WIRING wr
|
||||
WHERE wr.K_REST IN (%[1]s) AND wr.D_REST NOT IN (%[1]s) AND wr.IS_PLAN = 'F' AND YEAR(wr.WIRDATE) < 9000
|
||||
AND wr.WIRDATE >= @f AND wr.WIRDATE < @t AND (wr.D_AMOUNT <> 0 OR wr.K_AMOUNT <> 0))
|
||||
SELECT w.WIRDATE, CAST(ISNULL(w.EQ_,0) AS float), w.D_REST, w.K_REST,
|
||||
CAST(ISNULL(w.D_SUMMA,0) AS float), CAST(ISNULL(w.K_SUMMA,0) AS float),
|
||||
CAST(ISNULL(w.D_AMOUNT,0) AS float), CAST(ISNULL(w.K_AMOUNT,0) AS float),
|
||||
ISNULL(w.NAME,''), ISNULL(sv.NAME,''), ISNULL(sv.ISIN,''), ISNULL(mv.SYSNAME,'')
|
||||
FROM w
|
||||
LEFT JOIN OD_RESTS sr ON sr.ID = w.sec_rest
|
||||
LEFT JOIN OD_VALUES sv ON sv.ID = sr.REG_2
|
||||
LEFT JOIN OD_RESTS mr ON mr.ID = w.money_rest
|
||||
LEFT JOIN OD_VALUES mv ON mv.ID = mr.VALUE_ID
|
||||
ORDER BY w.WIRDATE`, in), sql.Named("f", fromDay), sql.Named("t", toEnd))
|
||||
wrows, err := conn.QueryContext(cctx, fmt.Sprintf(fsql.Arch07, in), sql.Named("f", fromDay), sql.Named("t", toEnd))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("проводки: %v", err)
|
||||
}
|
||||
@@ -501,14 +464,7 @@ func spectreCashOps(ctx context.Context, conn *sql.DB, cashIDs []string, fromDay
|
||||
}
|
||||
var out []LKOperationRow
|
||||
in := strings.Join(cashIDs, ",")
|
||||
crows, err := conn.QueryContext(ctx, fmt.Sprintf(`SELECT w.WIRDATE, CAST(ISNULL(w.EQ_,0) AS float), w.D_REST, w.K_REST,
|
||||
CAST(ISNULL(w.D_SUMMA,0) AS float), CAST(ISNULL(w.K_SUMMA,0) AS float), ISNULL(w.NAME,''), ISNULL(mv.SYSNAME,'')
|
||||
FROM OD_WIRING w
|
||||
JOIN OD_RESTS mr ON mr.ID = CASE WHEN w.D_REST IN (%[1]s) THEN w.D_REST ELSE w.K_REST END
|
||||
LEFT JOIN OD_VALUES mv ON mv.ID = mr.VALUE_ID
|
||||
WHERE (w.D_REST IN (%[1]s) OR w.K_REST IN (%[1]s)) AND w.IS_PLAN = 'F' AND YEAR(w.WIRDATE) < 9000
|
||||
AND w.WIRDATE >= @f AND w.WIRDATE < @t
|
||||
ORDER BY w.WIRDATE`, in), sql.Named("f", fromDay), sql.Named("t", toEnd))
|
||||
crows, err := conn.QueryContext(ctx, fmt.Sprintf(fsql.Arch08, in), sql.Named("f", fromDay), sql.Named("t", toEnd))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -571,7 +527,7 @@ func spectreDealKind(name string, onDebit bool) string {
|
||||
// spectreProceeds — выручка от продаж по (ISIN|день): [сумма в валюте, сумма в рублях].
|
||||
func spectreProceeds(ctx context.Context, conn *sql.DB, doc int64, from, to time.Time) map[string][2]float64 {
|
||||
out := map[string][2]float64{}
|
||||
rows, err := conn.QueryContext(ctx, `SELECT r.ID FROM OD_RESTS r JOIN OD_BALANCES b ON b.ID = r.BAL_ACC WHERE r.REG_3 = @c AND b.SYS_NAME = N'ВЫРУЧКА'`, sql.Named("c", doc))
|
||||
rows, err := conn.QueryContext(ctx, fsql.Arch09, sql.Named("c", doc))
|
||||
if err != nil {
|
||||
return out
|
||||
}
|
||||
@@ -589,22 +545,7 @@ func spectreProceeds(ctx context.Context, conn *sql.DB, doc int64, from, to time
|
||||
return out
|
||||
}
|
||||
in := strings.Join(ids, ",")
|
||||
wrows, err := conn.QueryContext(ctx, fmt.Sprintf(`
|
||||
WITH w AS (
|
||||
SELECT wr.WIRDATE, wr.EQ_, wr.D_REST, wr.K_REST, wr.D_SUMMA, wr.K_SUMMA, wr.D_REST AS sec_rest
|
||||
FROM OD_WIRING wr
|
||||
WHERE wr.K_REST IN (%[1]s) AND wr.IS_PLAN = 'F' AND YEAR(wr.WIRDATE) < 9000
|
||||
AND wr.WIRDATE >= @f AND wr.WIRDATE < @t AND wr.EQ_ <> 0
|
||||
UNION ALL
|
||||
SELECT wr.WIRDATE, wr.EQ_, wr.D_REST, wr.K_REST, wr.D_SUMMA, wr.K_SUMMA, wr.K_REST
|
||||
FROM OD_WIRING wr
|
||||
WHERE wr.D_REST IN (%[1]s) AND wr.K_REST NOT IN (%[1]s) AND wr.IS_PLAN = 'F' AND YEAR(wr.WIRDATE) < 9000
|
||||
AND wr.WIRDATE >= @f AND wr.WIRDATE < @t AND wr.EQ_ <> 0)
|
||||
SELECT w.WIRDATE, CAST(ISNULL(w.EQ_,0) AS float), w.D_REST, w.K_REST,
|
||||
CAST(ISNULL(w.D_SUMMA,0) AS float), CAST(ISNULL(w.K_SUMMA,0) AS float), ISNULL(sv.ISIN,'')
|
||||
FROM w
|
||||
LEFT JOIN OD_RESTS sr ON sr.ID = w.sec_rest
|
||||
LEFT JOIN OD_VALUES sv ON sv.ID = sr.REG_2`, in), sql.Named("f", from), sql.Named("t", to))
|
||||
wrows, err := conn.QueryContext(ctx, fmt.Sprintf(fsql.Arch10, in), sql.Named("f", from), sql.Named("t", to))
|
||||
if err != nil {
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ package lkgateway
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -85,8 +86,7 @@ func spectreContractFor(ctx context.Context, s FancyMSSQLSettings, contract stri
|
||||
var c spectreContract
|
||||
var open, closed sql.NullTime
|
||||
var state sql.NullInt64
|
||||
err = conn.QueryRowContext(cctx, `SELECT TOP 1 DOC, INVESTOR, NAME, C_OPEN, C_CLOSE, C_STATE FROM D_B_CONTRACTS
|
||||
WHERE UPPER(NAME) = @n OR UPPER(NAME) LIKE @n + ' %' ORDER BY C_STATE DESC, DOC DESC`, sql.Named("n", num)).
|
||||
err = conn.QueryRowContext(cctx, fsql.Cl01, sql.Named("n", num)).
|
||||
Scan(&c.DOC, &c.Investor, &c.Name, &open, &closed, &state)
|
||||
if err == nil {
|
||||
c.Name = strings.TrimSpace(c.Name)
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@@ -78,11 +79,7 @@ func lkCorpActions(ctx context.Context, s FancyMSSQLSettings, isins []string) ([
|
||||
names = append(names, fmt.Sprintf("@p%d", i+1))
|
||||
args = append(args, sql.Named(fmt.Sprintf("p%d", i+1), strings.ToUpper(strings.TrimSpace(isin))))
|
||||
}
|
||||
q := fmt.Sprintf(`SELECT TOP 40 ISNULL(a.KD_TYPE,''), ISNULL(v.ISIN,''), ISNULL(v.NAME,''), a.FIX_DATE, a.OPER_DATE, ISNULL(a.OFFER_NAME,'')
|
||||
FROM U_CA_ACTS a JOIN OD_VALUES v ON v.ID = a.SHARE
|
||||
WHERE UPPER(v.ISIN) IN (%s)
|
||||
AND ISNULL(a.FIX_DATE, a.OPER_DATE) >= DATEADD(month, -1, GETDATE())
|
||||
ORDER BY ISNULL(a.FIX_DATE, a.OPER_DATE)`, strings.Join(names, ","))
|
||||
q := fmt.Sprintf(fsql.Doc01, strings.Join(names, ","))
|
||||
rows, err := conn.QueryContext(cctx, q, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -121,23 +118,7 @@ type LKDocument struct {
|
||||
}
|
||||
|
||||
// lkDocSchema — таблица заявок на документы (создаётся вместе со схемой lk).
|
||||
const lkDocSchema = `
|
||||
CREATE TABLE IF NOT EXISTS lk.doc_requests (
|
||||
id bigserial PRIMARY KEY,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
contract_number text NOT NULL,
|
||||
client_name text,
|
||||
kind text NOT NULL,
|
||||
period_from date,
|
||||
period_to date,
|
||||
account text,
|
||||
comment text,
|
||||
status text NOT NULL DEFAULT 'new',
|
||||
staff_note text,
|
||||
done_at timestamptz
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS ix_lk_doc_requests_contract ON lk.doc_requests (contract_number, created_at DESC);
|
||||
`
|
||||
var lkDocSchema = fsql.Doc02
|
||||
|
||||
// lkDocKinds — виды документов, которые клиент может заказать в кабинете.
|
||||
var lkDocKinds = []string{
|
||||
@@ -173,8 +154,7 @@ func lkDocRequestAdd(ctx context.Context, rc *RuntimeConfig, contract, clientNam
|
||||
if t, err := time.Parse("2006-01-02", strings.TrimSpace(to)); err == nil {
|
||||
toP = t
|
||||
}
|
||||
_, err = db.ExecContext(ctx, `INSERT INTO lk.doc_requests (contract_number, client_name, kind, period_from, period_to, account, comment)
|
||||
VALUES ($1,$2,$3,$4,$5,$6,$7)`, contract, clientName, kind, fromP, toP, strings.TrimSpace(account), strings.TrimSpace(comment))
|
||||
_, err = db.ExecContext(ctx, fsql.Doc03, contract, clientName, kind, fromP, toP, strings.TrimSpace(account), strings.TrimSpace(comment))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -184,8 +164,7 @@ func lkDocRequests(ctx context.Context, rc *RuntimeConfig, contract string) ([]L
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rows, err := db.QueryContext(ctx, `SELECT id, created_at, kind, period_from, period_to, COALESCE(account,''), status, COALESCE(staff_note,'')
|
||||
FROM lk.doc_requests WHERE contract_number=$1 ORDER BY created_at DESC LIMIT 50`, contract)
|
||||
rows, err := db.QueryContext(ctx, fsql.Doc04, contract)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -232,9 +211,7 @@ func lkReadyDocuments(ctx context.Context, s FancyMSSQLSettings, contract string
|
||||
defer conn.Close()
|
||||
cctx, cancel := context.WithTimeout(ctx, 25*time.Second)
|
||||
defer cancel()
|
||||
q := fmt.Sprintf(`SELECT TOP 30 d.R_DATE, ISNULL(d.NUM,''), e.B_DATE, e.E_DATE, e.DEPO, d.STATE, ISNULL(e.IS_TURNS,0)
|
||||
FROM U_OP_INF_EXTRACT e JOIN OD_DOCS d ON d.ID = e.DOC
|
||||
WHERE e.DEPO IN (%s) ORDER BY d.R_DATE DESC`, inClause(ids))
|
||||
q := fmt.Sprintf(fsql.Doc05, inClause(ids))
|
||||
rows, err := conn.QueryContext(cctx, q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"log"
|
||||
"os"
|
||||
"sort"
|
||||
@@ -233,7 +234,7 @@ func lkDepoAnswer(ctx context.Context, rc *RuntimeConfig, guid, ourComment strin
|
||||
}
|
||||
defer db.Close()
|
||||
g := strings.ToUpper(guid)
|
||||
rows, err := db.QueryContext(ctx, "SELECT ISNULL(STATE,''), ISNULL(COMMENT,'') FROM dbo.FTV_M2M_EVENTS WHERE GUID=@g AND EVENT_TYPE='BJ_GATEWAY_REJECT'", sql.Named("g", g))
|
||||
rows, err := db.QueryContext(ctx, fsql.QFl01, sql.Named("g", g))
|
||||
if err != nil {
|
||||
return false, "", 0, "", err
|
||||
}
|
||||
@@ -270,9 +271,7 @@ func lkDepoAnswer(ctx context.Context, rc *RuntimeConfig, guid, ourComment strin
|
||||
docCol = "CAST(m.DOC AS varchar(32))"
|
||||
}
|
||||
var doc, mState, mComment, lineErr string
|
||||
_ = db.QueryRowContext(ctx, `SELECT ISNULL(`+docCol+`,''), ISNULL(m.STATE,''), ISNULL(m.COMMENT,''),
|
||||
ISNULL((SELECT TOP 1 ISNULL(l.COMMENT,'') FROM dbo.FTV_M2M_LINES l WHERE l.GUID=m.GUID AND ISNULL(l.STATE,'')='ERROR'),'')
|
||||
FROM dbo.FTV_M2M m WHERE m.GUID=@g`, sql.Named("g", g)).Scan(&doc, &mState, &mComment, &lineErr)
|
||||
_ = db.QueryRowContext(ctx, fsql.Flow01+docCol+fsql.Flow02, sql.Named("g", g)).Scan(&doc, &mState, &mComment, &lineErr)
|
||||
if strings.EqualFold(mState, "ERROR") && mComment != "" && !containsStr(errs, mComment) {
|
||||
errs = append(errs, mComment)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ package lkgateway
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -75,10 +76,7 @@ func lkFxAccounting(ctx context.Context, s FancyMSSQLSettings) map[string]LKFxRa
|
||||
continue
|
||||
}
|
||||
cctx, cancel := context.WithTimeout(ctx, 15*time.Second)
|
||||
rows, err := conn.QueryContext(cctx, `SELECT UPPER(LTRIM(RTRIM(v.SYSNAME))), r.OFICDATE, CAST(r.RATE AS float)
|
||||
FROM OD_VALUES_RATES r JOIN OD_VALUES v ON v.ID = r.VALUE_ID
|
||||
WHERE v.V_TYPE = 1 AND r.MARKET = 0 AND r.RATE > 0
|
||||
AND r.OFICDATE = (SELECT MAX(x.OFICDATE) FROM OD_VALUES_RATES x WHERE x.VALUE_ID = r.VALUE_ID AND x.MARKET = 0 AND x.RATE > 0)`)
|
||||
rows, err := conn.QueryContext(cctx, fsql.Fx01)
|
||||
if err == nil {
|
||||
for rows.Next() {
|
||||
var code string
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@@ -54,9 +55,7 @@ func depoClientIDs(ctx context.Context, s FancyMSSQLSettings, contract string) (
|
||||
defer conn.Close()
|
||||
cctx, cancel := context.WithTimeout(ctx, 20*time.Second)
|
||||
defer cancel()
|
||||
rows, err := conn.QueryContext(cctx, `SELECT DISTINCT c.ID, ISNULL(c.NUMBER,''), ISNULL(c.FACE,0)
|
||||
FROM OD_CLIENTS c JOIN OD_CLIENTS_PORTS p ON p.CLIENT = c.ID
|
||||
WHERE p.PORT_NUM = @p1 OR p.PORT_NUM LIKE @p2`, contract, likeEscape(contract)+" %")
|
||||
rows, err := conn.QueryContext(cctx, fsql.Hist01, contract, likeEscape(contract)+" %")
|
||||
if err != nil {
|
||||
return nil, 0, nil, err
|
||||
}
|
||||
@@ -137,32 +136,7 @@ func lkOperations(ctx context.Context, s FancyMSSQLSettings, contract, from, to
|
||||
}
|
||||
fromT, toT := parseRange(from, to)
|
||||
// Три вида операций в одном списке: зачисление, списание, перевод между счетами.
|
||||
q := fmt.Sprintf(`SELECT TOP %d * FROM (
|
||||
SELECT d.R_DATE AS RD, d.PROC_DATE AS PD, ISNULL(d.NUM,'') AS NUM, d.STATE AS ST, N'зачисление' AS KIND,
|
||||
z.DEPO AS ACC, ISNULL(v.ISIN,'') AS ISIN, ISNULL(v.NAME,'') AS SEC, CAST(ISNULL(z.AMOUNT,0) AS float) AS QTY,
|
||||
LTRIM(RTRIM(ISNULL(z.COMMENT,'') + ' ' + ISNULL(z.REJECT_REASON,''))) AS NOTE
|
||||
FROM U_OP_INV_ZACH z JOIN OD_DOCS d ON d.ID = z.DOC LEFT JOIN OD_VALUES v ON v.ID = z.SHARE
|
||||
WHERE z.DEPO IN (%s)
|
||||
UNION ALL
|
||||
SELECT d.R_DATE, d.PROC_DATE, ISNULL(d.NUM,''), d.STATE, N'списание',
|
||||
p.DEPO, ISNULL(v.ISIN,''), ISNULL(v.NAME,''), -CAST(ISNULL(p.AMOUNT,0) AS float),
|
||||
LTRIM(RTRIM(ISNULL(p.COMMENT,'') + ' ' + ISNULL(p.REJECT_REASON,'')))
|
||||
FROM U_OP_INV_SPIS p JOIN OD_DOCS d ON d.ID = p.DOC LEFT JOIN OD_VALUES v ON v.ID = p.SHARE
|
||||
WHERE p.DEPO IN (%s)
|
||||
UNION ALL
|
||||
SELECT d.R_DATE, d.PROC_DATE, ISNULL(d.NUM,''), d.STATE, N'перевод: списание',
|
||||
t.D_DEPO, ISNULL(v.ISIN,''), ISNULL(v.NAME,''), -CAST(ISNULL(t.AMOUNT,0) AS float),
|
||||
LTRIM(RTRIM(ISNULL(t.COMMENT,'') + ' ' + ISNULL(t.REJECT_REASON,'')))
|
||||
FROM U_OP_INV_PEREVOD t JOIN OD_DOCS d ON d.ID = t.DOC LEFT JOIN OD_VALUES v ON v.ID = t.SHARE
|
||||
WHERE t.D_DEPO IN (%s)
|
||||
UNION ALL
|
||||
SELECT d.R_DATE, d.PROC_DATE, ISNULL(d.NUM,''), d.STATE, N'перевод: зачисление',
|
||||
t.K_DEPO, ISNULL(v.ISIN,''), ISNULL(v.NAME,''), CAST(ISNULL(t.AMOUNT,0) AS float),
|
||||
LTRIM(RTRIM(ISNULL(t.COMMENT,'') + ' ' + ISNULL(t.REJECT_REASON,'')))
|
||||
FROM U_OP_INV_PEREVOD t JOIN OD_DOCS d ON d.ID = t.DOC LEFT JOIN OD_VALUES v ON v.ID = t.SHARE
|
||||
WHERE t.K_DEPO IN (%s)) x
|
||||
WHERE x.RD >= @p1 AND x.RD < DATEADD(day, 1, @p2)
|
||||
ORDER BY x.RD DESC, x.NUM DESC`, limit, inClause(ids), inClause(ids), inClause(ids), inClause(ids))
|
||||
q := fmt.Sprintf(fsql.Hist02, limit, inClause(ids), inClause(ids), inClause(ids), inClause(ids))
|
||||
rows, err := conn.QueryContext(cctx, q, fromT, toT)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -226,17 +200,7 @@ func lkIncome(ctx context.Context, s FancyMSSQLSettings, contract, from, to stri
|
||||
cctx, cancel := context.WithTimeout(ctx, 30*time.Second)
|
||||
defer cancel()
|
||||
fromT, toT := parseRange(from, to)
|
||||
q := fmt.Sprintf(`SELECT TOP 200 h.P_DATE, h.INCOME_KIND, ISNULL(v.ISIN,''), ISNULL(v.NAME,''),
|
||||
CAST(ISNULL(l.AMOUNT,0) AS float), CAST(ISNULL(l.SUMMA_TOTAL,0) AS float),
|
||||
CAST(ISNULL(l.TAX_HOLDED,0) AS float), CAST(ISNULL(l.TOTAL_TO_PAY,0) AS float),
|
||||
ISNULL(l.STATUS,''), ISNULL(l.DEPO,0)
|
||||
FROM U_OP_INF_INCOME_DOL l
|
||||
JOIN OD_DOLS o ON o.ID = l.DOL
|
||||
JOIN U_OP_INF_INCOME h ON h.DOC = o.DOC
|
||||
LEFT JOIN OD_VALUES v ON v.ID = h.SHARE
|
||||
WHERE (l.DEPO IN (%s) OR l.INCOME_FACE = @p3)
|
||||
AND h.P_DATE >= @p1 AND h.P_DATE < DATEADD(day, 1, @p2)
|
||||
ORDER BY h.P_DATE DESC`, inClause(ids))
|
||||
q := fmt.Sprintf(fsql.Hist03, inClause(ids))
|
||||
rows, err := conn.QueryContext(cctx, q, fromT, toT, face)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
@@ -266,8 +230,7 @@ func lkIncome(ctx context.Context, s FancyMSSQLSettings, contract, from, to stri
|
||||
}
|
||||
// Удержанный налог по лицу за период — по журналу НДФЛ депозитария.
|
||||
if face > 0 {
|
||||
_ = conn.QueryRowContext(cctx, `SELECT CAST(ISNULL(SUM(CAST(SUMMA AS float)),0) AS float) FROM OD_NDFL
|
||||
WHERE FACE = @p1 AND R_DATE >= @p2 AND R_DATE < DATEADD(day, 1, @p3)`,
|
||||
_ = conn.QueryRowContext(cctx, fsql.Hist04,
|
||||
sql.Named("p1", face), sql.Named("p2", fromT), sql.Named("p3", toT)).Scan(&taxTotal)
|
||||
}
|
||||
return rowsOut, taxTotal, nil
|
||||
|
||||
@@ -10,6 +10,7 @@ package lkgateway
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -88,14 +89,7 @@ func lkOnlinePortfolio(ctx context.Context, rc *RuntimeConfig, contract string)
|
||||
out := &LKPortfolio{Source: "quik"}
|
||||
|
||||
// Позиции: свежая строка по каждому (клиент, бумага, торговый счёт), затем сумма по бумаге.
|
||||
rows, err := p.Query(cctx, `
|
||||
WITH d AS (
|
||||
SELECT DISTINCT ON ("ClientCode","SecCode","Trdacc") "SecCode","CurrentBal","AwgPositionPrice","LoadDate"
|
||||
FROM "DepoLimits" WHERE "ClientCode" = ANY($1) AND "LimitKind"='T2'
|
||||
ORDER BY "ClientCode","SecCode","Trdacc","LoadDate" DESC)
|
||||
SELECT "SecCode", SUM("CurrentBal")::float8,
|
||||
COALESCE(SUM("CurrentBal"*"AwgPositionPrice")/NULLIF(SUM("CurrentBal"),0),0)::float8, MAX("LoadDate")
|
||||
FROM d WHERE "CurrentBal" <> 0 GROUP BY "SecCode" ORDER BY "SecCode"`, codes)
|
||||
rows, err := p.Query(cctx, fsql.On01, codes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("позиции: %v", err)
|
||||
}
|
||||
@@ -127,10 +121,7 @@ func lkOnlinePortfolio(ctx context.Context, rc *RuntimeConfig, contract string)
|
||||
for _, r := range pos {
|
||||
codesList = append(codesList, r.code)
|
||||
}
|
||||
srows, err := p.Query(cctx, `
|
||||
SELECT DISTINCT ON ("SecCode") "SecCode", upper(COALESCE("ISINCode",'')), COALESCE("SecShortName","SecName",''), "ClassCode", COALESCE("FaceValue",0)::float8
|
||||
FROM "Securities" WHERE "SecCode" = ANY($1)
|
||||
ORDER BY "SecCode", CASE "ClassCode" WHEN 'TQBR' THEN 1 WHEN 'TQOB' THEN 2 WHEN 'TQCB' THEN 3 WHEN 'TQTF' THEN 4 WHEN 'TQIF' THEN 5 WHEN 'TQRD' THEN 6 ELSE 9 END`, codesList)
|
||||
srows, err := p.Query(cctx, fsql.On02, codesList)
|
||||
if err == nil {
|
||||
for srows.Next() {
|
||||
var code, isin, name, class string
|
||||
@@ -189,12 +180,7 @@ func lkOnlinePortfolio(ctx context.Context, rc *RuntimeConfig, contract string)
|
||||
}
|
||||
|
||||
// Деньги по валютам.
|
||||
crows, err := p.Query(cctx, `
|
||||
WITH m AS (
|
||||
SELECT DISTINCT ON ("ClientCode","CurrCode","Tag") "CurrCode","CurrentBal","LoadDate"
|
||||
FROM "MoneyLimits" WHERE "ClientCode" = ANY($1) AND "LimitKind"='T2'
|
||||
ORDER BY "ClientCode","CurrCode","Tag","LoadDate" DESC)
|
||||
SELECT "CurrCode", SUM("CurrentBal")::float8, MAX("LoadDate") FROM m GROUP BY "CurrCode" HAVING SUM("CurrentBal") <> 0 ORDER BY "CurrCode"`, codes)
|
||||
crows, err := p.Query(cctx, fsql.On03, codes)
|
||||
if err == nil {
|
||||
for crows.Next() {
|
||||
var c LKCash
|
||||
|
||||
@@ -11,18 +11,13 @@ package lkgateway
|
||||
|
||||
import (
|
||||
"context"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const lkSnapshotSchema = `
|
||||
CREATE TABLE IF NOT EXISTS lk.portfolio_daily (
|
||||
day DATE NOT NULL, contract VARCHAR(64) NOT NULL,
|
||||
value DOUBLE PRECISION NOT NULL DEFAULT 0, cash DOUBLE PRECISION NOT NULL DEFAULT 0,
|
||||
positions INT NOT NULL DEFAULT 0, priced INT NOT NULL DEFAULT 0,
|
||||
source VARCHAR(16) NOT NULL DEFAULT 'quik', created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (day, contract))`
|
||||
var lkSnapshotSchema = fsql.Sn01
|
||||
|
||||
// lkSnapshotEnabled — ведём ли историю стоимости. По умолчанию (режим не выбран)
|
||||
// ведём, если настроен экспорт QUIK: история накапливается только вперёд, и
|
||||
@@ -76,8 +71,7 @@ func lkSnapshotHistory(ctx context.Context, rc *RuntimeConfig, contract string,
|
||||
}
|
||||
cctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||
defer cancel()
|
||||
rows, err := db.QueryContext(cctx, `SELECT day, value, cash, positions FROM lk.portfolio_daily
|
||||
WHERE contract = $1 AND day >= current_date - $2::int ORDER BY day`, num, days)
|
||||
rows, err := db.QueryContext(cctx, fsql.Sn02, num, days)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -104,10 +98,7 @@ func lkSnapshotSave(ctx context.Context, rc *RuntimeConfig, day time.Time, contr
|
||||
}
|
||||
cctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||
defer cancel()
|
||||
_, err = db.ExecContext(cctx, `INSERT INTO lk.portfolio_daily(day, contract, value, cash, positions, priced, source)
|
||||
VALUES ($1,$2,$3,$4,$5,$6,$7)
|
||||
ON CONFLICT (day, contract) DO UPDATE SET value = EXCLUDED.value, cash = EXCLUDED.cash,
|
||||
positions = EXCLUDED.positions, priced = EXCLUDED.priced, source = EXCLUDED.source, created_at = now()`,
|
||||
_, err = db.ExecContext(cctx, fsql.Sn03,
|
||||
day.Format("2006-01-02"), lkContractNumber(contract), p.Securities, p.CashRUB,
|
||||
len(p.Positions), p.Priced, p.Source)
|
||||
return err
|
||||
@@ -123,8 +114,7 @@ func lkSnapshotContracts(ctx context.Context, rc *RuntimeConfig) []string {
|
||||
}
|
||||
cctx, cancel := context.WithTimeout(ctx, 30*time.Second)
|
||||
defer cancel()
|
||||
rows, err := p.Query(cctx, `SELECT DISTINCT "ClientCode" FROM "DepoLimits"
|
||||
WHERE "LimitKind" = 'T2' AND "CurrentBal" <> 0 AND "ClientCode" <> ''`)
|
||||
rows, err := p.Query(cctx, fsql.Sn04)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -218,7 +208,7 @@ func lkSnapshotDone(ctx context.Context, rc *RuntimeConfig, day time.Time) bool
|
||||
cctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||
defer cancel()
|
||||
var n int
|
||||
if db.QueryRowContext(cctx, `SELECT count(*) FROM lk.portfolio_daily WHERE day = $1`,
|
||||
if db.QueryRowContext(cctx, fsql.Sn05,
|
||||
day.Format("2006-01-02")).Scan(&n) != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -75,9 +76,7 @@ func lkUpcoming(ctx context.Context, s FancyMSSQLSettings, positions []LKPositio
|
||||
}
|
||||
// Купоны: дата выплаты — P_DATE, до выплаты — конец периода. IS_PAY здесь означает
|
||||
// «купон выплачиваемый» (не «уже выплачен»), поэтому по нему не фильтруем.
|
||||
rows, err := conn.QueryContext(cctx, fmt.Sprintf(`SELECT UPPER(v.ISIN), ISNULL(c.P_DATE, c.E_DATE), CAST(ISNULL(c.SUMMA,0) AS float), CAST(ISNULL(c.PERCENT_,0) AS float)
|
||||
FROM OD_COUPONS c JOIN OD_VALUES v ON v.ID = c.SHARE
|
||||
WHERE UPPER(v.ISIN) IN (%s) AND ISNULL(c.P_DATE, c.E_DATE) >= @f AND ISNULL(c.P_DATE, c.E_DATE) <= @t`, in), args...)
|
||||
rows, err := conn.QueryContext(cctx, fmt.Sprintf(fsql.Up01, in), args...)
|
||||
if err == nil {
|
||||
for rows.Next() {
|
||||
var isin string
|
||||
@@ -90,9 +89,7 @@ func lkUpcoming(ctx context.Context, s FancyMSSQLSettings, positions []LKPositio
|
||||
rows.Close()
|
||||
}
|
||||
// Оферты.
|
||||
rows, err = conn.QueryContext(cctx, fmt.Sprintf(`SELECT UPPER(v.ISIN), o.P_DATE, CAST(ISNULL(o.O_PRICE,0) AS float)
|
||||
FROM OD_OFFERS o JOIN OD_VALUES v ON v.ID = o.SHARE
|
||||
WHERE UPPER(v.ISIN) IN (%s) AND o.CANCEL_DATE IS NULL AND o.P_DATE >= @f AND o.P_DATE <= @t`, in), args...)
|
||||
rows, err = conn.QueryContext(cctx, fmt.Sprintf(fsql.Up02, in), args...)
|
||||
if err == nil {
|
||||
for rows.Next() {
|
||||
var isin string
|
||||
@@ -105,9 +102,7 @@ func lkUpcoming(ctx context.Context, s FancyMSSQLSettings, positions []LKPositio
|
||||
rows.Close()
|
||||
}
|
||||
// Погашения: по номиналу в дату DEATHDATE.
|
||||
rows, err = conn.QueryContext(cctx, fmt.Sprintf(`SELECT UPPER(v.ISIN), sh.DEATHDATE, CAST(ISNULL(sh.NOMINAL,0) AS float)
|
||||
FROM OD_SHARES sh JOIN OD_VALUES v ON v.ID = sh.ID
|
||||
WHERE UPPER(v.ISIN) IN (%s) AND sh.E_DATE > GETDATE() AND sh.DEATHDATE >= @f AND sh.DEATHDATE <= @t`, in), args...)
|
||||
rows, err = conn.QueryContext(cctx, fmt.Sprintf(fsql.Up03, in), args...)
|
||||
if err == nil {
|
||||
for rows.Next() {
|
||||
var isin string
|
||||
@@ -120,9 +115,7 @@ func lkUpcoming(ctx context.Context, s FancyMSSQLSettings, positions []LKPositio
|
||||
rows.Close()
|
||||
}
|
||||
// Дивиденды (корпоративные действия DVCA): дата фиксации или выплаты, суммы нет.
|
||||
rows, err = conn.QueryContext(cctx, fmt.Sprintf(`SELECT UPPER(v.ISIN), ISNULL(a.OPER_DATE, a.FIX_DATE)
|
||||
FROM U_CA_ACTS a JOIN OD_VALUES v ON v.ID = a.SHARE
|
||||
WHERE UPPER(v.ISIN) IN (%s) AND UPPER(ISNULL(a.KD_TYPE,'')) = 'DVCA' AND ISNULL(a.OPER_DATE, a.FIX_DATE) >= @f AND ISNULL(a.OPER_DATE, a.FIX_DATE) <= @t`, in), args...)
|
||||
rows, err = conn.QueryContext(cctx, fmt.Sprintf(fsql.Up04, in), args...)
|
||||
if err == nil {
|
||||
for rows.Next() {
|
||||
var isin string
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -70,12 +71,7 @@ func manualDepoSearch(rc *RuntimeConfig, q string) ([]manualDepoFace, string) {
|
||||
defer db.Close()
|
||||
digits := strings.ReplaceAll(q, " ", "")
|
||||
// Действующая версия карточки (LAST_FLAG=1); счета привязаны к исходной записи (SELF_ID).
|
||||
rows, err := db.QueryContext(ctx, `SELECT TOP 20 ISNULL(NULLIF(f.SELF_ID,0),f.ID), ISNULL(f.NAME,''), f.DATE_BIRTH, ISNULL(f.DOC_TYPE,0), ISNULL(f.DOC_SER,''), ISNULL(f.DOC_NUM,''),
|
||||
f.DOC_DAT, ISNULL(f.DOC_PLACE,''), ISNULL(f.DOC_CODE,''), ISNULL(f.PHONE,'')
|
||||
FROM OD_FACES f
|
||||
WHERE ISNULL(f.LAST_FLAG,1)=1 AND (UPPER(f.NAME) LIKE UPPER(@q) OR f.DOC_NUM=@d OR REPLACE(ISNULL(f.DOC_SER,''),' ','')+f.DOC_NUM=@d)
|
||||
AND EXISTS (SELECT 1 FROM OD_CLIENTS c WHERE c.FACE=ISNULL(NULLIF(f.SELF_ID,0),f.ID) AND c.NUMBER LIKE N'ВТНКЦ%' AND c.STATE=0 AND c.D_CLOSE IS NULL)
|
||||
ORDER BY f.NAME`, sql.Named("q", q+"%"), sql.Named("d", digits))
|
||||
rows, err := db.QueryContext(ctx, fsql.Man01, sql.Named("q", q+"%"), sql.Named("d", digits))
|
||||
if err != nil {
|
||||
return nil, "поиск в DEPO: " + err.Error()
|
||||
}
|
||||
@@ -119,9 +115,7 @@ func manualDepoSearch(rc *RuntimeConfig, q string) ([]manualDepoFace, string) {
|
||||
rows.Close()
|
||||
out := make([]manualDepoFace, 0, len(found))
|
||||
for _, r := range found {
|
||||
ar, err := db.QueryContext(ctx, `SELECT c.ID, ISNULL(c.NUMBER,''),
|
||||
ISNULL((SELECT TOP 1 p.PORT_NUM FROM OD_CLIENTS_PORTS p WHERE p.CLIENT=c.ID ORDER BY p.PORT_DATE, p.PORT_NUM),'')
|
||||
FROM OD_CLIENTS c WHERE c.FACE=@f AND c.NUMBER LIKE N'ВТНКЦ%' AND c.STATE=0 AND c.D_CLOSE IS NULL ORDER BY c.ID`, sql.Named("f", r.id))
|
||||
ar, err := db.QueryContext(ctx, fsql.Man02, sql.Named("f", r.id))
|
||||
if err == nil {
|
||||
for ar.Next() {
|
||||
var a manualDepoAcc
|
||||
@@ -154,10 +148,7 @@ func manualDepoPositions(rc *RuntimeConfig, clientID int64) ([]manualDepoPos, st
|
||||
}
|
||||
defer cancel()
|
||||
defer db.Close()
|
||||
rows, err := db.QueryContext(ctx, `SELECT ISNULL(v.ISIN,''), ISNULL(v.NAME,''), SUM(CAST(r.K AS float))
|
||||
FROM OD_RESTS r JOIN OD_VALUES v ON v.ID=r.VALUE_ID
|
||||
WHERE r.REG_1=@c AND r.BAL_ACC=@b
|
||||
GROUP BY v.ISIN, v.NAME HAVING SUM(CAST(r.K AS float)) > 0 ORDER BY v.NAME`,
|
||||
rows, err := db.QueryContext(ctx, fsql.Man03,
|
||||
sql.Named("c", clientID), sql.Named("b", depoTradeBalAcc))
|
||||
if err != nil {
|
||||
return nil, "остатки в DEPO: " + err.Error()
|
||||
@@ -210,7 +201,7 @@ func manualDepoClientByAccount(rc *RuntimeConfig, number string) (int64, string)
|
||||
defer cancel()
|
||||
defer db.Close()
|
||||
var id int64
|
||||
err := db.QueryRowContext(ctx, `SELECT TOP 1 ID FROM OD_CLIENTS WHERE NUMBER=@n AND STATE=0 AND D_CLOSE IS NULL ORDER BY ID`,
|
||||
err := db.QueryRowContext(ctx, fsql.Man04,
|
||||
sql.Named("n", number)).Scan(&id)
|
||||
if err != nil {
|
||||
return 0, ""
|
||||
|
||||
@@ -10,6 +10,7 @@ package lkgateway
|
||||
|
||||
import (
|
||||
"context"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -88,17 +89,7 @@ func lkPrices(ctx context.Context, rc *RuntimeConfig, isins []string) map[string
|
||||
fxRates := lkFxRates(ctx, rc) // для выпусков с валютным номиналом
|
||||
// Одна цена на бумагу: берём класс основных торгов (акции TQBR, ОФЗ TQOB,
|
||||
// корпоративные облигации TQCB, фонды TQTF/TQIF), иначе — класс с торгами.
|
||||
rows, err := p.Query(cctx, `
|
||||
SELECT DISTINCT ON (s."ISINCode")
|
||||
upper(s."ISINCode"), s."ClassCode", COALESCE(s."SecShortName", s."SecName", ''),
|
||||
COALESCE(p.last, 0)::float8, COALESCE(p.prevprice, 0)::float8,
|
||||
COALESCE(s."FaceValue", 0)::float8, COALESCE(p.accruedint, 0)::float8, COALESCE(s."FaceUnit", '')
|
||||
FROM "Securities" s JOIN "Params" p ON p."SecCode" = s."SecCode" AND p."ClassCode" = s."ClassCode"
|
||||
WHERE s."ISINCode" <> '' AND (p.last > 0 OR p.prevprice > 0)
|
||||
ORDER BY s."ISINCode",
|
||||
CASE s."ClassCode" WHEN 'TQBR' THEN 1 WHEN 'TQOB' THEN 2 WHEN 'TQCB' THEN 3
|
||||
WHEN 'TQTF' THEN 4 WHEN 'TQIF' THEN 5 WHEN 'TQRD' THEN 6 ELSE 9 END,
|
||||
p.last DESC`)
|
||||
rows, err := p.Query(cctx, fsql.Pr01)
|
||||
if err != nil {
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -214,8 +215,7 @@ func quikM2MInstruments(ctx context.Context, s QuikMNPSettings) (in, out string,
|
||||
defer conn.Close()
|
||||
cctx, cancel := context.WithTimeout(ctx, 15*time.Second)
|
||||
defer cancel()
|
||||
rows, e := conn.QueryContext(cctx, `SELECT ic.ClassCode, sec.SecCode FROM ISecurities sec JOIN IClasses ic ON ic.ClassId=sec.ClassId
|
||||
WHERE sec.Enable=1 AND ic.ClassCode IN ('INSTRINM2M','INSTROUTM2M') ORDER BY sec.SecurityId`)
|
||||
rows, e := conn.QueryContext(cctx, fsql.Qk01)
|
||||
if e != nil {
|
||||
return "", "", fmt.Errorf("quik: справочник инструментов M2M: %s", quikErrorDetail(e))
|
||||
}
|
||||
@@ -445,10 +445,7 @@ func quikResolveClient(ctx context.Context, rc *RuntimeConfig, ser, num string)
|
||||
// Правило депозитария: при нескольких договорах клиента зачисление идёт на
|
||||
// САМЫЙ РАННИЙ договор — берём портфель с наименьшей датой (затем по дате
|
||||
// открытия счёта и номеру).
|
||||
rows, err := db.QueryContext(cctx, `SELECT TOP 5 p.PORT_NUM FROM OD_FACES f
|
||||
JOIN OD_CLIENTS c ON c.FACE=f.ID JOIN OD_CLIENTS_PORTS p ON p.CLIENT=c.ID
|
||||
WHERE REPLACE(f.DOC_SER,' ','')=@p1 AND f.DOC_NUM=@p2 AND c.NUMBER LIKE N'ВТНКЦ%' AND c.STATE=0
|
||||
ORDER BY ISNULL(p.PORT_DATE,'2099-01-01'), ISNULL(c.D_OPEN,'2099-01-01'), c.NUMBER`, serN, numN)
|
||||
rows, err := db.QueryContext(cctx, fsql.Qk02, serN, numN)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("DEPO: %w", err)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@@ -86,7 +87,7 @@ func securityCard(ctx context.Context, rc *RuntimeConfig, isin string, pos *Clie
|
||||
var valID int64
|
||||
var name, cfi string
|
||||
var vType, isIn sql.NullInt64
|
||||
err := db.QueryRowContext(dctx, `SELECT TOP 1 ID, ISNULL(NAME,''), ISNULL(CFI,''), V_TYPE, IS_IN FROM OD_VALUES WHERE ISIN=@p1 ORDER BY ID`,
|
||||
err := db.QueryRowContext(dctx, fsql.Sec01,
|
||||
sql.Named("p1", isin)).Scan(&valID, &name, &cfi, &vType, &isIn)
|
||||
if err != nil {
|
||||
card.Note = "бумаги нет в справочнике депозитария"
|
||||
@@ -102,8 +103,7 @@ func securityCard(ctx context.Context, rc *RuntimeConfig, isin string, pos *Clie
|
||||
var nominal sql.NullFloat64
|
||||
var regNum sql.NullString
|
||||
var death sql.NullTime
|
||||
err = db.QueryRowContext(dctx, `SELECT TOP 1 ISSUER, CAST(NOMINAL AS float), NUM_REG, DEATHDATE FROM OD_SHARES
|
||||
WHERE ID=@p1 AND E_DATE > GETDATE() ORDER BY B_DATE DESC`, sql.Named("p1", valID)).Scan(&issuer, &nominal, ®Num, &death)
|
||||
err = db.QueryRowContext(dctx, fsql.Sec02, sql.Named("p1", valID)).Scan(&issuer, &nominal, ®Num, &death)
|
||||
if err == nil {
|
||||
card.Face = nominal.Float64
|
||||
card.RegNumber = strings.TrimSpace(regNum.String)
|
||||
@@ -112,7 +112,7 @@ func securityCard(ctx context.Context, rc *RuntimeConfig, isin string, pos *Clie
|
||||
}
|
||||
if issuer.Valid && issuer.Int64 > 0 {
|
||||
var iname string
|
||||
if db.QueryRowContext(dctx, `SELECT TOP 1 ISNULL(NAME,'') FROM OD_FACES WHERE ID=@p1 OR SELF_ID=@p1 ORDER BY ISNULL(LAST_FLAG,0) DESC, ID DESC`,
|
||||
if db.QueryRowContext(dctx, fsql.Sec03,
|
||||
sql.Named("p1", issuer.Int64)).Scan(&iname) == nil {
|
||||
card.Issuer = strings.TrimSpace(iname)
|
||||
}
|
||||
@@ -122,10 +122,7 @@ func securityCard(ctx context.Context, rc *RuntimeConfig, isin string, pos *Clie
|
||||
|
||||
// График: купоны за полгода назад и вперёд, ближайшие оферты, погашение.
|
||||
// Дата выплаты купона: P_DATE, а пока купон не выплачен — конец купонного периода.
|
||||
rows, err := db.QueryContext(dctx, `SELECT TOP 12 ISNULL(P_DATE, E_DATE) AS PAY_DATE, CAST(ISNULL(SUMMA,0) AS float),
|
||||
CAST(ISNULL(PERCENT_,0) AS float), FIX_DATE, ISNULL(IS_PAY,0)
|
||||
FROM OD_COUPONS WHERE SHARE=@p1 AND ISNULL(P_DATE, E_DATE) >= DATEADD(month,-3,GETDATE())
|
||||
ORDER BY PAY_DATE`, sql.Named("p1", valID))
|
||||
rows, err := db.QueryContext(dctx, fsql.Sec04, sql.Named("p1", valID))
|
||||
if err == nil {
|
||||
for rows.Next() {
|
||||
var pd, fx sql.NullTime
|
||||
@@ -143,8 +140,7 @@ func securityCard(ctx context.Context, rc *RuntimeConfig, isin string, pos *Clie
|
||||
}
|
||||
rows.Close()
|
||||
}
|
||||
orows, err := db.QueryContext(dctx, `SELECT TOP 3 P_DATE, CAST(ISNULL(O_PRICE,0) AS float) FROM OD_OFFERS
|
||||
WHERE SHARE=@p1 AND CANCEL_DATE IS NULL AND P_DATE >= GETDATE() ORDER BY P_DATE`, sql.Named("p1", valID))
|
||||
orows, err := db.QueryContext(dctx, fsql.Sec05, sql.Named("p1", valID))
|
||||
if err == nil {
|
||||
for orows.Next() {
|
||||
var pd sql.NullTime
|
||||
|
||||
Reference in New Issue
Block a user