Баннер режима разработки в шапке с личным выключателем
Пока лицензия разрешает режим разработки, в шапке висит баннер; нажатие выключает режим визуально для этого пользователя и включает обратно. В шаблонах .DevMode заменён на devOn. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q4YVo4UMopqT5DzicqpPjL
This commit is contained in:
@@ -53,6 +53,8 @@ var templateFuncs = template.FuncMap{
|
||||
"quikCodeMap": quikClientCodeMapText,
|
||||
"curUser": authTemplateFuncs["curUser"],
|
||||
"can": authTemplateFuncs["can"],
|
||||
"devOn": authTemplateFuncs["devOn"],
|
||||
"devLicensed": authTemplateFuncs["devLicensed"],
|
||||
"authOpen": authOpen,
|
||||
"roleTitle": roleTitle,
|
||||
"stageCls": func(r depoQueueRow) string { c, _ := r.StageRu(); return c },
|
||||
|
||||
@@ -1272,15 +1272,18 @@ func registerUsersSetup(mux *http.ServeMux, h *setupHandlers) {
|
||||
mux.HandleFunc("/admin/setup/auth", h.saveAuth)
|
||||
mux.HandleFunc("/admin/setup/auth/test", h.testAD)
|
||||
mux.HandleFunc("/admin/setup/auth/recheck", h.recheckAD)
|
||||
mux.HandleFunc("/admin/dev-toggle", devToggle) // личный выключатель режима разработки
|
||||
}
|
||||
|
||||
// ---------- функции шаблонов ----------
|
||||
|
||||
// authTemplateFuncs — заглушки, переопределяются в render на текущего пользователя.
|
||||
var authTemplateFuncs = template.FuncMap{
|
||||
"curUser": func() *User { return nil },
|
||||
"can": func(perm string) bool { return true },
|
||||
"authOpen": authOpen,
|
||||
"curUser": func() *User { return nil },
|
||||
"can": func(perm string) bool { return true },
|
||||
"authOpen": authOpen,
|
||||
"devOn": func() bool { return devMode(globalRC) }, // режим действует для текущего пользователя
|
||||
"devLicensed": func() bool { return devMode(globalRC) }, // режим разрешён лицензией (для баннера)
|
||||
}
|
||||
|
||||
// renderFor — выполняет layout с функциями, привязанными к текущему пользователю.
|
||||
@@ -1290,11 +1293,14 @@ func renderFor(w http.ResponseWriter, t *template.Template, data any) error {
|
||||
if err != nil {
|
||||
return t.ExecuteTemplate(w, "layout", data)
|
||||
}
|
||||
on := devOnFor(u)
|
||||
t2.Funcs(template.FuncMap{
|
||||
"curUser": func() *User { return u },
|
||||
"curUser": func() *User { return u },
|
||||
"devOn": func() bool { return on },
|
||||
"devLicensed": func() bool { return devMode(globalRC) },
|
||||
"can": func(perm string) bool {
|
||||
if perm == "dev" {
|
||||
return devMode(globalRC) && (authOpen() || u.Can("settings"))
|
||||
return on && (authOpen() || u.Can("settings"))
|
||||
}
|
||||
if authOpen() {
|
||||
return true
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package lkgateway
|
||||
|
||||
// devbanner.go — баннер режима разработки в шапке.
|
||||
//
|
||||
// Режим разработки разрешает сервер лицензий (dev_until в ключе). Пока он разрешён, в
|
||||
// шапке висит баннер; нажатие на него выключает режим визуально для этого пользователя
|
||||
// (служебные разделы прячутся, имитации не показываются) и включает обратно. Это личная
|
||||
// настройка сотрудника, а не состояние системы: лицензия по-прежнему разрешает режим.
|
||||
// Когда лицензия режим не разрешает, баннера нет и выключатель ни на что не влияет.
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// devOff — пользователи, выключившие режим разработки у себя (по логину; без
|
||||
// авторизации — пустой логин). Хранится в памяти: после перезапуска режим снова включён.
|
||||
var devOff = struct {
|
||||
mu sync.Mutex
|
||||
m map[string]bool
|
||||
}{m: map[string]bool{}}
|
||||
|
||||
func devUserKey(u *User) string {
|
||||
if u == nil {
|
||||
return ""
|
||||
}
|
||||
return u.Login
|
||||
}
|
||||
|
||||
// devOnFor — режим разработки действует для пользователя: разрешён лицензией и не выключен им.
|
||||
func devOnFor(u *User) bool {
|
||||
if !devMode(globalRC) {
|
||||
return false
|
||||
}
|
||||
devOff.mu.Lock()
|
||||
defer devOff.mu.Unlock()
|
||||
return !devOff.m[devUserKey(u)]
|
||||
}
|
||||
|
||||
// devToggle — POST /admin/dev-toggle: переключить режим у себя и вернуться на ту же страницу.
|
||||
func devToggle(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "method", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
if devMode(globalRC) {
|
||||
key := devUserKey(currentUser(w))
|
||||
devOff.mu.Lock()
|
||||
devOff.m[key] = !devOff.m[key]
|
||||
devOff.mu.Unlock()
|
||||
}
|
||||
dest := safeReturnPath(r.FormValue("return_to"))
|
||||
if dest == "" {
|
||||
dest = "/admin"
|
||||
}
|
||||
http.Redirect(w, r, dest, http.StatusSeeOther)
|
||||
}
|
||||
@@ -58,7 +58,7 @@
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
{{if .DevMode}}{{with .Claim.TestResult}}
|
||||
{{if devOn}}{{with .Claim.TestResult}}
|
||||
<div class="card" style="background:{{if eq .Status "ok"}}var(--ok-weak){{else if eq .Status "mismatch"}}var(--err-weak){{else if eq .Status "error"}}var(--err-weak){{else}}var(--warn-weak){{end}}">
|
||||
<h2>
|
||||
{{if eq .Status "ok"}}<span style="color:var(--ok)">✓ Тест пройден</span>
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
</table>
|
||||
</div>
|
||||
{{else if not .Error}}
|
||||
<p class="muted">В трансферных таблицах пока нет переводов. Они появятся при входящем/исходящем переводе M2M{{if .DevMode}} или при прогоне «Тестирование M2M → выгрузка истории в DEPO»{{end}}.</p>
|
||||
<p class="muted">В трансферных таблицах пока нет переводов. Они появятся при входящем/исходящем переводе M2M{{if devOn}} или при прогоне «Тестирование M2M → выгрузка истории в DEPO»{{end}}.</p>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<a href="/admin/help/systems" style="text-decoration:none">
|
||||
<div class="card" style="height:100%">
|
||||
<h2 style="color:var(--accent)">Внешние системы →</h2>
|
||||
<p class="muted">ИШ НРД ({{if .DevMode}}профили GUEST/TEST3/PROD{{else}}тестовый и боевой контуры{{end}}), команда Fansy (ETL в staging), уведомления (e-mail, Yandex Messenger, Telegram), порядок согласования.</p>
|
||||
<p class="muted">ИШ НРД ({{if devOn}}профили GUEST/TEST3/PROD{{else}}тестовый и боевой контуры{{end}}), команда Fansy (ETL в staging), уведомления (e-mail, Yandex Messenger, Telegram), порядок согласования.</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href="/admin/help/manual" style="text-decoration:none">
|
||||
@@ -35,7 +35,7 @@
|
||||
<p class="muted">Исходящий перевод по бумажному поручению клиента: ввод, сверка с учётной и торговой системами, обязательные отметки, отправка, поручение 16, документы НРД.</p>
|
||||
</div>
|
||||
</a>
|
||||
{{if .DevMode}}<a href="/admin/help/robot" style="text-decoration:none">
|
||||
{{if devOn}}<a href="/admin/help/robot" style="text-decoration:none">
|
||||
<div class="card" style="height:100%">
|
||||
<h2 style="color:var(--accent)">Тестирование с роботом MOEX МОСТ →</h2>
|
||||
<p class="muted">Робот НРД на TEST3 (код <code>MC0012500000</code>), 4 тестовых сценария (отказ / принять все / частично / встречный перевод), управление через DocumentSeries и DocumentNumber, тестовые наборы депозитариев и кодов ошибок.</p>
|
||||
@@ -44,7 +44,7 @@
|
||||
<a href="/admin/help/architecture" style="text-decoration:none">
|
||||
<div class="card" style="height:100%">
|
||||
<h2 style="color:var(--accent)">Архитектура обмена с НРД →</h2>
|
||||
<p class="muted">Полная схема: bj-server → ИШ (на Astra Linux ВМ) → ONYX (НРД) → {{if .DevMode}}робот-автотест{{else}}депозитарий-контрагент{{end}}. Кто на чьей стороне, какое СКЗИ, какие сертификаты, FAQ.</p>
|
||||
<p class="muted">Полная схема: bj-server → ИШ (на Astra Linux ВМ) → ONYX (НРД) → {{if devOn}}робот-автотест{{else}}депозитарий-контрагент{{end}}. Кто на чьей стороне, какое СКЗИ, какие сертификаты, FAQ.</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href="/admin/help/fancy-events" style="text-decoration:none">
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
│ │ • стейт-машина │ │ Делает САМ: │ │
|
||||
│ │ • PostgreSQL │ │ • подпись │ │
|
||||
│ │ • админка :8080 │ │ • упаковку ЭДО │ │
|
||||
│ │ {{if .DevMode}}• lk-emulator {{else}}• коннектор ЛК {{end}}│ │ • проверку │ │
|
||||
│ │ {{if devOn}}• lk-emulator {{else}}• коннектор ЛК {{end}}│ │ • проверку │ │
|
||||
│ │ │ │ подписей НРД │ │
|
||||
│ └──────────────────┘ │ • БД PostgreSQL │ │
|
||||
│ │ (history) │ │
|
||||
@@ -46,7 +46,7 @@
|
||||
│ /onyxpr/WslService │
|
||||
│ │
|
||||
│ ↓ внутрь НРД │
|
||||
{{if .DevMode}} │ • робот-автотест │
|
||||
{{if devOn}} │ • робот-автотест │
|
||||
│ MC0012500000 │
|
||||
{{end}} │ • реальные депозитарии │
|
||||
│ • биржевые системы │
|
||||
@@ -64,7 +64,7 @@
|
||||
<td>наша</td>
|
||||
<td>Astra Linux SE 1.7 / Linux</td>
|
||||
<td>АПК «Валидата Клиент L» (PKCS#11)</td>
|
||||
<td>Стейт-машина, журнал в БД, веб-админка{{if .DevMode}}, lk-emulator{{end}}</td>
|
||||
<td>Стейт-машина, журнал в БД, веб-админка{{if devOn}}, lk-emulator{{end}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>ИШ (igate)</strong></td>
|
||||
@@ -80,7 +80,7 @@
|
||||
<td>—</td>
|
||||
<td>Web-сервис НРД — принимает пакеты от ИШ всех клиентов</td>
|
||||
</tr>
|
||||
{{if .DevMode}}<tr>
|
||||
{{if devOn}}<tr>
|
||||
<td><strong>Робот-автотест</strong></td>
|
||||
<td>НРД</td>
|
||||
<td>—</td>
|
||||
@@ -109,7 +109,7 @@
|
||||
<h3>Q: Какой сертификат нужен?</h3>
|
||||
<p>Только от <strong>УЦ Московской Биржи</strong> (<code>ca.moex.com</code>). Сертификаты других УЦ ИШ не примет. УЦ МБ выпускает сертификаты только для организаций, подключённых к ЭДО НРД (по договору).</p>
|
||||
|
||||
{{if .DevMode}}
|
||||
{{if devOn}}
|
||||
<h3>Q: Что делать, чтобы протестировать на роботе НРД на TEST3?</h3>
|
||||
<ol>
|
||||
<li>Получить сертификат УЦ МБ для нашей организации.</li>
|
||||
@@ -133,7 +133,7 @@
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
{{if .DevMode}}
|
||||
{{if devOn}}
|
||||
<div class="card">
|
||||
<h2>Что у нас уже готово</h2>
|
||||
<ul>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<a href="#actions">Действия джобы по событиям</a>
|
||||
<a href="#handbook">Справочник участников</a>
|
||||
<a href="#runmode">Кто запускает обработку</a>
|
||||
{{if .DevMode}}<a href="#replay">Выгрузка истории тестов</a>{{end}}
|
||||
{{if devOn}}<a href="#replay">Выгрузка истории тестов</a>{{end}}
|
||||
<div class="toc-group">Практика</div>
|
||||
<a href="#sql">Примеры SQL</a>
|
||||
<a href="#questions">Открытые вопросы</a>
|
||||
@@ -184,7 +184,7 @@ ORDER BY e.ID;</pre>
|
||||
<p class="muted">Включать нужно один вариант, иначе процедура будет вызываться параллельно из двух мест. Просьба к разработчику: сделать <code>FTV_M2M_JOB</code> безопасной при повторном/параллельном вызове (обработка только строк со <code>STATE='TODO'</code>, блокировка строки на время обработки) — тогда случайное двойное включение не навредит.</p>
|
||||
|
||||
|
||||
{{if .DevMode}}{{/* отчёт о выгрузке истории тестирования — только в режиме разработки */}}
|
||||
{{if devOn}}{{/* отчёт о выгрузке истории тестирования — только в режиме разработки */}}
|
||||
<h2 id="replay">Результат выгрузки истории тестов (14.09.2026)</h2>
|
||||
<p>Кнопкой «Выгрузить историю в DEPO» на вкладке «Тестирование» bj записал в трансферные таблицы все переводы, проведённые на TEST3 (робот НРД и банк Зенит): 78 переводов, 252 события с реальными датами. Джоба bj2depo создала по каждому документ в DEPO (D_CLISER_M2M + строки), сама определила контрагента, депонента, бумагу и место хранения. Что при этом выяснилось:</p>
|
||||
<ul>
|
||||
|
||||
@@ -70,7 +70,7 @@ LISTEN=127.0.0.1:8099 ./bj-lk</pre>
|
||||
<pre>curl -u "lk-user:lk-password" \
|
||||
-H "Content-Type: application/json" \
|
||||
http://10.10.10.22:8080/api/v1/back_office/claims/</pre>
|
||||
{{if .DevMode}}<p class="muted">На M2 (дев-стенд) аутентификация отключена; включится на M3 — параллельно с подключением реального ЛК.</p>{{end}}
|
||||
{{if devOn}}<p class="muted">На M2 (дев-стенд) аутентификация отключена; включится на M3 — параллельно с подключением реального ЛК.</p>{{end}}
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
@@ -133,7 +133,7 @@ LISTEN=127.0.0.1:8099 ./bj-lk</pre>
|
||||
}</pre>
|
||||
</div>
|
||||
|
||||
{{if .DevMode}}
|
||||
{{if devOn}}
|
||||
<div class="card">
|
||||
<h2>7. Эмулятор ЛК для тестов</h2>
|
||||
<p>На дев-стенде доступен <strong>lk-emulator</strong> на порту 8083 — имитация ЛК. Он сам регистрирует свой URL в bj-server как callback-приёмник.</p>
|
||||
@@ -146,8 +146,8 @@ LISTEN=127.0.0.1:8099 ./bj-lk</pre>
|
||||
{{end}}
|
||||
|
||||
<div class="card">
|
||||
<h2>{{if .DevMode}}8{{else}}7{{end}}. Подписание заявления</h2>
|
||||
<h2>{{if devOn}}8{{else}}7{{end}}. Подписание заявления</h2>
|
||||
<p>ЛК должен подписать заявление XMLDSig (ГОСТ или RSA) и положить в поле <code>signed_document</code> (base64). Мы проверяем подпись через crypto-service — см. <a href="/admin/help/crypto">инструкцию по криптографии</a>.</p>
|
||||
{{if .DevMode}}<p class="muted">На M2 проверка подписи отключена (stub). На M3-M4 включится после подключения СКЗИ.</p>{{end}}
|
||||
{{if devOn}}<p class="muted">На M2 проверка подписи отключена (stub). На M3-M4 включится после подключения СКЗИ.</p>{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<li>URL ONYX — например <code>https://gost-t3.nsd.ru/onyx-ms/OnyxEdoWSService/OnyxEdo</code></li>
|
||||
<li>Ключевой контейнер — имя контейнера Валидаты с ключами ЭДО НРД (выдаются УЦ НРД, см. ниже)</li>
|
||||
</ul>
|
||||
{{if .DevMode}}<p class="muted">Без настроенного ИШ система работает в <strong>mock-режиме</strong>: bj-server эмитирует синтетический Decision через 3 секунды для каждой заявки. Это удобно для дев-демо и не требует подключения к НРД.</p>{{else}}<p class="muted">Пока ИШ не настроен, обмен с НРД не выполняется: поручения в НРД не отправляются.</p>{{end}}
|
||||
{{if devOn}}<p class="muted">Без настроенного ИШ система работает в <strong>mock-режиме</strong>: bj-server эмитирует синтетический Decision через 3 секунды для каждой заявки. Это удобно для дев-демо и не требует подключения к НРД.</p>{{else}}<p class="muted">Пока ИШ не настроен, обмен с НРД не выполняется: поручения в НРД не отправляются.</p>{{end}}
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
@@ -96,10 +96,10 @@
|
||||
<table>
|
||||
<thead><tr><th>Внешняя сторона</th><th>Что согласовать</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>НРД (Национальный расчётный депозитарий)</td><td>{{if .DevMode}}Тестовые сертификаты GUEST/TEST3{{else}}Сертификаты для тестового и боевого контуров{{end}}, дистрибутив ИШ, доступ к личному кабинету УЦ НРД</td></tr>
|
||||
<tr><td>Команда ЛК (ESIA Finance)</td><td>Базовый URL ЛК, Basic-auth учётные данные, {{if .DevMode}}очерёдность подключения (сначала эмулятор, потом реальный ЛК){{else}}окружения ЛК (тест и бой){{end}}</td></tr>
|
||||
<tr><td>НРД (Национальный расчётный депозитарий)</td><td>{{if devOn}}Тестовые сертификаты GUEST/TEST3{{else}}Сертификаты для тестового и боевого контуров{{end}}, дистрибутив ИШ, доступ к личному кабинету УЦ НРД</td></tr>
|
||||
<tr><td>Команда ЛК (ESIA Finance)</td><td>Базовый URL ЛК, Basic-auth учётные данные, {{if devOn}}очерёдность подключения (сначала эмулятор, потом реальный ЛК){{else}}окружения ЛК (тест и бой){{end}}</td></tr>
|
||||
<tr><td>Команда Fansy</td><td>Контракт <code>docs/fansy-contract/v1/</code>, SLA, окна обслуживания, IP-allowlist</td></tr>
|
||||
<tr><td>Брокеры-контрагенты MOST</td><td>БКС (ИНН 5406121446), Ренессанс (7709258228), Альфа-Банк (7728168971){{if .DevMode}} — уже в seed{{end}}</td></tr>
|
||||
<tr><td>Брокеры-контрагенты MOST</td><td>БКС (ИНН 5406121446), Ренессанс (7709258228), Альфа-Банк (7728168971){{if devOn}} — уже в seed{{end}}</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
{{if and .DevMode .LKUrl}}
|
||||
{{if and devOn .LKUrl}}
|
||||
{{/* ===== Первичный тест интеграции с ЛК (режим разработки) ===== */}}
|
||||
<div class="card" style="display:flex;gap:16px;align-items:center;flex-wrap:wrap">
|
||||
<div style="width:42px;height:42px;border-radius:11px;background:var(--accent-weak);color:var(--accent);display:flex;align-items:center;justify-content:center;flex:none">
|
||||
@@ -30,10 +30,10 @@
|
||||
{{/* ===== Крупные плитки задач ===== */}}
|
||||
<div class="tiles">
|
||||
{{/* В режиме разработки — симулятор перевода роботу НРД, у клиента — ручной ввод поручения */}}
|
||||
<a {{if .DevMode}}href="#" onclick="document.getElementById('sim-modal').style.display='flex';return false"{{else}}href="/admin/manual"{{end}} class="tile brand">
|
||||
<a {{if devOn}}href="#" onclick="document.getElementById('sim-modal').style.display='flex';return false"{{else}}href="/admin/manual"{{end}} class="tile brand">
|
||||
<span class="ico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 8h12M12 4l4 4-4 4"/><path d="M20 16H8M12 20l-4-4 4-4"/></svg></span>
|
||||
<span class="t-title">Новый перевод</span>
|
||||
<span class="t-sub">{{if .DevMode}}Симулятор: сценарий робота + кол-во бумаг{{else}}Ручной ввод поручения клиента{{end}}</span>
|
||||
<span class="t-sub">{{if devOn}}Симулятор: сценарий робота + кол-во бумаг{{else}}Ручной ввод поручения клиента{{end}}</span>
|
||||
<span class="t-arrow"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg></span>
|
||||
</a>
|
||||
<a href="/admin/claims" class="tile">
|
||||
@@ -99,7 +99,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
{{else}}
|
||||
<p class="muted" style="margin:0">Переводов ещё нет. {{if .DevMode}}Нажмите «Новый перевод», чтобы создать первый.{{else}}Они появятся с заявками из личного кабинета, а поручение клиента можно ввести вручную — «Новый перевод».{{end}}</p>
|
||||
<p class="muted" style="margin:0">Переводов ещё нет. {{if devOn}}Нажмите «Новый перевод», чтобы создать первый.{{else}}Они появятся с заявками из личного кабинета, а поручение клиента можно ввести вручную — «Новый перевод».{{end}}</p>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
{{end}}
|
||||
|
||||
{{/* ===== Модалка-симулятор: тестовый перевод роботу НРД (режим разработки) ===== */}}
|
||||
{{if .DevMode}}
|
||||
{{if devOn}}
|
||||
<div id="sim-modal" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:1000;align-items:center;justify-content:center"
|
||||
onclick="if(event.target===this)this.style.display='none'">
|
||||
<div style="background:var(--card);border:1px solid var(--border);border-radius:14px;padding:24px;max-width:480px;width:92%;box-shadow:var(--shadow-lg)">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{{define "content"}}
|
||||
<div class="hero">
|
||||
<h1 class="hero-greeting">Входящие переводы</h1>
|
||||
<span class="hero-status">Запросы на перевод, где контрагент{{if .DevMode}} (или робот в сценарии 3333){{end}} — передающая сторона. Нужно ответить: принять или отказать по каждой бумаге.</span>
|
||||
<span class="hero-status">Запросы на перевод, где контрагент{{if devOn}} (или робот в сценарии 3333){{end}} — передающая сторона. Нужно ответить: принять или отказать по каждой бумаге.</span>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
@@ -16,14 +16,14 @@
|
||||
<td><code>{{short 8 .GUID}}</code></td>
|
||||
<td>{{$nm := m2mParty .SenderCode}}{{if not $nm}}{{$nm = m2mParty .SenderINN}}{{end}}{{if $nm}}<strong>{{$nm}}</strong><br>{{end}}<code>{{.SenderCode}}</code>{{if .SenderINN}} · ИНН {{.SenderINN}}{{end}}</td>
|
||||
<td>{{len .Securities}}</td>
|
||||
<td>{{$s := inStatus .}}<span class="badge {{$s.Class}}">{{$s.Text}}</span>{{if $s.Outcome}} <span class="badge {{if eq $s.Outcome "Принято"}}confirmed{{else if eq $s.Outcome "Отказано"}}rejected{{else}}awaiting_decision{{end}}">{{$s.Outcome}}</span>{{end}}{{if .DepoSummary}}<br><span class="badge {{if eq .DepoRecommend "confirm"}}confirmed{{else if eq .DepoRecommend "reject"}}rejected{{else}}awaiting_decision{{end}}" style="font-size:11px;margin-top:4px" title="Сверка с DEPO — {{if $.DevMode}}эмуляция ответа{{else}}рекомендация{{end}}, ничего не отправлено">сверка: {{.DepoSummary}}</span>{{end}}</td>
|
||||
<td>{{$s := inStatus .}}<span class="badge {{$s.Class}}">{{$s.Text}}</span>{{if $s.Outcome}} <span class="badge {{if eq $s.Outcome "Принято"}}confirmed{{else if eq $s.Outcome "Отказано"}}rejected{{else}}awaiting_decision{{end}}">{{$s.Outcome}}</span>{{end}}{{if .DepoSummary}}<br><span class="badge {{if eq .DepoRecommend "confirm"}}confirmed{{else if eq .DepoRecommend "reject"}}rejected{{else}}awaiting_decision{{end}}" style="font-size:11px;margin-top:4px" title="Сверка с DEPO — {{if devOn}}эмуляция ответа{{else}}рекомендация{{end}}, ничего не отправлено">сверка: {{.DepoSummary}}</span>{{end}}</td>
|
||||
<td><a href="/admin/incoming/{{.ID}}">{{if eq .Status "answered"}}просмотр{{else}}ответить{{end}} →</a></td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{else}}
|
||||
<p class="muted">Входящих переводов нет. Они появляются, когда другая сторона инициирует перевод к нам{{if .DevMode}} (напр. робот НРД в сценарии 3333 «Выступить принимающей стороной»){{end}}.</p>
|
||||
<p class="muted">Входящих переводов нет. Они появляются, когда другая сторона инициирует перевод к нам{{if devOn}} (напр. робот НРД в сценарии 3333 «Выступить принимающей стороной»){{end}}.</p>
|
||||
{{end}}
|
||||
<p class="muted" style="font-size:12px;margin-top:10px">🔄 Страница обновляется автоматически при появлении нового входящего.</p>
|
||||
</div>
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
.dc-rec.mixed{background:var(--warn-weak,#fff4e0);color:var(--warn,#9a6b12)}
|
||||
</style>
|
||||
<div style="display:flex;align-items:center;gap:10px;flex-wrap:wrap">
|
||||
<h2 style="margin:0">Сверка с DEPO — {{if .DevMode}}эмуляция ответа{{else}}рекомендация по ответу{{end}}</h2>
|
||||
<h2 style="margin:0">Сверка с DEPO — {{if devOn}}эмуляция ответа{{else}}рекомендация по ответу{{end}}</h2>
|
||||
{{if .Depo.Ran}}<span class="dc-rec {{.Depo.Recommend}}">рекомендуем: {{.Depo.Summary}}</span>{{end}}
|
||||
</div>
|
||||
<p class="muted" style="font-size:12.5px;margin:6px 0 0">Проверки по регламенту депозитария (инвестор, торговый счёт депо, бумага на обслуживании, договор не ИИС, блокировки). <b>Ответ контрагенту НЕ отправлен</b> — это только рекомендация; она подставлена в форму ниже, проверьте и нажмите «Отправить решение».</p>
|
||||
@@ -73,7 +73,7 @@
|
||||
<div class="card">
|
||||
<h2>Решение по бумагам ({{len .It.Securities}})</h2>
|
||||
{{if $answered}}
|
||||
<p class="muted">Решение уже отправлено {{if .DevMode}}роботу{{else}}контрагенту через НРД{{end}}. Ниже — что было выбрано по каждой бумаге.</p>
|
||||
<p class="muted">Решение уже отправлено {{if devOn}}роботу{{else}}контрагенту через НРД{{end}}. Ниже — что было выбрано по каждой бумаге.</p>
|
||||
<table>
|
||||
<thead><tr><th>ReferenceId</th><th>Код НРД / ISIN</th><th>Кол-во</th><th>Счёт зачисления</th><th>Решение</th></tr></thead>
|
||||
<tbody>
|
||||
@@ -89,9 +89,9 @@
|
||||
</tbody>
|
||||
</table>
|
||||
{{else}}
|
||||
<p class="muted">По каждой бумаге выберите: <b>принять</b> (зачислим на наш депо-счёт из настроек НРД) или <b>отказать</b> (с кодом отказа). Решение уйдёт {{if .DevMode}}роботу{{else}}контрагенту через НРД{{end}} одним сообщением M2MTransferDecision.</p>
|
||||
<p class="muted">По каждой бумаге выберите: <b>принять</b> (зачислим на наш депо-счёт из настроек НРД) или <b>отказать</b> (с кодом отказа). Решение уйдёт {{if devOn}}роботу{{else}}контрагенту через НРД{{end}} одним сообщением M2MTransferDecision.</p>
|
||||
|
||||
{{if .DevMode}}{{/* подсказки по сценариям робота НРД — только в режиме разработки */}}
|
||||
{{if devOn}}{{/* подсказки по сценариям робота НРД — только в режиме разработки */}}
|
||||
<div style="padding:10px 14px;background:var(--accent-weak,#e7f0fb);border-radius:10px;margin:6px 0 14px">
|
||||
<label style="font-size:13px;font-weight:600">Сценарий тестирования:
|
||||
<select id="m2m-scen" style="margin-left:8px;padding:5px 8px;border-radius:7px;border:1px solid var(--border);background:var(--card);color:var(--text)">
|
||||
@@ -142,7 +142,7 @@
|
||||
</table>
|
||||
<p class="muted" style="font-size:12.5px;margin:10px 0 0">Пакет принимается только целиком: при отказе по одной бумаге отказ ставится всем бумагам с тем же кодом (так и будет отправлено).</p>
|
||||
<div style="display:flex;gap:8px;margin-top:14px;flex-wrap:wrap">
|
||||
<button type="submit" class="btn btn-ok">Отправить решение{{if .DevMode}} роботу{{end}}</button>
|
||||
<button type="submit" class="btn btn-ok">Отправить решение{{if devOn}} роботу{{end}}</button>
|
||||
<button type="button" class="btn" onclick="m2mSetAll('confirm')">Принять все</button>
|
||||
<button type="button" class="btn" onclick="m2mSetAll('reject')">Отказать все</button>
|
||||
</div>
|
||||
@@ -356,7 +356,7 @@
|
||||
{{/* ===== QUIK МНП: зачисление клиенту ===== */}}
|
||||
{{$back := printf "/admin/incoming/%s" .It.ID}}
|
||||
|
||||
{{if .DevMode}}{{/* прогон копии в DEPO — служебный инструмент режима разработки */}}
|
||||
{{if devOn}}{{/* прогон копии в DEPO — служебный инструмент режима разработки */}}
|
||||
<div class="card">
|
||||
<h2 style="margin:0">Тестовый прогон в DEPO с реальным клиентом</h2>
|
||||
<p class="muted" style="font-size:12.5px;margin:6px 0 8px">Копия этого входящего (те же бумаги и решения) записывается в трансферные таблицы DEPO под новым GUID на реального клиента из картотеки — по паспорту. Джоба bj2depo создаёт по нему документ; в НРД ничего не уходит. Полный сценарий приёма: получен → приняли → подали 16/1 → НРД принял → исполнено.</p>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<p>Ключ установлен на флешку, справочник сертификатов сформирован, Валидата проверена.</p>
|
||||
{{if $s.Backup}}<p class="muted">Бэкап прежнего носителя: <code>{{$s.Backup}}</code></p>{{end}}
|
||||
<div style="display:flex;gap:8px;margin-top:12px;flex-wrap:wrap">
|
||||
{{if .DevMode}}<form method="post" action="/admin/setup/test-nsd" style="margin:0">
|
||||
{{if devOn}}<form method="post" action="/admin/setup/test-nsd" style="margin:0">
|
||||
<input type="hidden" name="scenario" value="2001">
|
||||
<button type="submit" class="btn btn-ok">→ Отправить тестовый документ роботу</button>
|
||||
</form>{{else}}<a href="/admin/status" class="btn btn-ok">→ Проверить подключения</a>{{end}}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<button data-sec="update"><span class="nico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20V8M6 12l6-6 6 6"/><path d="M5 4h14"/></svg></span>Обновления{{if .Settings.Update.Available}}<span class="ind warn"></span>{{end}}</button>
|
||||
<button data-sec="license"><span class="nico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><circle cx="8" cy="12" r="4"/><path d="M12 12h9M18 12v3M15 12v2"/></svg></span>Лицензия{{if .License.Present}}<span class="ind {{if .License.Valid}}ok{{else}}err{{end}}"></span>{{end}}</button>
|
||||
<button data-sec="branding"><span class="nico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/><circle cx="8.5" cy="10" r="1.5"/><path d="M21 16l-5-5L5 19"/></svg></span>Оформление{{if .Settings.Branding.LogoDataURI}}<span class="ind ok"></span>{{end}}</button>
|
||||
{{if .DevMode}} <button data-sec="advanced"><span class="nico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="11" width="14" height="9" rx="2"/><path d="M8 11V8a4 4 0 0 1 8 0v3"/></svg></span>Перспективные{{if .AdvancedUnlocked}}<span class="ind ok"></span>{{end}}</button>{{end}}
|
||||
{{if devOn}} <button data-sec="advanced"><span class="nico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="11" width="14" height="9" rx="2"/><path d="M8 11V8a4 4 0 0 1 8 0v3"/></svg></span>Перспективные{{if .AdvancedUnlocked}}<span class="ind ok"></span>{{end}}</button>{{end}}
|
||||
</nav>
|
||||
|
||||
<div class="settings-body">
|
||||
@@ -59,7 +59,7 @@
|
||||
<div class="card">
|
||||
<h2><span class="dot {{if .Settings.Postgres.DSN}}ok{{else}}err{{end}}"></span>PostgreSQL</h2>
|
||||
<p class="muted">Журнал сделок m2m-core и принимающая БД. Сейчас: {{if .Settings.Postgres.DSN}}<code>подключено</code>{{else}}<code>in-memory</code> (данные не сохраняются){{end}}.</p>
|
||||
{{if and .DevMode (not .Settings.Postgres.DSN)}}
|
||||
{{if and devOn (not .Settings.Postgres.DSN)}}
|
||||
<div style="background:var(--card-2);border:1px solid var(--accent);border-radius:10px;padding:16px;margin-top:12px">
|
||||
<h3 style="margin:0 0 8px">Подключить автоматически</h3>
|
||||
<p class="muted" style="margin:0 0 12px">Поднимем локальный PostgreSQL в контейнере, применим миграции и запишем DSN. Для дев-стенда. Для прода — укажите свой DSN ниже.</p>
|
||||
@@ -227,14 +227,14 @@
|
||||
</div>
|
||||
|
||||
<div class="card" id="sec-quik-cycle">
|
||||
<h2><span class="dot {{if .Settings.Quik.Emulate}}warn{{else if not .Settings.Quik.WritesEnabled}}warn{{else if or .Settings.Quik.AutoOut .Settings.Quik.AutoIn}}ok{{else}}warn{{end}}"></span>Автоматический цикл M2M в МНП{{if .Settings.Quik.Emulate}} <span class="hero-status warn">{{if .DevMode}}имитация{{else}}остановлен{{end}}</span>{{end}}</h2>
|
||||
<h2><span class="dot {{if .Settings.Quik.Emulate}}warn{{else if not .Settings.Quik.WritesEnabled}}warn{{else if or .Settings.Quik.AutoOut .Settings.Quik.AutoIn}}ok{{else}}warn{{end}}"></span>Автоматический цикл M2M в МНП{{if .Settings.Quik.Emulate}} <span class="hero-status warn">{{if devOn}}имитация{{else}}остановлен{{end}}</span>{{end}}</h2>
|
||||
<p class="muted">Что делает bj в Модуле неторговых поручений по ходу перевода: <strong>исходящий</strong> — при отправке в НРД регистрирует «Вывод ЦБ (M2M)» (QUIK блокирует бумаги), по подтверждению подписывает (списание), по отказу снимает с причиной; <strong>входящий</strong> — после приёма нашего поручения НРД регистрирует «Ввод ЦБ (M2M)» (зачисление сразу). Каждый шаг виден в карточке перевода и на странице <a href="/admin/quik">QUIK МНП</a>.</p>
|
||||
<form method="post" action="/admin/setup/quik/cycle" style="margin-top:12px;display:grid;gap:10px;max-width:640px">
|
||||
<input type="hidden" name="section" value="sec-quik-cycle">
|
||||
<label style="display:flex;gap:8px;align-items:center;font-weight:600">
|
||||
<input type="checkbox" name="writes_enabled" value="1" {{if .Settings.Quik.WritesEnabled}}checked{{end}}>
|
||||
Разрешить записи в МНП (главный предохранитель — база боевая)</label>
|
||||
{{if .DevMode}} <label style="display:flex;gap:8px;align-items:center;font-weight:600">
|
||||
{{if devOn}} <label style="display:flex;gap:8px;align-items:center;font-weight:600">
|
||||
<input type="checkbox" name="emulate" value="1" {{if .Settings.Quik.Emulate}}checked{{end}}>
|
||||
Имитация: шаги цикла (блокировка, подпись, снятие, зачисление) проходят и отмечаются «имитация», в МНП ничего не пишется — пока нет пользователя QUIK для блокировок и лимитов. Имеет приоритет над записью.</label>{{end}}
|
||||
<label style="display:flex;gap:8px;align-items:center;font-weight:400;margin-left:22px">
|
||||
@@ -411,7 +411,7 @@
|
||||
|
||||
<div class="card">
|
||||
<h2><span class="dot {{if .Settings.Crypto.Profile}}ok{{else}}warn{{end}}"></span>СКЗИ «Валидата Клиент L»</h2>
|
||||
<p class="muted">Активный профиль: <code>{{if .Settings.Crypto.Profile}}{{.Settings.Crypto.Profile}}{{else}}—{{end}}</code> · провайдер {{if and (not .DevMode) (or (eq .Settings.Crypto.Provider "stub") (eq .Settings.Crypto.Provider ""))}}<code>не настроен</code>{{else}}<code>{{.Settings.Crypto.Provider}}</code>{{end}}. Подробно — <a href="/admin/help/crypto">справка</a>.</p>
|
||||
<p class="muted">Активный профиль: <code>{{if .Settings.Crypto.Profile}}{{.Settings.Crypto.Profile}}{{else}}—{{end}}</code> · провайдер {{if and (not devOn) (or (eq .Settings.Crypto.Provider "stub") (eq .Settings.Crypto.Provider ""))}}<code>не настроен</code>{{else}}<code>{{.Settings.Crypto.Provider}}</code>{{end}}. Подробно — <a href="/admin/help/crypto">справка</a>.</p>
|
||||
<div style="display:flex;gap:8px;flex-wrap:wrap;margin-top:12px">
|
||||
<form method="post" action="/admin/setup/crypto/check" style="margin:0"><button type="submit" class="btn btn-ok">✓ Проверить СКЗИ</button></form>
|
||||
<form method="post" action="/admin/setup/crypto/test-sign" style="margin:0"><button type="submit" class="btn">✎ Пробная подпись</button></form>
|
||||
@@ -423,7 +423,7 @@
|
||||
<form method="post" action="/admin/setup/crypto" style="margin-top:12px;display:grid;gap:10px;max-width:640px">
|
||||
<label>Провайдер</label>
|
||||
<select name="provider">
|
||||
{{if .DevMode}} <option value="stub" {{if eq .Settings.Crypto.Provider "stub"}}selected{{end}}>stub — без криптографии (демо)</option>{{end}}
|
||||
{{if devOn}} <option value="stub" {{if eq .Settings.Crypto.Provider "stub"}}selected{{end}}>stub — без криптографии (демо)</option>{{end}}
|
||||
<option value="validata" {{if eq .Settings.Crypto.Provider "validata"}}selected{{end}}>Валидата Клиент L</option>
|
||||
</select>
|
||||
<label>Путь к модулю PKCS#11</label>
|
||||
@@ -555,17 +555,17 @@ function hbBind(inp,box,list,onPick){
|
||||
<label style="display:flex;gap:8px;align-items:center;font-weight:600;margin:0"><input type="checkbox" name="enabled" value="1" {{if .Settings.M2MAuto.Enabled}}checked{{end}}> Автоматический режим включён</label>
|
||||
<button type="submit" class="btn btn-ok">Сохранить</button>
|
||||
</form>
|
||||
{{if not .Settings.M2MAuto.ChangedAt.IsZero}}<p class="muted" style="font-size:12px;margin-top:8px">{{if .Settings.M2MAuto.Enabled}}Включён{{else}}Выключен{{end}} {{msk .Settings.M2MAuto.ChangedAt}}{{with .Settings.M2MAuto.ChangedBy}} · {{.}}{{end}}.{{if .Settings.Quik.Emulate}}{{if .DevMode}} Шаги QUIK МНП — в режиме имитации.{{else}} Записи в QUIK МНП сейчас не выполняются.{{end}}{{end}}</p>{{end}}
|
||||
{{if not .Settings.M2MAuto.ChangedAt.IsZero}}<p class="muted" style="font-size:12px;margin-top:8px">{{if .Settings.M2MAuto.Enabled}}Включён{{else}}Выключен{{end}} {{msk .Settings.M2MAuto.ChangedAt}}{{with .Settings.M2MAuto.ChangedBy}} · {{.}}{{end}}.{{if .Settings.Quik.Emulate}}{{if devOn}} Шаги QUIK МНП — в режиме имитации.{{else}} Записи в QUIK МНП сейчас не выполняются.{{end}}{{end}}</p>{{end}}
|
||||
</div>
|
||||
<div class="card">
|
||||
<h2><span class="dot {{if .Settings.NSD.IGWBaseURL}}ok{{else}}warn{{end}}"></span>Интеграционный шлюз (ИШ)</h2>
|
||||
<p class="muted">{{if not .Settings.NSD.IGWBaseURL}}{{if .DevMode}}<code>mock-режим</code> — без реального ИШ.{{else}}ИШ не настроен — обмен с НРД не выполняется.{{end}}{{else}}Профиль <code>{{.Settings.NSD.Profile}}</code>, ИШ <code>{{.Settings.NSD.IGWBaseURL}}</code>.{{end}} Стенды и установка — <a href="/admin/help/systems">справка</a>.</p>
|
||||
<p class="muted">{{if not .Settings.NSD.IGWBaseURL}}{{if devOn}}<code>mock-режим</code> — без реального ИШ.{{else}}ИШ не настроен — обмен с НРД не выполняется.{{end}}{{else}}Профиль <code>{{.Settings.NSD.Profile}}</code>, ИШ <code>{{.Settings.NSD.IGWBaseURL}}</code>.{{end}} Стенды и установка — <a href="/admin/help/systems">справка</a>.</p>
|
||||
<form method="post" action="/admin/setup/nsd" style="margin-top:12px;display:grid;gap:10px;max-width:680px">
|
||||
<label>Профиль / контур</label>
|
||||
<select name="profile" id="nsd-profile">
|
||||
{{/* mock и GUEST — для разработчиков; у клиента — только контуры НРД */}}
|
||||
<option value="" {{if eq .Settings.NSD.Profile ""}}selected{{end}}>{{if .DevMode}}— mock (демо) —{{else}}— не выбран —{{end}}</option>
|
||||
{{if or .DevMode (eq .Settings.NSD.Profile "guest-gost") (eq .Settings.NSD.Profile "guest-rsa")}} <option value="guest-gost" {{if eq .Settings.NSD.Profile "guest-gost"}}selected{{end}}>guest-gost — GUEST, ГОСТ</option>
|
||||
<option value="" {{if eq .Settings.NSD.Profile ""}}selected{{end}}>{{if devOn}}— mock (демо) —{{else}}— не выбран —{{end}}</option>
|
||||
{{if or devOn (eq .Settings.NSD.Profile "guest-gost") (eq .Settings.NSD.Profile "guest-rsa")}} <option value="guest-gost" {{if eq .Settings.NSD.Profile "guest-gost"}}selected{{end}}>guest-gost — GUEST, ГОСТ</option>
|
||||
<option value="guest-rsa" {{if eq .Settings.NSD.Profile "guest-rsa"}}selected{{end}}>guest-rsa — GUEST, RSA</option>{{end}}
|
||||
<option value="test3-gost" {{if eq .Settings.NSD.Profile "test3-gost"}}selected{{end}}>test3-gost — тестовый контур НРД (TEST3), ГОСТ</option>
|
||||
<option value="test3-rsa" {{if eq .Settings.NSD.Profile "test3-rsa"}}selected{{end}}>test3-rsa — тестовый контур НРД (TEST3), RSA</option>
|
||||
@@ -736,7 +736,7 @@ function hbBind(inp,box,list,onPick){
|
||||
<input type="text" name="lk_public_url" value="{{.Settings.LK.PublicURL}}" placeholder="https://lk.example.ru" style="flex:1">
|
||||
{{if .Settings.LK.PublicURL}}<a class="btn btn-secondary" href="{{.Settings.LK.PublicURL}}" target="_blank" rel="noopener">Открыть →</a>{{end}}
|
||||
</div>
|
||||
<span class="muted" style="font-size:12px">{{if .DevMode}}Показывается ссылкой на дашборде для первичного теста.{{else}}Адрес, по которому клиенты входят в личный кабинет.{{end}}</span>
|
||||
<span class="muted" style="font-size:12px">{{if devOn}}Показывается ссылкой на дашборде для первичного теста.{{else}}Адрес, по которому клиенты входят в личный кабинет.{{end}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<label>Callback URL <span class="muted" style="font-weight:400">(куда bj шлёт статус заявки)</span></label>
|
||||
@@ -801,12 +801,12 @@ function hbBind(inp,box,list,onPick){
|
||||
<option value="prod" {{if eq .Settings.LK.ActiveEnv "prod"}}selected{{end}}>Бой</option>
|
||||
</select>
|
||||
<span class="muted" style="font-size:12px">bj работает с ЛК через выбранное окружение.</span>
|
||||
{{if .DevMode}} <input type="hidden" name="emulate_nsd_form" value="1">
|
||||
{{if devOn}} <input type="hidden" name="emulate_nsd_form" value="1">
|
||||
<label style="display:flex;align-items:flex-start;gap:8px;font-weight:400;flex-basis:100%;margin-top:6px"><input type="checkbox" name="emulate_nsd" style="width:auto;margin-top:3px" {{if .Settings.LK.EmulateNSD}}checked{{end}} onchange="this.form.submit()"> <span><b>Имитация НРД</b> — заявки ЛК проходят сверку с DEPO, блокировку в QUIK и получают статус в ЛК, но в НРД не отправляются: ответ контрагента имитирует bj.{{if and (eq .Settings.LK.ActiveEnv "prod") (not .Settings.LK.EmulateNSD)}} <span style="color:var(--warn)">Сейчас включена принудительно: боевой ЛК при тестовом профиле ИШ ({{.Settings.NSD.Profile}}).</span>{{end}}</span></label>{{end}}
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{{if .DevMode}} <div class="card">
|
||||
{{if devOn}} <div class="card">
|
||||
<h2>Симулятор заявки M2M</h2>
|
||||
<p class="muted">Пока подача через веб-форму у ЕСИА Финанс не готова — bj сам собирает заявку <code>depo_m2m</code> и <strong>отправляет её в API ЛК</strong> (<code>POST /claims/</code>) через активное окружение. Ответ показывается ниже; затем заявку ловим опросом в «Переводы». Поля предзаполнены рабочим тестовым договором.</p>
|
||||
<form method="post" action="/admin/setup/lk-simulate" style="margin-top:12px">
|
||||
@@ -846,7 +846,7 @@ function hbBind(inp,box,list,onPick){
|
||||
|
||||
<div class="card">
|
||||
<h2>Забрать заявки из ЛК</h2>
|
||||
<p class="muted">Коннектор bj вычитывает заявки <code>depo_m2m</code> активного окружения в статусах «В очереди» и «В работе», которые ещё не обрабатывал, для каждой собирает M2M-пакет, отправляет в НРД и переводит заявку в статус <strong>«В работе»</strong>. По ответу НРД статус в ЛК замыкается автоматически (Исполнена / Отклонена).{{if .DevMode}} В режиме имитации НРД перед отправкой идёт сверка с DEPO: отказ сразу уходит в ЛК с кодом и причиной, одобренная заявка блокируется в QUIK и через 30 с получает имитированный ответ контрагента.{{end}} Штатно это делает фоновый поллер раз в минуту — кнопка для ручного запуска.</p>
|
||||
<p class="muted">Коннектор bj вычитывает заявки <code>depo_m2m</code> активного окружения в статусах «В очереди» и «В работе», которые ещё не обрабатывал, для каждой собирает M2M-пакет, отправляет в НРД и переводит заявку в статус <strong>«В работе»</strong>. По ответу НРД статус в ЛК замыкается автоматически (Исполнена / Отклонена).{{if devOn}} В режиме имитации НРД перед отправкой идёт сверка с DEPO: отказ сразу уходит в ЛК с кодом и причиной, одобренная заявка блокируется в QUIK и через 30 с получает имитированный ответ контрагента.{{end}} Штатно это делает фоновый поллер раз в минуту — кнопка для ручного запуска.</p>
|
||||
<form method="post" action="/admin/setup/lk-pull" style="margin-top:12px"><button type="submit" class="btn">Забрать заявки сейчас</button></form>
|
||||
<p class="muted" style="font-size:12px;margin-top:10px">Итог (сколько получено / отправлено, ошибки) появится вверху страницы.</p>
|
||||
</div>
|
||||
@@ -887,7 +887,7 @@ function hbBind(inp,box,list,onPick){
|
||||
<p class="muted" style="font-size:12px;margin-top:8px">Ответ придёт во входящие ИШ (~30-60с). Список появится в логе bj-server и в <code>m2m-handbook.json</code>.</p>
|
||||
</div>
|
||||
|
||||
{{if .DevMode}} <div class="card">
|
||||
{{if devOn}} <div class="card">
|
||||
<h2>Тестовый пакет роботу НРД</h2>
|
||||
<p class="muted">Робот <code>MC0012500000</code> эмулирует вторую сторону перевода. Выберите сценарий — bj-server отправит эталонный запрос через ИШ, ответ придёт во входящие. Требуется настроенный ИШ + профиль Валидаты.</p>
|
||||
<form method="post" action="/admin/setup/test-nsd" style="margin-top:12px;display:flex;gap:8px;flex-wrap:wrap;align-items:center">
|
||||
@@ -1108,7 +1108,7 @@ function hbBind(inp,box,list,onPick){
|
||||
<h1>Оформление отчётов</h1>
|
||||
<div class="card">
|
||||
<h2>Логотип организации в шапке отчётов</h2>
|
||||
<p class="muted">Логотип показывается <b>справа</b> в шапке всех отчётов для регулятора (слева — логотип MOEX МОСТ / НРД){{if .DevMode}} и на титульной сводке пакета тестов{{end}}. Встраивается прямо в HTML — отчёт остаётся автономным. Если не загружать — используется стандартный логотип «Фонтвьель».</p>
|
||||
<p class="muted">Логотип показывается <b>справа</b> в шапке всех отчётов для регулятора (слева — логотип MOEX МОСТ / НРД){{if devOn}} и на титульной сводке пакета тестов{{end}}. Встраивается прямо в HTML — отчёт остаётся автономным. Если не загружать — используется стандартный логотип «Фонтвьель».</p>
|
||||
|
||||
<div style="display:flex;align-items:center;gap:18px;flex-wrap:wrap;margin:14px 0;padding:14px;background:var(--card-2);border-radius:12px">
|
||||
<div>
|
||||
@@ -1134,7 +1134,7 @@ function hbBind(inp,box,list,onPick){
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{{if .DevMode}} {{/* ============ ПЕРСПЕКТИВНЫЕ МОДУЛИ (под паролем) ============ */}}
|
||||
{{if devOn}} {{/* ============ ПЕРСПЕКТИВНЫЕ МОДУЛИ (под паролем) ============ */}}
|
||||
<section class="settings-section" id="sec-advanced">
|
||||
<h1>Перспективные модули</h1>
|
||||
<p class="muted" style="max-width:64ch">Модули для будущих профилей внедрения <strong>«автомат»</strong> и <strong>«полуавтомат»</strong> (когда используется собственный личный кабинет, а не ЕСИА Финанс). Пока не в проде — скрыты, чтобы не мешать текущей работе. В профиле «через Финансы» они не нужны: проверку и блокировку бумаг закрывает сам ЕСИА Финанс.</p>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<p class="muted" style="margin-top: 16px">Проверка выполнена в {{.CheckedAt.Format "15:04:05 02.01.2006"}}.</p>
|
||||
</div>
|
||||
|
||||
{{if .DevMode}}{{/* дорожная карта разработки — только в режиме разработки */}}
|
||||
{{if devOn}}{{/* дорожная карта разработки — только в режиме разработки */}}
|
||||
<div class="card">
|
||||
<h2>Что подключается на следующих этапах</h2>
|
||||
<table>
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<strong>Что выбрать?</strong> Если у вас уже есть рабочий PostgreSQL — нажмите «У меня уже есть PostgreSQL» и введите DSN. Если впервые настраиваете — выберите «Поднять автоматически», система сама развернёт контейнер с PostgreSQL и накатит миграции.
|
||||
</div>
|
||||
|
||||
{{if and .DevMode (not .Settings.Postgres.DSN)}}
|
||||
{{if and devOn (not .Settings.Postgres.DSN)}}
|
||||
<div style="background:var(--bg);border:1px solid var(--accent);border-radius:6px;padding:14px;margin-top:12px">
|
||||
<h3 style="margin:0 0 8px 0;font-size:15px">Вариант А — для тех, у кого нет своего PostgreSQL</h3>
|
||||
<p class="muted" style="margin:0 0 10px 0">Bridge-and-Join-s сам поднимет PostgreSQL в контейнере (podman-compose), создаст БД <code>bj</code> и накатит миграции. Подходит для дев-стенда. Для продакшена лучше указать свой DSN.</p>
|
||||
@@ -91,9 +91,9 @@
|
||||
<summary style="cursor:pointer;color:var(--accent)">Параметры провайдера</summary>
|
||||
<form method="post" action="/admin/setup/crypto" style="margin-top:12px;display:grid;gap:10px">
|
||||
<div>
|
||||
<label>Провайдер <span class="tooltip" title="validata — АПК «Валидата Клиент L»{{if .DevMode}}; stub — без криптографии (демо-режим без подписи){{end}}">?</span></label>
|
||||
<label>Провайдер <span class="tooltip" title="validata — АПК «Валидата Клиент L»{{if devOn}}; stub — без криптографии (демо-режим без подписи){{end}}">?</span></label>
|
||||
<select name="provider" style="padding:8px;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:4px;width:100%">
|
||||
{{if .DevMode}} <option value="stub" {{if eq .Settings.Crypto.Provider "stub"}}selected{{end}}>stub — без криптографии (демо)</option>{{end}}
|
||||
{{if devOn}} <option value="stub" {{if eq .Settings.Crypto.Provider "stub"}}selected{{end}}>stub — без криптографии (демо)</option>{{end}}
|
||||
<option value="validata" {{if eq .Settings.Crypto.Provider "validata"}}selected{{end}}>Валидата Клиент L</option>
|
||||
</select>
|
||||
</div>
|
||||
@@ -186,17 +186,17 @@
|
||||
<p>Адрес web-сервиса ONYX и имя ключевого контейнера НРД.</p>
|
||||
|
||||
<div class="help-block">
|
||||
<strong>Что это?</strong> Интеграционный шлюз (ИШ) НРД — это компонент, через который наши M2M-сообщения отправляются в НРД. {{if .DevMode}}У НРД есть 4 контура: <em>GUEST</em> (для разработки) и <em>TEST3</em> (предпродакшен), каждый в варианте ГОСТ или RSA.{{else}}У НРД есть тестовый контур (<em>TEST3</em>) и боевой контур, каждый в варианте ГОСТ или RSA.{{end}}<br>
|
||||
<strong>Что это?</strong> Интеграционный шлюз (ИШ) НРД — это компонент, через который наши M2M-сообщения отправляются в НРД. {{if devOn}}У НРД есть 4 контура: <em>GUEST</em> (для разработки) и <em>TEST3</em> (предпродакшен), каждый в варианте ГОСТ или RSA.{{else}}У НРД есть тестовый контур (<em>TEST3</em>) и боевой контур, каждый в варианте ГОСТ или RSA.{{end}}<br>
|
||||
<strong>Где взять?</strong> Дистрибутив ИШ и инструкции — на сайте НРД <a href="https://www.nsd.ru/workflow/system/programs/" target="_blank">nsd.ru/workflow/system/programs/</a>. Доступ к тестовым контурам выдаётся НРД по заявке (см. <code>DOC/instr_podkl_stend_v3.pdf</code>).
|
||||
</div>
|
||||
|
||||
<form method="post" action="/admin/setup/nsd" style="margin-top:12px;display:grid;gap:10px">
|
||||
<div>
|
||||
<label>Профиль <span class="tooltip" title="{{if .DevMode}}GUEST — гостевой контур для разработчиков (gost-gt.nsd.ru), {{end}}TEST3 — тестовый контур НРД (gost-t3.nsd.ru), prod — боевой контур НРД">?</span></label>
|
||||
<label>Профиль <span class="tooltip" title="{{if devOn}}GUEST — гостевой контур для разработчиков (gost-gt.nsd.ru), {{end}}TEST3 — тестовый контур НРД (gost-t3.nsd.ru), prod — боевой контур НРД">?</span></label>
|
||||
<select name="profile" id="nsd-profile" style="padding:8px;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:4px;width:100%">
|
||||
<option value="test3-gost" {{if eq .Settings.NSD.Profile "test3-gost"}}selected{{end}}>TEST3 · ГОСТ — тестовый контур НРД</option>
|
||||
<option value="test3-rsa" {{if eq .Settings.NSD.Profile "test3-rsa"}}selected{{end}}>TEST3 · RSA — тестовый контур НРД</option>
|
||||
{{if or .DevMode (eq .Settings.NSD.Profile "guest-gost") (eq .Settings.NSD.Profile "guest-rsa")}} <option value="guest-gost" {{if eq .Settings.NSD.Profile "guest-gost"}}selected{{end}}>GUEST · ГОСТ</option>
|
||||
{{if or devOn (eq .Settings.NSD.Profile "guest-gost") (eq .Settings.NSD.Profile "guest-rsa")}} <option value="guest-gost" {{if eq .Settings.NSD.Profile "guest-gost"}}selected{{end}}>GUEST · ГОСТ</option>
|
||||
<option value="guest-rsa" {{if eq .Settings.NSD.Profile "guest-rsa"}}selected{{end}}>GUEST · RSA</option>{{end}}
|
||||
<option value="prod" {{if eq .Settings.NSD.Profile "prod"}}selected{{end}}>prod — боевой контур НРД (осторожно)</option>
|
||||
</select>
|
||||
@@ -228,7 +228,7 @@
|
||||
|
||||
<div style="margin-top:20px;display:flex;justify-content:space-between">
|
||||
<a href="/admin/wizard?step=3" class="btn" style="background:var(--card);text-decoration:none">← К шагу 3</a>
|
||||
{{if .Done.NSD}}<a href="/admin/wizard?step=5" class="btn" style="text-decoration:none">К шагу 5 →</a>{{else}}<a href="/admin/wizard?step=5&skip=nsd" class="btn" style="background:var(--card);text-decoration:none">Пропустить ({{if .DevMode}}mock-режим{{else}}обмен с НРД не настроен{{end}}) →</a>{{end}}
|
||||
{{if .Done.NSD}}<a href="/admin/wizard?step=5" class="btn" style="text-decoration:none">К шагу 5 →</a>{{else}}<a href="/admin/wizard?step=5&skip=nsd" class="btn" style="background:var(--card);text-decoration:none">Пропустить ({{if devOn}}mock-режим{{else}}обмен с НРД не настроен{{end}}) →</a>{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -236,7 +236,7 @@
|
||||
{{/* ============= ШАГ 5: Тест-ран (режим разработки) / проверка подключений ============= */}}
|
||||
{{if eq .Step 5}}
|
||||
<div class="card">
|
||||
{{if .DevMode}}
|
||||
{{if devOn}}
|
||||
<h2><span class="dot {{if .Done.TestRun}}ok{{else}}err{{end}}"></span>Шаг 5. Тестовая заявка</h2>
|
||||
<p>Прогон полного цикла: создание заявки → валидация → подпись → отправка в НРД (или mock) → ожидание Decision → подтверждение.</p>
|
||||
|
||||
@@ -268,8 +268,8 @@
|
||||
<tr><td class="muted">PostgreSQL</td><td>{{if .Done.Postgres}}<span style="color:var(--ok)">настроен</span>{{else}}<span class="muted">in-memory</span>{{end}}</td></tr>
|
||||
<tr><td class="muted">Крипто-провайдер</td><td>{{if .Done.Crypto}}<span style="color:var(--ok)">{{.Settings.Crypto.Provider}}</span>{{else}}<span style="color:var(--err)">не настроен</span>{{end}}</td></tr>
|
||||
<tr><td class="muted">Сертификатов установлено</td><td>{{len .Certs}}</td></tr>
|
||||
<tr><td class="muted">ИШ НРД</td><td>{{if .Done.NSD}}<span style="color:var(--ok)">{{.Settings.NSD.Profile}}</span>{{else}}<span class="muted">{{if .DevMode}}mock-режим{{else}}не настроен{{end}}</span>{{end}}</td></tr>
|
||||
{{if .DevMode}}<tr><td class="muted">Тестовый прогон</td><td>{{if .Done.TestRun}}<span style="color:var(--ok)">пройден</span>{{else}}<span class="muted">не запускался</span>{{end}}</td></tr>{{end}}
|
||||
<tr><td class="muted">ИШ НРД</td><td>{{if .Done.NSD}}<span style="color:var(--ok)">{{.Settings.NSD.Profile}}</span>{{else}}<span class="muted">{{if devOn}}mock-режим{{else}}не настроен{{end}}</span>{{end}}</td></tr>
|
||||
{{if devOn}}<tr><td class="muted">Тестовый прогон</td><td>{{if .Done.TestRun}}<span style="color:var(--ok)">пройден</span>{{else}}<span class="muted">не запускался</span>{{end}}</td></tr>{{end}}
|
||||
</table>
|
||||
|
||||
<div style="margin-top:20px;display:flex;justify-content:space-between">
|
||||
|
||||
@@ -263,6 +263,12 @@ label { font-size:13px; font-weight:500; }
|
||||
#bj-toast.visible { opacity:1; transform:translateY(0); }
|
||||
#bj-toast .close { position:absolute; top:6px; right:10px; cursor:pointer; color:var(--muted); font-size:15px; }
|
||||
#bj-toast .close:hover { color:var(--text); }
|
||||
|
||||
.banner-dev{margin:0;border-bottom:1px solid var(--border)}
|
||||
.banner-dev button{width:100%;display:flex;gap:10px;align-items:center;padding:7px 18px;background:transparent;border:0;font:inherit;font-size:13px;color:var(--text);cursor:pointer;text-align:left}
|
||||
.banner-dev.on{background:color-mix(in srgb,var(--warn) 12%,var(--card))}
|
||||
.banner-dev.off{background:color-mix(in srgb,var(--ok) 10%,var(--card))}
|
||||
.banner-dev button:hover{filter:brightness(.97)}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -287,7 +293,7 @@ label { font-size:13px; font-weight:500; }
|
||||
<a href="/admin/incoming">Входящие<span id="nav-incoming-badge" style="display:none;margin-left:5px;background:var(--err);color:#fff;border-radius:10px;padding:1px 7px;font-size:11px;font-weight:700"></span></a>
|
||||
</span>
|
||||
</span>
|
||||
{{end}}{{if can "view"}}<a href="/admin/manual" class="{{if eq .Active "manual"}}active{{end}}">Ручной ввод M2M</a>{{end}}{{if and .DevMode (can "operate")}}<a href="/admin/m2m-testing" class="{{if eq .Active "m2mtest"}}active{{end}}">Тестирование M2M</a>{{end}}
|
||||
{{end}}{{if can "view"}}<a href="/admin/manual" class="{{if eq .Active "manual"}}active{{end}}">Ручной ввод M2M</a>{{end}}{{if and devOn (can "operate")}}<a href="/admin/m2m-testing" class="{{if eq .Active "m2mtest"}}active{{end}}">Тестирование M2M</a>{{end}}
|
||||
{{if and .NPR (can "npr")}}<a href="/admin/npr" class="{{if eq .Active "npr"}}active{{end}}">НПР / УДС</a>{{end}}
|
||||
{{if or (can "view") (can "quik")}}<span class="dd{{if or (eq .Active "fancy") (eq .Active "quik") (eq .Active "news") (eq .Active "handbook")}} active{{end}}">
|
||||
<span class="ddbtn">Обмен ▾</span>
|
||||
@@ -306,16 +312,25 @@ label { font-size:13px; font-weight:500; }
|
||||
<div class="topbar-right">
|
||||
{{with curUser}}<span class="user-chip" title="{{.RoleTitle}}{{if eq .Source "ad"}} · вход через AD{{end}}"><span class="user-name">{{if .Name}}{{.Name}}{{else}}{{.Login}}{{end}}</span><span class="user-role">{{.RoleTitle}}</span></span><a class="user-logout" href="/logout" title="Выйти">Выйти</a>{{else}}{{if authOpen}}<a class="user-logout" href="/admin/setup#users" title="Пользователи не созданы — вход открыт">без входа</a>{{end}}{{end}}
|
||||
<span class="sys-status {{if .IsMockMode}}warn{{end}}" title="Состояние обмена с НРД">
|
||||
<span class="pulse"></span>{{if .IsMockMode}}{{if .DevMode}}Эмуляция{{else}}Нет связи с НРД{{end}}{{else}}НРД на связи{{end}}</span>
|
||||
<span class="pulse"></span>{{if .IsMockMode}}{{if devOn}}Эмуляция{{else}}Нет связи с НРД{{end}}{{else}}НРД на связи{{end}}</span>
|
||||
<span class="clock">{{.Now}}</span>
|
||||
<button class="theme-toggle" id="theme-toggle" title="Светлая/тёмная тема" aria-label="Переключить тему"></button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{{if devLicensed}}
|
||||
<form method="post" action="/admin/dev-toggle" class="banner-dev {{if devOn}}on{{else}}off{{end}}" title="{{if devOn}}Нажмите, чтобы скрыть у себя служебные разделы и имитации{{else}}Нажмите, чтобы снова показать служебные разделы{{end}}">
|
||||
<input type="hidden" name="return_to" value="">
|
||||
<button type="submit"><span class="dot {{if devOn}}warn{{else}}ok{{end}}" style="width:9px;height:9px;margin:0"></span>
|
||||
{{if devOn}}<strong>Режим разработки включён</strong><span class="muted"> — видны служебные разделы, тестовые сценарии и имитации. Нажмите, чтобы выключить у себя.</span>{{else}}<strong>Режим разработки выключен у вас</strong><span class="muted"> — лицензия его разрешает; нажмите, чтобы включить.</span>{{end}}
|
||||
</button>
|
||||
</form>
|
||||
<script>(function(){var f=document.querySelector('.banner-dev input[name=return_to]');if(f)f.value=location.pathname+location.search;})();</script>
|
||||
{{end}}
|
||||
{{if .IsMockMode}}
|
||||
<div class="banner-mock">
|
||||
<span class="dot warn" style="width:9px;height:9px;margin:0"></span>
|
||||
<div><strong style="color:var(--warn)">{{if .DevMode}}Режим эмуляции{{else}}Обмен с НРД не настроен{{end}}</strong> — {{if .DevMode}}реального обмена с НРД нет{{else}}поручения в НРД не отправляются{{end}}. <span class="muted">{{.MockReason}}</span></div>
|
||||
<div><strong style="color:var(--warn)">{{if devOn}}Режим эмуляции{{else}}Обмен с НРД не настроен{{end}}</strong> — {{if devOn}}реального обмена с НРД нет{{else}}поручения в НРД не отправляются{{end}}. <span class="muted">{{.MockReason}}</span></div>
|
||||
<a href="/admin/wizard" style="margin-left:auto">Открыть мастер настройки →</a>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
Reference in New Issue
Block a user