From 9b0d0af2777cc5eae897ea13ff1e4806306be2c2 Mon Sep 17 00:00:00 2001 From: wasrusgen Date: Mon, 1 Jun 2026 08:00:44 +0300 Subject: [PATCH] =?UTF-8?q?ui:=20=D0=BF=D0=BE=D0=BB=D0=BD=D0=BE=D0=B5=20?= =?UTF-8?q?=D1=80=D0=B5=D0=B4=D0=B0=D0=BA=D1=82=D0=B8=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D0=B5=20=D1=81=D0=BC=D0=B5=D1=82=D1=8B=20?= =?UTF-8?q?=E2=80=94=20=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B0=20=D1=86=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D1=8D=D1=82=D0=B0=D0=BF=D0=B0,=20=D0=BE=D1=82?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D0=B0=20=D0=BE=D0=BF=D0=BB=D0=B0=D1=82=D1=8B?= =?UTF-8?q?,=20=D1=81=D0=B8=D0=BD=D1=85=D1=80=D0=BE=D0=BD=D0=B8=D0=B7?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D1=8F=20=D1=81=20=D1=80=D0=B5=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D1=80=D0=BE=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/crm.html | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/docs/crm.html b/docs/crm.html index a25fd24..0075c7e 100644 --- a/docs/crm.html +++ b/docs/crm.html @@ -499,6 +499,17 @@ async function confirmStagePay(k){ ]); 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(){ const box=document.getElementById("planBox");if(!box)return; const billing=(state.crm&&state.crm.billing_type)||"paid"; @@ -532,7 +543,7 @@ function renderPaymentPlan(){ ${CX_SHORT[cx]} -
Получено ${money(paidTotal)} из ${money(total)} · нажмите цену чтобы изменить
+
Получено ${money(paidTotal)} из ${money(total)} · — изменить цену · — отменить оплату · «↻ Пересчитать» сбрасывает к ставкам
${CLIENT_STAGES.map(s=>{ const done=stageIsDone(s.key); const paid=pays[s.key]; @@ -562,7 +573,7 @@ function renderPaymentPlan(){
${s.name}${badge}
${sub} - ${action} +
${action}${paid?``:''}
`; }).join("")}
@@ -649,7 +660,15 @@ function addPayment(){ } 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){ 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});