Первичная настройка, часть 1: префикс торгового счёта DEPO — настройка с подсказкой по учёту (был зашит «ВТНКЦ» в 7 запросах); шаг 8 — адрес ИШ вместо ONYX, профили prod-gost/prod-rsa (пункт prod уводил bj в имитацию), без неиспользуемого контейнера, перезапуск bj после смены контура; реквизиты НРД на шаге 4; точная проверка процедур bj2depo и таблиц Fancy M2M; QUIK — объекты M2M и справочник получателей, без зашитого IP; сертификаты из справочника ИШ (FindCertificates — заглушка), уведомления о сроке за 30/14/7/3/1 день; тексты мастера, нумерация, режим разработки; уникальные id оповещений с русскими заголовками

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
This commit is contained in:
zuevav
2026-10-05 16:04:43 +03:00
parent 9360543589
commit fdf0ddd498
37 changed files with 807 additions and 129 deletions
+102
View File
@@ -0,0 +1,102 @@
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)
}