From a9dc14969b98166da0f05eb6dc0d15c172e72192 Mon Sep 17 00:00:00 2001 From: zuevav Date: Thu, 17 Sep 2026 20:02:42 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A1=D0=BF=D1=80=D0=B0=D0=B2=D0=BE=D1=87?= =?UTF-8?q?=D0=BD=D0=B8=D0=BA=20=D1=83=D1=87=D0=B0=D1=81=D1=82=D0=BD=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=B2:=20=D0=BF=D0=BE=D0=B8=D1=81=D0=BA=20=D0=BF?= =?UTF-8?q?=D0=BE=20=D0=98=D0=9D=D0=9D/=D0=BD=D0=B0=D0=B7=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8E/=D0=BA=D0=BE=D0=B4=D1=83=20=D0=B2=D0=BC?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D0=BE=20=D1=81=D0=BF=D0=B8=D1=81=D0=BA=D0=B0?= =?UTF-8?q?=20(=D1=80=D1=83=D1=87=D0=BD=D0=BE=D0=B9=20=D0=B2=D0=B2=D0=BE?= =?UTF-8?q?=D0=B4,=20=D0=BE=D1=80=D0=B3=D0=B0=D0=BD=D0=B8=D0=B7=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F);=20=D1=80=D1=83=D1=87=D0=BD=D0=BE=D0=B9=20?= =?UTF-8?q?=D0=B2=D0=B2=D0=BE=D0=B4=20=E2=80=94=20=D1=82=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D0=BA=D0=BE=20=D0=9D=D0=A0=D0=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5 (1M context) --- internal/lkgateway/manual.go | 2 +- internal/lkgateway/manual_handlers.go | 4 +- .../web/templates/admin_help_manual.html | 2 +- .../lkgateway/web/templates/admin_manual.html | 38 +++++++++++++++---- .../lkgateway/web/templates/admin_setup.html | 37 +++++++++++++++--- 5 files changed, 65 insertions(+), 18 deletions(-) diff --git a/internal/lkgateway/manual.go b/internal/lkgateway/manual.go index 4922702..49599c2 100644 --- a/internal/lkgateway/manual.go +++ b/internal/lkgateway/manual.go @@ -94,7 +94,7 @@ type ManualOrder struct { RecvCode string `json:"recv_code,omitempty"` RecvName string `json:"recv_name,omitempty"` RecvAccount string `json:"recv_account,omitempty"` // счёт клиента у принимающего (для сведения) - SettlePlace string `json:"settle_place"` // nrd | spb + SettlePlace string `json:"settle_place"` // nrd (СПБ Банк пока не используется) CostInfo bool `json:"cost_info"` Securities []ManualSec `json:"securities"` diff --git a/internal/lkgateway/manual_handlers.go b/internal/lkgateway/manual_handlers.go index dc554f7..e63a760 100644 --- a/internal/lkgateway/manual_handlers.go +++ b/internal/lkgateway/manual_handlers.go @@ -329,9 +329,7 @@ func manualFromForm(r *http.Request) *ManualOrder { RecvINN: f("recv_inn"), RecvName: f("recv_name"), RecvAccount: f("recv_account"), SettlePlace: f("settle_place"), CostInfo: r.FormValue("cost_info") != "", Comment: f("comment"), } - if o.SettlePlace != "spb" { - o.SettlePlace = "nrd" - } + o.SettlePlace = "nrd" // СПБ Банк пока не используется isins, codes, names, qtys := r.Form["sec_isin"], r.Form["sec_code"], r.Form["sec_name"], r.Form["sec_qty"] at := func(a []string, i int) string { if i < len(a) { diff --git a/internal/lkgateway/web/templates/admin_help_manual.html b/internal/lkgateway/web/templates/admin_help_manual.html index 09cf0e3..f95dff6 100644 --- a/internal/lkgateway/web/templates/admin_help_manual.html +++ b/internal/lkgateway/web/templates/admin_help_manual.html @@ -51,7 +51,7 @@ Ценная бумагаОдно поручение — одна бумага: если клиент переводит несколько бумаг, на каждую оформляется отдельное поручение. ISIN (только российские выпуски, начинаются с RU) и количество; дробное количество допускается для паёв. Код НРД можно не указывать. Принимающий депозитарийВыбирается из справочника участников M2M, который bj получает от НРД. Если депозитария нет в справочнике, перевод через MOEX МОСТ невозможен. Счёт у принимающегоДля сведения: принимающий депозитарий сам находит клиента по документу. - Место расчётовНРД или СПБ Банк — как в поручении клиента. + Место расчётовНРД. Сведения о расходахОтметьте, если клиент просит передать сведения о расходах на приобретение бумаг.

Если после сверки или отметок изменить данные поручения, сверка и отметки сбросятся: их нужно пройти заново.

diff --git a/internal/lkgateway/web/templates/admin_manual.html b/internal/lkgateway/web/templates/admin_manual.html index e550f8b..7cd55a4 100644 --- a/internal/lkgateway/web/templates/admin_manual.html +++ b/internal/lkgateway/web/templates/admin_manual.html @@ -37,6 +37,12 @@ .mf-hit{display:flex;justify-content:space-between;gap:10px;flex-wrap:wrap;align-items:center;padding:7px 0;border-top:1px solid var(--border)} .mf-pos{display:block;width:100%;text-align:left;padding:7px 10px;margin:3px 0;border-radius:8px;border:1px solid var(--border);background:var(--card);color:var(--text);cursor:pointer;font-size:13px} .mf-pos:hover:not([disabled]){border-color:var(--accent)}.mf-pos[disabled]{opacity:.5;cursor:not-allowed} + .hb-box{position:relative} + .hb-res{margin-top:4px;max-height:300px;overflow:auto;border-radius:8px} + .hb-res:empty{display:none} + .hb-hit{display:block;width:100%;text-align:left;padding:7px 10px;margin:2px 0;border-radius:8px;border:1px solid var(--border);background:var(--card);color:var(--text);cursor:pointer;font-size:13px} + .hb-hit:hover{border-color:var(--accent)} + .hb-m{color:var(--muted);font-size:12px} .mf-sign{display:grid;grid-template-columns:1fr 1fr;gap:40px;margin-top:40px} .mf-sign div{border-top:1px solid #000;padding-top:4px;font-size:12px} @media print{ @@ -114,7 +120,7 @@
Документ
код {{$o.DocType}} · {{$o.DocSeries}} № {{$o.DocNumber}}{{if $o.DocIssueDate}} · выдан {{$o.DocIssueDate}}{{end}}{{if $o.DocIssuer}} · {{$o.DocIssuer}}{{end}}
Счёт депо / договор
{{$o.Account}}{{if $o.Contract}} · договор {{$o.Contract}}{{end}}{{if $o.QuikCode}} · код в торговой системе {{$o.QuikCode}}{{end}}
Принимающий депозитарий
{{$o.RecvName}} · ИНН {{$o.RecvINN}}{{if $o.RecvCode}} · {{$o.RecvCode}}{{end}}{{if $o.RecvAccount}} · счёт клиента {{$o.RecvAccount}}{{end}}
-
Место расчётов
{{if eq $o.SettlePlace "spb"}}СПБ Банк{{else}}НРД{{end}}{{if $o.CostInfo}} · со сведениями о расходах{{end}}
+
Место расчётов
НРД{{if $o.CostInfo}} · со сведениями о расходах{{end}}
Бумаги
{{range $o.Securities}}
{{.ISIN}}{{if .Code}} ({{.Code}}){{end}}{{if .Name}} — {{.Name}}{{end}} × {{.Qty}}
{{end}}
{{if $o.Comment}}
Комментарий
{{$o.Comment}}
{{end}} {{if $o.GUID}}
Идентификатор перевода
{{$o.GUID}}, отправлено {{msk $o.SentAt}} · {{$o.SentBy}}
{{end}} @@ -332,17 +338,15 @@ function mfRerun(){const f=document.getElementById('mf');if(f&&f.closest('detail
4. Принимающая сторона
-
- +
+ +
{{if not .Handbook}}Справочник участников ещё не получен от НРД — введите ИНН вручную.{{end}}
-
+

Бумаги списываются с нашего места хранения в НРД: {{if .NSD.DeponentCode}}депонент {{.NSD.DeponentCode}}, счёт {{.NSD.AccountID}}, раздел {{.NSD.SectionID}}{{else}}реквизиты не заданы в настройках НРД{{end}}.

@@ -387,6 +391,24 @@ async function mfPick(i,j){ } let mfPos=[]; function mfSec(k){const p=mfPos[k];document.getElementById('f_isin').value=p.isin;document.getElementById('f_sname').value=p.name;const q=document.getElementById('f_qty');q.placeholder='доступно '+p.qty;q.focus()} -function mfPickHB(s){const o=s.options[s.selectedIndex];if(!o.value)return;document.getElementById('recv_inn').value=o.value;document.getElementById('recv_name').value=o.dataset.name||''} +// hbFind — подбор участника справочника НРД по ИНН, названию или коду (без учёта регистра и кавычек). +function hbNorm(s){return String(s||'').toLowerCase().replace(/ё/g,'е').replace(/[«»"'“”.,()]/g,' ').replace(/\s+/g,' ').trim()} +function hbFind(list,q){q=hbNorm(q);if(q.length<2)return[];const words=q.split(' '); + return list.map(p=>{const hay=hbNorm([p.inn,p.code,p.name,p.full_name,p.display_name,p.eng_name].join(' ')); + if(!words.every(w=>hay.includes(w)))return null; + const score=(String(p.inn).startsWith(q)||String(p.code).toLowerCase().startsWith(q)?0:hbNorm(p.name).startsWith(q)||hbNorm(p.display_name).startsWith(q)?1:2)+(p.kind==='depo'?0:0.5); + return {p,score}}).filter(Boolean).sort((a,b)=>a.score-b.score).slice(0,12).map(x=>x.p)} +function hbBind(inp,box,list,onPick){ + const esc=s=>String(s??'').replace(/[&<>"]/g,c=>({'&':'&','<':'<','>':'>','"':'"'}[c])); + let hits=[]; + const draw=()=>{hits=hbFind(list,inp.value);box.innerHTML=inp.value.trim().length<2?'':(hits.length?hits.map((p,i)=>'').join(''):'
В справочнике не найдено — введите ИНН и наименование в поля ниже.
')}; + inp.addEventListener('input',draw); + inp.addEventListener('keydown',e=>{if(e.key==='Enter'){e.preventDefault();if(hits[0]){onPick(hits[0]);box.innerHTML=''}}if(e.key==='Escape')box.innerHTML=''}); + box.addEventListener('click',e=>{const b=e.target.closest('.hb-hit');if(!b)return;onPick(hits[+b.dataset.i]);box.innerHTML=''}); +} +{ + const inp=document.getElementById('hbq'); + if(inp)hbBind(inp,document.getElementById('hbres'),{{.Handbook}}||[],p=>{document.getElementById('recv_inn').value=p.inn;document.getElementById('recv_name').value=p.name;inp.value=p.name+' · ИНН '+p.inn}) +} {{end}} diff --git a/internal/lkgateway/web/templates/admin_setup.html b/internal/lkgateway/web/templates/admin_setup.html index 58682be..4eacb87 100644 --- a/internal/lkgateway/web/templates/admin_setup.html +++ b/internal/lkgateway/web/templates/admin_setup.html @@ -479,11 +479,38 @@ {{else}}

Организация не задана — переводы не будут сформированы.

{{end}}
- - + + +
+ + {{if not .Participants}}Справочник участников ещё не получен — запросите его в «Диагностике» или введите данные вручную.{{end}}