Своя организация в настройках (справочник НРД или вручную) вместо зашитого ИНН; ручной ввод: поиск клиента и бумаг в DEPO, одна бумага на поручение
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -31,6 +31,12 @@
|
||||
.mf-kv{display:grid;grid-template-columns:minmax(150px,220px) 1fr;gap:4px 14px;font-size:13.5px}
|
||||
.mf-kv .k{color:var(--muted)}
|
||||
.dc-ok{color:var(--ok);font-weight:700}.dc-bad{color:var(--err);font-weight:700}.dc-warn{color:var(--warn);font-weight:700}
|
||||
.mf-find{background:var(--card-2);border:1px solid var(--border);border-radius:10px;padding:10px;margin-bottom:10px}
|
||||
.mf-find input{padding:7px 9px;border-radius:8px;border:1px solid var(--border);background:var(--card);color:var(--text);font-size:13.5px}
|
||||
.mf-res:empty{display:none}.mf-res{margin:8px 0}
|
||||
.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}
|
||||
.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{
|
||||
@@ -291,12 +297,20 @@ function mfRerun(){const f=document.getElementById('mf');if(f&&f.closest('detail
|
||||
</div>
|
||||
|
||||
<div class="mf-h">2. Клиент (как в поручении и анкете депонента)</div>
|
||||
{{if .DepoOn}}
|
||||
<div class="mf-find">
|
||||
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
||||
<input id="dq" placeholder="Фамилия (или ФИО), либо серия и номер документа" style="flex:1;min-width:260px" onkeydown="if(event.key==='Enter'){event.preventDefault();mfFind()}">
|
||||
<button type="button" class="btn" onclick="mfFind()">Найти в DEPO</button>
|
||||
</div>
|
||||
<div id="dres" class="mf-res"></div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="mf-grid">
|
||||
<div><label class="mf-req">Вид документа</label>
|
||||
<select name="doc_type">{{$dt := .O.DocType}}{{range .DocTypes}}<option value="{{.Code}}" {{if eq $dt .Code}}selected{{end}}>{{.Code}} — {{.Title}}</option>{{end}}</select></div>
|
||||
<div><label>Серия</label><input name="doc_series" value="{{.O.DocSeries}}" placeholder="4 цифры для паспорта РФ"></div>
|
||||
<div><label class="mf-req">Номер</label><input name="doc_number" value="{{.O.DocNumber}}"></div>
|
||||
<div style="display:flex;align-items:flex-end">{{if .DepoOn}}<button type="submit" name="do" value="lookup" class="btn btn-secondary" style="width:100%" title="Найти клиента в учётной системе по документу и заполнить пустые поля">Найти в DEPO по документу</button>{{end}}</div>
|
||||
<div><label>Дата выдачи</label><input type="date" name="doc_issue_date" value="{{.O.DocIssueDate}}"></div>
|
||||
<div class="wide"><label>Кем выдан</label><input name="doc_issuer" value="{{.O.DocIssuer}}"></div>
|
||||
<div><label class="mf-req">Фамилия</label><input name="last_name" value="{{.O.LastName}}"></div>
|
||||
@@ -304,20 +318,17 @@ function mfRerun(){const f=document.getElementById('mf');if(f&&f.closest('detail
|
||||
<div><label>Отчество</label><input name="middle_name" value="{{.O.MiddleName}}"></div>
|
||||
<div><label class="mf-req">Дата рождения</label><input type="date" name="birth_date" value="{{.O.BirthDate}}"></div>
|
||||
<div><label>Договор (брокерский / депозитарный)</label><input name="contract" value="{{.O.Contract}}"></div>
|
||||
<div><label class="mf-req">Счёт депо клиента</label><input name="account" value="{{.O.Account}}" placeholder="торговый счёт депо"></div>
|
||||
<div><label class="mf-req">Счёт депо клиента</label><input name="account" id="f_account" value="{{.O.Account}}" placeholder="торговый счёт депо"></div>
|
||||
<div><label>Код клиента в торговой системе</label><input name="quik_code" value="{{.O.QuikCode}}"></div>
|
||||
<div><label>Телефон для связи</label><input name="phone" value="{{.O.Phone}}"></div>
|
||||
</div>
|
||||
|
||||
<div class="mf-h">3. Ценные бумаги</div>
|
||||
<div class="mf-h">3. Ценная бумага</div>
|
||||
<div id="dpos" class="mf-res"></div>
|
||||
<div class="mf-sec mf-note" style="margin-bottom:2px"><span class="mf-req">ISIN</span><span>Код НРД</span><span class="nm">Наименование</span><span class="mf-req">Количество</span><span></span></div>
|
||||
<div id="secs">
|
||||
{{range .O.Securities}}
|
||||
<div class="mf-sec"><input name="sec_isin" value="{{.ISIN}}" placeholder="RU…" maxlength="12"><input name="sec_code" value="{{.Code}}" placeholder="необязательно"><input class="nm" name="sec_name" value="{{.Name}}" placeholder="заполнится из DEPO"><input name="sec_qty" value="{{.Qty}}" inputmode="decimal"><button type="button" class="x" onclick="mfDel(this)" title="Убрать">×</button></div>
|
||||
{{end}}
|
||||
</div>
|
||||
<button type="button" class="btn btn-secondary" onclick="mfAdd()" style="margin-top:4px">+ Бумага</button>
|
||||
<p class="mf-note">Через MOEX МОСТ переводятся только российские выпуски (ISIN начинается с RU). Дробное количество — для паёв, через точку или запятую.</p>
|
||||
{{$sec := index .O.Securities 0}}
|
||||
<div class="mf-sec"><input name="sec_isin" id="f_isin" value="{{$sec.ISIN}}" placeholder="RU…" maxlength="12"><input name="sec_code" value="{{$sec.Code}}" placeholder="необязательно"><input class="nm" name="sec_name" id="f_sname" value="{{$sec.Name}}" placeholder="заполнится из DEPO"><input name="sec_qty" id="f_qty" value="{{$sec.Qty}}" inputmode="decimal"><span></span></div>
|
||||
<p class="mf-note">Одно поручение — одна бумага: на каждую бумагу оформляется отдельное поручение. Через MOEX МОСТ переводятся только российские выпуски (ISIN начинается с RU). Дробное количество — для паёв, через точку или запятую.</p>
|
||||
|
||||
<div class="mf-h">4. Принимающая сторона</div>
|
||||
<div class="mf-grid">
|
||||
@@ -345,10 +356,37 @@ function mfRerun(){const f=document.getElementById('mf');if(f&&f.closest('detail
|
||||
<a href="/admin/manual" class="btn btn-secondary">К списку</a>
|
||||
</div>
|
||||
</form>
|
||||
<template id="secRow"><div class="mf-sec"><input name="sec_isin" placeholder="RU…" maxlength="12"><input name="sec_code" placeholder="необязательно"><input class="nm" name="sec_name" placeholder="заполнится из DEPO"><input name="sec_qty" inputmode="decimal"><button type="button" class="x" onclick="mfDel(this)" title="Убрать">×</button></div></template>
|
||||
<script>
|
||||
function mfAdd(){document.getElementById('secs').appendChild(document.getElementById('secRow').content.cloneNode(true))}
|
||||
function mfDel(b){const rows=document.querySelectorAll('#secs .mf-sec');if(rows.length>1){b.parentNode.remove()}else{b.parentNode.querySelectorAll('input').forEach(i=>i.value='')}}
|
||||
const mfEsc=s=>String(s??'').replace(/[&<>"]/g,c=>({'&':'&','<':'<','>':'>','"':'"'}[c]));
|
||||
let mfFaces=[];
|
||||
function mfSet(n,v){const e=document.querySelector('#mf [name="'+n+'"]');if(e&&v!==undefined&&v!==null)e.value=v}
|
||||
async function mfFind(){
|
||||
const q=document.getElementById('dq').value.trim(),box=document.getElementById('dres');
|
||||
box.innerHTML='<span class="mf-note">Поиск…</span>';
|
||||
try{const r=await (await fetch('/admin/manual/depo/search?q='+encodeURIComponent(q))).json();
|
||||
if(r.error){box.innerHTML='<span class="dc-bad">'+mfEsc(r.error)+'</span>';return}
|
||||
mfFaces=r.items||[];
|
||||
box.innerHTML=mfFaces.map((f,i)=>'<div class="mf-hit"><div><b>'+mfEsc(f.name)+'</b><div class="mf-note">'+(f.birth?'д.р. '+mfEsc(f.birth)+' · ':'')+'документ '+mfEsc(f.doc_ser)+' '+mfEsc(f.doc_num)+'</div></div><div style="display:flex;gap:6px;flex-wrap:wrap">'+
|
||||
(f.accounts||[]).map((a,j)=>'<button type="button" class="btn btn-secondary" onclick="mfPick('+i+','+j+')"'+(a.iis?' title="ИИС — перевод через M2M не выполняется"':'')+'>'+mfEsc(a.number)+(a.contract?' · '+mfEsc(a.contract):'')+(a.iis?' · ИИС':'')+'</button>').join('')+'</div></div>').join('');
|
||||
}catch(e){box.innerHTML='<span class="dc-bad">Поиск не выполнен: '+mfEsc(e)+'</span>'}
|
||||
}
|
||||
async function mfPick(i,j){
|
||||
const f=mfFaces[i],a=f.accounts[j];
|
||||
mfSet('last_name',f.last_name);mfSet('first_name',f.first_name);mfSet('middle_name',f.middle_name||'');mfSet('birth_date',f.birth||'');
|
||||
if(f.doc_type)mfSet('doc_type',f.doc_type);
|
||||
mfSet('doc_series',f.doc_ser||'');mfSet('doc_number',f.doc_num);mfSet('doc_issue_date',f.doc_date||'');mfSet('doc_issuer',f.doc_issuer||'');
|
||||
mfSet('account',a.number);mfSet('contract',a.contract||'');if(f.phone)mfSet('phone',f.phone);
|
||||
document.getElementById('dres').innerHTML='<span class="dc-ok">Подставлено из DEPO: '+mfEsc(f.name)+', счёт '+mfEsc(a.number)+'. Сверьте с поручением клиента.</span>';
|
||||
const box=document.getElementById('dpos');box.innerHTML='<span class="mf-note">Загрузка бумаг клиента…</span>';
|
||||
try{const r=await (await fetch('/admin/manual/depo/positions?client='+a.client_id)).json();
|
||||
if(r.error){box.innerHTML='<span class="dc-bad">'+mfEsc(r.error)+'</span>';return}
|
||||
const items=r.items||[];mfPos=items;
|
||||
if(!items.length){box.innerHTML='<span class="mf-note">На торговом разделе счёта '+mfEsc(a.number)+' бумаг нет.</span>';return}
|
||||
box.innerHTML='<div class="mf-note" style="margin-bottom:4px">Бумаги на торговом разделе '+mfEsc(a.number)+' — выберите одну:</div>'+items.map((p,k)=>'<button type="button" class="mf-pos"'+(p.russian?'':' disabled title="иностранный выпуск — через M2M не переводится"')+' onclick="mfSec('+k+')"><b>'+mfEsc(p.isin)+'</b> '+mfEsc(p.name)+' <span class="mf-note">· '+p.qty+' шт.</span></button>').join('');
|
||||
}catch(e){box.innerHTML='<span class="dc-bad">'+mfEsc(e)+'</span>'}
|
||||
}
|
||||
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||''}
|
||||
</script>
|
||||
{{end}}
|
||||
|
||||
Reference in New Issue
Block a user