Портфель ДЕПО в ЛК: режим «для всех клиентов» + автозаполнение именования
- Кнопка «Включить для всех пользователей» с предупреждением: заполнение портфеля запускается для ВСЕХ открытых торговых счетов DEPO (по префиксу), договор ЛК выводится из счёта по шаблону — так же как в тесте с одним клиентом, только по торговым счетам. Поле AllClients; tick берёт пары из lkPortfolioAllPairs. Прежний режим «по списку» (Pairs) сохранён. - Поля именования (префикс счёта, шаблон договора, раздел, место хранения) предзаполняются из базы DEPO (префикс — depoAccPrefix) и значений по умолчанию, остаются редактируемыми. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
This commit is contained in:
@@ -173,6 +173,9 @@ type LKPortfolioSyncSettings struct {
|
||||
ContractTemplate string `json:"contract_template,omitempty"` // номер договора депо в ЛК: «ДД-{n}», {n} — номер счёта без префикса и ведущих нулей
|
||||
Section string `json:"section,omitempty"` // раздел счёта депо в ЛК: «Основной»
|
||||
Storage string `json:"storage,omitempty"` // место хранения: «НРД»
|
||||
// AllClients — заполнять портфель ВСЕМ клиентам: все открытые торговые счета DEPO
|
||||
// (по префиксу), договор ЛК выводится из счёта по шаблону. Иначе — только Pairs.
|
||||
AllClients bool `json:"all_clients,omitempty"`
|
||||
}
|
||||
|
||||
func (s LKPortfolioSyncSettings) accountPrefix() string {
|
||||
@@ -223,7 +226,16 @@ func lkPortfolioSyncTick(ctx context.Context, rc *RuntimeConfig, force bool) {
|
||||
if !st.Enabled {
|
||||
return
|
||||
}
|
||||
for _, pr := range st.pairs() {
|
||||
prs := st.pairs()
|
||||
if st.AllClients {
|
||||
all, err := lkPortfolioAllPairs(ctx, rc)
|
||||
if err != nil {
|
||||
log.Printf("lk-portfolio: список клиентов (все): %v", err)
|
||||
return
|
||||
}
|
||||
prs = all
|
||||
}
|
||||
for _, pr := range prs {
|
||||
lines, skipped, err := lkPortfolioLines(ctx, rc, pr.Depo, nil)
|
||||
lkPortfolioState.Lock()
|
||||
s := lkPortfolioState.m[pr.LK]
|
||||
@@ -310,9 +322,11 @@ func registerLKPortfolioSync(mux *http.ServeMux, rc *RuntimeConfig) {
|
||||
}
|
||||
switch r.FormValue("action") {
|
||||
case "on":
|
||||
lk.PortfolioSync.Enabled = lk.PortfolioSync.Pairs != ""
|
||||
lk.PortfolioSync.Enabled = lk.PortfolioSync.Pairs != "" || lk.PortfolioSync.AllClients
|
||||
case "on_all":
|
||||
lk.PortfolioSync.AllClients, lk.PortfolioSync.Enabled = true, true
|
||||
case "off":
|
||||
lk.PortfolioSync.Enabled = false
|
||||
lk.PortfolioSync.Enabled, lk.PortfolioSync.AllClients = false, false
|
||||
}
|
||||
if err := rc.UpdateLK(lk); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
@@ -339,7 +353,7 @@ func registerLKPortfolioSync(mux *http.ServeMux, rc *RuntimeConfig) {
|
||||
http.Redirect(w, r, "/admin/setup#lk-portfolio", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
if a := r.FormValue("action"); a == "sync" || a == "on" { // включили или «Заполнить сейчас» — сразу отправить
|
||||
if a := r.FormValue("action"); a == "sync" || a == "on" || a == "on_all" { // включили или «Заполнить сейчас» — сразу отправить
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 2*time.Minute)
|
||||
lkPortfolioSyncTick(ctx, rc, true)
|
||||
cancel()
|
||||
@@ -405,6 +419,44 @@ func lkPortfolioClients(ctx context.Context, rc *RuntimeConfig, q string) ([]LKP
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
// lkPortfolioAllPairs — все открытые торговые счета DEPO с портфелем (режим «для всех
|
||||
// клиентов»): фильтр по префиксу счёта, договор ЛК выводится из счёта по шаблону,
|
||||
// портфель — PORT_NUM. Только MSSQL-база DEPO (как и поиск одного клиента).
|
||||
func lkPortfolioAllPairs(ctx context.Context, rc *RuntimeConfig) ([]lkPortfolioPair, error) {
|
||||
fs := rc.Snapshot().Fancy
|
||||
ps := rc.Snapshot().LK.PortfolioSync
|
||||
db, err := fancyOpen(fs, fs.DepoDB())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer db.Close()
|
||||
cctx, cancel := context.WithTimeout(ctx, 30*time.Second)
|
||||
defer cancel()
|
||||
rows, err := db.QueryContext(cctx, `SELECT ISNULL(p.PORT_NUM,''), c.NUMBER
|
||||
FROM OD_CLIENTS c LEFT JOIN OD_CLIENTS_PORTS p ON p.CLIENT=c.ID
|
||||
WHERE c.NUMBER LIKE @pre AND c.STATE=0 AND c.D_CLOSE IS NULL AND p.PORT_NUM IS NOT NULL`,
|
||||
sql.Named("pre", likeEscape(ps.accountPrefix())+"%"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var out []lkPortfolioPair
|
||||
seen := map[string]bool{}
|
||||
for rows.Next() {
|
||||
var port, acc string
|
||||
if rows.Scan(&port, &acc) != nil || strings.TrimSpace(port) == "" {
|
||||
continue
|
||||
}
|
||||
lk := lkContractByAccount(ps, acc)
|
||||
if lk == "" || seen[lk] {
|
||||
continue
|
||||
}
|
||||
seen[lk] = true
|
||||
out = append(out, lkPortfolioPair{LK: lk, Depo: strings.TrimSpace(port)})
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
// lkPortfolioPushPair — залить портфель одного клиента сейчас (тест / «Залить сейчас»).
|
||||
func lkPortfolioPushPair(ctx context.Context, rc *RuntimeConfig, pr lkPortfolioPair) {
|
||||
lines, skipped, err := lkPortfolioLines(ctx, rc, pr.Depo, nil)
|
||||
|
||||
Reference in New Issue
Block a user