QUIK: автоподбор счёта — устойчив к разным колонкам; отчёт свёрнут

- quikDetectAccounts: Export не имеет колонки QuikFirm (ошибка 207 Invalid column
  name) — запросы по Actions/Export выполняются по отдельности, источник без нужной
  колонки пропускается.
- «Полный ответ сервера (последняя проверка)» свёрнут в details, чтобы не прятать
  настройки ниже.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
This commit is contained in:
fontvielle
2026-10-20 15:58:27 +03:00
parent 9397af94a9
commit a13c9d6184
2 changed files with 35 additions and 22 deletions
+31 -19
View File
@@ -4,6 +4,7 @@ import (
"context"
"database/sql"
"net/http"
"sort"
"strings"
"time"
)
@@ -13,7 +14,9 @@ import (
// коду нашей фирмы (QuikFirm/FirmID = код участника). Если счёт один — подставляем;
// несколько — показываем на выбор; нет истории — просим ввести вручную.
// quikDetectAccounts — торговые счета фирмы firm из БД МНП (только чтение).
// quikDetectAccounts — торговые счета фирмы firm из БД МНП (только чтение). Разные версии
// модуля отличаются колонками (у Export нет QuikFirm и т. п.), поэтому пробуем несколько
// источников по отдельности и пропускаем те, где колонки нет (Invalid column name).
func quikDetectAccounts(ctx context.Context, s QuikMNPSettings, firm string) ([]string, error) {
db, err := quikOpen(s)
if err != nil {
@@ -22,29 +25,38 @@ func quikDetectAccounts(ctx context.Context, s QuikMNPSettings, firm string) ([]
defer db.Close()
cctx, cancel := context.WithTimeout(ctx, 20*time.Second)
defer cancel()
const q = `SELECT DISTINCT LTRIM(RTRIM(Account)) AS acc FROM (
SELECT Account, QuikFirm, FirmID FROM dbo.Actions
UNION ALL
SELECT Account, QuikFirm, FirmID FROM dbo.Export
) t
WHERE Account IS NOT NULL AND LTRIM(RTRIM(Account)) <> ''
AND (@firm = '' OR QuikFirm = @firm OR FirmID = @firm)
ORDER BY acc`
rows, err := db.QueryContext(cctx, q, sql.Named("firm", firm))
if err != nil {
return nil, err
queries := []string{
`SELECT DISTINCT LTRIM(RTRIM(Account)) FROM dbo.Actions WHERE Account IS NOT NULL AND LTRIM(RTRIM(Account)) <> '' AND (@firm = '' OR FirmID = @firm)`,
`SELECT DISTINCT LTRIM(RTRIM(Account)) FROM dbo.Actions WHERE Account IS NOT NULL AND LTRIM(RTRIM(Account)) <> '' AND (@firm = '' OR QuikFirm = @firm)`,
`SELECT DISTINCT LTRIM(RTRIM(Account)) FROM dbo.Export WHERE Account IS NOT NULL AND LTRIM(RTRIM(Account)) <> '' AND (@firm = '' OR FirmID = @firm)`,
}
defer rows.Close()
seen := map[string]bool{}
var out []string
for rows.Next() {
var a string
if err := rows.Scan(&a); err == nil {
if a = strings.TrimSpace(a); a != "" {
out = append(out, a)
okAny := false
var lastErr error
for _, q := range queries {
rows, err := db.QueryContext(cctx, q, sql.Named("firm", firm))
if err != nil {
lastErr = err // чаще всего «Invalid column name» — этот источник пропускаем
continue
}
okAny = true
for rows.Next() {
var a string
if rows.Scan(&a) == nil {
if a = strings.TrimSpace(a); a != "" && !seen[a] {
seen[a] = true
out = append(out, a)
}
}
}
rows.Close()
}
return out, rows.Err()
if !okAny && lastErr != nil {
return nil, lastErr
}
sort.Strings(out)
return out, nil
}
// detectQuikAccount — POST /admin/setup/quik/detect-account: подобрать торговый счёт из QUIK.
@@ -77,13 +77,14 @@
{{if .Settings.Quik.LastReport}}
<div class="card">
<h2>Полный ответ сервера (последняя проверка)</h2>
<p class="muted">Можно выделить и скопировать целиком — для отправки коллегам/аутсорсеру QUIK.
{{if not .Settings.Quik.LastAt.IsZero}}Проверка от {{.Settings.Quik.LastAt.Format "02.01.2006 15:04:05"}} UTC.{{end}}</p>
<details>
<summary style="cursor:pointer;font-weight:600;font-size:16px">Полный ответ сервера (последняя проверка){{if not .Settings.Quik.LastAt.IsZero}} · проверка от {{.Settings.Quik.LastAt.Format "02.01.2006 15:04:05"}} UTC{{end}}</summary>
<p class="muted" style="margin-top:8px">Можно выделить и скопировать целиком — для отправки коллегам/аутсорсеру QUIK.</p>
<div style="display:flex;gap:8px;margin:8px 0">
<button type="button" class="btn" onclick="var t=document.getElementById('quik-report').textContent;window.bjCopy(t);this.textContent='Скопировано ✓';setTimeout(()=>this.textContent='Скопировать отчёт',1500)">Скопировать отчёт</button>
</div>
<pre id="quik-report" style="white-space:pre-wrap;word-break:break-word;background:var(--surface-2,#0d1117);color:var(--code-fg,#c9d1d9);padding:14px;border-radius:8px;font-size:12.5px;line-height:1.5;overflow:auto;max-height:420px;user-select:all">{{.Settings.Quik.LastReport}}</pre>
</details>
</div>
{{end}}
{{end}}