fdf0ddd498
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
103 lines
3.4 KiB
Go
103 lines
3.4 KiB
Go
package lkgateway
|
||
|
||
// Префикс торгового счёта клиента в учёте DEPO (OD_CLIENTS.NUMBER). У Фонтвьель — «ВТНКЦ…»; у другого
|
||
// депозитария счета могут называться иначе, поэтому префикс — настройка (Fancy.AccountPrefix), и запросы
|
||
// к учёту берут его через accSQL. Подсказка — какие префиксы у открытых счетов этого учёта.
|
||
|
||
import (
|
||
"context"
|
||
"net/http"
|
||
"regexp"
|
||
"strings"
|
||
"time"
|
||
|
||
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/lkgateway/fsql"
|
||
)
|
||
|
||
const defaultAccPrefix = "ВТНКЦ"
|
||
|
||
// accPrefixRe — только буквы, цифры и «_»: префикс подставляется в текст запроса.
|
||
var accPrefixRe = regexp.MustCompile(`^[\p{L}\p{N}_]{1,20}$`)
|
||
|
||
func cleanAccPrefix(p string) string {
|
||
p = strings.TrimSpace(p)
|
||
if accPrefixRe.MatchString(p) {
|
||
return p
|
||
}
|
||
return ""
|
||
}
|
||
|
||
// depoAccPrefix — префикс торговых счетов из настроек (по умолчанию «ВТНКЦ»).
|
||
func depoAccPrefix() string {
|
||
if globalRC != nil {
|
||
if p := cleanAccPrefix(globalRC.Snapshot().Fancy.AccountPrefix); p != "" {
|
||
return p
|
||
}
|
||
}
|
||
return defaultAccPrefix
|
||
}
|
||
|
||
// accSQL — запрос к учёту с подставленным префиксом торгового счёта.
|
||
func accSQL(q string) string { return strings.ReplaceAll(q, "{ACC}", depoAccPrefix()) }
|
||
|
||
type accPrefixCount struct {
|
||
Prefix string `json:"prefix"`
|
||
Count int `json:"count"`
|
||
}
|
||
|
||
// depoAccPrefixInfo — сколько открытых счетов с текущим префиксом и какие префиксы вообще есть.
|
||
func depoAccPrefixInfo(ctx context.Context, f FancyMSSQLSettings) (cur int, cands []accPrefixCount, err error) {
|
||
if f.IsPostgres() {
|
||
return 0, nil, nil
|
||
}
|
||
db, err := fancyOpen(f, f.DepoDB())
|
||
if err != nil {
|
||
return 0, nil, err
|
||
}
|
||
defer db.Close()
|
||
if err := db.QueryRowContext(ctx, accSQL(fsql.Acc02)).Scan(&cur); err != nil {
|
||
return 0, nil, err
|
||
}
|
||
rows, err := db.QueryContext(ctx, fsql.Acc01)
|
||
if err != nil {
|
||
return cur, nil, err
|
||
}
|
||
defer rows.Close()
|
||
for rows.Next() {
|
||
var c accPrefixCount
|
||
if rows.Scan(&c.Prefix, &c.Count) == nil {
|
||
cands = append(cands, c)
|
||
}
|
||
}
|
||
return cur, cands, rows.Err()
|
||
}
|
||
|
||
// GET /admin/setup/fancy/acc-prefix — текущий префикс и подсказка; POST — сохранить.
|
||
func (h *setupHandlers) accPrefix(w http.ResponseWriter, r *http.Request) {
|
||
if r.Method == http.MethodPost {
|
||
p := strings.TrimSpace(r.FormValue("account_prefix"))
|
||
if p != "" && cleanAccPrefix(p) == "" {
|
||
jsonOut(w, map[string]any{"ok": false, "error": "префикс — только буквы и цифры, до 20 знаков"})
|
||
return
|
||
}
|
||
s := h.rc.Snapshot().Fancy
|
||
s.AccountPrefix = p
|
||
if err := h.rc.UpdateFancy(s); err != nil {
|
||
jsonOut(w, map[string]any{"ok": false, "error": err.Error()})
|
||
return
|
||
}
|
||
}
|
||
s := h.rc.Snapshot().Fancy
|
||
out := map[string]any{"ok": true, "prefix": depoAccPrefix(), "set": cleanAccPrefix(s.AccountPrefix) != ""}
|
||
if strings.TrimSpace(s.Server) != "" {
|
||
ctx, cancel := context.WithTimeout(r.Context(), 15*time.Second)
|
||
defer cancel()
|
||
cur, cands, err := depoAccPrefixInfo(ctx, s)
|
||
if err != nil {
|
||
out["error"] = quikErrorDetail(err)
|
||
}
|
||
out["count"], out["candidates"] = cur, cands
|
||
}
|
||
jsonOut(w, out)
|
||
}
|