fd238c1078
В режиме разработки новая страница /admin/emulators с двумя клавишами: - «Эмулятор НРД» (флаг LK.EmulateNSD): заявки ЛК и ручного ввода идут через внутренний имитатор, в НРД ничего не отправляется. Настройки: задержка решения (0–300 с), исход (подтвердить/отклонить/не отвечать), код отказа M2M01–M2M09/18. Сендер перенастраивается в рантайме через потокобезопасный mock.Sender.Reconfigure — без перезапуска. - «Эмулятор МНП QUIK» (флаг QuikMNP.Emulate): шаги цикла без записи в боевую БД МНП. Настройки: задержка шага (0–60 с), точечные отказы по шагам (регистрация/подпись/отказ/зачисление) — эмулированный отказ ведёт себя как боевой: шаг OK=false, состояние не продвигается, повтор на следующем проходе. Настройки хранятся в setup.json (nsd_emu/mnp_emu), обратная совместимость — дефолты. Баннер «Режим эмуляции» показывается и при ручном включении эмуляторов (раньше зависел только от отсутствия ИШ). Пункт меню «Эмуляторы» и две плитки на дашборде — только в dev. Пути занесены в devOnlyPath. Попутно: исправлен race в TestLicenseActivateAndRenew (cleanup восстанавливал DefaultLicensePublicKey без moduleEnforceMu — падал под -race и на чистом HEAD).
91 lines
7.5 KiB
HTML
91 lines
7.5 KiB
HTML
{{define "content"}}
|
|
{{if .Flash}}<div class="card" style="background:var(--accent-weak,#e7f0fb)">{{.Flash}}</div>{{end}}
|
|
|
|
<div class="card">
|
|
<h2>Эмуляторы</h2>
|
|
<p class="muted" style="margin:0">Служебные переключатели режима разработки: оба эмулятора работают только пока действует режим разработки.
|
|
Эти же флаги доступны в «Настройке» (ЛК — «Имитация НРД», QUIK — «имитация») — состояние общее.</p>
|
|
</div>
|
|
|
|
{{/* ===== Эмулятор НРД ===== */}}
|
|
<div class="card" id="emu-nsd-card">
|
|
<h2><span class="dot {{if .NSDEmuOn}}warn{{else}}ok{{end}}"></span>Эмулятор НРД
|
|
{{if .NSDEmuOn}}<span class="hero-status warn">включён</span>{{end}}</h2>
|
|
<p class="muted">Заявки из личного кабинета и ручного ввода проходят весь путь (сверка с DEPO, блокировка в QUIK, сделка, статусы),
|
|
но <b>в НРД ничего не отправляется</b>: ответ контрагента формирует внутренний имитатор.</p>
|
|
{{if and .NSDEmuOn (ne .NSDEmuWhy "включена в настройках")}}
|
|
<p class="dq-warn">Сейчас имитация действует принудительно: {{.NSDEmuWhy}} — переключатель её не выключает.</p>
|
|
{{end}}
|
|
<form method="post" action="/admin/emulators/nsd" id="emu-nsd-form" class="dq">
|
|
<label style="display:flex;gap:8px;align-items:center;font-weight:600">
|
|
<input type="checkbox" name="emulate" value="1" {{if .NSDFlag}}checked{{end}}>
|
|
Эмулировать НРД (заявки в настоящий НРД не уходят)</label>
|
|
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:10px;margin-top:10px">
|
|
<label>Задержка решения, сек <span class="muted">(0..300)</span>
|
|
<input type="number" name="delay_sec" min="0" max="300" value="{{.NSD.DelaySec}}" style="width:100%"></label>
|
|
<label>Исход по заявке
|
|
<select name="outcome" style="width:100%">
|
|
<option value="confirm" {{if eq .NSD.Outcome "confirm"}}selected{{end}}>Подтвердить перевод</option>
|
|
<option value="reject" {{if eq .NSD.Outcome "reject"}}selected{{end}}>Отклонить (код ниже)</option>
|
|
<option value="timeout" {{if eq .NSD.Outcome "timeout"}}selected{{end}}>Не отвечать (таймаут)</option>
|
|
</select></label>
|
|
<label id="emu-nsd-code">Код отказа
|
|
<select name="reject_code" style="width:100%">
|
|
{{range .RejectCodes}}<option value="{{.Code}}" {{if eq $.NSD.RejectCode .Code}}selected{{end}}>{{.Label}}</option>{{end}}
|
|
</select></label>
|
|
</div>
|
|
<p class="dq-note" id="emu-nsd-st" aria-live="polite">Изменения сохраняются сразу.</p>
|
|
<noscript><button type="submit" class="btn">Сохранить</button></noscript>
|
|
</form>
|
|
</div>
|
|
<script>(function(){
|
|
var f=document.getElementById('emu-nsd-form'), st=document.getElementById('emu-nsd-st'), code=document.getElementById('emu-nsd-code');
|
|
function sync(){ code.style.opacity=(f.outcome.value==='reject')?'1':'.45'; }
|
|
f.addEventListener('change', function(){ sync();
|
|
fetch(f.action,{method:'POST',body:new URLSearchParams(new FormData(f)),headers:{'Content-Type':'application/x-www-form-urlencoded','X-BJ-Ajax':'1'},cache:'no-store'})
|
|
.then(function(r){ return r.text().then(function(t){ st.textContent=(r.ok?'✓ Сохранено: ':'✗ ')+t; }); })
|
|
.catch(function(){ st.textContent='✗ Не сохранилось — обновите страницу и выберите ещё раз.'; });
|
|
});
|
|
f.addEventListener('submit', function(e){ if(window.fetch) e.preventDefault(); });
|
|
sync();
|
|
})();</script>
|
|
|
|
{{/* ===== Эмулятор МНП QUIK ===== */}}
|
|
<div class="card" id="emu-quik-card">
|
|
<h2><span class="dot {{if .QuikEmuOn}}warn{{else}}ok{{end}}"></span>Эмулятор МНП QUIK
|
|
{{if .QuikEmuOn}}<span class="hero-status warn">включён</span>{{end}}</h2>
|
|
<p class="muted">Шаги цикла M2M в Модуле неторговых поручений (регистрация вывода и блокировка бумаг, подпись, снятие поручения,
|
|
зачисление входящих) проходят и отмечаются «имитация», но <b>в боевую базу МНП ничего не записывается</b>.
|
|
Имитация имеет приоритет над «записями в МНП».</p>
|
|
<form method="post" action="/admin/emulators/quik" id="emu-quik-form" class="dq">
|
|
<label style="display:flex;gap:8px;align-items:center;font-weight:600">
|
|
<input type="checkbox" name="emulate" value="1" {{if .QuikEmuOn}}checked{{end}}>
|
|
Эмулировать МНП (в QUIK ничего не пишется)</label>
|
|
<div style="margin-top:10px;max-width:280px">
|
|
<label>Задержка шага, сек <span class="muted">(0..60, повторяет ожидание ответа МНП)</span>
|
|
<input type="number" name="step_delay_sec" min="0" max="60" value="{{.MNP.StepDelaySec}}" style="width:100%"></label>
|
|
</div>
|
|
<fieldset style="border:1px solid var(--border);border-radius:8px;margin-top:10px;padding:8px 12px">
|
|
<legend class="muted" style="font-size:12px">Имитировать отказ МНП на шаге (состояние не продвигается, повтор — как при боевом отказе)</legend>
|
|
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:6px">
|
|
<label style="display:flex;gap:8px;align-items:center"><input type="checkbox" name="fail_register" value="1" {{if .MNP.FailRegister}}checked{{end}}> Регистрация (вывод)</label>
|
|
<label style="display:flex;gap:8px;align-items:center"><input type="checkbox" name="fail_sign" value="1" {{if .MNP.FailSign}}checked{{end}}> Подпись (исполнение)</label>
|
|
<label style="display:flex;gap:8px;align-items:center"><input type="checkbox" name="fail_deny" value="1" {{if .MNP.FailDeny}}checked{{end}}> Снятие поручения</label>
|
|
<label style="display:flex;gap:8px;align-items:center"><input type="checkbox" name="fail_deposit" value="1" {{if .MNP.FailDeposit}}checked{{end}}> Зачисление (ввод)</label>
|
|
</div>
|
|
</fieldset>
|
|
<p class="dq-note" id="emu-quik-st" aria-live="polite">Изменения сохраняются сразу.</p>
|
|
<noscript><button type="submit" class="btn">Сохранить</button></noscript>
|
|
</form>
|
|
</div>
|
|
<script>(function(){
|
|
var f=document.getElementById('emu-quik-form'), st=document.getElementById('emu-quik-st');
|
|
f.addEventListener('change', function(){
|
|
fetch(f.action,{method:'POST',body:new URLSearchParams(new FormData(f)),headers:{'Content-Type':'application/x-www-form-urlencoded','X-BJ-Ajax':'1'},cache:'no-store'})
|
|
.then(function(r){ return r.text().then(function(t){ st.textContent=(r.ok?'✓ Сохранено: ':'✗ ')+t; }); })
|
|
.catch(function(){ st.textContent='✗ Не сохранилось — обновите страницу и выберите ещё раз.'; });
|
|
});
|
|
f.addEventListener('submit', function(e){ if(window.fetch) e.preventDefault(); });
|
|
})();</script>
|
|
{{end}}
|