Files
Bridge-and-Join-s/modules/lk/templates.go
T
zuevav 02fabb483d Кабинет клиента: портфель как у брокера — «Онлайн» по QUIK, «Архив» на дату и операции по SPECTRE
- lkclient.go: договор → код QUIK (БР-1545 → BR1545, +OUT), договор → D_B_CONTRACTS SPECTRE
- lkonline.go: позиции DepoLimits (T2, свежая строка на счёт), средняя цена покупки, деньги
  MoneyLimits по валютам, цены и P&L; стоимость, доли
- lkarchive.go: портфель на дату по остаткам OD_RESTS (REG_3 = договор, раздел 39, счета
  50/51/52/55 и 58.01/58.02; 58.05 НКД не показываем) с откатом по OD_TURNS после даты
  (индекс REST+WIRDATE, знак TYPE_ проверен: сумма оборотов = остаток); оценка по котировке
  OD_VALUES_RATES ≤ 90 дней (в рублях за бумагу), иначе балансовая; операции из OD_WIRING
  (покупка/продажа/ввод/вывод/погашение/конвертация, продажа — по счёту ВЫРУЧКА) и
  пополнения/выводы денег; рецепт — InvestControl Hub (build_portfolio_base, deals_report)
- API: /api/lk/portfolio2?view=online|archive&date=, /api/lk/ops (сделки + выплаты дохода);
  без клиента в QUIK онлайн падает на брокерский учёт за сегодня
- кабинет: разделы Портфель (вкладки Онлайн/Архив с датой), Операции, Поручения, Документы,
  Профиль; депозитарные реестр и доходы из клиентского вида убраны (/portfolio → /,
  /income → /operations); проверено на БР-704 и БР-1545
- настройка Fancy.SpectreDatabase (по умолчанию BJ_SPECTRE_DATA)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4YVo4UMopqT5DzicqpPjL
2026-09-18 15:44:53 +03:00

