mirror of
https://github.com/wasrusgen/wasrusgen1-crm.git
synced 2026-06-03 19:04:47 +00:00
ui: полное редактирование сметы — правка цены этапа, отмена оплаты, синхронизация с реестром
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
24bd0e29d5
commit
9b0d0af277
@ -499,6 +499,17 @@ async function confirmStagePay(k){
|
|||||||
]);
|
]);
|
||||||
renderClient();
|
renderClient();
|
||||||
}
|
}
|
||||||
|
async function unStagePay(k){
|
||||||
|
const pays=getStagePays();if(!pays[k])return;
|
||||||
|
if(!confirm('Отменить оплату этапа «'+CLIENT_STAGES.find(s=>s.key===k).name+'»? Связанный платёж удалится из реестра.'))return;
|
||||||
|
delete pays[k];
|
||||||
|
state.crm.stage_payments=pays;
|
||||||
|
const arr=state.crm.payments||[];
|
||||||
|
for(let i=arr.length-1;i>=0;i--){if(arr[i].stage===k){arr.splice(i,1);break;}}
|
||||||
|
state.crm.payments=arr;
|
||||||
|
await fetch(`${API}/api/project/crm`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:current,stage_payments:pays,payments:arr})});
|
||||||
|
await loadProjects();renderClient();
|
||||||
|
}
|
||||||
function renderPaymentPlan(){
|
function renderPaymentPlan(){
|
||||||
const box=document.getElementById("planBox");if(!box)return;
|
const box=document.getElementById("planBox");if(!box)return;
|
||||||
const billing=(state.crm&&state.crm.billing_type)||"paid";
|
const billing=(state.crm&&state.crm.billing_type)||"paid";
|
||||||
@ -532,7 +543,7 @@ function renderPaymentPlan(){
|
|||||||
<span style="font-size:11px;font-weight:700;color:var(--primary);background:#ECFDF5;padding:3px 9px;border-radius:6px">${CX_SHORT[cx]}</span>
|
<span style="font-size:11px;font-weight:700;color:var(--primary);background:#ECFDF5;padding:3px 9px;border-radius:6px">${CX_SHORT[cx]}</span>
|
||||||
<button class="cp-btn cp-r" style="padding:4px 9px;margin-left:auto" onclick="buildEstimate()">↻ Пересчитать</button>
|
<button class="cp-btn cp-r" style="padding:4px 9px;margin-left:auto" onclick="buildEstimate()">↻ Пересчитать</button>
|
||||||
</div>
|
</div>
|
||||||
<div style="font-size:11px;color:var(--muted);margin-bottom:12px">Получено <b style="color:var(--primary)">${money(paidTotal)}</b> из ${money(total)} · нажмите цену чтобы изменить</div>
|
<div style="font-size:11px;color:var(--muted);margin-bottom:12px">Получено <b style="color:var(--primary)">${money(paidTotal)}</b> из ${money(total)} · <b>✎</b> — изменить цену · <b style="color:#DC2626">↺</b> — отменить оплату · «↻ Пересчитать» сбрасывает к ставкам</div>
|
||||||
${CLIENT_STAGES.map(s=>{
|
${CLIENT_STAGES.map(s=>{
|
||||||
const done=stageIsDone(s.key);
|
const done=stageIsDone(s.key);
|
||||||
const paid=pays[s.key];
|
const paid=pays[s.key];
|
||||||
@ -562,7 +573,7 @@ function renderPaymentPlan(){
|
|||||||
<div style="font-weight:700;font-size:13px;color:${done||isFree?'var(--text)':'#9CA3AF'}">${s.name}${badge}</div>
|
<div style="font-weight:700;font-size:13px;color:${done||isFree?'var(--text)':'#9CA3AF'}">${s.name}${badge}</div>
|
||||||
${sub}
|
${sub}
|
||||||
</div>
|
</div>
|
||||||
${action}
|
<div style="display:flex;align-items:center;gap:7px">${action}<span onclick="event.stopPropagation();editStagePrice('${s.key}')" title="Изменить цену этапа" style="cursor:pointer;color:#9CA3AF;font-size:14px;line-height:1">✎</span>${paid?`<span onclick="event.stopPropagation();unStagePay('${s.key}')" title="Отменить оплату" style="cursor:pointer;color:#DC2626;font-size:14px;line-height:1">↺</span>`:''}</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
}).join("")}
|
}).join("")}
|
||||||
<div style="display:flex;align-items:center;gap:10px;padding:12px 0 2px;border-top:2px solid var(--bg);margin-top:4px">
|
<div style="display:flex;align-items:center;gap:10px;padding:12px 0 2px;border-top:2px solid var(--bg);margin-top:4px">
|
||||||
@ -649,7 +660,15 @@ function addPayment(){
|
|||||||
}
|
}
|
||||||
savePayments();renderClient();
|
savePayments();renderClient();
|
||||||
}
|
}
|
||||||
function delPayment(i){state.crm.payments.splice(i,1);savePayments();renderClient();}
|
function delPayment(i){
|
||||||
|
const removed=state.crm.payments[i];
|
||||||
|
state.crm.payments.splice(i,1);
|
||||||
|
if(removed&&removed.stage&&state.crm.stage_payments){
|
||||||
|
const stillPaid=state.crm.payments.some(p=>p.stage===removed.stage);
|
||||||
|
if(!stillPaid)delete state.crm.stage_payments[removed.stage];
|
||||||
|
}
|
||||||
|
savePayments();renderClient();
|
||||||
|
}
|
||||||
function remindBalance(left){
|
function remindBalance(left){
|
||||||
const due=new Date(Date.now()+7*864e5).toISOString().slice(0,10);
|
const due=new Date(Date.now()+7*864e5).toISOString().slice(0,10);
|
||||||
state.tasks=state.tasks||[];state.tasks.push({text:`Получить остаток ${money(left)} от ${state.client_name||'клиента'}`,due,done:false});
|
state.tasks=state.tasks||[];state.tasks.push({text:`Получить остаток ${money(left)} от ${state.client_name||'клиента'}`,due,done:false});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user