feat(admin): эмулятор МНП — режим реальной записи в МНП на подставного клиента
Третий режим МНП (между «внутренняя имитация» и «боевая запись»): в bj цикл идёт по обычному пользователю, а поручение в QUIK МНП уходит РЕАЛЬНО, но с кодом другого, реально существующего в QUIK клиента (обобщение ручного теста realtest «боевой ЛК → TEST3»). - QuikMNPSettings: RealWrite + RealClientCode (валидация формата кода). - Подмена кода — единая точка quikClientCodeFromPort (после ClientCodeMap); портфель не трогаем. quikActive: RealWrite только при devMode и непустом коде; Emulate (внутренняя имитация) в приоритете. - Шаги боевого пути помечаются «[на подставного клиента <код>]» — видно в «Поручениях QUIK». - Карточка МНП на /admin/emulators — три взаимоисключающих режима (выключено / имитация / реальная запись), поле кода, крупное предупреждение; отдельный красный баннер «Реальные поручения в МНП на клиента <код> (режим разработки)» — не смешиваем с баннером эмуляции НРД. - disableEmulatorsIfDevOff сбрасывает и RealWrite (код остаётся, инертен), новость явно фиксирует прекращение реальных поручений.
This commit is contained in:
@@ -52,39 +52,55 @@
|
||||
|
||||
{{/* ===== Эмулятор МНП 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>
|
||||
<h2><span class="dot {{if ne .QuikMode "off"}}warn{{else}}ok{{end}}"></span>Эмулятор МНП QUIK
|
||||
{{if eq .QuikMode "emulate"}}<span class="hero-status warn">имитация</span>{{end}}
|
||||
{{if eq .QuikMode "real"}}<span class="hero-status warn">запись на подставного</span>{{end}}</h2>
|
||||
<p class="muted">Режим цикла M2M в Модуле неторговых поручений на время разработки.
|
||||
Имитация имеет приоритет над «записями в МНП»; оба dev-режима сбрасываются автоматически, когда режим разработки заканчивается.</p>
|
||||
{{if eq .QuikMode "real"}}
|
||||
<p class="dq-warn" style="font-weight:700">ВНИМАНИЕ: в боевую МНП будут записываться РЕАЛЬНЫЕ поручения на клиента {{.QuikRealCode}}.</p>
|
||||
{{end}}
|
||||
<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 class="dq-tiles">
|
||||
<label class="dq-tile"><input type="radio" name="mode" value="off" {{if eq .QuikMode "off"}}checked{{end}}><span><b>Выключено</b><small>Шаги цикла выполняются в QUIK по-настоящему (при разрешённых записях в МНП) — как в боевой работе.</small></span></label>
|
||||
<label class="dq-tile"><input type="radio" name="mode" value="emulate" {{if eq .QuikMode "emulate"}}checked{{end}}><span><b>Внутренняя имитация</b><small>Шаги цикла (регистрация и блокировка, подпись, снятие, зачисление) проходят и отмечаются «имитация», в боевую базу МНП ничего не записывается.</small></span></label>
|
||||
<label class="dq-tile"><input type="radio" name="mode" value="real" {{if eq .QuikMode "real"}}checked{{end}}><span><b>Реальная запись на подставного клиента</b><small>Цикл идёт по обычному клиенту, но поручения в боевую МНП уходят РЕАЛЬНО — с кодом другого, реально существующего в QUIK клиента.</small></span></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 id="emu-quik-code" style="margin-top:10px;max-width:280px">
|
||||
<label>Код клиента в QUIK <span class="muted">(код реального клиента QUIK, напр. BR859 — поручения уйдут на него)</span>
|
||||
<input type="text" name="real_client_code" value="{{.QuikRealCode}}" spellcheck="false" class="dq-mono" style="width:100%"></label>
|
||||
</div>
|
||||
<p class="dq-warn" id="emu-quik-warn" style="font-weight:700" hidden>ВНИМАНИЕ: в боевую МНП будут записываться РЕАЛЬНЫЕ поручения на указанного клиента.</p>
|
||||
<div id="emu-quik-emu">
|
||||
<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>
|
||||
<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>
|
||||
</div>
|
||||
<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(){
|
||||
var f=document.getElementById('emu-quik-form'), st=document.getElementById('emu-quik-st'),
|
||||
code=document.getElementById('emu-quik-code'), warn=document.getElementById('emu-quik-warn'),
|
||||
emu=document.getElementById('emu-quik-emu');
|
||||
function sync(){ var m=f.mode.value; code.hidden=(m!=='real'); warn.hidden=(m!=='real'); emu.hidden=(m==='real'); }
|
||||
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>
|
||||
{{end}}
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
<a href="/admin/emulators" class="tile">
|
||||
<span class="ico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="14" rx="2"/><path d="M7 9h4M7 13h7"/></svg></span>
|
||||
<span class="t-title">Эмулятор МНП QUIK</span>
|
||||
<span class="t-sub">{{if .QuikEmuOn}}ВКЛЮЧЁН — в МНП ничего не пишется{{else}}выключен{{end}}</span>
|
||||
<span class="t-sub">{{if .QuikRealCode}}ЗАПИСЬ в МНП на {{.QuikRealCode}} (реальные поручения){{else if .QuikEmuOn}}ВКЛЮЧЁН — в МНП ничего не пишется{{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>
|
||||
</div>
|
||||
|
||||
@@ -605,6 +605,12 @@ button.dq-link, .dq-link { background:none !important; border:0 !important; padd
|
||||
{{if ne .Active "wizard"}}<a href="/admin/wizard" style="margin-left:auto">Открыть мастер настройки →</a>{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .MNPReal}}
|
||||
<div class="banner-mock" style="border-color:var(--err);background:var(--err-weak,rgba(200,40,40,.08))">
|
||||
<span class="dot err" style="width:9px;height:9px;margin:0"></span>
|
||||
<div><strong style="color:var(--err)">Реальные поручения в МНП на клиента {{.MNPReal}}</strong><span class="muted"> (режим разработки) — в боевую базу МНП пишутся настоящие поручения с подменой кода клиента. Управляется на странице <a href="/admin/emulators">«Эмуляторы»</a>, сбрасывается автоматически по окончании режима разработки.</span></div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<main>
|
||||
{{template "content" .}}
|
||||
|
||||
Reference in New Issue
Block a user