577 lines
51 KiB
Go
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.
package lk
// pageTemplates — встроенные страницы Личного кабинета (без внешних зависимостей,
// чтобы модуль был одним файлом и ставился на любой веб-сервер).
//
// Визуальный мир — «Табло» (см. DESIGN.md, раздел «Личный кабинет клиента»):
// графитовая доска состояния сверху, светлая бумага реестра, янтарь — «в пути»
// и первичное действие, все величины моноширинные табличные. Шрифты грузятся с
// Google Fonts, при недоступности сети подхватываются системные аналоги.
const pageTemplates = `
{{define "head"}}<!DOCTYPE html><html lang="ru"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>{{.Title}}</title>
<link rel="stylesheet" href="/assets/fonts.css">
<style>
:root{--paper:#edebe4;--sheet:#f7f5ef;--ink:#191a1c;--ink-2:#45403a;--mut:#6a6357;
--line:#ded8ca;--line-2:#c9c3b4;--board:#191a1c;--board-2:#1f2124;--board-3:#2b2d31;
--dim:#a49b8a;--amber:#e8a33d;--amber-bg:#f6e2c0;--amber-tx:#7a4e07;
--ok-bg:#dcefe2;--ok-tx:#1f6b3e;--err-bg:#f7dedb;--err-tx:#a32d22;--neu-bg:#e3e0d6;
--acc:#2c46c0;--mono:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
*{box-sizing:border-box}
body{margin:0;font-family:"Golos Text",system-ui,-apple-system,"Segoe UI",sans-serif;background:var(--paper);color:var(--ink);line-height:1.5}
a{color:var(--acc)}a:hover{color:#1e3395}
.lbl{font-family:var(--mono);font-size:10.5px;font-weight:500;letter-spacing:.1em;text-transform:uppercase}
.n{font-family:var(--mono);font-variant-numeric:tabular-nums}
.top{background:var(--board);color:#f3f0e7;padding:0 20px;min-height:58px;display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.brand{display:flex;align-items:center;gap:10px;white-space:nowrap}
.top nav{display:flex;gap:2px;flex-grow:1;overflow-x:auto;scrollbar-width:none}
.top nav::-webkit-scrollbar{display:none}
.top nav a{color:var(--dim);text-decoration:none;padding:8px 12px;border-radius:3px;white-space:nowrap}
.top nav a:hover{background:var(--board-3);color:#f3f0e7}
.top nav a.on{background:var(--board-3);color:#f3f0e7}
.top .who{color:var(--dim);font-size:12px;white-space:nowrap}
.top .exit{color:var(--dim);text-decoration:none}
.lnk{background:none;border:0;padding:0;font:inherit;color:inherit;cursor:pointer;text-decoration:underline;text-underline-offset:2px}
.tabs{display:flex;gap:6px;align-items:center;flex-wrap:wrap;margin:0 0 16px}
.tab{font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:.1em;text-transform:uppercase;padding:8px 14px;border:1px solid var(--line-2);border-radius:3px;text-decoration:none;color:var(--ink-2)}
.tab.on{background:var(--ink);color:#f3f0e7;border-color:var(--ink)}
.tabform{display:flex;gap:8px;align-items:center;margin-left:8px}
.tabform input[type=date]{padding:7px 10px;border:1px solid var(--line-2);border-radius:3px;background:#fff;font:inherit;font-size:14px}
.pos{color:var(--ok-tx)}.neg{color:var(--err-tx)}
.kind{font-family:var(--mono);font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--mut)}
.cta{display:inline-flex;align-items:center;gap:8px;min-height:38px;padding:0 14px;background:var(--amber);color:var(--ink);text-decoration:none;border:0;border-radius:3px;cursor:pointer;font:inherit}
.cta:hover{filter:brightness(1.05);color:var(--ink)}
.board{background:var(--board-2);color:#f3f0e7;border-bottom:3px solid var(--amber);padding:22px 20px}
.board .big{font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:40px;font-weight:700;letter-spacing:-.02em;line-height:1;position:relative;display:inline-block}
.board .big::after{content:"";position:absolute;left:0;right:0;top:50%;height:1px;background:rgba(0,0,0,.28)}
.board-row{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:20px;max-width:1180px;margin:0 auto}
.stats{display:flex;gap:28px;flex-wrap:wrap}
.stat{display:flex;flex-direction:column;gap:3px}
.stat .v{font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:22px}
.imp{background:var(--board);color:#f3f0e7;padding:10px 20px;font-size:13px;display:flex;gap:10px;align-items:center;flex-wrap:wrap}
main{max-width:1180px;margin:0 auto;padding:22px 20px 34px}
h1{font-size:23px;margin:0 0 6px;letter-spacing:-.01em}h2{font-size:15px;margin:0 0 12px;letter-spacing:-.005em}
.sec{margin-bottom:28px}
.sec-h{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin-bottom:10px}
.tw{overflow-x:auto;-webkit-overflow-scrolling:touch}
table{width:100%;border-collapse:collapse;font-size:14px}
th{font-family:var(--mono);font-size:10.5px;font-weight:500;letter-spacing:.1em;text-transform:uppercase;color:var(--mut);text-align:left;padding:0 12px 9px 0;border-bottom:1px solid var(--line-2);white-space:nowrap}
td{padding:12px 12px 12px 0;border-bottom:1px solid var(--line);vertical-align:middle}
td.num,th.num{text-align:right;padding-right:0;font-family:var(--mono);font-variant-numeric:tabular-nums}
tr.grp td{background:#e4e1d8;border-bottom:1px solid var(--line-2);padding:7px 0 7px 8px}
.sheet{background:var(--sheet);border:1px solid var(--line-2);padding:20px}
.chip{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:3px;font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;background:var(--neu-bg);color:var(--ink-2)}
.chip.go{background:var(--amber-bg);color:var(--amber-tx)}
.chip.ok{background:var(--ok-bg);color:var(--ok-tx)}
.chip.err{background:var(--err-bg);color:var(--err-tx)}
.chip.dark{background:var(--board);color:#f3f0e7}
@keyframes flip{from{transform:rotateX(-88deg)}to{transform:rotateX(0)}}
.live{animation:flip 420ms cubic-bezier(.2,.9,.25,1) 1;transform-origin:50% 0}
@media(prefers-reduced-motion:reduce){.live{animation:none}}
label{display:block;font-family:var(--mono);font-size:10.5px;font-weight:500;letter-spacing:.1em;text-transform:uppercase;color:var(--mut);margin-bottom:6px}
input,select,textarea{width:100%;min-height:44px;padding:10px 12px;border:1px solid var(--line-2);border-radius:2px;background:#fff;color:var(--ink);font:inherit;font-size:16px}
input:focus,select:focus,textarea:focus{outline:2px solid var(--acc);outline-offset:1px}
input[type=checkbox]{width:20px;min-height:20px;height:20px}
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:46px;padding:0 18px;border:1px solid var(--line-2);border-radius:3px;background:#fff;color:var(--ink);font:inherit;font-size:14px;font-weight:600;cursor:pointer;text-decoration:none}
.btn:hover{border-color:var(--ink);color:var(--ink)}
.btn.main{background:var(--amber);border-color:var(--amber);color:var(--ink)}
.btn.dark{background:var(--board);border-color:var(--board);color:#f3f0e7}
.btn.sm{min-height:38px;font-size:13px;font-weight:500}
.msg{padding:12px 14px;border-radius:3px;margin-bottom:16px;font-size:14px}
.msg.err{background:var(--err-bg);color:var(--err-tx)}
.msg.ok{background:var(--ok-bg);color:var(--ok-tx)}
.mut{color:var(--ink-2);font-size:12.5px;line-height:1.65}
.grid2{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:22px}
.rows{display:flex;flex-direction:column}
.row{display:flex;justify-content:space-between;gap:14px;padding:11px 0;border-bottom:1px solid var(--line);font-size:14px}
.empty{padding:26px 0;color:var(--ink-2);font-size:14px}
.login{min-height:100vh;display:grid;grid-template-columns:minmax(0,460px) 1fr}
.login .side{background:var(--board);color:#d9d3c6;padding:40px 36px;display:flex;flex-direction:column;justify-content:space-between;gap:30px}
.login .side h1{color:#f3f0e7;font-size:30px;line-height:1.2;margin:0}
.login .form{display:flex;align-items:center;justify-content:center;padding:36px 20px}
.login form{width:100%;max-width:380px;display:flex;flex-direction:column;gap:16px}
@media(max-width:820px){.login{grid-template-columns:1fr}.login .side{padding:26px 20px}.login .side h1{font-size:24px}}
@media(max-width:600px){main{padding:18px 14px 28px}.board{padding:18px 14px}.board .big{font-size:32px}.top{padding:0 14px}.sheet{padding:16px 14px}}
</style></head><body>{{end}}
{{define "money"}}{{if gt . 0.0}}{{fmtmoney .}} ₽{{else}}—{{end}}{{end}}
{{define "mark"}}<svg viewBox="0 0 28 28" width="21" height="21" fill="none" stroke="#e8a33d" stroke-width="1.8" stroke-linecap="round" aria-hidden="true"><circle cx="6" cy="14" r="3"/><circle cx="22" cy="14" r="3"/><path d="M9 14h10"/><path d="M11 10.5h6M11 17.5h6"/></svg>{{end}}
{{define "nav"}}<header class="top">
<a class="brand" href="/" title="На табло" style="text-decoration:none;color:inherit">{{template "mark" .}}<span class="lbl" style="font-size:12px;letter-spacing:.14em">{{.Title}}</span></a>
<nav>
{{if .IsAdmin}}<a href="/clients" class="lbl {{if eq .Nav "a"}}on{{end}}">Клиенты</a>{{end}}
<a href="/" class="lbl {{if eq .Nav "b"}}on{{end}}">Портфель</a>
<a href="/operations" class="lbl {{if eq .Nav "o"}}on{{end}}">Операции</a>
<a href="/orders" class="lbl {{if eq .Nav "c"}}on{{end}}">Поручения</a>
<a href="/documents" class="lbl {{if eq .Nav "d"}}on{{end}}">Документы</a>
<a href="/profile" class="lbl {{if eq .Nav "u"}}on{{end}}">Профиль</a>
</nav>
<a href="/order" class="cta lbl"><svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M8 3v10M3 8h10"/></svg>Новое поручение</a>
<span class="who">{{with .FullName}}{{.}}{{end}}{{with .Contract}} · {{.}}{{end}}</span>
<form method="post" action="/logout" style="margin:0"><input type="hidden" name="csrf" value="{{.CSRF}}"><button class="exit lbl lnk" type="submit" style="text-decoration:none">Выход</button></form>
</header>
{{if .AsClient}}<div class="imp">
<svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="#e8a33d" stroke-width="1.8" stroke-linecap="round" aria-hidden="true"><circle cx="8" cy="8" r="6.5"/><path d="M8 5v4M8 11h.01"/></svg>
<span>Вы в кабинете клиента <b>{{.AsClient}}</b> от имени сотрудника. Поручение можно подготовить, подписывает его клиент.</span>
<form method="post" action="/back-to-admin" style="margin:0"><input type="hidden" name="csrf" value="{{.CSRF}}"><button class="lnk" type="submit" style="color:#e8a33d">вернуться к списку клиентов</button></form></div>{{end}}{{end}}
{{define "login"}}{{template "head" .}}
<div class="login">
<section class="side">
<span class="brand">{{template "mark" .}}<span class="lbl" style="font-size:12px;letter-spacing:.14em;color:#f3f0e7">{{.Title}}</span></span>
<div>
<h1>Ваши бумаги, поручения и выплаты — на одном табло</h1>
<div style="display:flex;flex-direction:column;gap:12px;margin-top:22px;font-size:14.5px">
<span style="display:flex;gap:12px"><span class="n" style="color:#e8a33d">01</span><span>Реестр бумаг по счетам депо и остаток, свободный к переводу</span></span>
<span style="display:flex;gap:12px"><span class="n" style="color:#e8a33d">02</span><span>Поручения депозитарию и их состояние по шагам</span></span>
<span style="display:flex;gap:12px"><span class="n" style="color:#e8a33d">03</span><span>Перевод бумаг в другой депозитарий через сервис MOEX МОСТ</span></span>
</div>
</div>
<p class="mut" style="color:#8e8879;margin:0">Кабинет работает на сервере депозитария и обращается к учётной системе по защищённому каналу. Данные о вас хранятся в учётной системе, а не в кабинете.</p>
</section>
<section class="form">
<form method="post" action="/login"><input type="hidden" name="csrf" value="{{$.CSRF}}">
<h1 style="margin:0">Вход</h1>
{{if .Error}}<div class="msg err">{{.Error}}</div>{{end}}
{{if .Flash}}<div class="msg ok">{{.Flash}}</div>{{end}}
<div><label for="login">Логин или номер договора</label><input id="login" name="login" autocomplete="username" autofocus></div>
<div><label for="password">Пароль</label><input id="password" name="password" type="password" autocomplete="current-password"></div>
<button class="btn main" type="submit">Войти</button>
<p class="mut" style="margin:0">Логин выдаёт депозитарий. Сотрудник входит под своей учётной записью и не знает пароль клиента.</p>
</form>
</section>
</div>
</body></html>{{end}}
{{define "portfolio"}}{{template "head" .}}{{template "nav" .}}{{$p := .P}}
<section class="board"><div class="board-row">
<div>
<span class="lbl" style="color:var(--dim)">Стоимость портфеля{{if eq .View "archive"}} на {{$p.AsOf}}{{end}}</span>
<div class="big" style="margin-top:8px">{{fmtmoney $p.Total}} ₽</div>
<div class="n" style="font-size:13px;color:var(--dim);margin-top:6px">{{with .FullName}}{{.}} · {{end}}договор {{.Contract}}{{if and (ne .View "archive") $p.AsOf}} · данные на {{$p.AsOf}}{{end}}{{if $p.Note}} · {{$p.Note}}{{end}}</div>
</div>
<div class="stats">
<span class="stat"><span class="lbl" style="color:var(--dim)">Бумаги</span><span class="v">{{fmtmoney $p.Securities}} ₽</span></span>
<span class="stat"><span class="lbl" style="color:var(--dim)">Деньги</span><span class="v">{{fmtmoney $p.CashRUB}} ₽</span></span>
<span class="stat"><span class="lbl" style="color:var(--dim)">Результат</span><span class="v" style="color:{{if lt $p.PnL 0.0}}#f0a090{{else if gt $p.PnL 0.0}}#8fd19e{{else}}inherit{{end}}">{{if ne $p.Cost 0.0}}{{fmtsigned $p.PnL}} ₽ · {{fmtpct $p.PnLPct}}{{else}}—{{end}}</span></span>
</div>
</div></section>
<main>
{{if .Flash}}<div class="msg ok">{{.Flash}}</div>{{end}}
{{if .Error}}<div class="msg err">{{.Error}}</div>{{end}}
<div class="tabs">
<a class="tab {{if ne .View "archive"}}on{{end}}" href="/">Онлайн</a>
<a class="tab {{if eq .View "archive"}}on{{end}}" href="/?view=archive">Архив</a>
{{if eq .View "archive"}}<form method="get" action="/" class="tabform"><input type="hidden" name="view" value="archive"><input type="date" name="date" value="{{.Date}}" max="{{.Today}}"><button class="btn sm" type="submit">Показать</button></form>{{end}}
<span class="mut" style="margin-left:auto;font-size:12.5px">{{if eq .View "archive"}}Портфель по брокерскому учёту на выбранную дату{{else if eq $p.Source "quik"}}Позиции и деньги в торговой системе, цены биржи{{else}}Портфель по брокерскому учёту{{end}}</span>
</div>
{{if $p.Cash}}<section class="sec" style="margin-bottom:18px">
<div class="sec-h"><h2 class="lbl" style="font-size:12px;letter-spacing:.14em">Денежные средства</h2></div>
<div style="display:flex;gap:8px;flex-wrap:wrap">{{range $p.Cash}}<span class="chip" style="font-size:13px;text-transform:none;letter-spacing:0"><b class="n">{{fmtmoney .Amount}}</b>&nbsp;{{if eq .Currency "SUR"}}₽{{else}}{{.Currency}}{{end}}</span>{{end}}</div>
</section>{{end}}
<section class="sec">
<div class="sec-h"><h2 class="lbl" style="font-size:12px;letter-spacing:.14em">Бумаги</h2><span class="mut" style="font-size:12.5px">{{len $p.Positions}} позиций{{if $p.Positions}}, с ценой {{$p.Priced}}{{end}}</span></div>
{{if $p.Positions}}<div class="tw"><table>
<thead><tr><th>Бумага</th><th class="num">Кол-во</th><th class="num">Средняя</th><th class="num">Цена</th><th class="num">Стоимость</th><th class="num">Результат</th><th class="num">Доля</th></tr></thead>
<tbody>{{range $p.Positions}}<tr>
<td>{{if .ISIN}}<a href="/security?isin={{.ISIN}}" style="text-decoration:none;font-weight:600">{{.Name}}</a>{{else}}<b>{{.Name}}</b>{{end}}<div class="kind">{{.Kind}}{{if .ISIN}} · <span class="n" style="text-transform:none;letter-spacing:0">{{.ISIN}}</span>{{end}}{{if .Note}} · {{.Note}}{{end}}</div></td>
<td class="num">{{fmtnum .Quantity}}</td>
<td class="num">{{if gt .AvgPrice 0.0}}{{fmtprice .AvgPrice}}{{if .InPct}}%{{end}}{{else}}—{{end}}</td>
<td class="num">{{if gt .Price 0.0}}{{fmtprice .Price}}{{if .InPct}}%{{end}}{{if ne .DayPct 0.0}}<div class="{{if lt .DayPct 0.0}}neg{{else}}pos{{end}}" style="font-size:11.5px">{{fmtpct .DayPct}}</div>{{end}}{{else}}—{{end}}</td>
<td class="num">{{template "money" .Value}}</td>
<td class="num">{{if ne .Cost 0.0}}<span class="{{if lt .PnL 0.0}}neg{{else if gt .PnL 0.0}}pos{{end}}">{{fmtsigned .PnL}}<div style="font-size:11.5px">{{fmtpct .PnLPct}}</div></span>{{else}}—{{end}}</td>
<td class="num">{{if gt .Share 0.0}}{{fmtpct1 .Share}}{{else}}—{{end}}</td>
</tr>{{end}}</tbody></table></div>
{{else}}<p class="empty">{{if eq .View "archive"}}На эту дату бумаг на счёте не было.{{else}}Бумаг на счёте нет.{{end}}</p>{{end}}
</section>
</main></body></html>{{end}}
{{define "transfer"}}{{template "head" .}}{{template "nav" .}}
<main>
{{if .Error}}<div class="msg err">{{.Error}}</div>{{end}}
<form method="post" action="/order" id="orderForm"><input type="hidden" name="csrf" value="{{$.CSRF}}">
<div class="sheet">
<div style="display:flex;align-items:flex-end;justify-content:space-between;gap:20px;border-bottom:2px solid var(--ink);padding-bottom:14px;flex-wrap:wrap">
<div><h1 style="margin:0">Поручение депозитарию</h1>
<span class="lbl" style="color:var(--mut);margin-top:6px;display:block">Заполняется по видам, как и другие поручения кабинета</span></div>
<div style="text-align:right"><span class="lbl" style="color:var(--mut);display:block">Черновик</span>
<span class="n" style="font-size:16px;font-weight:700">{{.Today}}</span></div>
</div>
<div style="margin-top:20px">
<span class="lbl" style="display:block;margin-bottom:10px;color:var(--ink)">1. Вид поручения</span>
<select name="kind" aria-label="Вид поручения">
<option value="m2m">Перевод бумаг в другой депозитарий</option>
<option value="other" disabled>Другие виды — подаются в депозитарии, скоро появятся здесь</option>
</select>
</div>
<div style="margin-top:20px">
<span class="lbl" style="display:block;margin-bottom:10px;color:var(--ink)">2. Что переводим</span>
{{if .Positions}}<div class="tw"><table>
<thead><tr><th style="width:40px"></th><th>Выпуск</th><th class="num">Свободно</th><th style="width:180px">Количество</th></tr></thead>
<tbody>{{range .Positions}}<tr>
<td>{{if and .Transferable (gt .Available 0.0)}}<input type="checkbox" name="isin" value="{{.ISIN}}" id="c{{.ISIN}}"{{if eq $.PickISIN .ISIN}} checked{{end}}>{{end}}</td>
<td><label for="c{{.ISIN}}" style="font-family:inherit;font-size:14px;letter-spacing:0;text-transform:none;color:var(--ink);margin:0;font-weight:600">{{.SecurityName}}</label>
<div class="n" style="font-size:12.5px;color:var(--mut)">{{.ISIN}}{{if not .Transferable}} · иностранный выпуск, перевод недоступен{{else if eq .Available 0.0}} · свободного остатка нет{{end}}</div></td>
<td class="num">{{fmtnum .Available}}</td>
<td>{{if and .Transferable (gt .Available 0.0)}}<input class="n" name="qty_{{.ISIN}}" inputmode="decimal" style="min-height:40px;text-align:right" aria-label="Количество {{.SecurityName}}">{{else}}<span class="lbl" style="color:var(--mut)">недоступно</span>{{end}}</td>
</tr>{{end}}</tbody></table></div>
{{else}}<p class="empty">Свободных бумаг для перевода нет.</p>{{end}}
</div>
<div style="margin-top:20px">
<span class="lbl" style="display:block;margin-bottom:10px;color:var(--ink)">3. Куда переводим</span>
<div class="grid2">
<div><label for="inn">ИНН принимающего депозитария</label>
<input id="inn" name="receiving_inn" inputmode="numeric" maxlength="12" required aria-describedby="innh">
<span id="innh" class="mut" style="display:block;margin-top:6px">10 цифр для организации. ИНН можно спросить у депозитария, куда переводите бумаги.</span></div>
<div><label for="rname">Наименование</label><input id="rname" name="receiving_name" placeholder="как в договоре"></div>
<div><label for="racc">Ваш счёт депо у принимающего</label><input id="racc" name="account_at_recv" placeholder="если знаете"></div>
<div><label for="cmt">Комментарий депозитарию</label><input id="cmt" name="comment" placeholder="необязательно"></div>
</div>
</div>
<div style="display:flex;gap:12px;flex-wrap:wrap;margin-top:22px">
<button class="btn main" type="submit">Подать поручение</button>
<a class="btn" href="/">Отмена</a>
</div>
<p class="mut" style="margin-top:14px">Переводятся только российские выпуски. Бумаги для квалифицированных инвесторов принимающая сторона может не принять. После отправки в НРД отменить поручение нельзя — состояние будет видно в разделе «Поручения».</p>
</div>
</form>
</main></body></html>{{end}}
{{define "claims"}}{{template "head" .}}{{template "nav" .}}
<section class="board"><div class="board-row">
<div><span class="lbl" style="color:var(--dim)">Поручения депозитарию</span>
<div class="n" style="font-size:13px;color:var(--dim);margin-top:6px">все виды поручений кабинета</div></div>
<div class="stats">
<span class="stat"><span class="lbl" style="color:var(--dim)">Всего</span><span class="v">{{.Total}}</span></span>
<span class="stat"><span class="lbl" style="color:var(--dim)">В работе</span><span class="v" style="color:var(--amber)">{{.Active}}</span></span>
<span class="stat"><span class="lbl" style="color:var(--dim)">Исполнено</span><span class="v">{{.Done}}</span></span>
</div>
</div></section>
<main>
{{if .Flash}}<div class="msg ok">{{.Flash}}</div>{{end}}
{{if .Error}}<div class="msg err">{{.Error}}</div>{{end}}
{{if .Claims}}<div class="tw"><table>
<thead><tr><th>Номер</th><th>Дата</th><th>Вид поручения</th><th class="num">Бумаг</th><th>Состояние</th><th>Примечание</th></tr></thead>
<tbody>{{range .Claims}}<tr>
<td class="n">{{shortid .GUID}}</td>
<td class="n">{{.CreatedAt}}</td>
<td>Перевод в другой депозитарий</td>
<td class="num">{{.Securit}}</td>
<td><span class="chip {{if eq .Status "done"}}ok{{else if eq .Status "rejected"}}err{{else if eq .Status "declined"}}err{{else if eq .Status "error"}}err{{else}}go{{end}}">{{.StatusRu}}</span></td>
<td class="mut">{{if .Reason}}{{.Reason}}{{else}}—{{end}}</td>
</tr>{{end}}</tbody></table></div>
<p class="mut" style="margin-top:18px">Пока поручение в работе, бумаги остаются на счёте, но перевести их повторно нельзя. Если принимающая сторона откажет, бумаги освободятся в тот же день, а причина появится в примечании.</p>
{{else}}<p class="empty">Поручений пока нет.</p>{{end}}
</main></body></html>{{end}}
{{define "install"}}{{template "head" .}}{{$d := .D}}
<div class="login">
<section class="side">
<span class="brand">{{template "mark" .}}<span class="lbl" style="font-size:12px;letter-spacing:.14em;color:#f3f0e7">Установка кабинета</span></span>
<div>
<h1>Три шага — и кабинет работает</h1>
<div style="display:flex;flex-direction:column;gap:12px;margin-top:22px;font-size:14.5px">
<span style="display:flex;gap:12px"><span class="n" style="color:{{if ge $d.Step 1}}#e8a33d{{else}}#8e8879{{end}}">01</span><span>Проверка сервера{{if gt $d.Step 1}} — готово{{end}}</span></span>
<span style="display:flex;gap:12px"><span class="n" style="color:{{if ge $d.Step 2}}#e8a33d{{else}}#8e8879{{end}}">02</span><span>Связь с ядром депозитария{{if gt $d.Step 2}} — готово{{end}}</span></span>
<span style="display:flex;gap:12px"><span class="n" style="color:{{if ge $d.Step 3}}#e8a33d{{else}}#8e8879{{end}}">03</span><span>Администратор кабинета</span></span>
</div>
</div>
<p class="mut" style="color:#8e8879;margin:0">Кабинет ничего не хранит у себя: пользователи, пароли и данные клиентов живут в ядре. Здесь сохраняется только способ связи с ним.</p>
</section>
<section class="form">
<form method="post" action="/install" style="max-width:520px"><input type="hidden" name="csrf" value="{{$.CSRF}}">
{{if $d.Error}}<div class="msg err">{{$d.Error}}</div>{{end}}
{{if $d.Notice}}<div class="msg ok">{{$d.Notice}}</div>{{end}}
{{if lt $d.Step 3}}
<h1 style="margin:0">Сервер и связь с ядром</h1>
<div style="display:grid;gap:8px">
{{range $d.Checks}}<div style="display:flex;gap:10px;align-items:flex-start;font-size:14px"><span style="color:{{if .OK}}{{if .Warn}}#e8a33d{{else}}#3f8f5a{{end}}{{else}}#c0392b{{end}};font-weight:700">{{if .OK}}✓{{else}}✗{{end}}</span><span><b>{{.Name}}.</b> {{.Note}}</span></div>{{end}}
</div>
{{if $d.Waiting}}
<meta http-equiv="refresh" content="5">
<div class="msg ok">Настройки сохранены. Ждём, когда ядро подключится к кабинету по адресу <b>{{$d.Host}}</b>… Страница обновляется сама.</div>
<p class="mut" style="margin:0">В настройках ядра (раздел «Кабинет клиента») выберите «Ядро подключается к кабинету» и укажите этот адрес. Ключ должен совпадать.</p>
<input type="hidden" name="step" value="wait">
{{else}}
<input type="hidden" name="step" value="connect">
<div>
<label>Заголовок кабинета</label>
<input name="title" value="{{$d.Cfg.Title}}" placeholder="Депозитарий · личный кабинет">
</div>
<div>
<label>Как связаться с ядром</label>
<label style="display:flex;gap:8px;align-items:flex-start;text-transform:none;letter-spacing:0;font-family:inherit;font-size:14px;color:var(--ink);margin-top:6px"><input type="radio" name="mode" value="direct" {{if not $d.Cfg.Agent}}checked{{end}}> <span><b>Кабинет обращается к ядру</b> — у ядра есть адрес, доступный с этого сервера.</span></label>
<label style="display:flex;gap:8px;align-items:flex-start;text-transform:none;letter-spacing:0;font-family:inherit;font-size:14px;color:var(--ink);margin-top:6px"><input type="radio" name="mode" value="agent" {{if $d.Cfg.Agent}}checked{{end}}> <span><b>Ядро подключается к кабинету</b> — у ядра нет адреса в интернете; оно само дозвонится сюда.</span></label>
</div>
<div>
<label>Где собираются страницы</label>
<label style="display:flex;gap:8px;align-items:flex-start;text-transform:none;letter-spacing:0;font-family:inherit;font-size:14px;color:var(--ink);margin-top:6px"><input type="radio" name="render" value="core" {{if $d.Cfg.Relay}}checked{{end}}> <span><b>В ядре</b> — здесь только передача; новые разделы появляются обновлением ядра.</span></label>
<label style="display:flex;gap:8px;align-items:flex-start;text-transform:none;letter-spacing:0;font-family:inherit;font-size:14px;color:var(--ink);margin-top:6px"><input type="radio" name="render" value="local" {{if not $d.Cfg.Relay}}checked{{end}}> <span><b>Здесь</b> — эта программа собирает страницы сама из данных ядра.</span></label>
</div>
<div>
<label for="bj_url">Адрес ядра <span style="text-transform:none;letter-spacing:0">(только для первого способа)</span></label>
<input id="bj_url" name="bj_url" value="{{$d.Cfg.BJURL}}" placeholder="https://bj.депозитарий.ru" autocomplete="off">
</div>
<div>
<label for="bj_key">Ключ доступа модуля</label>
<input id="bj_key" name="bj_key" type="password" value="{{$d.Cfg.BJKey}}" autocomplete="off" placeholder="lk-…">
<p class="mut" style="margin:6px 0 0">Создаётся в настройках ядра: «Кабинет клиента» → «Создать ключ».</p>
</div>
<button class="btn main" type="submit">Проверить связь и сохранить</button>
{{end}}
{{else}}
<h1 style="margin:0">Администратор кабинета</h1>
<p class="mut" style="margin:0">Сотрудник депозитария, который входит в кабинет, видит список клиентов и может открыть кабинет клиента на просмотр. Учётная запись заводится в ядре. Если администратор уже есть — шаг можно пропустить.</p>
<input type="hidden" name="step" value="admin">
<div><label for="login">Логин</label><input id="login" name="login" autocomplete="off"></div>
<div><label for="full_name">Имя сотрудника</label><input id="full_name" name="full_name" autocomplete="off"></div>
<div><label for="email">Электронная почта <span style="text-transform:none;letter-spacing:0">(письма пока не отправляются)</span></label><input id="email" name="email" type="email" autocomplete="off"></div>
<div><label for="password">Пароль <span style="text-transform:none;letter-spacing:0">(от 10 символов, буквы и цифра)</span></label><input id="password" name="password" type="password" autocomplete="new-password"></div>
<div><label for="password2">Пароль ещё раз</label><input id="password2" name="password2" type="password" autocomplete="new-password"></div>
<div style="display:flex;gap:10px;flex-wrap:wrap">
<button class="btn main" type="submit">Создать и завершить</button>
<button class="btn" type="submit" name="skip" value="1">Пропустить</button>
</div>
{{end}}
</form>
</section>
</div>
</body></html>{{end}}
{{define "install_done"}}{{template "head" .}}
<div class="login"><section class="side"><span class="brand">{{template "mark" .}}<span class="lbl" style="font-size:12px;letter-spacing:.14em;color:#f3f0e7">Установка кабинета</span></span><div><h1>Кабинет установлен</h1></div><p class="mut" style="color:#8e8879;margin:0">Настройки — в файле <span class="n">{{.File}}</span>. Чтобы пройти установку заново, удалите его.</p></section>
<section class="form"><form action="/login" method="get" style="max-width:420px"><h1 style="margin:0">Готово</h1><p class="mut" style="margin:0">Клиенты входят по логину и паролю, которые выдаёт депозитарий. Учётные записи заводятся в настройках ядра, раздел «Кабинет клиента».</p><button class="btn main" type="submit">Перейти ко входу</button></form></section></div>
</body></html>{{end}}
{{define "installed"}}{{template "head" .}}
<div class="login"><section class="side"><span class="brand">{{template "mark" .}}<span class="lbl" style="font-size:12px;letter-spacing:.14em;color:#f3f0e7">Установка кабинета</span></span><div><h1>Кабинет уже настроен</h1></div></section>
<section class="form"><form action="/login" method="get" style="max-width:420px"><p class="mut" style="margin:0">Установщик закрыт: настройки сохранены в <span class="n">{{.File}}</span>. Чтобы изменить их, отредактируйте файл или удалите его и откройте эту страницу снова.</p><button class="btn main" type="submit">Перейти ко входу</button></form></section></div>
</body></html>{{end}}
{{define "relay_error"}}{{template "head" .}}
<div class="login"><section class="side"><span class="brand">{{template "mark" .}}<span class="lbl" style="font-size:12px;letter-spacing:.14em;color:#f3f0e7">{{.Title}}</span></span><div><h1>Кабинет временно недоступен</h1></div><p class="mut" style="color:#8e8879;margin:0">Страницы кабинета собирает учётная система депозитария; сейчас связи с ней нет.</p></section>
<section class="form"><form action="/" method="get" style="max-width:420px"><div class="msg err">{{.Error}}</div><p class="mut" style="margin:0">Попробуйте обновить страницу через минуту. Если не помогает — сообщите в депозитарий.</p><button class="btn main" type="submit">Обновить</button></form></section></div>
</body></html>{{end}}
{{define "profile"}}{{template "head" .}}{{template "nav" .}}
<section class="board"><div class="board-row">
<div><span class="lbl" style="color:var(--dim)">Профиль</span>
<div style="font-size:23px;font-weight:700;margin-top:8px">{{if .FullName}}{{.FullName}}{{else}}Клиент депозитария{{end}}</div></div>
<div class="stats">
<span class="stat"><span class="lbl" style="color:var(--dim)">Договор</span><span class="v">{{.Contract}}</span></span>
<span class="stat"><span class="lbl" style="color:var(--dim)">Счетов депо</span><span class="v">{{.Accounts}}</span></span>
<span class="stat"><span class="lbl" style="color:var(--dim)">Подача поручений</span><span class="v">{{if .ReadOnly}}выключена{{else}}доступна{{end}}</span></span>
</div>
</div></section>
<main>
{{if .Error}}<div class="msg err">{{.Error}}</div>{{end}}
<div class="grid2">
<section class="sec">
<h2 class="lbl" style="font-size:12px;letter-spacing:.14em">Счета депо</h2>
<div class="rows">{{range .AccountList}}<div class="row"><span class="n">{{.}}</span><span class="chip ok">открыт</span></div>{{else}}<p class="empty">Счета не найдены.</p>{{end}}</div>
</section>
<section class="sec">
<h2 class="lbl" style="font-size:12px;letter-spacing:.14em">Доступ и безопасность</h2>
<div class="rows">
<div class="row"><span>Вход в кабинет</span><span class="n">{{.Login}}</span></div>
<div class="row"><span>Подача поручений</span><span>{{if .ReadOnly}}выключена депозитарием{{else}}доступна{{end}}</span></div>
{{if .AsClient}}<div class="row"><span>Сейчас в кабинете</span><span>сотрудник депозитария</span></div>{{end}}
<div class="row"><span>Завершить работу</span><form method="post" action="/logout" style="margin:0"><input type="hidden" name="csrf" value="{{.CSRF}}"><button class="lnk" type="submit">выйти</button></form></div>
</div>
<p class="mut" style="margin-top:14px">Контакты, паспортные данные и реквизиты для выплат меняет депозитарий: обратитесь к своему менеджеру, изменения появятся в кабинете после внесения в анкету.</p>
</section>
</div>
</main></body></html>{{end}}
{{define "clients"}}{{template "head" .}}{{template "nav" .}}
<section class="board"><div class="board-row">
<div><span class="lbl" style="color:var(--dim)">Режим сотрудника</span>
<div style="font-size:23px;font-weight:700;margin-top:8px">Клиенты депозитария</div></div>
<div class="stats">
<span class="stat"><span class="lbl" style="color:var(--dim)">Учётных записей</span><span class="v">{{len .Clients}}</span></span>
<span class="stat"><span class="lbl" style="color:var(--dim)">Договоров в учёте</span><span class="v">{{len .Depo}}</span></span>
</div>
</div></section>
<main>
{{if .Error}}<div class="msg err">{{.Error}}</div>{{end}}
<section class="sec">
<h2 class="lbl" style="font-size:12px;letter-spacing:.14em">Учётные записи кабинета</h2>
{{if .Clients}}<div class="tw"><table>
<thead><tr><th>Клиент</th><th>Логин</th><th>Договор</th><th>Состояние</th><th></th></tr></thead>
<tbody>{{range .Clients}}<tr>
<td><b>{{.FullName}}</b></td><td class="n">{{.Login}}</td><td class="n">{{.Contract}}</td>
<td>{{if .Active}}<span class="chip ok">активна</span>{{else}}<span class="chip err">заблокирована</span>{{end}}</td>
<td style="text-align:right"><form method="post" action="/impersonate" style="margin:0"><input type="hidden" name="login" value="{{.Login}}"><input type="hidden" name="csrf" value="{{$.CSRF}}"><button class="btn sm" type="submit">Открыть кабинет</button></form></td>
</tr>{{end}}</tbody></table></div>
{{else}}<p class="empty">Учётных записей кабинета пока нет.</p>{{end}}
</section>
<section class="sec">
<div class="sec-h"><h2 class="lbl" style="font-size:12px;letter-spacing:.14em">Клиенты депозитария</h2></div>
<form method="get" action="/clients" style="display:flex;gap:10px;align-items:flex-end;max-width:560px;margin-bottom:14px">
<div style="flex-grow:1"><label for="s">Поиск</label><input id="s" name="search" value="{{.Search}}" placeholder="фамилия или номер договора"></div>
<button class="btn" type="submit">Найти</button>
</form>
{{if .DepoError}}<div class="msg err">{{.DepoError}}</div>{{end}}
{{if .Depo}}<div class="tw"><table>
<thead><tr><th>Клиент</th><th>Договор</th><th class="num">Бумаг</th><th></th></tr></thead>
<tbody>{{range .Depo}}<tr>
<td><b>{{.Name}}</b></td><td class="n">{{.Contract}}</td><td class="num">{{.Securities}}</td>
<td style="text-align:right"><form method="post" action="/impersonate" style="margin:0"><input type="hidden" name="contract" value="{{.Contract}}"><input type="hidden" name="csrf" value="{{$.CSRF}}"><button class="btn sm" type="submit">Открыть кабинет</button></form></td>
</tr>{{end}}</tbody></table></div>
{{else}}<p class="empty">Ничего не найдено.</p>{{end}}
</section>
<p class="mut">В кабинете клиента сотрудник готовит поручение, подписывает его клиент. Каждый вход сотрудника записывается в журнал.</p>
</main></body></html>{{end}}
{{define "security"}}{{template "head" .}}{{template "nav" .}}
{{$s := .S}}
<section class="board"><div class="board-row">
<div>
<a href="/portfolio" class="lbl" style="color:var(--dim);text-decoration:none">← Реестр</a>
<div style="font-size:23px;font-weight:700;margin-top:8px">{{if $s.Name}}{{$s.Name}}{{else}}{{.ISIN}}{{end}}</div>
<div class="n" style="font-size:13px;color:var(--dim);margin-top:6px">{{.ISIN}}{{with $s.Kind}} · {{.}}{{end}}{{with $s.RegNumber}} · {{.}}{{end}}</div>
</div>
<div class="stats">
{{with $s.Position}}<span class="stat"><span class="lbl" style="color:var(--dim)">В портфеле</span><span class="v">{{fmtnum .Quantity}}</span></span>
<span class="stat"><span class="lbl" style="color:var(--dim)">Свободно</span><span class="v">{{fmtnum .Available}}</span></span>{{end}}
{{if gt $s.Price 0.0}}<span class="stat"><span class="lbl" style="color:var(--dim)">Цена</span><span class="v">{{fmtmoney $s.Price}}</span></span>{{end}}
{{with $s.Position}}{{if gt .Value 0.0}}<span class="stat"><span class="lbl" style="color:var(--dim)">Оценка</span><span class="v">{{fmtmoney .Value}} ₽</span></span>{{end}}{{end}}
</div>
</div></section>
<main>
{{if .Error}}<div class="msg err">{{.Error}}</div>{{end}}
{{with $s.Note}}<div class="msg">{{.}}</div>{{end}}
<div class="grid2">
<section class="sec">
<h2 class="lbl" style="font-size:12px;letter-spacing:.14em">Выпуск</h2>
<div class="rows">
{{with $s.Issuer}}<div class="row"><span>Эмитент</span><span style="text-align:right">{{.}}</span></div>{{end}}
{{with $s.Kind}}<div class="row"><span>Вид бумаги</span><span>{{.}}</span></div>{{end}}
{{if gt $s.Face 0.0}}<div class="row"><span>Номинал</span><span class="n">{{fmtmoney $s.Face}} ₽</span></div>{{end}}
{{with $s.Maturity}}<div class="row"><span>Погашение</span><span class="n">{{.}}</span></div>{{end}}
{{with $s.RegNumber}}<div class="row"><span>Государственная регистрация</span><span class="n">{{.}}</span></div>{{end}}
{{with $s.CFI}}<div class="row"><span>Код CFI</span><span class="n">{{.}}</span></div>{{end}}
<div class="row"><span>Обслуживание в депозитарии</span><span>{{if $s.Accepted}}принята{{else}}не принята{{end}}</span></div>
<div class="row"><span>Для квалифицированных инвесторов</span><span>{{if $s.QualOnly}}да{{else}}ограничений нет{{end}}</span></div>
{{if gt $s.Price 0.0}}<div class="row"><span>Цена{{with $s.Board}} · {{.}}{{end}}</span><span class="n">{{fmtmoney $s.Price}}{{with $s.PriceIn}} <span style="color:var(--mut)">{{.}}</span>{{end}}</span></div>{{end}}
</div>
{{with $s.Position}}{{if and .Transferable (gt .Available 0.0)}}
<a href="/order?isin={{$s.ISIN}}" class="btn main" style="margin-top:16px">Перевести эту бумагу</a>{{end}}{{end}}
</section>
<section class="sec">
<h2 class="lbl" style="font-size:12px;letter-spacing:.14em">График выплат и событий</h2>
{{if $s.Payments}}<div class="tw"><table>
<thead><tr><th>Дата</th><th>Событие</th><th class="num">На бумагу</th><th class="num">Ставка</th><th>Состояние</th></tr></thead>
<tbody>{{range $s.Payments}}<tr>
<td class="n">{{.Date}}</td>
<td>{{.Kind}}{{with .FixDate}}<div class="mut">фиксация {{.}}</div>{{end}}</td>
<td class="num">{{if gt .Amount 0.0}}{{fmtmoney .Amount}} ₽{{else}}—{{end}}</td>
<td class="num">{{if gt .Percent 0.0}}{{fmtpct .Percent}}{{else}}—{{end}}</td>
<td>{{if .Paid}}<span class="chip ok">выплачено</span>{{else}}<span class="chip">ожидается</span>{{end}}</td>
</tr>{{end}}</tbody></table></div>
{{else}}<p class="empty">Выплат по этой бумаге в справочнике депозитария нет.</p>{{end}}
<p class="mut" style="margin-top:14px">Суммы приведены на одну бумагу по данным справочника депозитария. Фактическая выплата и удержанный налог появятся в операциях по счёту.</p>
</section>
</div>
</main></body></html>{{end}}
{{define "operations"}}{{template "head" .}}{{template "nav" .}}
<section class="board"><div class="board-row">
<div>
<span class="lbl" style="color:var(--dim)">Операции</span>
<div class="big" style="margin-top:8px">{{len .Rows}}</div>
<div class="n" style="font-size:13px;color:var(--dim);margin-top:6px">за период {{.From}} — {{.To}}</div>
</div>
<div class="stats">
<span class="stat"><span class="lbl" style="color:var(--dim)">Покупки</span><span class="v">{{fmtmoney .BuyRUB}} ₽</span></span>
<span class="stat"><span class="lbl" style="color:var(--dim)">Продажи</span><span class="v">{{fmtmoney .SellRUB}} ₽</span></span>
<span class="stat"><span class="lbl" style="color:var(--dim)">Выплаты</span><span class="v">{{fmtmoney .IncomeRUB}} ₽</span></span>
</div>
</div></section>
<main>
{{if .Error}}<div class="msg err">{{.Error}}</div>{{end}}
{{if .Note}}<div class="msg ok">{{.Note}}</div>{{end}}
<form method="get" action="/operations" class="tabform" style="margin:0 0 18px">
<div><label for="from">Период с</label><input id="from" type="date" name="from" value="{{.From}}"></div>
<div><label for="to">по</label><input id="to" type="date" name="to" value="{{.To}}"></div>
<button class="btn sm" type="submit" style="align-self:flex-end">Показать</button>
</form>
{{if .Rows}}<div class="tw"><table>
<thead><tr><th>Дата</th><th>Операция</th><th>Инструмент</th><th class="num">Кол-во</th><th class="num">Цена</th><th class="num">Сумма</th></tr></thead>
<tbody>{{range .Rows}}<tr>
<td class="n">{{.Date}}</td>
<td><span class="chip {{if eq .Side "in"}}ok{{else}}go{{end}}">{{.Kind}}</span></td>
<td>{{if .ISIN}}<a href="/security?isin={{.ISIN}}" style="text-decoration:none;font-weight:600">{{.Name}}</a><div class="n" style="font-size:12px;color:var(--mut)">{{.ISIN}}</div>{{else}}{{.Name}}{{end}}</td>
<td class="num">{{if ne .Quantity 0.0}}{{fmtnum .Quantity}}{{else}}—{{end}}</td>
<td class="num">{{if gt .Price 0.0}}{{fmtprice .Price}}{{else}}—{{end}}</td>
<td class="num"><span class="{{if eq .Side "in"}}pos{{else}}neg{{end}}">{{if eq .Side "in"}}+{{else}}−{{end}}{{fmtmoney .AmountRUB}} ₽</span>{{if and .Currency (ne .Currency "SUR")}}<div style="font-size:11.5px;color:var(--mut)">{{fmtmoney .Amount}} {{.Currency}}</div>{{end}}</td>
</tr>{{end}}</tbody></table></div>
{{else}}<p class="empty">За выбранный период операций нет.</p>{{end}}
</main></body></html>{{end}}
{{define "documents"}}{{template "head" .}}{{template "nav" .}}
<section class="board"><div class="board-row">
<div><span class="lbl" style="color:var(--dim)">Документы депозитария</span>
<div class="big" style="margin-top:8px;font-size:32px">{{len .Ready}}</div>
<div class="n" style="font-size:13px;color:var(--dim);margin-top:6px">готовых документов{{if .Requests}} · заявок {{len .Requests}}{{end}}</div></div>
</div></section>
<main>
{{if .Flash}}<div class="msg ok">{{.Flash}}</div>{{end}}
{{if .Error}}<div class="msg err">{{.Error}}</div>{{end}}
<section class="sec">
<h2 class="lbl" style="font-size:12px;letter-spacing:.14em">Готовые документы</h2>
{{if .Ready}}<div class="tw"><table>
<thead><tr><th>Дата</th><th>Документ</th><th>Период</th><th>Счёт депо</th><th>Состояние</th></tr></thead>
<tbody>{{range .Ready}}<tr>
<td class="n">{{.Date}}</td>
<td>{{.Title}}{{with .Note}}<div class="n mut">№ {{.}}</div>{{end}}</td>
<td class="n">{{if .Period}}{{.Period}}{{else}}—{{end}}</td>
<td class="n" style="font-size:13px">{{.Account}}</td>
<td>{{if eq .State "исполнено"}}<span class="chip ok">готов</span>{{else}}<span class="chip go">{{.State}}</span>{{end}}</td>
</tr>{{end}}</tbody></table></div>
<p class="mut" style="margin-top:14px">Файлы документов выдаёт депозитарий: бумажный экземпляр в офисе или по электронной почте. В кабинете виден факт подготовки и период документа.</p>
{{else}}<p class="empty">Готовых документов пока нет.</p>{{end}}
</section>
<div class="grid2">
<section class="sec">
<h2 class="lbl" style="font-size:12px;letter-spacing:.14em">Мои заявки</h2>
{{if .Requests}}<div class="rows">{{range .Requests}}
<div class="row"><span>{{.Title}}<span class="n mut" style="display:block">{{.Date}}{{if .Period}} · {{.Period}}{{end}}</span>{{with .Note}}<span class="mut" style="display:block">{{.}}</span>{{end}}</span>
<span class="chip {{if eq .State "готов"}}ok{{else if eq .State "отклонён"}}err{{else}}go{{end}}" style="align-self:center">{{.State}}</span></div>
{{end}}</div>
{{else}}<p class="empty">Заявок пока нет.</p>{{end}}
</section>
<section class="sec">
<h2 class="lbl" style="font-size:12px;letter-spacing:.14em">Заказать документ</h2>
<form method="post" action="/documents" class="sheet" style="display:grid;gap:12px;padding:18px 20px"><input type="hidden" name="csrf" value="{{$.CSRF}}">
<div><label for="kind">Вид документа</label>
<select id="kind" name="kind">{{range .Kinds}}<option>{{.}}</option>{{end}}</select></div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px">
<div><label for="from">Период с</label><input id="from" type="date" name="from" value="{{.From}}"></div>
<div><label for="to">по</label><input id="to" type="date" name="to" value="{{.To}}"></div>
</div>
<div><label for="comment">Комментарий</label><input id="comment" name="comment" placeholder="необязательно"></div>
<button class="btn main" type="submit">Отправить заявку</button>
<p class="mut" style="margin:0">Заявка уходит сотруднику депозитария. Срок подготовки и стоимость — по тарифам депозитария; готовый документ появится в списке слева.</p>
</form>
</section>
</div>
</main></body></html>{{end}}
`