Files
Bridge-and-Join-s/internal/lkgateway/web/templates/admin_incoming_detail.html
T
fontvielle 3a3bfa82af Интерфейс: без служебных пометок у оператора — «(TEST3)» в подаче 16/1, стенд разработки в справке API ЛК, «для теста»
Проверка шаблонов (23.10.2026): кнопок и форм режима разработки вне devOn нет; убраны тексты:
- подтверждение подачи 16/1 — без «(TEST3)» (контур выбирается в настройках);
- справка API ЛК — адрес <адрес bj> вместо стенда 10.10.10.22, путь к спецификации в репозитории — только в режиме разработки;
- предупреждение «боевой ЛК при тестовом контуре» — про тест «боевой ЛК → тестовый НРД» только в режиме разработки;
- «Залить одному клиенту» — без «(для теста)».

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
2026-10-23 16:08:06 +03:00

414 lines
33 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{{define "content"}}
{{$answered := eq .It.Status "answered"}}
<style>
.in-tl{position:fixed;right:18px;top:84px;width:230px;max-height:84vh;overflow:auto;
background:var(--card,#fff);border:1px solid var(--border,#e3e3e8);border-radius:14px;
padding:14px 16px;box-shadow:var(--shadow-lg,0 8px 30px rgba(0,0,0,.10));z-index:40}
.in-tl h3{margin:0 0 12px;font-size:13px}
.in-tl .st{position:relative;padding:0 0 12px 20px}
.in-tl .st::before{content:'';position:absolute;left:3px;top:3px;width:10px;height:10px;border-radius:50%;
background:var(--c,#2563eb);box-shadow:0 0 0 3px color-mix(in srgb, var(--c,#2563eb) 20%, transparent)}
.in-tl .st::after{content:'';position:absolute;left:7px;top:15px;bottom:0;width:2px;background:var(--border,#e3e3e8)}
.in-tl .st:last-child::after{display:none}
.in-tl .tm{font-size:10.5px;color:var(--muted,#888);font-variant-numeric:tabular-nums}
.in-tl .ti{font-size:12.5px;font-weight:600;margin:1px 0;line-height:1.3}
.in-tl .de{font-size:10.5px;color:var(--muted,#888);line-height:1.4}
.st-req{--c:#2563eb}.st-gw{--c:#7c3aed}.st-resp{--c:#0891b2}.st-rej{--c:#dc2626}.st-ord{--c:#16a34a}.st-nrd{--c:#0891b2}
@media (max-width:1500px){.in-tl{position:static;width:auto;max-height:none;margin-top:16px;box-shadow:none}}
</style>
<p style="margin:0 0 12px"><a href="/admin/incoming" class="btn" onclick="if(history.length>1){history.back();return false}">← Назад</a></p>
<div class="card">
<h2>Входящий перевод <code>{{short 8 .It.GUID}}</code>
{{if $answered}}<span class="badge confirmed">отвечено</span>{{else}}<span class="badge awaiting_decision">ждёт решения</span>{{end}}
</h2>
{{$l := liveIn .It}}<div class="live live-big live-{{$l.Kind}}" data-live="in:{{.It.ID}}" data-sig="{{$l.Sig}}"{{if $l.Active}} data-active="1"{{else}} title="Завершено: состояние больше не проверяется"{{end}}>{{$l.Text}}</div>
<table>
<tr><td style="width:220px" class="muted">Запрос сформирован (отправитель)</td><td>{{msk .It.RequestCreated}}</td></tr>
<tr><td class="muted">Забрали из шлюза (получено нами)</td><td>{{msk .It.ReceivedAt}}{{if not .It.RequestCreated.IsZero}} <span class="muted" style="font-size:12px">· прохождение: {{transit .It.RequestCreated .It.ReceivedAt}}</span>{{end}}</td></tr>
{{if $answered}}<tr><td class="muted">Ответ отправлен</td><td>{{msk .It.AnsweredAt}}{{if not .It.ReceivedAt.IsZero}} <span class="muted" style="font-size:12px">· обработка: {{transit .It.ReceivedAt .It.AnsweredAt}}</span>{{end}}</td></tr>{{end}}
<tr><td class="muted">GUID перевода</td><td><code>{{.It.GUID}}</code> <span class="muted">(в нашем решении используется этот же GUID)</span></td></tr>
<tr><td class="muted">От кого (передающий)</td><td>{{$nm := m2mParty .It.SenderCode}}{{if not $nm}}{{$nm = m2mParty .It.SenderINN}}{{end}}{{if $nm}}<strong>{{$nm}}</strong> · {{end}}<code>{{.It.SenderCode}}</code>{{if .It.SenderINN}} · ИНН {{.It.SenderINN}}{{end}}</td></tr>
<tr><td class="muted">Кому (мы)</td><td>{{$rn := m2mParty .It.ReceiverCode}}{{if not $rn}}{{$rn = m2mParty .It.ReceivingINN}}{{end}}{{if $rn}}<strong>{{$rn}}</strong> · {{end}}<code>{{.It.ReceiverCode}}</code>{{if .It.ReceivingINN}} · ИНН {{.It.ReceivingINN}}{{end}}</td></tr>
<tr><td class="muted">Инвестор (ФИО)</td><td><strong>{{.It.InvestorLast}} {{.It.InvestorFirst}} {{.It.InvestorMiddle}}</strong></td></tr>
<tr><td class="muted">Документ</td><td>{{docType .It.DocType}}{{if .It.DocSeries}} · серия {{.It.DocSeries}}{{end}}{{if .It.DocNumber}} · № {{.It.DocNumber}}{{end}}</td></tr>
{{if .It.AnswerNote}}<tr><td class="muted">Результат</td><td>{{if .It.Auto}}<span class="badge confirmed">авто</span> {{end}}{{.It.AnswerNote}}</td></tr>{{end}}
</table>
</div>
<div class="card">
<style>
.dc-tbl td{vertical-align:top}
.dc-ok{color:var(--ok,#12813f);font-weight:700}.dc-bad{color:var(--err,#b3261e);font-weight:700}
.dc-rec{display:inline-block;padding:4px 12px;border-radius:999px;font-weight:700;font-size:13px}
.dc-rec.confirm{background:var(--ok-weak,#e6f4ea);color:var(--ok,#12813f)}
.dc-rec.reject{background:var(--err-weak,#fbe9e7);color:var(--err,#b3261e)}
.dc-rec.mixed,.dc-rec.partial{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 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>
{{if not .Depo.Ran}}
<p class="muted" style="margin-top:10px">Сверка не выполнена: {{.Depo.Err}}</p>
{{else}}
<table style="margin-top:10px">
<tr><td class="muted" style="width:220px">Инвестор в картотеке</td><td>{{if .Depo.Investor}}<b>{{.Depo.Investor}}</b>{{else}}<span class="dc-bad">не найден</span>{{end}}</td></tr>
<tr><td class="muted">Торговый счёт депо</td><td>{{if .Depo.Account}}<code>{{.Depo.Account}}</code> — открыт{{else}}<span class="dc-bad">открытого торгового счёта нет</span>{{end}}</td></tr>
</table>
{{range .Depo.Secs}}
<span class="depo-rec" data-ref="{{.ReferenceID}}" data-rec="{{.Recommend}}" data-code="{{.RejectCode}}" hidden></span>
<h3 style="font-size:13.5px;margin:14px 0 4px"><code>{{.Security}}</code> → {{if eq .Recommend "confirm"}}<span class="dc-ok">принять</span>{{else}}<span class="dc-bad">отказ {{.RejectCode}}</span> <span class="muted" style="font-weight:400">({{m2mCode .RejectCode}})</span>{{end}}</h3>
<table class="dc-tbl">
<thead><tr><th style="width:36px"></th><th style="width:250px">Проверка</th><th>Результат</th></tr></thead>
<tbody>
{{range .Checks}}
<tr><td>{{if .OK}}<span class="dc-ok">🟢</span>{{else}}<span class="dc-bad">🔴</span>{{end}}</td><td>{{.Name}}{{if not .OK}} <span class="muted" style="font-size:11px">→ {{.Code}}</span>{{end}}</td><td style="font-size:12.5px">{{.Detail}}</td></tr>
{{end}}
</tbody>
</table>
{{end}}
{{end}}
</div>
<div class="card">
<h2>Решение по бумагам ({{len .It.Securities}})</h2>
{{if $answered}}
<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>
{{range .It.Securities}}
<tr>
<td><code>{{.ReferenceID}}</code></td>
<td><code>{{.SecurityCode}}</code>{{if .ISIN}} / {{.ISIN}}{{end}}</td>
<td>{{.Quantity}}</td>
<td style="font-size:12px">{{if .DeponentCode}}депонент <code>{{.DeponentCode}}</code>{{end}}{{if .AccountID}}<br>счёт <code>{{.AccountID}}</code>{{end}}{{if .SectionID}} / раздел <code>{{.SectionID}}</code>{{end}}{{if .SettleINN}}<br>расч.деп. ИНН {{.SettleINN}}{{end}}</td>
<td>{{if eq .Decision "confirmed"}}<span class="badge confirmed">принято</span>{{else if eq .Decision "rejected"}}<span class="badge rejected">отказ</span> <span class="muted" style="font-size:12px">{{m2mCode .RejectCode}}</span>{{else}}—{{end}}</td>
</tr>
{{end}}
</tbody>
</table>
{{else}}
<p class="muted">По каждой бумаге выберите: <b>принять</b> (зачислим на наш депо-счёт из настроек НРД) или <b>отказать</b> (с кодом отказа). Решение уйдёт {{if devOn}}роботу{{else}}контрагенту через НРД{{end}} одним сообщением M2MTransferDecision.</p>
{{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)">
<option value="">— выберите кейс —</option>
</select>
</label>
<div id="m2m-guide" style="margin-top:8px;font-size:13px;color:var(--text)">Выберите кейс — подскажу, что нужно сделать (принять или отклонить с кодом). Автоматически ничего не меняется.</div>
</div>
<script>
(function(){
var H = {{m2mHints}};
var sel = document.getElementById('m2m-scen'), g = document.getElementById('m2m-guide');
if(!sel||!Array.isArray(H)) return;
H.forEach(function(h){ var o=document.createElement('option'); o.value=h.id; o.textContent=h.title; sel.appendChild(o); });
sel.addEventListener('change', function(){
var h = null; for(var i=0;i<H.length;i++){ if(H[i].id===sel.value){h=H[i];break;} }
if(!h){ g.textContent='Выберите кейс — подскажу, что нужно сделать.'; return; }
var color = h.action==='confirm' ? '#1a7f37' : '#b3261e';
g.innerHTML = '<b style="color:'+color+'">Что делать: </b>'+h.text.replace(/</g,'&lt;');
});
})();
</script>
{{end}}
<form method="post" action="/admin/incoming/{{.It.ID}}/answer">
<table>
<thead><tr><th>ReferenceId</th><th>Код НРД / ISIN</th><th>Кол-во</th><th>Счёт зачисления</th><th>Принять</th><th>Отказать</th><th>Код отказа</th></tr></thead>
<tbody>
{{range .It.Securities}}
<tr>
<td><code>{{.ReferenceID}}</code></td>
<td><code>{{.SecurityCode}}</code>{{if .ISIN}} / {{.ISIN}}{{end}}</td>
<td>{{.Quantity}}</td>
<td style="font-size:12px">{{if .DeponentCode}}депонент <code>{{.DeponentCode}}</code>{{end}}{{if .AccountID}}<br>счёт <code>{{.AccountID}}</code>{{end}}{{if .SectionID}} / раздел <code>{{.SectionID}}</code>{{end}}{{if .SettleINN}}<br>расч.деп. ИНН {{.SettleINN}}{{end}}</td>
<td style="text-align:center"><input type="radio" class="dec" data-ref="{{.ReferenceID}}" name="decision_{{.ReferenceID}}" value="confirm" checked></td>
<td style="text-align:center"><input type="radio" class="dec" data-ref="{{.ReferenceID}}" name="decision_{{.ReferenceID}}" value="reject"></td>
<td>
<span class="reject-dash" data-ref="{{.ReferenceID}}" style="color:var(--muted)">—</span>
<span class="reject-box" data-ref="{{.ReferenceID}}" style="display:none">
<select name="reject_{{.ReferenceID}}" style="max-width:280px">
{{range rejectOptions}}<option value="{{.Code}}">{{.Label}}</option>{{end}}
</select>
</span>
</td>
</tr>
{{end}}
</tbody>
</table>
<p class="muted" style="font-size:12.5px;margin:10px 0 0">Решение по каждой бумаге отдельно: принятые бумаги НРД переведёт (по каждой придёт свой черновик 16/1), по остальным уйдёт отказ с выбранным кодом.{{if and $.It (isIIS $.It)}} <b>Перевод на ИИС — такие мы не принимаем: отказ M2M06 по всем бумагам будет отправлен в любом случае.</b>{{end}}</p>
<div style="display:flex;gap:8px;margin-top:14px;flex-wrap:wrap">
<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>
</form>
<script>
(function(){
function toggle(ref){
var rej = document.querySelector('input[name="decision_'+ref+'"][value="reject"]');
var box = document.querySelector('.reject-box[data-ref="'+ref+'"]');
var dash = document.querySelector('.reject-dash[data-ref="'+ref+'"]');
var show = rej && rej.checked;
if(box) box.style.display = show ? '' : 'none';
if(dash) dash.style.display = show ? 'none' : '';
}
document.querySelectorAll('input.dec').forEach(function(r){
r.addEventListener('change', function(){
toggle(r.getAttribute('data-ref'));
});
});
window.m2mSetAll = function(val){
document.querySelectorAll('input.dec[value="'+val+'"]').forEach(function(r){
r.checked = true; toggle(r.getAttribute('data-ref'));
});
};
})();
</script>
<script>
// Подставляем рекомендацию сверки с DEPO в форму: только предзаполнение,
// отправка — по кнопке оператора.
(function(){
var recs = document.querySelectorAll('.depo-rec');
if(!recs.length) return;
recs.forEach(function(el){
var ref = el.getAttribute('data-ref'), rec = el.getAttribute('data-rec'), code = el.getAttribute('data-code');
var r = document.querySelector('input[name="decision_'+ref+'"][value="'+rec+'"]');
if(r){ r.checked = true; r.dispatchEvent(new Event('change')); }
if(rec === 'reject' && code){
var sel = document.querySelector('select[name="reject_'+ref+'"]');
if(sel) sel.value = code;
}
});
})();
</script>
{{end}}
</div>
{{if .It.RawXML}}
<div class="card">
<details>
<summary style="cursor:pointer;font-weight:600">Данные запроса — поля и сырой XML</summary>
<p class="muted" style="font-size:12px;margin:6px 0">Слева — те же данные из XML, разобранные по полям для удобного просмотра; ниже — исходный XML дословно.</p>
{{xmlFields .It.RawXML}}
<div style="margin-top:12px;font-weight:600;font-size:13px">Сырой XML:</div>
<pre style="white-space:pre-wrap;word-break:break-all;background:var(--surface-2,#f5f5f7);padding:12px;border-radius:8px;font-size:12px;overflow:auto;max-height:340px;margin-top:4px">{{.It.RawXML}}</pre>
</details>
</div>
{{end}}
<div class="card">
<style>
.ord-steps{display:flex;gap:12px;margin:12px 0 14px;flex-wrap:wrap}
.ord-step{flex:1 1 190px;display:flex;gap:12px;align-items:flex-start;padding:14px 16px;border-radius:13px;border:2px solid var(--border);background:var(--card)}
.ord-step .dot{width:30px;height:30px;border-radius:50%;flex:none;display:flex;align-items:center;justify-content:center;font-size:15px;font-weight:800;background:var(--border);color:var(--muted)}
.ord-step .t{font-size:14px;font-weight:700;line-height:1.2}
.ord-step .s{font-size:11.5px;margin-top:3px;font-weight:600;color:var(--muted)}
.ord-step.done{border-color:#16a34a;background:color-mix(in srgb,#16a34a 13%,var(--card))}
.ord-step.done .dot{background:#16a34a;color:#fff}
.ord-step.done .s{color:#0f7a37}
.ord-step.wait{border-color:#f59e0b;background:color-mix(in srgb,#f59e0b 15%,var(--card))}
.ord-step.wait .dot{background:#f59e0b;color:#fff;box-shadow:0 0 0 4px color-mix(in srgb,#f59e0b 28%,transparent)}
.ord-step.wait .s{color:#b45309}
.ord-step.todo{opacity:.55}
.ord-step.bad{border-color:#dc2626;background:color-mix(in srgb,#dc2626 12%,var(--card))}
.ord-step.bad .dot{background:#dc2626;color:#fff}
.ord-step.bad .s{color:#b3261e}
.ord-dl.bad{border-color:#dc2626;color:#b3261e}
.ord-dl{display:inline-block;margin-top:9px;font-size:11.5px;font-weight:700;padding:4px 10px;border-radius:8px;background:var(--card);border:1px solid #16a34a;color:#0f7a37;text-decoration:none;white-space:nowrap}
.ord-dl:hover{background:color-mix(in srgb,#16a34a 12%,var(--card))}
</style>
{{if .Rejected}}
<div style="display:flex;align-items:center;gap:10px;flex-wrap:wrap">
<h2 style="margin:0">Депозитарное поручение 16/1</h2>
<span class="badge rejected">не требуется — перевод отклонён</span>
</div>
<div class="ord-steps">
<div class="ord-step bad">
<span class="dot">✕</span>
<div><div class="t">Операция завершена отказом</div>
<div class="s">Отказ {{.RejectCodes}}{{with .RejectCodes}} ({{m2mCode .}}){{end}} отправлен {{msk .It.AnsweredAt}}{{if .It.Auto}} автоматически{{end}}. Бумаги не зачисляются, поручение 16/1 не подаётся — со стороны депозитария действий не требуется.</div></div>
</div>
</div>
{{else}}
<div style="display:flex;align-items:center;gap:10px;flex-wrap:wrap">
<h2 style="margin:0">Депозитарное поручение 16/1</h2>
{{if .OrderDone}}<span class="badge confirmed">проведено · MS010</span>
{{else if .It.OrderSubmitted}}<span class="badge awaiting_decision">подано, ждём MS010</span>
{{else if not $answered}}<span class="badge" style="background:var(--card-2);color:var(--muted)">после решения по переводу</span>
{{else if .AutoMode}}<span class="badge awaiting_decision">подаст bj автоматически</span>
{{else}}<span class="badge" style="background:var(--card-2);color:var(--muted)">не подано</span>{{end}}
</div>
{{if .Watch}}<div style="margin:8px 0 0;padding:8px 12px;border-radius:9px;font-size:13px;font-weight:600;{{if eq .Watch.Kind "ok"}}background:color-mix(in srgb,#16a34a 12%,var(--card));color:#0f7a37{{else if eq .Watch.Kind "warn"}}background:color-mix(in srgb,#d97706 14%,var(--card));color:#9a6b12{{else if eq .Watch.Kind "bad"}}background:color-mix(in srgb,#dc2626 12%,var(--card));color:#b3261e{{else}}background:var(--card-2);color:var(--muted){{end}}">⏱ Срок по регламенту: {{.Watch.StatusRu}}</div>{{end}}
<div class="ord-steps">
<div class="ord-step {{if .DraftReceived}}done{{else if $answered}}wait{{else}}todo{{end}}">
<span class="dot">{{if .DraftReceived}}✓{{else}}1{{end}}</span>
<div><div class="t">Черновик получен</div><div class="s">{{if .DraftReceived}}{{.DraftReceived}}{{else if $answered}}ждём черновик MF010 от НРД{{else}}после нашего согласия{{end}}</div>
{{if .DraftReceived}}<a class="ord-dl" href="/admin/incoming/{{.It.ID}}/draft.zip">⬇ Черновик от НРД</a>{{end}}</div>
</div>
<div class="ord-step {{if .It.OrderSubmitted}}done{{else if .DraftReceived}}wait{{else}}todo{{end}}">
<span class="dot">{{if .It.OrderSubmitted}}✓{{else}}2{{end}}</span>
<div><div class="t">Поручение подано в НРД</div><div class="s">{{if .It.OrderSubmitted}}{{msk .It.OrderAt}}{{else if .AutoMode}}bj подаст автоматически по черновику{{else if .DraftReceived}}нужно подать{{else}}после черновика{{end}}</div>
{{if .It.OrderXML}}<a class="ord-dl" href="/admin/incoming/{{.It.ID}}/order.xml">⬇ Отправленная форма 16/1</a>{{end}}</div>
</div>
<div class="ord-step {{if and .OrderDone .OrderRejected}}bad{{else if .OrderDone}}done{{else if .It.OrderSubmitted}}wait{{else}}todo{{end}}">
<span class="dot">{{if and .OrderDone .OrderRejected}}✕{{else if .OrderDone}}✓{{else}}3{{end}}</span>
<div><div class="t">{{if and .OrderDone .OrderRejected}}Операция завершена отказом · MS010{{else}}Проведено · MS010{{end}}</div><div class="s">{{if and .OrderDone .OrderRejected}}НРД отказал в исполнении{{if .OrderDoneAt}} · {{.OrderDoneAt}}{{end}}{{else if .OrderDone}}{{if .OrderDoneAt}}{{.OrderDoneAt}}{{else}}отчёт получен от НРД{{end}}{{else if .It.OrderSubmitted}}ждём MS010 от НРД{{else}}после подачи{{end}}</div>
{{if .OrderResponses}}<a class="ord-dl" href="/admin/incoming/{{.It.ID}}/ms010.zip">⬇ Ответ НРД (MS010)</a>{{end}}</div>
</div>
</div>
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center">
{{if and (not .It.OrderSubmitted) .DraftReceived}}
<form method="post" action="/admin/incoming/{{.It.ID}}/submit-order" onsubmit="return confirm('Подать поручение 16/1 (тип ЭД ORDXM) в НРД?');">
<button type="submit" class="btn btn-ok">▶ Подать поручение 16/1 в НРД</button>
</form>
{{end}}
</div>
{{if .It.OrderSubmitted}}
<div class="muted" style="font-size:12px;margin-top:10px">Подано {{msk .It.OrderAt}} · пакет <code>{{.It.OrderPkgs}}</code>{{if .It.OrderContrDID}} · № поручения <code>{{.It.OrderContrDID}}</code>{{end}}</div>
{{if .OrderResponses}}
<table style="margin-top:8px">
<thead><tr><th style="width:150px">Время</th><th>Ответ НРД</th></tr></thead>
<tbody>
{{range .OrderResponses}}<tr><td style="white-space:nowrap">{{.Time}}</td><td{{if .Rejected}} style="color:#b3261e;font-weight:600"{{end}}>{{.Kind}}</td></tr>{{end}}
</tbody>
</table>
{{else}}
<p class="muted" style="font-size:12px;margin-top:8px">Ответ НРД (квитанция → принятие → отчёт MS010) появится здесь. Обновите страницу.</p>
{{end}}
{{if .It.OrderXML}}
<details style="margin-top:8px"><summary style="cursor:pointer;font-size:12px;color:var(--muted)">Посмотреть отправленный XML поручения</summary>
<pre style="white-space:pre-wrap;word-break:break-all;background:var(--card-2);padding:12px;border-radius:8px;font-size:12px;overflow:auto;max-height:300px;margin-top:6px">{{.It.OrderXML}}</pre>
</details>
{{end}}
{{end}}
<details style="margin-top:12px"><summary style="cursor:pointer;font-size:12px;color:var(--muted)">Как это работает</summary>
<p class="muted" style="font-size:12px;margin-top:6px">После нашего согласия на прием НРД формирует <b>черновик поручения 16/1</b> (MF010). Депозитарий подаёт его в НРД (тип ЭД <code>ORDXM</code>) — НРД сматчит со встречным поручением 16 контрагента, проведёт зачисление и выпустит отчёт <code>XMLRP</code> = <b>MS010</b>. Кнопка «Подать» отправляет черновик через шлюз НРД (подпись ставит шлюз); пока Fancy-DEPO не подключена, можно скачать черновик и обработать вручную.</p>
</details>
{{end}}
</div>
<p style="margin-top:16px">
<a href="/admin/incoming" class="muted">← Все входящие</a>
&nbsp;·&nbsp;
<a href="/admin/incoming/{{.It.ID}}/export.zip" class="btn">⬇ Выгрузка для регулятора (ZIP: отчёт + request.xml + decision.xml)</a>
</p>
<aside class="in-tl">
<h3>Путь сообщения</h3>
<div class="st st-req">
<div class="tm">{{msk .It.RequestCreated}}</div>
<div class="ti">Запрос сформирован</div>
<div class="de">отправитель (контрагент)</div>
</div>
<div class="st st-gw">
<div class="tm">{{msk .It.ReceivedAt}}</div>
<div class="ti">Получено нами</div>
<div class="de">забрали из шлюза НРД{{if not .It.RequestCreated.IsZero}} · прохождение {{transit .It.RequestCreated .It.ReceivedAt}}{{end}}</div>
</div>
{{if .DraftReceived}}
<div class="st st-gw">
<div class="tm">{{.DraftReceived}}</div>
<div class="ti">Черновик 16/1 получен</div>
<div class="de">НРД прислал MF010 в INBOX</div>
</div>
{{end}}
{{if $answered}}
<div class="st st-resp">
<div class="tm">{{msk .It.AnsweredAt}}</div>
<div class="ti">Ответ отправлен{{if .It.Auto}} (авто){{end}}</div>
<div class="de">M2MTransferDecision{{if not .It.ReceivedAt.IsZero}} · {{transit .It.ReceivedAt .It.AnsweredAt}}{{end}}</div>
</div>
{{end}}
{{if .It.OrderSubmitted}}
<div class="st st-ord">
<div class="tm">{{msk .It.OrderAt}}</div>
<div class="ti">Поручение 16/1 подано</div>
<div class="de">тип ORDXM · пакет {{.It.OrderPkgs}}</div>
</div>
{{end}}
{{range .OrderResponses}}
<div class="st st-nrd">
<div class="tm">{{.Time}}</div>
<div class="ti">Ответ НРД</div>
<div class="de"{{if .Rejected}} style="color:#b3261e;font-weight:600"{{end}}>{{.Kind}}</div>
</div>
{{end}}
</aside>
{{/* ===== QUIK МНП: зачисление клиенту ===== */}}
{{$back := printf "/admin/incoming/%s" .It.ID}}
{{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>
<form method="post" action="/admin/incoming/depo-sim" style="display:flex;gap:8px;flex-wrap:wrap;align-items:center" onsubmit="return confirm('Записать копию перевода в трансферные таблицы DEPO на клиента с этим паспортом?')">
<input type="hidden" name="id" value="{{.It.ID}}">
<label style="margin:0;font-size:12.5px">серия <input type="text" name="ser" value="" placeholder="0000" required style="width:70px"></label>
<label style="margin:0;font-size:12.5px">номер <input type="text" name="num" value="" placeholder="000000" required style="width:90px"></label>
<button type="submit" class="btn">🗂 Прогнать в DEPO с реальным клиентом</button>
<span class="muted" style="font-size:12px">паспорт клиента из картотеки DEPO</span>
</form>
</div>
{{end}}
<div class="card">
<style>
.qk-steps{display:flex;gap:8px;flex-wrap:wrap;margin:8px 0}
.qk-step{padding:6px 10px;border-radius:9px;border:1.5px solid var(--border);font-size:12.5px;background:var(--card-2)}
.qk-step.ok{border-color:color-mix(in srgb,#16a34a 45%,transparent);background:color-mix(in srgb,#16a34a 12%,var(--card));color:#0f7a37;font-weight:600}
.qk-step.bad{border-color:color-mix(in srgb,#dc2626 45%,transparent);background:color-mix(in srgb,#dc2626 10%,var(--card));color:#b3261e;font-weight:600}
.qk-state{display:inline-block;padding:3px 10px;border-radius:999px;font-size:12px;font-weight:700}
.qk-state.registered,.qk-state.wait_depo{background:color-mix(in srgb,#d97706 15%,var(--card));color:#9a6b12}
.qk-state.signed,.qk-state.deposited{background:color-mix(in srgb,#16a34a 15%,var(--card));color:#0f7a37}
.qk-state.denied{background:var(--card-2);color:var(--muted)}
.qk-state.error{background:color-mix(in srgb,#dc2626 15%,var(--card));color:#b3261e}
.qk-state.manual{background:color-mix(in srgb,#2563eb 12%,var(--card));color:#1d4ed8}
</style>
<div style="display:flex;align-items:center;gap:12px;flex-wrap:wrap">
<h2 style="margin:0">QUIK МНП — зачисление бумаг клиенту</h2>
<a href="/admin/quik" class="muted" style="font-size:12px">все поручения →</a>
</div>
{{if .DepoL}}<div style="margin:8px 0 0;padding:8px 12px;border-radius:9px;font-size:13px;{{if .DepoL.Errors}}background:color-mix(in srgb,#dc2626 12%,var(--card));color:#b3261e{{else}}background:var(--card-2){{end}}">🗂 DEPO (bj2depo): {{if .DepoL.DocNo}}поручение <b>№{{.DepoL.DocNo}}</b> создано {{msk .DepoL.DocAt}}{{if .DepoL.DocState}} · состояние в DEPO: <b>{{.DepoL.DocState}}</b>{{end}}{{else}}поручение ещё не создано{{end}}{{range .DepoL.Errors}}<div>ошибка: {{.}}</div>{{end}}{{if and .DepoL.FixedErr (not .DepoL.Errors)}}<div class="muted" style="font-size:12px">была ошибка: {{.DepoL.FixedErr}} — после возврата в очередь обработано {{msk .DepoL.FixedAt}}</div>{{end}}</div>{{end}}
{{if .Rejected}}
<p class="muted" style="font-size:12.5px;margin:10px 0 0">Зачисление в QUIK не требуется — перевод отклонён ({{.RejectCodes}}), бумаги клиенту не поступают.</p>
{{else}}
<p class="muted" style="font-size:12.5px;margin:6px 0 0">Когда НРД принимает наше поручение 16/1 (отчёт MS010), bj регистрирует в Модуле неторговых поручений «Ввод ЦБ (M2M)» по ISIN — оно исполняется сразу, бумаги появляются на позиции клиента в QUIK.{{if not .QuikOn}} <b>Записи в МНП сейчас выключены</b> (Настройка → QUIK МНП).{{end}}</p>
{{if not .Quik}}<div style="margin-top:8px;display:flex;gap:8px;flex-wrap:wrap;align-items:center"><span class="muted">Зачислений по этому переводу ещё нет.</span>
{{range .It.Securities}}{{if eq .Decision "confirmed"}}
<form method="post" action="/admin/quik/op" style="margin:0;display:inline"><input type="hidden" name="guid" value="{{$.It.GUID}}"><input type="hidden" name="isin" value="{{.ISIN}}"><input type="hidden" name="op" value="deposit"><input type="hidden" name="back" value="{{$back}}"><button class="btn" style="font-size:12px" onclick="return confirm('Зачислить {{.ISIN}} × {{.Quantity}} клиенту в QUIK? Исполняется сразу.')">⊕ Зачислить {{.ISIN}} × {{.Quantity}}</button></form>
{{end}}{{end}}</div>{{end}}
{{range .Quik}}
<div style="border:1px solid var(--border);border-radius:10px;padding:10px 12px;margin-top:10px">
<div style="display:flex;gap:10px;align-items:center;flex-wrap:wrap">
<b><code>{{.ISIN}}</code> × {{.Qty}}</b>
<span class="muted" style="font-size:12px">клиент QUIK <code>{{.ClientID}}</code>{{if .Contract}} · {{.Contract}}{{end}}{{if .InstrNo}} · поручение МНП <b>№{{.InstrNo}}</b>{{end}}</span>
<span class="qk-state {{.State}}">{{.StateRu}}</span>
</div>
{{if .Err}}<div style="{{if eq .State "wait_depo"}}color:var(--muted){{else}}color:#b3261e{{end}};font-size:12.5px;margin-top:4px">{{.Err}}</div>{{end}}
{{if .Steps}}<div class="qk-steps">{{range .Steps}}<span class="qk-step {{if .OK}}ok{{else}}bad{{end}}" title="{{.Reply}}">{{msk .At}} · {{.Action}}{{if .ActionID}} #{{.ActionID}}{{end}}: {{.Reply}}</span>{{end}}</div>{{end}}
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-top:6px">
{{if or (eq .State "error") (eq .State "manual") (not .InstrNo)}}
<form method="post" action="/admin/quik/op" style="margin:0;display:inline"><input type="hidden" name="guid" value="{{.GUID}}"><input type="hidden" name="isin" value="{{.ISIN}}"><input type="hidden" name="op" value="deposit"><input type="hidden" name="back" value="{{$back}}"><button class="btn btn-ok" style="font-size:12px" onclick="return confirm('Зачислить бумаги клиенту в QUIK («Ввод ЦБ (M2M)»)? Исполняется сразу.')">⊕ Зачислить в QUIK</button></form>
{{end}}
</div>
</div>
{{end}}
{{end}}
</div>
{{end}}