mirror of
https://github.com/wasrusgen/zashita-brandbook.git
synced 2026-06-03 14:24:48 +00:00
feat: damage estimate shown inline in audit gaps + doc checklist + Sokolov ready
This commit is contained in:
parent
f4136f6d31
commit
383c74f706
135
mockup.html
135
mockup.html
@ -8076,6 +8076,55 @@ function _initOrgUser() {
|
||||
_updateSidebarUser();
|
||||
}
|
||||
|
||||
// ── ИЗВЛЕЧЕНИЕ ПАРАМЕТРОВ ДОГОВОРА ───────────────────────────────────────────
|
||||
|
||||
function _extractContractParams(contractType) {
|
||||
var params = {};
|
||||
// 1. Из загруженного договора (_DEADLINES и contracts store)
|
||||
var contracts = _getContracts();
|
||||
if (contracts.length) {
|
||||
var c = contracts.find(function(x){ return (x.type||'').toLowerCase().includes(contractType); }) || contracts[0];
|
||||
if (c) {
|
||||
// Пробуем вытащить суммы из preview
|
||||
var text = (c.preview || '') + ' ' + (c.type || '');
|
||||
var amtMatch = text.match(/(\d[\d\s]{3,})\s*(?:руб|₽)/i);
|
||||
if (amtMatch) params.amount = parseInt(amtMatch[1].replace(/\s/g,''));
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Из истории чата — ищем суммы
|
||||
var history = _chatHistory.slice(-10).map(function(m){ return m.content||''; }).join(' ');
|
||||
var deposits = history.match(/депозит[а-я\s]*(\d[\d\s]+)\s*(?:руб|₽|тыс|к₽)/i);
|
||||
if (deposits) params.deposit = parseInt(deposits[1].replace(/\s/g,'')) * (history.match(/тыс|к₽/) ? 1000 : 1);
|
||||
|
||||
var days_match = history.match(/(\d+)\s*(?:день|дней|дня)/i);
|
||||
if (days_match) params.days = parseInt(days_match[1]);
|
||||
|
||||
// 3. Из активных дедлайнов
|
||||
if (typeof _DEADLINES !== 'undefined' && _DEADLINES.length) {
|
||||
var dl = _DEADLINES[0];
|
||||
if (dl && dl.date) {
|
||||
var diff = Math.round((new Date(dl.date) - new Date()) / 86400000);
|
||||
params.days = Math.abs(diff);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Из b2b-реквизитов
|
||||
try {
|
||||
var b2b = JSON.parse(localStorage.getItem('zashita_b2b') || 'null');
|
||||
if (b2b && b2b.amount) params.amount = b2b.amount;
|
||||
} catch(e){}
|
||||
|
||||
// Дефолты по типу
|
||||
if (!params.amount) {
|
||||
var defaults = { аренда: 80000, подряд: 500000, 'купля-продажа': 300000, трудовой: 60000, займ: 100000, дду: 5000000 };
|
||||
params.amount = defaults[contractType] || 100000;
|
||||
}
|
||||
if (!params.deposit && contractType === 'аренда') params.deposit = params.amount;
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
// ── КАРТА ДЕЛА ───────────────────────────────────────────────────────────────
|
||||
|
||||
var _CASE_NOTES_KEY = 'zashita_case_notes';
|
||||
@ -8722,6 +8771,54 @@ function _showAuditGaps(contractType, intent) {
|
||||
});
|
||||
}
|
||||
|
||||
// ── РАСЧЁТ УЩЕРБА INLINE ──
|
||||
// Запускаем /api/estimate чтобы показать финансовый риск прямо в блоке
|
||||
var _contractParams = _extractContractParams(contractType);
|
||||
var _situationText = _chatHistory.slice(-6).map(function(m){ return m.content||''; }).join(' ');
|
||||
|
||||
fetch(API_BASE + '/api/estimate', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type':'application/json'},
|
||||
body: JSON.stringify({
|
||||
situation: _situationText,
|
||||
contract_type: contractType,
|
||||
contract_params: _contractParams,
|
||||
history: _chatHistory.slice(-4)
|
||||
})
|
||||
})
|
||||
.then(function(r){ return r.json(); })
|
||||
.then(function(est) {
|
||||
if (!est.damage_min && !est.damage_max) return;
|
||||
var dmgDiv = document.getElementById('audit-damage');
|
||||
if (dmgDiv) dmgDiv.remove();
|
||||
var dmg = document.createElement('div');
|
||||
dmg.id = 'audit-damage';
|
||||
dmg.className = 'hc-msg hc-elena';
|
||||
var minF = (est.damage_min||0).toLocaleString('ru');
|
||||
var maxF = (est.damage_max||0).toLocaleString('ru');
|
||||
dmg.innerHTML =
|
||||
'<img class="hc-av" src="logos/elena-photo.jpg">' +
|
||||
'<div class="hc-bubble" style="max-width:480px">' +
|
||||
'<div style="font-size:12px;color:var(--mut);margin-bottom:6px">Финансовый риск при текущем состоянии документов:</div>' +
|
||||
'<div style="background:#fef2f2;border:1.5px solid #fca5a5;border-radius:10px;padding:12px 16px;margin-bottom:10px">' +
|
||||
'<div style="font-size:12px;color:#6b7280;margin-bottom:2px">Примерный ущерб</div>' +
|
||||
'<div style="font-family:var(--font-logo,\'Montserrat\');font-size:22px;font-weight:900;color:#dc2626">' +
|
||||
minF + ' — ' + maxF + ' ₽' +
|
||||
'</div>' +
|
||||
(est.damage_comment ? '<div style="font-size:11px;color:#6b7280;margin-top:4px">' + est.damage_comment + '</div>' : '') +
|
||||
(est.damage_formula ? '<div style="font-size:11px;color:#9ca3af;margin-top:2px">Формула: ' + est.damage_formula + '</div>' : '') +
|
||||
'</div>' +
|
||||
(est.summary ? '<div style="font-size:13px;color:#374151">' + est.summary + '</div>' : '') +
|
||||
'</div>';
|
||||
var msgs2 = document.getElementById('rchat-msgs');
|
||||
if (msgs2) { msgs2.appendChild(dmg); dmg.scrollIntoView({behavior:'smooth'}); }
|
||||
// Сохраняем в карту дела
|
||||
_addCaseNote('risk', 'Расчётный ущерб: ' + minF + '–' + maxF + '₽ · ' + (est.damage_comment||''), {contractType: contractType});
|
||||
// После показа ущерба — оффер услуги
|
||||
setTimeout(function(){ _checkAndOfferService(msgs2); }, 1500);
|
||||
})
|
||||
.catch(function(){});
|
||||
|
||||
// Кнопки: исправить + ПРИНЯТЬ РИСКИ И ПРОДОЛЖИТЬ
|
||||
gapsHtml += '<div style="margin-top:14px">';
|
||||
|
||||
@ -8787,11 +8884,16 @@ function _acknowledgeRisksAndProceed(contractType, intent) {
|
||||
_rcAddBubble(reply, false);
|
||||
if (apiActions && apiActions.length) _renderElenaActions(apiActions, msgs);
|
||||
|
||||
// Небольшая пауза → запускаем оффер услуги
|
||||
// Небольшая пауза → аудит документов (Блок Д) → потом оффер
|
||||
var detectedType = _detectContractType(ctx + ' ' + reply);
|
||||
setTimeout(function(){
|
||||
var wrap = document.querySelector('.chatwrap') || msgs;
|
||||
_checkAndOfferService(wrap);
|
||||
}, 1500);
|
||||
if (detectedType) {
|
||||
_showDocAuditInChat(detectedType, intent);
|
||||
} else {
|
||||
var wrap2 = document.querySelector('.chatwrap') || msgs;
|
||||
_checkAndOfferService(wrap2);
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
_rcShowControls();
|
||||
});
|
||||
@ -8972,6 +9074,31 @@ function renderDocChecklist(contractType) {
|
||||
});
|
||||
html += '</div>';
|
||||
|
||||
// Расчёт ущерба по пробелам
|
||||
if (missing.length && _apiAvailable) {
|
||||
var params = _extractContractParams(key);
|
||||
var situation = 'Договор ' + key + '. Отсутствуют документы: ' + missing.map(function(d){ return d.label; }).join(', ');
|
||||
fetch(API_BASE + '/api/estimate', {
|
||||
method: 'POST', headers: {'Content-Type':'application/json'},
|
||||
body: JSON.stringify({ situation: situation, contract_type: key, contract_params: params, history: [] })
|
||||
})
|
||||
.then(function(r){ return r.json(); })
|
||||
.then(function(est) {
|
||||
if (!est.damage_min) return;
|
||||
var dmgEl = document.getElementById('checklist-damage');
|
||||
if (!dmgEl) return;
|
||||
var minF = (est.damage_min||0).toLocaleString('ru');
|
||||
var maxF = (est.damage_max||0).toLocaleString('ru');
|
||||
dmgEl.innerHTML =
|
||||
'<div style="background:#fef2f2;border:1.5px solid #fca5a5;border-radius:10px;padding:12px 16px;margin-top:12px">' +
|
||||
'<div style="font-size:11px;color:#6b7280;margin-bottom:3px">Примерный ущерб при текущих пробелах</div>' +
|
||||
'<div style="font-size:20px;font-weight:900;color:#dc2626;font-family:inherit">' + minF + ' — ' + maxF + ' ₽</div>' +
|
||||
(est.damage_comment ? '<div style="font-size:11px;color:#6b7280;margin-top:3px">' + est.damage_comment + '</div>' : '') +
|
||||
'</div>';
|
||||
}).catch(function(){});
|
||||
}
|
||||
html += '<div id="checklist-damage"></div>';
|
||||
|
||||
// Кнопка загрузить недостающие
|
||||
if (missing.length) {
|
||||
html += '<div style="margin-top:16px;padding:12px;background:#fffbeb;border:1.5px solid #fcd34d;border-radius:10px;font-size:13px">' +
|
||||
|
||||
Loading…
Reference in New Issue
Block a user