Мастер настройки — 4 главы (Сервер, Учёт и организация, НРД, Запуск) вместо 10 шагов: в пути только нужное этой установке — без лицензии учёта DEPO, QUIK и модулей их шагов нет, сделанное установщиком (база, Валидата) показано строкой; общая навигация «Назад/Далее»; раздел «Время и сеть» с часовым поясом; модули по лицензии (кабинет, ЕСИА Финанс, экспорт QUIK, НПР) с переходом в раздел и возвратом в мастер; «Проверить всю цепочку» (DEPO, QUIK, пробная блокировка по желанию, подпись, НРД); готовые письма в НРД, ARQA и администратору DEPO; ИШ с образа без интернета
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
package lkgateway
|
||||
|
||||
// Мастер настройки — 4 главы вместо 10 шагов (05.10.2026). Внутри глав — прежние шаги (адреса ?step=N не
|
||||
// меняются: на них ссылаются проверка готовности, письма, кнопки «Исправить»). Шаг показывается, только
|
||||
// если он нужен этой установке:
|
||||
// - не входит в лицензию (учёт DEPO и QUIK — «quik-mnp», модули) — шага нет вовсе;
|
||||
// - сделан установщиком без участия человека (база bj, Валидата) — шага нет в пути, в главе «Сервер»
|
||||
// это показано строкой «сделано автоматически».
|
||||
|
||||
// wizChapters — главы мастера: название и шаги по порядку.
|
||||
var wizChapters = []struct {
|
||||
Title string
|
||||
Steps []int
|
||||
}{
|
||||
{"Сервер", []int{1, 2, 6, 12}},
|
||||
{"Учёт и организация", []int{3, 4, 5}},
|
||||
{"НРД", []int{7, 8}},
|
||||
{"Запуск", []int{11, 9, 10}},
|
||||
}
|
||||
|
||||
// wizStepTitles — короткие названия шагов (подзаголовки внутри главы).
|
||||
var wizStepTitles = map[int]string{
|
||||
1: "Лицензия", 2: "База bj", 6: "Валидата", 12: "Время и сеть",
|
||||
3: "Учёт DEPO", 4: "Организация", 5: "QUIK МНП",
|
||||
7: "Шлюз НРД", 8: "Ключ",
|
||||
11: "Модули", 9: "Оповещения и копии", 10: "Проверка",
|
||||
}
|
||||
|
||||
// wizRequired — шаги, без которых обмен не работает: на них мастер возвращает, пока они не сделаны.
|
||||
var wizRequired = map[int]bool{1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true}
|
||||
|
||||
// wizModules — лицензируемые модули, которые настраиваются в главе «Запуск».
|
||||
var wizModules = []string{"web-cabinet", "esia-finance", "quik-export", "npr"}
|
||||
|
||||
// WizStep — шаг в пути мастера.
|
||||
type WizStep struct {
|
||||
N int
|
||||
Title string
|
||||
Done bool
|
||||
Current bool
|
||||
}
|
||||
|
||||
// WizChapter — глава в шапке мастера.
|
||||
type WizChapter struct {
|
||||
N int
|
||||
Title string
|
||||
Steps []WizStep
|
||||
Done bool
|
||||
Current bool
|
||||
First int // первый шаг главы (переход по клику)
|
||||
}
|
||||
|
||||
// wizVisible — нужен ли шаг этой установке (лицензия и автоматика).
|
||||
func wizVisible(rc *RuntimeConfig, n int, done map[int]bool) bool {
|
||||
switch n {
|
||||
case 2, 6: // база bj и Валидата обычно ставятся установщиком — шаг нужен, только если не сделано
|
||||
return !done[n]
|
||||
case 3, 5:
|
||||
return moduleAllowed(rc, "quik-mnp")
|
||||
case 11:
|
||||
for _, m := range wizModules {
|
||||
if moduleAllowed(rc, m) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// wizPath — шаги этой установки по порядку и главы для шапки.
|
||||
func wizPath(rc *RuntimeConfig, done map[int]bool, current int) (path []int, chapters []WizChapter) {
|
||||
for ci, ch := range wizChapters {
|
||||
c := WizChapter{N: ci + 1, Title: ch.Title, Done: true}
|
||||
for _, n := range ch.Steps {
|
||||
if !wizVisible(rc, n, done) {
|
||||
continue
|
||||
}
|
||||
path = append(path, n)
|
||||
c.Steps = append(c.Steps, WizStep{N: n, Title: wizStepTitles[n], Done: done[n], Current: n == current})
|
||||
if c.First == 0 {
|
||||
c.First = n
|
||||
}
|
||||
if !done[n] {
|
||||
c.Done = false
|
||||
}
|
||||
if n == current {
|
||||
c.Current = true
|
||||
}
|
||||
}
|
||||
if len(c.Steps) == 0 {
|
||||
continue
|
||||
}
|
||||
// переход по главе — на первый несделанный шаг главы
|
||||
for _, s := range c.Steps {
|
||||
if !s.Done {
|
||||
c.First = s.N
|
||||
break
|
||||
}
|
||||
}
|
||||
chapters = append(chapters, c)
|
||||
}
|
||||
return path, chapters
|
||||
}
|
||||
|
||||
// wizNeighbours — предыдущий и следующий шаг в пути (0 — нет).
|
||||
func wizNeighbours(path []int, current int) (prev, next int) {
|
||||
for i, n := range path {
|
||||
if n == current {
|
||||
if i > 0 {
|
||||
prev = path[i-1]
|
||||
}
|
||||
if i+1 < len(path) {
|
||||
next = path[i+1]
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
if len(path) > 0 { // текущий шаг не в пути (открыт по прямой ссылке) — «Далее» ведёт в начало пути
|
||||
next = path[0]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// wizDefaultStep — куда открывается мастер без ?step: первый обязательный несделанный шаг, иначе проверка.
|
||||
func wizDefaultStep(path []int, done map[int]bool) int {
|
||||
for _, n := range path {
|
||||
if wizRequired[n] && !done[n] {
|
||||
return n
|
||||
}
|
||||
}
|
||||
return 10
|
||||
}
|
||||
|
||||
// WizModule — модуль по лицензии в главе «Запуск»: что делает, готов ли, где настраивается.
|
||||
type WizModule struct {
|
||||
Key, Title, What, Status, Link string
|
||||
Ready bool
|
||||
}
|
||||
|
||||
// wizModuleViews — модули этой лицензии (без лицензии модуля в мастере нет).
|
||||
func wizModuleViews(rc *RuntimeConfig, s Settings) []WizModule {
|
||||
var out []WizModule
|
||||
for _, key := range wizModules {
|
||||
if !moduleAllowed(rc, key) {
|
||||
continue
|
||||
}
|
||||
m := WizModule{Key: key}
|
||||
switch key {
|
||||
case "web-cabinet":
|
||||
m.Title = "Личный кабинет клиента"
|
||||
m.What = "Наш кабинет для клиентов депозитария: программа bj-lk на веб-сервере организации — клиент подаёт поручения на перевод, видит портфель и ход перевода."
|
||||
m.Link = "/admin/setup?from=wizard#cabinet"
|
||||
m.Ready = s.LK.APIKey != ""
|
||||
m.Status = map[bool]string{true: "ключ кабинета выдан — кабинет подключается к bj", false: "кабинет ещё не установлен: скачайте дистрибутив и ключ в разделе модуля"}[m.Ready]
|
||||
case "esia-finance":
|
||||
m.Title = "ЕСИА Финанс"
|
||||
m.What = "Интеграция с платформой личного кабинета ЕСИА Финанс: заявки клиентов на перевод приходят в bj, статусы и портфель уходят обратно."
|
||||
m.Link = "/admin/setup?from=wizard#lk"
|
||||
m.Ready = s.LK.PublicURL != "" && (s.LK.Prod.LastOK || s.LK.Test.LastOK)
|
||||
switch {
|
||||
case m.Ready:
|
||||
m.Status = "адрес кабинета задан, связь с API проверена"
|
||||
case s.LK.PublicURL != "":
|
||||
m.Status = "адрес кабинета задан, связь с API ещё не проверена"
|
||||
default:
|
||||
m.Status = "не настроено: адрес кабинета и доступ к API"
|
||||
}
|
||||
case "quik-export":
|
||||
m.Title = "Экспорт биржевой информации QUIK"
|
||||
m.What = "Выгрузка данных QUIK (позиции, сделки, клиенты) в базу bj — для кабинета клиента и риск-монитора."
|
||||
m.Link = "/admin/setup?from=wizard#quikexport"
|
||||
m.Ready = unitState("bj-quikexport").State == "active"
|
||||
m.Status = map[bool]string{true: "служба экспорта работает", false: "служба экспорта не запущена — настройте подключение в разделе модуля"}[m.Ready]
|
||||
case "npr":
|
||||
m.Title = "Риск-монитор НПР / УДС"
|
||||
m.What = "Нормативы покрытия риска и уровень достаточности средств клиентов маржинальной торговли по данным экспорта QUIK."
|
||||
m.Link = "/admin/setup?from=wizard#quikexport"
|
||||
m.Ready = s.NPR.Enabled && s.NPR.DSN != ""
|
||||
m.Status = map[bool]string{true: "включён, база экспорта QUIK подключена", false: "не включён"}[m.Ready]
|
||||
}
|
||||
out = append(out, m)
|
||||
}
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user