Files
Bridge-and-Join-s/internal/lkgateway/web/templates/admin_npr_client.html
T
zuevav da12a9ec1c feat(bj): модуль ЛК на PostgreSQL, обмен с DEPO, боевой ЛК с имитатором НРД, QUIK, НПР
- bj_exchange и «кран» Fancy убраны: данные модуля ЛК в PostgreSQL (схема lk)
- трансферные таблицы FTV_M2M: создание при установке, события, справочник участников
- сверка с DEPO: счёт, ФИО, дата рождения, ИИС по договору, квал-инвестор из опции DEPO
- боевой ЛК ЕСИА Финанс при тестовом ИШ: журнал, отказ через DEPO, статусы в ЛК
- онлайн-лицензирование в bj, план тестирования M2M для контрагента (интерактивный HTML)
- модули QUIK МНП, экспорт QUIK, НПР/УДС; документы и тестовые материалы

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 19:41:12 +03:00

48 lines
5.8 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"}}
{{template "npr_css"}}
<p style="margin:0 0 12px;display:flex;align-items:center;gap:12px"><a href="/admin/npr" class="btn">← К списку клиентов</a>{{if not .Custom}}<span class="muted" id="autoupd" style="margin-left:auto">⟳ Страница обновится автоматически через 60 сек</span>{{end}}</p>
{{if not .Custom}}<script>(function(){let left=60;const el=document.getElementById('autoupd');const t=setInterval(function(){left-=1;if(el)el.textContent='⟳ Обновление через '+left+' сек';if(left<=0){clearInterval(t);location.reload();}},1000);})();</script>{{end}}
<div class="card">
<div style="display:flex;align-items:baseline;gap:12px;flex-wrap:wrap"><h2 style="margin:0">Клиент <code style="font-size:1.1em">{{.C.ClientCode}}</code></h2><span class="muted">Тип: <strong>{{if .C.MarginType}}{{.C.MarginType}}{{else}}—{{end}}</strong> · Данные на {{.C.TS.Local.Format "02.01.2006 15:04:05"}}</span></div>
<section class="nmetrics">
<article class="{{if or (eq .C.UDSFlag "CALL") (and .C.UDS (lt (deref .C.UDS) 1.0))}}m-call{{else if eq .C.UDSFlag "INF"}}m-ok{{end}}"><header>Уровень достаточности средств (УДС)</header><strong>{{if .C.UDS}}{{nprF .C.UDS}}{{else if eq .C.UDSFlag "INF"}}∞{{else if eq .C.UDSFlag "CALL"}}маржин-колл{{else}}—{{end}}</strong>{{if .C.BadgeClass}}<div style="margin-top:4px"><span class="badge {{.C.BadgeClass}}">{{.C.BadgeText}}</span></div>{{end}}</article>
<article><header>НПР1 (запас до начальной маржи)</header><strong>{{nprF .C.RCV1}}</strong></article>
<article><header>НПР2 (запас до минимальной маржи)</header><strong>{{nprF .C.RCV2}}</strong></article>
<article><header>Стоимость портфеля</header><strong>{{nprF .C.PortfolioValue}}</strong></article>
<article><header>Маржинальное требование</header><strong>{{nprF .C.MarginReq}}</strong></article>
</section>
<section style="display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin:12px 0">
<div class="nmini"><header>Начальная маржа</header><strong>{{nprF .C.InitMargin}}</strong></div>
<div class="nmini"><header>Минимальная маржа</header><strong>{{nprF .C.MinMargin}}</strong></div>
<div class="nmini"><header>Скорректированная маржа</header><strong>{{nprF .C.CorrMargin}}</strong></div>
</section>
</div>
<div class="card">
<h3 style="margin:0 0 8px">История изменений</h3>
<div style="display:flex;gap:6px;align-items:center;flex-wrap:wrap;margin-bottom:8px">{{range .Periods}}<a class="btn{{if and (eq $.Hours .H) (not $.Custom)}} btn-ok{{end}}" href="?hours={{.H}}">{{.T}}</a>{{end}}<span class="muted" style="margin-left:auto">или свой диапазон (МСК):</span></div>
<form method="get" action="" style="display:flex;gap:8px;align-items:end;flex-wrap:wrap;margin-bottom:8px">
<label style="margin:0;font-size:12px">С<br><input type="datetime-local" name="dt_from" value="{{.DtFrom}}"></label>
<label style="margin:0;font-size:12px">По<br><input type="datetime-local" name="dt_to" value="{{.DtTo}}"></label>
<button type="submit" class="btn">Показать</button><a class="btn" href="?hours=24">Сбросить</a>
<a class="btn" style="margin-left:auto" href="/admin/npr/c/{{.C.ClientCode}}/export.csv?{{if .Custom}}dt_from={{.DtFrom}}&dt_to={{.DtTo}}{{else}}hours={{.Hours}}{{end}}">⤓ Скачать CSV (для регулятора)</a>
</form>
<p class="muted">Показано: с <strong>{{.TF.Local.Format "02.01.2006 15:04"}}</strong> по <strong>{{.TT.Local.Format "02.01.2006 15:04"}}</strong> (МСК).</p>
<canvas id="chart" style="max-height:340px;margin-bottom:14px"></canvas>
<h4 style="margin:0 0 6px">Последние {{len .History}} записей</h4>
<table class="ntable"><thead><tr><th>Время</th><th class="num">УДС</th><th>Статус</th><th class="num">НПР1</th><th class="num">НПР2</th><th class="num">Марж. требование</th></tr></thead>
<tbody>{{range .History}}<tr class="{{.Class}}"><td><small>{{.TS.Local.Format "02.01.2006 15:04:05"}}</small></td><td class="num">{{nprF .UDS}}</td><td>{{if .BadgeClass}}<span class="badge {{.BadgeClass}}">{{.BadgeText}}</span>{{else}}—{{end}}</td><td class="num">{{nprF .RCV1}}</td><td class="num">{{nprF .RCV2}}</td><td class="num">{{nprF .MarginReq}}</td></tr>{{end}}</tbody></table>
</div>
<script src="/admin/npr/static/chart.umd.min.js"></script>
<script>
fetch("/admin/npr/c/{{.C.ClientCode}}/series?{{if .Custom}}dt_from={{.DtFrom}}&dt_to={{.DtTo}}{{else}}hours={{.Hours}}{{end}}").then(r=>r.json()).then(d=>{
const labels=d.labels.map(s=>new Date(s).toLocaleString('ru-RU',{day:'2-digit',month:'2-digit',hour:'2-digit',minute:'2-digit'}));
new Chart(document.getElementById('chart'),{type:'line',data:{labels:labels,datasets:[
{label:'НПР1',data:d.rcv1,borderColor:'#059669',backgroundColor:'#05966920',tension:.2,spanGaps:true,yAxisID:'y',pointRadius:1.5},
{label:'НПР2',data:d.rcv2,borderColor:'#2563eb',backgroundColor:'#2563eb20',tension:.2,spanGaps:true,yAxisID:'y',pointRadius:1.5},
{label:'УДС',data:d.uds,borderColor:'#dc2626',backgroundColor:'#dc262620',tension:.2,spanGaps:true,yAxisID:'y2',pointRadius:1.5,borderDash:[5,3]}]},
options:{animation:false,responsive:true,maintainAspectRatio:false,interaction:{mode:'index',intersect:false},plugins:{legend:{position:'top'},tooltip:{callbacks:{label:c=>c.dataset.label+': '+(c.parsed.y===null?'—':c.parsed.y.toLocaleString('ru-RU',{maximumFractionDigits:2}))}}},
scales:{y:{position:'left',title:{display:true,text:'НПР'}},y2:{position:'right',title:{display:true,text:'УДС'},grid:{drawOnChartArea:false},suggestedMin:-1,suggestedMax:3}}}});
});
</script>
{{end}}