var _tk=localStorage.getItem("mol_tok")||"",ieData=[],smData=[],charts={}; function $(id){return document.getElementById(id)} function money(n){return Math.round(n||0).toLocaleString("uz-UZ")} function sh(n){n=Math.round(n||0);return n>=1e9?(n/1e9).toFixed(1)+"mlrd":n>=1e6?(n/1e6).toFixed(1)+"mln":n>=1e3?Math.round(n/1e3)+"ming":String(n)} function esc(v){return String(v==null?"":v).replace(/[&<>"']/g,function(c){return {"&":"&","<":"<",">":">",'"':""","'":"'"}[c]})} function ntf(t,c){var e=$("toast");e.textContent=t;e.style.background=c||"#172033";e.style.display="block";clearTimeout(e._t);e._t=setTimeout(function(){e.style.display="none"},2600)} function dC(id){if(charts[id]){charts[id].destroy();delete charts[id]}} var stC={"jarayonda":["#fef9c3","#854d0e"],"yetkazildi":["#dbeafe","#1e40af"],"yopilgan":["#dcfce7","#166534"],"bekor":["#fee2e2","#991b1b"],"jarima":["#fee2e2","#991b1b"],"olingan":["#dcfce7","#166534"]}; function stBd(s){var c=stC[s]||["#e2e8f0","#334155"];return ''+esc(s)+''} function employeeOptions(selectedId){ var sel=String(selectedId||""); var html=''; (empData||[]).forEach(function(e){ html+=''; }); return html; } function fillIEEmployeeSelects(item){ item=item||{}; if($("ieSalesResp"))$("ieSalesResp").innerHTML=employeeOptions(item.sales_responsible_id||""); if($("ieVedResp"))$("ieVedResp").innerHTML=employeeOptions(item.ved_responsible_id||""); if($("ieInstallResp"))$("ieInstallResp").innerHTML=employeeOptions(item.installation_responsible_id||""); } // AUTH async function api(r,mt,bd){ mt=mt||"GET"; // r ichida query param bo'lishi mumkin: "tabel?oy=2026-06" var rParts=r.split("?"); var resource=rParts[0]; var extra=rParts[1]?"&"+rParts[1]:""; var q="r="+encodeURIComponent(resource)+extra; var o={method:mt,headers:{"Content-Type":"application/json","X-Token":_tk},credentials:"include"}; if(bd)o.body=JSON.stringify(bd); var res=await fetch("?"+q,o); var j=await res.json(); if(!j.ok){if(res.status===401&&r!=="login"){_tk="";localStorage.removeItem("mol_tok");showL()}throw new Error(j.error||"Xato")} return j.data } function showL(){$("lbg").style.display="flex";$("app").classList.remove("on")} function hideL(){$("lbg").style.display="none";$("app").classList.add("on");lchState("")} window.lchState = function(st){ var el=document.querySelector(".lch"); if(!el)return; el.className="lch"+(st?" "+st:""); }; // Tabel: yangilangan tezkor kiritish va ko'p belgilash. function tabelBulkSet(){ var m=document.createElement('div'); m.className='mbg open'; m.onclick=function(e){if(e.target===m)m.remove();}; var oy=$('tabelOy')?$('tabelOy').value:curOy(); var visible=empData.filter(function(e){return empActiveInMonth(e,oy);}); m.innerHTML='
'+ '
Ko\'p xodimga belgilash
'+ '
'+ '
'+ '
'+ ''+ ''+ ''+ ''+ ''+ ''+ '
'+ '
'+ '
'+ ''+ ''+ '
'+ ''+ '
'+ '
'+ '
'+ ''+ '
'; document.body.appendChild(m); } function bulkSelectEmps(on){ var empSel=$('bulk_emp');if(!empSel)return; for(var i=0;itoDate)continue; if($('bulk_work_only')&&$('bulk_work_only').checked&&!tabelIsWorkDay(dateStr))continue; selectedEmps.forEach(function(eid){ var emp=empData.find(function(x){return x.id===eid;}); if(emp&&empActiveOnDate(emp,dateStr))promises.push(api('tabel','POST',{emp_id:eid,sana:dateStr,holat:holat})); }); } try{ await Promise.all(promises); ntf("Qo'llandi: "+promises.length+" ta yozuv",'#10b981'); var modal=document.querySelector('.mbg.open:last-child');if(modal)modal.remove(); await loadTabel(); }catch(e){ntf(e.message,'#ef4444');} } async function setAllKeldi(){ var oy=$('tabelOy').value,parts=oy.split('-'),yr=+parts[0],mn=+parts[1],daysInMonth=new Date(yr,mn,0).getDate(); var visible=empData.filter(function(e){return empActiveInMonth(e,oy);}); var promises=[]; for(var d=1;d<=daysInMonth;d++){ var dateStr=yr+'-'+(mn<10?'0':'')+mn+'-'+(d<10?'0':'')+d; if(!tabelIsWorkDay(dateStr))continue; visible.forEach(function(e){ if(empActiveOnDate(e,dateStr))promises.push(api('tabel','POST',{emp_id:e.id,sana:dateStr,holat:'K'})); }); } try{ await Promise.all(promises); ntf("Hamma faol xodim uchun K qo'yildi ("+promises.length+" ta)",'#10b981'); await loadTabel(); }catch(e){ntf(e.message,'#ef4444');} } async function doLogin(){ var b=$("lb"),e=$("le"); var user=$("lu").value.trim(); var pass=$("lp").value; if(!user){e.textContent="Login kiriting";e.style.display="block";$("lu").focus();return} if(!pass){e.textContent="Parol kiriting";e.style.display="block";$("lp").focus();return} b.classList.add("loading");b.innerHTML="";e.style.display="none"; try{ var d=await api("login","POST",{username:user,password:pass}); _tk=d.token;localStorage.setItem("mol_tok",_tk); b.classList.remove("loading");b.classList.add("success"); b.textContent="Muvaffaqiyatli!"; lchState("happy"); setTimeout(function(){ $("lbg").style.opacity="0";$("lbg").style.transition="opacity .4s"; setTimeout(function(){hideL();$("lbg").style.opacity="1";b.classList.remove("success");b.textContent="Kirish";},400); },600); await loadAll(); }catch(x){ b.classList.remove("loading"); b.textContent="Kirish"; e.textContent=x.message;e.style.display="block"; $("lp").value=""; lchState("sad"); setTimeout(function(){lchState("")},3000); $("lp").focus(); } } async function doLogout(){try{await api("logout","POST")}catch(x){}_tk="";localStorage.removeItem("mol_tok");showL()} async function openLogs(){ try{ var d=await api("logs"); var html='
'; (d||[]).forEach(function(l){ html+=''; }); html+='
VaqtLoginIPHolatSabab
'+esc(l.created_at)+''+esc(l.username)+''+esc(l.ip||'-')+''+( l.success?'OK':'Rad')+''+esc(l.reason||'')+'
'; var m=document.createElement('div');m.className='mbg open';m.onclick=function(e){if(e.target===m)m.remove()}; m.innerHTML='
Kirish tarixi
'+html+'
'; document.body.appendChild(m); }catch(x){ntf(x.message,'#ef4444')} } function openPass(){$("pM").classList.add("open")}function clP(){$("pM").classList.remove("open")} async function chP(){var n=$("pN").value;if(n!==$("pR").value)return ntf("Mos emas","#f59e0b");if(n.length<4)return ntf("Min 4","#f59e0b");try{await api("chg","POST",{old:$("pO").value,new:n});clP();ntf("Parol ozgartirildi","#10b981")}catch(x){ntf(x.message,"#ef4444")}} // ── VALYUTA KURSI ──────────────────────────── var _kursCache={USD:12850,EUR:14400}; async function fetchKurs(){ try{ var r=await fetch("https://cbu.uz/uz/arkhiv-kursov-valyut/json/"); var d=await r.json(); d.forEach(function(v){ if(v.Ccy==="USD")_kursCache.USD=parseFloat(v.Rate); if(v.Ccy==="EUR")_kursCache.EUR=parseFloat(v.Rate); }); }catch(x){console.warn("Kurs yuklanmadi, default ishlatiladi");} } fetchKurs(); // ── CUSTOMS.UZ QIDIRISH ────────────────────── async function cuzSearch(){ var idn=$("cuzIdn").value.trim(); if(!idn){ntf("IDN kiriting!","#f59e0b");return} if(idn.length<10){ntf("IDN juda qisqa","#f59e0b");return} var res=$("cuzResult"); res.style.display="block"; res.innerHTML='
Customs.uz dan qidirilmoqda...
'; try{ var d=await api("customs","POST",{idn:idn}); // Formani to'ldirish $("ieKl").value=d.contractorForName||d.contractorName||""; $("ieYn").value=d.contractorForName||d.contractorName||""; $("ieYd").value=d.contractorForCountryCode?ecCountry(d.contractorForCountryCode):(d.contractorCountry||""); $("ieKr").value=d.docNo||""; if(d.docDate){ var parts=(d.docDate+"").split("."); if(parts.length===3)$("ieKs").value=parts[2]+"-"+parts[1]+"-"+parts[0]; else $("ieKs").value=d.docDate; } // Valyuta var _cc=d.currCode1?ecCurr(d.currCode1):(d.currency||"UZS"); if(_cc&&_cc!=="UZS"){ $("ieValyuta").value=_cc; ieKursUpdate(); } // Summa var _am=d.amount1||d.amount||0; if(_am>0){ $("ieTovarVal").value=Math.round(_am); ieCalc(); } // Natijani korsatish res.innerHTML='
'+ '
Shartnoma topildi!
'+ '
'+ '
IDN: '+d.idn+'
'+ '
Raqam: '+(d.docNo||"-")+'
'+ '
Sana: '+(d.docDate||"-")+'
'+ '
Sherik: '+(d.contractorForName||d.contractorName||"-")+'
'+ '
Davlat: '+(d.contractorForCountryCode?ecCountry(d.contractorForCountryCode):(d.contractorCountry||"-"))+'
'+ '
Summa: '+money(Math.round(d.amount1||d.amount||0))+' '+(d.currCode1?ecCurr(d.currCode1):(d.currency||""))+'
'+ '
'; ntf("Shartnoma topildi va forma to\'ldirildi!","#10b981"); }catch(x){ res.innerHTML='
'+x.message+'
'; } } function ieKursUpdate(){ var v=$("ieValyuta").value; if(v==="UZS"){$("ieKurs").value="1";$("ieKurs").readOnly=true;} else{$("ieKurs").value=_kursCache[v]||1;$("ieKurs").readOnly=false;} ieCalc(); } // ── AVTOMATIK HISOB ────────────────────────── function ieCalc(){ var tovarVal=+$("ieTovarVal").value||0; var kurs=parseFloat($("ieKurs").value)||1; // Shartnoma summa: agar tovar narxi kiritilgan bo'lsa — avto hisoblash // Agar qolda kiritilgan bo'lsa — saqlab qolish var shartEl=$("ieShart"); if(tovarVal>0){ var shartSumma=Math.round(tovarVal*kurs); shartEl.value=shartSumma; } var shartSumma=+shartEl.value||0; var sotish=+$("ieSs").value||0; // Bank/Birja = Sotish * 0.15% var bankBirja=Math.round(sotish*0.0015); $("ieBb").value=bankBirja; // Xarajatlar var poshlina=+$("ieBp").value||0; var deklar=+$("ieDe").value||0; var sertXar=+$("ieSx").value||0; var metrXar=+$("ieMx").value||0; var transpXar=+$("ieTx").value||0; var saqlashXar=+$("ieSaq").value||0; var boshqaXar=+$("ieBx").value||0; // UMUMIY TANNARX = Shartnoma + xarajatlar (Boshqa xarajat KIRMAYDI!) var tannarx=shartSumma+bankBirja+poshlina+deklar+sertXar+metrXar+transpXar+saqlashXar; $("ieUt").value=tannarx; // NDS 12% = Sotish - (Sotish * 100 / 112) var nds=Math.round(sotish-(sotish*100/112)); $("ieNd").value=nds; // DAROMAD = Sotish - (Tannarx + NDS) var daromad=sotish-tannarx-nds; $("ieDr").value=daromad; // Foyda solighi 15% = Daromad * 15% (faqat foyda bo\'lsa) var foydaSoliq=daromad>0?Math.round(daromad*0.15):0; $("ieFs").value=foydaSoliq; // SOF FOYDA = Daromad - Foyda solighi - Boshqa xarajat var sofFoyda=daromad-foydaSoliq-boshqaXar; $("ieSofFoyda").value=sofFoyda; // Rang o\'zgartirish var sfEl=$("ieSofFoyda"); if(sofFoyda>=0){sfEl.style.color="#10b981";sfEl.style.borderColor="#10b981";} else{sfEl.style.color="#ef4444";sfEl.style.borderColor="#ef4444";} var drEl=$("ieDr"); if(daromad>=0){drEl.style.color="#10b981";}else{drEl.style.color="#ef4444";} } // ── SERTIFIKATGA NUSXALASH ─────────────────── async function copyToSM(ieItem){ if(!$("ieCopySM")||!$("ieCopySM").checked)return; try{ await api("sm","POST",{ status:"jarayonda", klient:ieItem.klient||"", mahsulot:ieItem.mahsulot||"", kontrakt_raqam:ieItem.kontrakt_raqam||"", bojxona_holat:ieItem.bojxona_holat||"", sert_status:"jarayonda", sert_info:"", sert_narx:ieItem.sertifikat_xar||0, sert_markaz:"",sert_shartnoma:"",sert_punkt:"", metro_status:"jarayonda", metro_info:"", metro_narx:ieItem.metrologiya_xar||0, metro_markaz:"",metro_shartnoma:"",metro_punkt:"", qoshimcha_xar:0, umumiy_narx:(ieItem.sertifikat_xar||0)+(ieItem.metrologiya_xar||0), masul:ieItem.masul||"", izoh:"" }); }catch(x){console.warn("SM nusxa xatosi:",x.message);} } function gT(id,el){ if(id==="ieAdd"){openIEForm(0);return} if(id==="smAdd"){openSMForm(0);return} if(id==="maosh"){id="xodimlar";setTimeout(function(){var b=document.querySelector(".sub-tab[onclick*='xt-list']");if(b)subTab("xt-list",b)},0)} if(id==="analitika"){id="dash";setTimeout(function(){var a=$("alertBanners");if(a)a.scrollIntoView({behavior:"smooth",block:"start"})},0)} document.querySelectorAll(".pg,.tab").forEach(function(x){x.classList.remove("on")}); var pg=$(id);if(pg)pg.classList.add("on"); el=el||document.querySelector('.tab[data-tab='+id+']'); if(el)el.classList.add("on"); if(id==="ie") { rIE(); } if(id==="sm") { rSM(); } if(id==="econ"&&!_ecTabOpened){ _ecTabOpened=true; ecLoad(); } if(id==="econ") { ecFilter(); ecStats(); ecCharts(); ecDebKred(); } if(id==="xodimlar"){ embedPayrollInEmployeeList(); fillOySel("maoshOy"); loadEmps(); loadMaosh(); } window.scrollTo({top:0,behavior:'smooth'}); } // LOAD async function loadAll(){ try{ieData=await api("ie")}catch(x){ieData=[];console.warn("IE yuklash:",x.message)} try{smData=await api("sm")}catch(x){smData=[];console.warn("SM yuklash:",x.message)} try{empData=await api("xodimlar")}catch(x){empData=[];console.warn("Xodim yuklash:",x.message)} try{tabelData=await api("tabel?oy="+curOy())||{}}catch(x){tabelData={}} try{avansData=await api("avanslar?oy="+curOy())||{}}catch(x){avansData={}} try{oyStavkaData=await api("oy-stavka?oy="+curOy())||{}}catch(x){oyStavkaData={}} try{maoshHisobData=await api("maosh-hisob?oy="+curOy())||{}}catch(x){maoshHisobData={}} try{rDash()}catch(x){console.warn("rDash xato:",x.message)} rIE();rSM(); if($("dXodim"))$("dXodim").textContent=empData.length; // Analitika tab ochiq bo'lsa yangilash if($("analitika")&&$("analitika").classList.contains('on'))loadAnalitika(); } // DASHBOARD function rDash(){ // Kontraktlar var allCnt=ieData.length+smData.length; var ieJar=ieData.filter(function(x){return x.status==="jarayonda"}).length; var smJar=smData.filter(function(x){return x.status==="jarayonda"}).length; var ieYop=ieData.filter(function(x){return x.status==="yopilgan"||x.status==="yetkazildi"}).length; var smYop=smData.filter(function(x){return x.status==="yopilgan"||x.status==="olingan"}).length; $("dAll").textContent=allCnt; $("dJar").textContent=ieJar+smJar;$("dJarS").textContent="IE:"+ieJar+" SM:"+smJar; $("dYop").textContent=ieYop+smYop; $("dSM").textContent=smData.length; var smJar2=smData.filter(function(x){return x.status==="jarayonda"}).length; $("dSMs").textContent=smJar2+" jarayonda"; // Deklaratsiya IM40/ND40 var dIM40=ieData.filter(function(x){return(x.bojxona_holat||"")==="IM40"}); var dIM70=ieData.filter(function(x){return(x.bojxona_holat||"")==="IM70"}); var dND40=ieData.filter(function(x){return(x.bojxona_holat||"")==="ND40"}); $("dIM40").textContent=dIM40.length+dND40.length; $("dIM40s").textContent="IM40:"+dIM40.length+" ND40:"+dND40.length; $("dOchiq").textContent=dIM40.filter(function(x){return x.status!=="yopilgan"&&x.status!=="yetkazildi"}).length+dIM70.length; // Moliya var tDar=ieData.reduce(function(s,x){return s+(x.daromad||0)},0); var tTan=ieData.reduce(function(s,x){return s+(x.umumiy_tannarx||0)},0); var tNds=ieData.reduce(function(s,x){return s+(x.nds||0)},0); var tFs=ieData.reduce(function(s,x){return s+(x.foyda_soliq||0)},0); var tBoshqa=ieData.reduce(function(s,x){return s+(x.boshqa_xar||0)},0); var foy=ieData.reduce(function(s,x){return s+((x.daromad||0)-(x.foyda_soliq||0)-(x.boshqa_xar||0))},0); $("dDar").textContent=sh(tDar);$("dTan").textContent=sh(tTan); $("dFoy").textContent=(foy<0?"-":"")+sh(Math.abs(foy));$("dFoy").className="vl "+(foy>=0?"gt":"rt"); $("dNDS").textContent=sh(tNds); $("dFS").textContent=sh(tFs); $("dSert").textContent=sh(smData.reduce(function(s,x){return s+(x.umumiy_narx||0)},0)); // Status pie var stMap={};ieData.forEach(function(x){stMap[x.status]=(stMap[x.status]||0)+1}); var sk=Object.keys(stMap); dC("cSt");if(sk.length){charts["cSt"]=new Chart($("cSt"),{type:"doughnut",data:{labels:sk,datasets:[{data:sk.map(function(k){return stMap[k]}),backgroundColor:sk.map(function(k){return(stC[k]||["#64748b"])[1]}),borderWidth:0}]},options:{responsive:true,maintainAspectRatio:false,cutout:"50%",plugins:{legend:{position:"right",labels:{color:"#94a3b8",font:{size:10}}}}}})} // Xarajat tarkibi var xLabels=["Bojxona","Bank/Birja","Sertifikat","Metrologiya","Transport","Boshqa"]; var xData=[ ieData.reduce(function(s,x){return s+x.bojxona_poshlina+x.deklaratsiya},0), ieData.reduce(function(s,x){return s+x.bank_birja},0), ieData.reduce(function(s,x){return s+x.sertifikat_xar},0), ieData.reduce(function(s,x){return s+x.metrologiya_xar},0), ieData.reduce(function(s,x){return s+x.transport_xar+x.saqlash_xar},0), ieData.reduce(function(s,x){return s+x.boshqa_xar},0) ]; dC("cXar");charts["cXar"]=new Chart($("cXar"),{type:"bar",data:{labels:xLabels,datasets:[{data:xData,backgroundColor:["#f59e0b","#3b82f6","#22d3ee","#a78bfa","#ec4899","#64748b"],borderRadius:5}]},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{display:false},tooltip:{callbacks:{label:function(c){return money(c.raw)+" som"}}}},scales:{x:{ticks:{color:"#94a3b8",font:{size:10}},grid:{display:false}},y:{ticks:{color:"#94a3b8",callback:function(v){return sh(v)}},grid:{color:"#1e293b"}}}}}); // Moliyaviy chart dC("cMol"); var molLabels=["Daromad","Tannarx","NDS","Foyda sol.","Boshqa","Sof foyda"]; var molData=[tDar,tTan,tNds,tFs,tBoshqa,Math.abs(foy)]; var molColors=["#10b981","#ef4444","#f59e0b","#a78bfa","#64748b",foy>=0?"#10b981":"#ef4444"]; var molHasData=molData.some(function(v){return v>0}); if(molHasData){ charts["cMol"]=new Chart($("cMol"),{type:"bar",data:{labels:molLabels,datasets:[{data:molData,backgroundColor:molColors,borderRadius:5}]},options:{responsive:true,maintainAspectRatio:false,indexAxis:"y",plugins:{legend:{display:false},tooltip:{callbacks:{label:function(c){return money(c.raw)+" som"}}}},scales:{x:{ticks:{color:"#94a3b8",callback:function(v){return sh(v)}},grid:{color:"#1e293b"}},y:{ticks:{color:"#94a3b8",font:{size:11}},grid:{display:false}}}}}); }else{$("cMol").parentElement.innerHTML="
IE kontraktda Sotish summasi va xarajatlarni kiriting

Kerakli maydonlar:
Sotish summasi + Tovar narxi = avtomatik hisob
";} // Deklaratsiya pie dC("cDek"); var dekHas=dIM40.length+dIM70.length+dND40.length; if(dekHas>0){ charts["cDek"]=new Chart($("cDek"),{type:"doughnut",data:{labels:["IM40 ("+dIM40.length+")","IM70 ("+dIM70.length+")","ND40 ("+dND40.length+")"],datasets:[{data:[dIM40.length,dIM70.length,dND40.length],backgroundColor:["#10b981","#3b82f6","#f59e0b"],borderWidth:0}]},options:{responsive:true,maintainAspectRatio:false,cutout:"50%",plugins:{legend:{position:"bottom",labels:{color:"#94a3b8",font:{size:10}}}}}}); }else{$("cDek").parentElement.innerHTML="
IE kontraktda Bojxona holatini tanlang
(IM40 / IM70 / ND40)
";} // Yangi vizualizatsiyalar rPipeline();rTimeline();rDashCountry();rDashCurr();rDashDebKred();rExecutive(); } // ── PIPELINE ────────────────────────────────── function rExecutive(){ if(!$("exNet"))return; var revenue=ieData.reduce(function(s,x){return s+(x.sotish_summa||0)},0); var income=ieData.reduce(function(s,x){return s+(x.daromad||0)},0); var cost=ieData.reduce(function(s,x){return s+(x.umumiy_tannarx||0)+(x.nds||0)+(x.foyda_soliq||0)+(x.boshqa_xar||0)},0); var net=ieData.reduce(function(s,x){return s+((x.daromad||0)-(x.foyda_soliq||0)-(x.boshqa_xar||0))},0); var activeIE=ieData.filter(function(x){return x.status==="jarayonda"||x.status==="yetkazildi"}).length; var activeSM=smData.filter(function(x){return x.status==="jarayonda"}).length; var payroll=0, payrollRows=[]; empData.forEach(function(emp){ var os=getOySt(emp.id,curOy()); var gross=Math.round((os.stavka||0)*(os.band||1)); var ijt=Math.round(gross*(os.ijt||12)/100); var av=avansData[emp.id]||{naqd:emp.av_naqd||0,perech:0}; var bon=bonusData[emp.id]||{summa:0}; var hand=gross+(+bon.summa||0)-ijt-(+av.naqd||0)-(+av.perech||0); payroll+=gross+(+bon.summa||0); payrollRows.push({name:emp.ism,lav:emp.lav||"",gross:gross,hand:hand}); }); var debitor=ecData.reduce(function(s,x){return s+(x.debitor||0)},0); var kreditor=ecData.reduce(function(s,x){return s+(x.kreditor||0)},0); var today=new Date(); var risky=ieData.filter(function(x){ if(x.status==="yopilgan"||x.status==="yetkazildi")return false; if(!x.yetkazish_muddat)return false; return Math.floor((new Date(x.yetkazish_muddat)-today)/(1000*60*60*24))<=14; }); $("exNet").textContent=(net<0?"-":"")+sh(Math.abs(net));$("exNet").className="v "+(net>=0?"gt":"rt"); $("exRevenue").textContent=sh(revenue||income); $("exPayroll").textContent=sh(payroll); $("exCost").textContent=sh(cost+payroll); $("exDebitor").textContent=debitor?sh(debitor):"0"; $("exKreditor").textContent=kreditor?sh(kreditor):"0"; $("exActive").textContent=activeIE+activeSM; $("exRisk").textContent=risky.length; var signals=[]; if(risky.length)signals.push({t:risky.length+" ta shartnoma muddati yaqin yoki o'tgan",c:"bad",i:"ti-alert-triangle"}); if(debitor>0)signals.push({t:"Debitor qarz: "+money(Math.round(debitor))+" customs qiymati nazoratda",c:"warn",i:"ti-arrow-down-circle"}); if(kreditor>0)signals.push({t:"Kreditor majburiyat: "+money(Math.round(kreditor))+" to'lov rejasini tekshiring",c:"bad",i:"ti-arrow-up-circle"}); if(payroll>0)signals.push({t:"Joriy oy oylik fondi: "+money(payroll)+" so'm",c:"info",i:"ti-cash"}); if(net>0)signals.push({t:"Sof foyda musbat: "+money(net)+" so'm",c:"good",i:"ti-trending-up"}); if(!signals.length)signals.push({t:"Faol ogohlantirish yo'q. Asosiy ko'rsatkichlar barqaror.",c:"good",i:"ti-circle-check"}); $("exSignalCnt").textContent=signals.length+" signal"; $("exSignals").innerHTML=signals.slice(0,5).map(function(s){return '
'+s.t+'
';}).join(""); var contracts=ieData.slice().sort(function(a,b){ var pa=(a.status==="jarayonda"?2:0)+(a.yetkazish_muddat?1:0); var pb=(b.status==="jarayonda"?2:0)+(b.yetkazish_muddat?1:0); return pb-pa || ((b.sof_foyda||0)-(a.sof_foyda||0)); }).slice(0,6); $("exContracts").innerHTML=contracts.length?contracts.map(function(x){ var amt=x.sof_foyda||((x.daromad||0)-(x.foyda_soliq||0)-(x.boshqa_xar||0)); return '
'+(x.kontrakt_raqam||"#"+x.id)+' - '+(x.klient||"").substring(0,48)+'
'+(x.status||"-")+' | '+(x.yetk_davlat||"davlat yoq")+' | '+(x.yetkazish_muddat||"muddat yoq")+'
'+sh(Math.abs(amt))+'
'; }).join(""):'
Shartnoma kiritilmagan
'; payrollRows.sort(function(a,b){return b.hand-a.hand}); $("exPayrollList").innerHTML=payrollRows.length?payrollRows.slice(0,6).map(function(x){ return '
'+x.name+'
'+(x.lav||"lavozim yoq")+' | hisob: '+money(x.gross)+'
'+money(x.hand)+'
'; }).join(""):'
Xodim kiritilmagan
'; } function rPipeline(){ var el=$("dashPipe");if(!el)return; if(!ieData.length){el.innerHTML='
IE kontrakt kiriting
';return} var stages=["Shartnoma","Tolangan","Yetkazish","Bojxona","Sertifikat","Yopilgan"]; function getStage(x){ if(x.status==="yopilgan")return 5; if(x.status==="yetkazildi")return 4; if((x.sertifikat_xar||0)>0||(x.metrologiya_xar||0)>0)return 4; if(x.bojxona_holat)return 3; if(x.status==="yetkazildi"||(x.transport_xar||0)>0)return 2; if((x.sotish_summa||0)>0||(x.shartnoma_summa||0)>0)return 1; return 0; } var h=""; ieData.forEach(function(x){ var cur=getStage(x); var warn=""; var isOpen=x.status==="jarayonda"; if(isOpen&&x.yetkazish_muddat){ var diff=Math.floor((new Date(x.yetkazish_muddat)-new Date())/(1000*60*60*24)); if(diff<0)warn=' '+Math.abs(diff)+' kun otdi'; else if(diff<14)warn=' '+diff+' kun qoldi'; } h+='
'+(x.kontrakt_raqam||"#"+x.id)+' — '+(x.klient||"").substring(0,35)+warn+'
'; stages.forEach(function(st,si){ var cls=si0?'':'')+ ''+st+''; }); h+='
'; }); el.innerHTML=h; } // ── TIMELINE ────────────────────────────────── function rTimeline(){ var el=$("dashTimeline");if(!el)return; var items=ieData.filter(function(x){return x.yetkazish_muddat||x.kontrakt_sana}).map(function(x){ var d=x.yetkazish_muddat||x.kontrakt_sana; var diff=Math.floor((new Date(d)-new Date())/(1000*60*60*24)); return {k:x.kontrakt_raqam||"#"+x.id,kl:x.klient||"",d:d,diff:diff,st:x.status,amt:x.sotish_summa||0}; }).sort(function(a,b){return a.diff-b.diff}); if(!items.length){el.innerHTML='
Muddat kiritilmagan
';return} var h='
'; items.forEach(function(x){ var dotColor=x.diff<0?"#ef4444":x.diff<14?"#f59e0b":x.st==="yopilgan"?"#10b981":"#3b82f6"; var tag=""; if(x.st==="yopilgan"||x.st==="yetkazildi")tag=''+x.st+''; else if(x.diff<0)tag=''+Math.abs(x.diff)+' kun otdi'; else if(x.diff<14)tag=''+x.diff+' kun qoldi'; else tag=''+x.diff+' kun'; h+='
'; h+='
'+x.k+' — '+x.kl.substring(0,30)+tag+'
'; h+='
'+x.d+(x.amt?' | '+money(x.amt)+' UZS':'')+'
'; }); h+='
'; el.innerHTML=h; } // ── DAVLATLAR ────────────────────────────────── function rDashCountry(){ var el=$("dashCountry");if(!el)return; var m={};ieData.forEach(function(x){var d=x.yetk_davlat||"Noaniq";m[d]=(m[d]||0)+1}); var arr=Object.keys(m).map(function(k){return{n:k,c:m[k]}}).sort(function(a,b){return b.c-a.c}); if(!arr.length){el.innerHTML='
Davlat kiritilmagan
';return} var mx=arr[0].c; var colors=["#3b82f6","#10b981","#f59e0b","#a78bfa","#22d3ee","#ec4899","#64748b"]; var h=""; arr.forEach(function(x,i){ var pct=Math.round(x.c/mx*100); h+='
'+x.n+'
'+x.c+'
'; }); el.innerHTML=h; } // ── VALYUTA ────────────────────────────────── function rDashCurr(){ var el=$("dashCurr");if(!el)return; var m={};ieData.forEach(function(x){var v=x.tovar_valyuta||"UZS";if(!m[v])m[v]={cnt:0,sum:0};m[v].cnt++;m[v].sum+=x.tovar_val||0}); var arr=Object.keys(m).map(function(k){return{v:k,cnt:m[k].cnt,sum:m[k].sum}}).sort(function(a,b){return b.sum-a.sum}); if(!arr.length){el.innerHTML='
Valyuta kiritilmagan
';return} var h=""; arr.forEach(function(x){ var kurs=_kursCache[x.v]||1; h+='
'+x.v+' ('+x.cnt+' ta)
'; h+='
'+money(Math.round(x.sum))+' '+x.v+''; if(x.v!=="UZS")h+='
'+money(Math.round(x.sum*kurs))+' UZS (kurs: '+money(Math.round(kurs))+')'; h+='
'; }); el.innerHTML=h; } // ── DASHBOARD DEBITOR/KREDITOR ────────────── function rDashDebKred(){ var debEl=$("dashDeb");var kredEl=$("dashKred"); if(!debEl||!kredEl)return; // ecData dan (E-Contract kesh) // Agar ecData bosh bo'lsa — DB dan yuklash if(!ecData.length){ api("customs-cache").then(function(d){ ecData=ecNormalize(d.list||[]); _renderDashDK(); }).catch(function(){ debEl.innerHTML='
E-Contract sinxronlang
'; kredEl.innerHTML='
E-Contract sinxronlang
'; }); }else{_renderDashDK()} } function _renderDashDK(){ var debEl=$("dashDeb");var kredEl=$("dashKred"); if(!debEl||!kredEl)return; var hasDetail=ecData.some(function(x){return x.detailLoaded}); // Debitorlar var debTotal=ecData.reduce(function(s,x){return s+(x.debitor||0)},0); var debItems=ecData.filter(function(x){return(x.debitor||0)>0}).sort(function(a,b){return(b.debitor||0)-(a.debitor||0)}); if(debTotal>0){ var h='
'+money(Math.round(debTotal))+'
'; debItems.slice(0,5).forEach(function(x){ h+='
'+(x.docNo||"-")+' '+(x.contractorForName||"").substring(0,25)+''+money(Math.round(x.debitor))+' '+ecCurr(x.currCode1)+'
'; }); debEl.innerHTML=h; }else{ debEl.innerHTML='
'+(hasDetail?'0':'—')+'
'+(hasDetail?'Debitorlik yoq':'Sinxronlang')+'
'; } // Kreditorlar var kredTotal=ecData.reduce(function(s,x){return s+(x.kreditor||0)},0); var kredItems=ecData.filter(function(x){return(x.kreditor||0)>0}).sort(function(a,b){return(b.kreditor||0)-(a.kreditor||0)}); if(kredTotal>0){ var h2='
'+money(Math.round(kredTotal))+'
'; kredItems.slice(0,5).forEach(function(x){ h2+='
'+(x.docNo||"-")+' '+(x.contractorForName||"").substring(0,25)+''+money(Math.round(x.kreditor))+' '+ecCurr(x.currCode1)+'
'; }); kredEl.innerHTML=h2; }else{ kredEl.innerHTML='
'+(hasDetail?'0':'—')+'
'+(hasDetail?'Kreditorlik yoq':'Sinxronlang')+'
'; } } // IE LIST function rIE(){ var q=$("ieSrch").value.toLowerCase(),f=$("ieFlt").value; var ls=ieData.filter(function(x){return(!q||x.klient.toLowerCase().includes(q)||(x.mahsulot||"").toLowerCase().includes(q)||(x.kontrakt_raqam||"").includes(q))&&(!f||x.status===f)}); $("ieCnt").textContent="· "+ls.length+" ta"; $("ieTb").innerHTML=ls.length?ls.map(function(x,i){ var sofFoyda=(x.daromad||0)-(x.foyda_soliq||0)-(x.boshqa_xar||0); return ""+(i+1)+""+stBd(x.status)+""+esc(x.klient)+""+esc(x.mahsulot||"-")+""+esc(x.kontrakt_raqam||"-")+""+esc(x.kontrakt_sana||"-")+""+money(x.elon_summa)+""+money(x.sotish_summa)+""+esc(x.yetkazuvchi||"-")+""+esc(x.yetk_davlat||"-")+""+esc(x.bojxona_holat||"-")+""+money(x.umumiy_tannarx)+""+money(x.nds)+""+money(x.daromad)+""+money(x.foyda_soliq)+""+money(sofFoyda)+""+esc(x.masul||"-")+" " }).join(""):'Kontrakt yoq' } // IE SAVE async function saveIE(){ var kl=$("ieKl").value.trim();if(!kl)return ntf("Klient kiriting!","#f59e0b"); var d={status:$("ieS").value,klient:kl,inn:$("ieInn").value.trim(),mahsulot:$("ieMah").value.trim(),predoplata:+$("iePr").value,kontrakt_raqam:$("ieKr").value.trim(),kontrakt_sana:$("ieKs").value||null,yetkazish_muddat:$("ieYm").value||null,elon_summa:+$("ieEl").value,sotish_summa:+$("ieSs").value,yetkazuvchi:$("ieYn").value.trim(),yetk_davlat:$("ieYd").value.trim(),yetk_shartnoma:$("ieYsh").value.trim(),kompaniya_importer:$("ieKi").value.trim(),bojxona_holat:$("ieBh").value.trim(),bojxona_poshlina:+$("ieBp").value,deklaratsiya:+$("ieDe").value,bank_birja:+$("ieBb").value,sertifikat_xar:+$("ieSx").value,metrologiya_xar:+$("ieMx").value,transport_xar:+$("ieTx").value,saqlash_xar:+($("ieSaq")?$("ieSaq").value:0),boshqa_xar:+$("ieBx").value,umumiy_tannarx:+$("ieUt").value,nds:+$("ieNd").value,daromad:+$("ieDr").value,foyda_soliq:+$("ieFs").value,masul:$("ieMa").value.trim(),hisob_sana:$("ieHs").value||null,izoh:$("ieIz").value.trim(), tovar_val:+$("ieTovarVal").value||0, tovar_valyuta:$("ieValyuta")?$("ieValyuta").value:"UZS", tovar_kurs:parseFloat($("ieKurs")?$("ieKurs").value:1)||1, shartnoma_summa:+$("ieShart").value||0, sales_responsible_id:+($("ieSalesResp")?$("ieSalesResp").value:0)||0, ved_responsible_id:+($("ieVedResp")?$("ieVedResp").value:0)||0, installation_responsible_id:+($("ieInstallResp")?$("ieInstallResp").value:0)||0, closed_at:($("ieClosedAt")?$("ieClosedAt").value:"")||null}; var id=$("ieId").value; try{ if(id){d.id=+id;await api("ie-upd","POST",d);ntf("Yangilandi","#10b981");copyToSM(d)} else{await api("ie","POST",d);ntf("Saqlandi!","#10b981");copyToSM(d)} clrIE();loadAll();gT("ie",document.querySelector(".tab[data-tab=ie]")); }catch(x){ntf(x.message,"#ef4444")} } function editIE(id){ var x=ieData.find(function(i){return i.id===id});if(!x)return; $("ieId").value=id;$("ieS").value=x.status;$("ieKl").value=x.klient;$("ieInn").value=x.inn||"";$("ieKr").value=x.kontrakt_raqam||"";$("ieMah").value=x.mahsulot||"";$("iePr").value=x.predoplata||30;$("ieKs").value=x.kontrakt_sana||"";$("ieYm").value=x.yetkazish_muddat||"";$("ieEl").value=x.elon_summa||0;$("ieSs").value=x.sotish_summa||0;$("ieYn").value=x.yetkazuvchi||"";$("ieYd").value=x.yetk_davlat||"";$("ieYsh").value=x.yetk_shartnoma||"";$("ieKi").value=x.kompaniya_importer||"";$("ieBh").value=x.bojxona_holat||"";$("ieBp").value=x.bojxona_poshlina||0;$("ieDe").value=x.deklaratsiya||0;$("ieBb").value=x.bank_birja||0;$("ieSx").value=x.sertifikat_xar||0;$("ieMx").value=x.metrologiya_xar||0;$("ieTx").value=x.transport_xar||0;$("ieBx").value=x.boshqa_xar||0;$("ieUt").value=x.umumiy_tannarx||0; // Valyuta, kurs, tovar narxi, shartnoma summa tiklash if($("ieValyuta"))$("ieValyuta").value=x.tovar_valyuta||"UZS"; if($("ieKurs")){$("ieKurs").value=x.tovar_kurs||1;$("ieKurs").readOnly=(x.tovar_valyuta||"UZS")==="UZS";} if($("ieTovarVal"))$("ieTovarVal").value=x.tovar_val||0; if($("ieShart"))$("ieShart").value=x.shartnoma_summa||0;$("ieNd").value=x.nds||0;$("ieDr").value=x.daromad||0;$("ieFs").value=x.foyda_soliq||0;$("ieMa").value=x.masul||"";$("ieHs").value=x.hisob_sana||"";$("ieIz").value=x.izoh||""; if($("ieSaq"))$("ieSaq").value=x.saqlash_xar||0; if($("ieSofFoyda"))$("ieSofFoyda").value=(x.daromad||0)-(x.foyda_soliq||0)-(x.boshqa_xar||0); fillIEEmployeeSelects(x); if($("ieClosedAt"))$("ieClosedAt").value=x.closed_at||""; openIEForm(id); } async function delIE(id){if(!confirm("Arxivga otkazilsinmi?"))return;try{await api("ie-del","POST",{id:id});loadAll();ntf("Arxivlandi","#f59e0b")}catch(x){ntf(x.message,"#ef4444")}} function clrIE(){$("ieId").value="";["ieKl","ieInn","ieKr","ieMah","ieYn","ieYd","ieYsh","ieKi","ieBh","ieMa","ieIz"].forEach(function(id){$(id).value=""});["iePr"].forEach(function(id){$(id).value="30"});["ieEl","ieSs","ieBp","ieDe","ieBb","ieSx","ieMx","ieTx","ieBx","ieUt","ieNd","ieDr","ieFs","ieTovarVal","ieShart","ieSofFoyda"].forEach(function(id){if($(id))$(id).value="0"}); if($("ieSaq"))$("ieSaq").value="0"; if($("ieValyuta"))$("ieValyuta").value="UZS"; fillIEEmployeeSelects({}); if($("ieClosedAt"))$("ieClosedAt").value=""; if($("ieKurs")){$("ieKurs").value="1";$("ieKurs").readOnly=true;}$("ieS").value="jarayonda";$("ieKs").value="";$("ieYm").value="";$("ieHs").value=""} // SM LIST function rSM(){ var q=$("smSrch").value.toLowerCase(),f=$("smFlt").value; var ls=smData.filter(function(x){return(!q||x.klient.toLowerCase().includes(q)||(x.mahsulot||"").toLowerCase().includes(q))&&(!f||x.status===f)}); $("smCnt").textContent="· "+ls.length+" ta"; $("smTb").innerHTML=ls.length?ls.map(function(x,i){ return ""+(i+1)+""+stBd(x.status)+""+esc(x.klient)+""+esc(x.mahsulot||"-")+""+esc(x.kontrakt_raqam||"-")+""+esc(x.bojxona_holat||"-")+""+stBd(x.sert_status||"jarayonda")+""+money(x.sert_narx)+""+esc(x.sert_markaz||"-")+""+stBd(x.metro_status||"jarayonda")+""+money(x.metro_narx)+""+esc(x.metro_markaz||"-")+""+money(x.umumiy_narx)+""+esc(x.masul||"-")+" " }).join(""):'Sertifikat / Metrologiya yoq' } // SM SAVE async function saveSM(){ var kl=$("smKl").value.trim();if(!kl)return ntf("Klient kiriting!","#f59e0b"); var d={status:$("smS").value,klient:kl,mahsulot:$("smMah").value.trim(),kontrakt_raqam:$("smKr").value.trim(),bojxona_holat:$("smBh").value.trim(),bojxona_raqam:$("smBr").value.trim(), sert_status:$("smSs").value,sert_info:($("smSi")?$("smSi").value:"").trim(),sert_narx:+$("smSn").value,sert_markaz:$("smSm").value.trim(),sert_shartnoma:$("smSh").value.trim(),sert_muddat:$("smSmd")?$("smSmd").value||null:null,sert_punkt:$("smSp")?$("smSp").value.trim():"", metro_status:$("smMs")?$("smMs").value:"jarayonda",metro_info:($("smMi")?$("smMi").value:"").trim(),metro_narx:+$("smMn").value,metro_markaz:$("smMm")?$("smMm").value.trim():"",metro_shartnoma:$("smMsh")?$("smMsh").value.trim():"",metro_muddat:$("smMmd")?$("smMmd").value||null:null,metro_punkt:$("smMp")?$("smMp").value.trim():"", qoshimcha_xar:+$("smQx").value,umumiy_narx:+$("smUn").value,masul:$("smMa").value.trim(),izoh:$("smIz").value.trim()}; var id=$("smId").value; try{ if(id){d.id=+id;await api("sm-upd","POST",d);ntf("Yangilandi","#10b981")} else{await api("sm","POST",d);ntf("Saqlandi!","#10b981")} clrSM();loadAll();gT("sm",document.querySelector(".tab[data-tab=sm]")); }catch(x){ntf(x.message,"#ef4444")} } function editSM(id){ var x=smData.find(function(i){return i.id===id});if(!x)return; $("smId").value=id;$("smS").value=x.status;$("smKl").value=x.klient;$("smMah").value=x.mahsulot||"";$("smKr").value=x.kontrakt_raqam||"";$("smBh").value=x.bojxona_holat||"";$("smBr").value=x.bojxona_raqam||"";// Sertifikat $("smSs").value=x.sert_status||"jarayonda";$("smSn").value=x.sert_narx||0; if($("smSm"))$("smSm").value=x.sert_markaz||""; if($("smSh"))$("smSh").value=x.sert_shartnoma||""; if($("smSmd"))$("smSmd").value=x.sert_muddat||""; if($("smSp"))$("smSp").value=x.sert_punkt||""; if($("smSi"))$("smSi").value=x.sert_info||""; // Metrologiya if($("smMs"))$("smMs").value=x.metro_status||"jarayonda"; $("smMn").value=x.metro_narx||0; if($("smMm"))$("smMm").value=x.metro_markaz||""; if($("smMsh"))$("smMsh").value=x.metro_shartnoma||""; if($("smMmd"))$("smMmd").value=x.metro_muddat||""; if($("smMp"))$("smMp").value=x.metro_punkt||""; if($("smMi"))$("smMi").value=x.metro_info||""; // Umumiy $("smQx").value=x.qoshimcha_xar||0;$("smUn").value=x.umumiy_narx||0; $("smMa").value=x.masul||"";$("smIz").value=x.izoh||""; openSMForm(id); } async function delSM(id){if(!confirm("Arxivga otkazilsinmi?"))return;try{await api("sm-del","POST",{id:id});loadAll();ntf("Arxivlandi","#f59e0b")}catch(x){ntf(x.message,"#ef4444")}} function smCalc(){ var sn=+($("smSn")?$("smSn").value:0); var mn=+($("smMn")?$("smMn").value:0); var qx=+($("smQx")?$("smQx").value:0); if($("smUn"))$("smUn").value=sn+mn+qx; } function clrSM(){$("smId").value=""; ["smKl","smMah","smKr","smBh","smBr","smSi","smSm","smSh","smSp","smMm","smMsh","smMp","smMi","smMa","smIz"].forEach(function(id){if($(id))$(id).value=""}); ["smSn","smMn","smQx","smUn"].forEach(function(id){if($(id))$(id).value="0"}); $("smS").value="jarayonda";$("smSs").value="jarayonda"; if($("smMs"))$("smMs").value="jarayonda"; if($("smSmd"))$("smSmd").value="";if($("smMmd"))$("smMmd").value=""} // ── E-CONTRACT ────────────────────────────── var ecData=[];var ecFiltered=[];var ecLastDetail=null;var ecFilterReady=false; var _cN={"156":"Xitoy","643":"Rossiya","398":"Qozogiston","792":"Turkiya","840":"AQSH","276":"Germaniya","380":"Italiya","392":"Yaponiya","826":"Buyuk Britaniya","356":"Hindiston","410":"Koreya","250":"Fransiya","784":"BAA","124":"Kanada","702":"Singapur","704":"Vyetnam","586":"Pokiston","616":"Polsha","112":"Belarus","804":"Ukraina","344":"Gonkong","752":"Shvetsiya","756":"Shveytsariya","364":"Eron","158":"Tayvan","860":"O'zbekiston","036":"Avstraliya","040":"Avstriya","050":"Bangladesh","428":"Latviya","440":"Litva"}; var _cU={"840":"USD","978":"EUR","156":"CNY","643":"RUB","392":"JPY","826":"GBP","860":"UZS","398":"KZT","682":"SAR","784":"AED"}; function ecCountry(code){return _cN[String(code)]||("Davlat "+(code||"-"))} function ecCurr(code){return _cU[String(code)]||String(code||"UZS")} function ecType(t){var s=String(t);return s==="01"||s==="1"?"Eksport":s==="02"||s==="2"?"Import":"Noaniq"} function ecStatus(s){var n=Number(s);return n===0?"Amal qilmoqda":n===1?"Bajarilgan":n===3?"Bekor qilingan":"Noaniq ("+s+")"} function ecStColor(s){var n=Number(s);return n===0?"var(--a)":n===1?"var(--g)":"var(--r)"} function isImport(x){var t=String(x.cntrType||"");return t==="02"||t==="2"} function isExport(x){var t=String(x.cntrType||"");return t==="01"||t==="1"} function ecYearOf(x){return String(x.docDate||"").slice(0,4)||""} function ecTodayKey(){var d=new Date();return d.getFullYear()+"-"+String(d.getMonth()+1).padStart(2,"0")+"-"+String(d.getDate()).padStart(2,"0")} async function ecTest(){ntf("Test tugmasi olib tashlangan. Sinxronlash avtomatik ishlaydi.","#22d3ee")} async function ecLoad(){ $("ecStatus").innerHTML='
Yuklanmoqda...
'; try{ var d=await api("customs-cache"); ecData=ecNormalize(d.list||[]); ecPrepareFilters(); ecFilter();ecStats();ecCharts();ecDebKred(); if(ecData.length){$("ecStatus").innerHTML='
'+ecData.length+' ta shartnoma keshdan yuklandi.
';setTimeout(function(){$("ecStatus").innerHTML=""},2500)} await ecAutoSync(); }catch(x){ $("ecStatus").innerHTML='
'+x.message+'
'; ecData=[];ecFilter(); } } async function ecAutoSync(){ var key="ec_auto_sync_"+ecTodayKey(); if(localStorage.getItem(key)==="1")return; try{ var d=await ecSync(true,false); localStorage.setItem(key,"1"); if($("ecStatus")){ $("ecStatus").innerHTML='
Avtomatik sinxronlash bajarildi. Yangilangan: '+(d.synced||0)+'
'; setTimeout(function(){$("ecStatus").innerHTML=""},3500); } }catch(e){ localStorage.removeItem(key); console.warn("E-contract auto sync:",e.message); if($("ecStatus"))$("ecStatus").innerHTML='
Avto sync xatosi: '+esc(e.message)+'
'; } } async function ecManualSync(){ var key="ec_auto_sync_"+ecTodayKey(); localStorage.removeItem(key); try{ var d=await ecSync(false,true); localStorage.setItem(key,"1"); ntf("E-contract yangilandi: "+(d.synced||0)+" ta","#10b981"); }catch(e){ localStorage.removeItem(key); if($("ecStatus"))$("ecStatus").innerHTML='
Sync xatosi: '+esc(e.message)+'
'; ntf(e.message,"#ef4444"); } } async function ecRefreshDebts(){ try{ await ecSyncDetails(true); ntf("Debitor/kreditor qayta hisoblandi","#10b981"); }catch(e){ if($("ecStatus"))$("ecStatus").innerHTML='
Qarzlarni hisoblash xatosi: '+esc(e.message)+'
'; ntf(e.message,"#ef4444"); } } async function ecSync(silent,forceDetails){ var from=$("ecFrom")&&$("ecFrom").value?$("ecFrom").value:"2020-01-01"; var to=$("ecTo")&&$("ecTo").value?$("ecTo").value:"2050-01-01"; if(!silent)$("ecStatus").innerHTML='
Customs.uz dan sinxronlanmoqda...
'; var d=await api("customs-sync","POST",{from:from,to:to}); ecData=ecNormalize(d.list||[]); ecPrepareFilters(); ecFilter();ecStats();ecCharts();ecDebKred(); if($("ecStatus")){ $("ecStatus").innerHTML='
'+(d.synced||0)+' ta shartnoma yangilandi. Jami: '+ecData.length+'
'; setTimeout(function(){$("ecStatus").innerHTML=""},3500); } await ecSyncDetails(!!forceDetails); return d; } async function ecSyncDetails(force){ if(force){ if($("ecStatus"))$("ecStatus").innerHTML='
Eski qarz malumotlari tozalanmoqda...
'; await api('customs-reset-details','POST'); ecData.forEach(function(x){x.detailLoaded=0;x.debitor=0;x.kreditor=0;x.overdueDebitor=0;x.paidAmount=0;x.declAmount=0;}); ecFilter();ecDebKred();rDashDebKred(); } var notLoaded=ecData.filter(function(x){return !x.detailLoaded}); if(!notLoaded.length){ecFilter();ecDebKred();rDashDebKred();return;} var done=0; var failed=0; for(var i=0;i Qarz tafsilotlari yuklanmoqda: '+(i+1)+' / '+notLoaded.length+''; var d=await api("customs-detail-sync","POST",{idn:notLoaded[i].idn}); var ecIdx=ecData.findIndex(function(x){return x.idn===notLoaded[i].idn}); if(ecIdx>=0){ecData[ecIdx].debitor=d.debitor||0;ecData[ecIdx].kreditor=d.kreditor||0;ecData[ecIdx].overdueDebitor=d.overdue||0;ecData[ecIdx].paidAmount=d.paid||0;ecData[ecIdx].declAmount=d.decl||0;ecData[ecIdx].detailLoaded=1;} notLoaded[i].debitor=d.debitor||0;notLoaded[i].kreditor=d.kreditor||0;notLoaded[i].overdueDebitor=d.overdue||0;notLoaded[i].paidAmount=d.paid||0;notLoaded[i].declAmount=d.decl||0;notLoaded[i].detailLoaded=1; }catch(x){failed++;console.warn("Detail xato:",notLoaded[i].idn,x.message)} done++; if(done%5===0||done===notLoaded.length){ecFilter();ecDebKred();rDashDebKred();} } if($("ecStatus")){ $("ecStatus").innerHTML='
Qarz tafsilotlari yangilandi: '+(done-failed)+' / '+notLoaded.length+(failed?' (xato: '+failed+')':'')+'
'; setTimeout(function(){$("ecStatus").innerHTML=""},4500); } } async function ecReloadAll(){await api('customs-reset-details','POST');ecData.forEach(function(x){x.detailLoaded=0;x.debitor=0;x.kreditor=0;x.overdueDebitor=0;});ecFilter();ecDebKred();await ecSyncDetails();} function ecNormalize(list){ return list.map(function(x){ if(x.doc_no!==undefined){ return {idn:x.idn,docNo:x.doc_no,docDate:x.doc_date,cntrStatus:x.cntr_status,cntrType:x.cntr_type,cntrSubject:x.cntr_subject,contractorUzName:x.contractor_uz,contractorForName:x.contractor_for,contractorForCountryCode:x.country_code,currCode1:x.curr_code,amount1:x.amount,bankId:x.bank_id,debitor:x.debitor||0,kreditor:x.kreditor||0,overdueDebitor:x.overdue_debitor||0,paidAmount:x.paid_amount||0,declAmount:x.decl_amount||0,detailLoaded:x.detail_loaded||0}; } return x; }); } function ecPrepareFilters(){ var curs={};ecData.forEach(function(x){curs[ecCurr(x.currCode1)]=1}); var cSel=$("ecCurFlt");if(cSel){var cur=cSel.value;var cs=Object.keys(curs).sort();cSel.innerHTML=''+cs.map(function(c){return ''}).join("");if(cur)cSel.value=cur;} } function ecStats(){ var base=ecFilterReady?ecFiltered:ecData; if($("ecAll"))$("ecAll").textContent=base.length; if($("ecImp"))$("ecImp").textContent=base.filter(isImport).length; if($("ecExp"))$("ecExp").textContent=base.filter(isExport).length; if($("ecActive"))$("ecActive").textContent=base.filter(function(x){return Number(x.cntrStatus)===0}).length; if($("ecDone"))$("ecDone").textContent=base.filter(function(x){return Number(x.cntrStatus)===1}).length; } function ecCharts(){ var list=ecFilterReady?ecFiltered:ecData; var impC=list.filter(isImport).length,expC=list.filter(isExport).length; dC("cImpExp"); if(impC+expC>0)charts["cImpExp"]=new Chart($("cImpExp"),{type:"doughnut",data:{labels:["Import ("+impC+")","Eksport ("+expC+")"],datasets:[{data:[impC,expC],backgroundColor:["#ef4444","#10b981"],borderWidth:0}]},options:{responsive:true,maintainAspectRatio:false,cutout:"50%",onClick:function(evt,els){if(!els.length)return;$("ecFlt").value=els[0].index===0?"imp":"exp";ecFilter();},plugins:{legend:{position:"bottom",labels:{color:"#94a3b8",font:{size:11}},onClick:function(e,item){$("ecFlt").value=item.index===0?"imp":"exp";ecFilter();}}}}}); var vm={};list.forEach(function(x){var cu=ecCurr(x.currCode1);vm[cu]=(vm[cu]||0)+1}); var vk=Object.keys(vm);var vColors=["#3b82f6","#f59e0b","#a78bfa","#22d3ee","#ec4899","#64748b"]; dC("cValyuta"); if(vk.length)charts["cValyuta"]=new Chart($("cValyuta"),{type:"doughnut",data:{labels:vk.map(function(k){return k+" ("+vm[k]+")"}),datasets:[{data:vk.map(function(k){return vm[k]}),backgroundColor:vColors.slice(0,vk.length),borderWidth:0}]},options:{responsive:true,maintainAspectRatio:false,cutout:"50%",onClick:function(evt,els){if(!els.length)return;$("ecCurFlt").value=vk[els[0].index];ecFilter();},plugins:{legend:{position:"bottom",labels:{color:"#94a3b8",font:{size:11}},onClick:function(e,item){$("ecCurFlt").value=vk[item.index];ecFilter();}}}}}); } function ecFilter(){ var q=($("ecSrch")?$("ecSrch").value:"").toLowerCase(); var ft=$("ecFlt")?$("ecFlt").value:""; var cur=$("ecCurFlt")?$("ecCurFlt").value:""; var st=$("ecStatusFlt")?$("ecStatusFlt").value:""; var from=$("ecFrom")?$("ecFrom").value:""; var to=$("ecTo")?$("ecTo").value:""; ecFiltered=ecData.filter(function(x){ var n=(x.contractorForName||"").toLowerCase(); var qOk=!q||n.includes(q)||(x.idn||"").includes(q)||(x.docNo||"").toLowerCase().includes(q); var fOk=!ft||(ft==="imp"&&isImport(x))||(ft==="exp"&&isExport(x)); var cOk=!cur||ecCurr(x.currCode1)===cur; var sOk=!st||String(Number(x.cntrStatus))===st; var dt=String(x.docDate||"").slice(0,10); var dOk=(!from||dt>=from)&&(!to||dt<=to); return qOk&&fOk&&cOk&&sOk&&dOk; }); ecFilterReady=true; if($("ecCnt"))$("ecCnt").textContent="("+ecFiltered.length+")"; ecStats();ecCharts(); var tb=$("ecTb");if(!tb)return; if(!ecFiltered.length){tb.innerHTML='Shartnoma yoq.';return} tb.innerHTML=ecFiltered.map(function(x,i){ var typ=ecType(x.cntrType); return ""+(i+1)+""+ ""+typ+""+ ""+esc(x.docNo||"-")+""+ ""+esc(ecYearOf(x)||"-")+""+ ""+esc(x.contractorForName||"-")+""+ ""+esc(ecCountry(x.contractorForCountryCode))+""+ ""+esc(ecCurr(x.currCode1))+""+ ""+money(Math.round(x.amount1||0))+""+ ""+(x.debitor>0?money(Math.round(x.debitor)):"-")+""+ ""+(x.kreditor>0?money(Math.round(x.kreditor)):"-")+""+ ""+ecStatus(x.cntrStatus)+""+ ""; }).join(""); } function ecDetailValue(obj,keys,def){for(var i=0;i/g,">").replace(/"/g,""")} function ecDetailData(x,d){ var ct=ecInfoObj(d),cur=ecCurr(x.currCode1),amount=x.amount1||ecDetailValue(ct,['amount1'],0); var spec=d&&d.spec&&!d.spec._err?(d.spec.specificationList||d.spec):[];if(!Array.isArray(spec))spec=[]; var journal=d&&d.journal&&!d.journal._err?(d.journal.journalList||d.journal):[];if(!Array.isArray(journal))journal=[]; var pays=[]; if(ct&&Array.isArray(ct.payments))pays=ct.payments; if(!pays.length&&ct&&Array.isArray(ct.funds))pays=ct.funds; if(!pays.length&&x.paidAmount)pays=[{paymentNo:'',paymentDate:'',invoiceValue:x.paidAmount,currency:cur,goodsAmount1:x.paidAmount,serviceAmount1:0}]; var ops=journal.length?journal:[]; if(!ops.length){ops=[{docDate:x.docDate,operName:'Внесение нового контракта',absNo:''}];if(x.paidAmount)ops.push({docDate:'',operName:'Оплата по контракту',absNo:'',payment1:x.paidAmount,balance1:-Math.abs(x.paidAmount)});} return {ct:ct,cur:cur,amount:amount,spec:spec,pays:pays,ops:ops}; } function ecContractRows(x,d){ var z=ecDetailData(x,d),ct=z.ct,cur=z.cur; return [ ['ID договора',x.idn||ecDetailValue(ct,['idn'])], ['Дата внесения в TSOYAEAT',ecDetailValue(ct,['insTime','createdAt','createdDate'],'')], ['Номер контракта',x.docNo||ecDetailValue(ct,['docNo'])], ['Дата заключения контракта',x.docDate||ecDetailValue(ct,['docDate'])], ['Тип контракта',isImport(x)?'Импортный контракт':isExport(x)?'Экспортный контракт':ecType(x.cntrType)], ['', ''], ['Предмет контракта',ecDetailValue(ct,['subjectName','cntrSubjectName'],'товар')], ['Общее название товаров/услуг',ecDetailValue(ct,['goodsName','productName','productInfo'],'')], ['', ''], ['Первая валюта договора',cur==='USD'?'Доллар США':cur], ['Сумма в первой валюте договора',ecMoney(z.amount)], ['Вторая валюта договора',ecDetailValue(ct,['currCode2'],'')], ['Сумма во второй валюте договора',ecMoney(ecDetailValue(ct,['amount2'],0))], ['', ''], ['Владелец договора (Респ.Узб.)',ecDetailValue(ct,['contractorUzName','ownerName'],'ANALYTIC LAB MCHJ')], ['Адрес владельца договора',ecDetailValue(ct,['contractorUzAddress','ownerAddress'],'Toshkent shahri Shayxontoxur tumani')], ['', ''], ['Название иностранного партнера',x.contractorForName||ecDetailValue(ct,['contractorForName'])], ['Страна инопартнера',ecCountry(x.contractorForCountryCode||ecDetailValue(ct,['contractorForCountryCode']))], ['Адрес инопартнера',ecDetailValue(ct,['contractorForAddress','foreignPartnerAddress'],'')], ['Банк инопартнера',ecDetailValue(ct,['bankName','contractorForBankName'],'')], ['Страна банка иностранного партнера',ecDetailValue(ct,['bankCountryName','bankCountry'],ecCountry(x.contractorForCountryCode||''))], ['Реквизиты банка иностранного партнера',ecDetailValue(ct,['bankAccount','bankRequisites','bankInfo'],x.bankId||'')], ['', ''], ['Условия поставки',ecDetailValue(ct,['deliveryTerms','termsDelivery','incoterms'],'')], ['', ''], ['Формы оплаты/Условия экспорта',ecDetailValue(ct,['paymentTerms','paymentForm'],'')], ['', ''], ['Отправки в первой валюте','0,00'], ['Платежи в первой валюте',ecMoney(x.paidAmount||0)], ['Баланс в первой валюте',ecMoney(x.debitor||x.kreditor||0)], ['', ''], ['Отправки во второй валюте','0,00'], ['Платежи во второй валюте','0,00'], ['Баланс во второй валюте','0,00'] ]; } function ecSpecRows(x,d){var z=ecDetailData(x,d);var spec=z.spec.length?z.spec:[{goodsName:ecDetailValue(z.ct,['goodsName','productName'],'-'),tnvedCode:ecDetailValue(z.ct,['tnvedCode','code'],''),price:z.amount,quantity:1,unit:'шт',totalCost:z.amount}];return spec.map(function(s,i){return [i+1,ecDetailValue(s,['goodsName','name','productName'],'-'),ecDetailValue(s,['tnvedCode','code'],''),ecMoney(ecDetailValue(s,['price','cost'],z.amount)),ecDetailValue(s,['quantity','qty'],1),ecDetailValue(s,['unitName','unit'],'шт'),ecMoney(ecDetailValue(s,['totalCost','amount','invoiceValue'],z.amount))]})} function ecPayRows(x,d){var z=ecDetailData(x,d);return z.pays.map(function(p,i){var v=ecDetailValue(p,['invoiceValue','amount','value'],x.paidAmount||0);return [i+1,ecDetailValue(p,['type','operation'],'Оплата'),ecDetailValue(p,['paymentNo','absNo','number'],''),ecDetailValue(p,['paymentDate','date','docDate'],''),ecMoney(v),ecDetailValue(p,['currency'],z.cur==='USD'?'Доллар США':z.cur),ecMoney(ecDetailValue(p,['goodsAmount1'],v)),ecMoney(ecDetailValue(p,['serviceAmount1'],0)),z.cur==='USD'?'Доллар США':z.cur,ecMoney(ecDetailValue(p,['goodsAmount2'],0)),ecMoney(ecDetailValue(p,['serviceAmount2'],0)),ecDetailValue(p,['currency2'],'')];})} function ecOperationRows(x,d){var z=ecDetailData(x,d);return z.ops.map(function(o,i){var pay=ecDetailValue(o,['payment1','invoiceValue','amount'],i===1?x.paidAmount:0);return [ecDetailValue(o,['docDate','date','operDate'],i===0?x.docDate:''),ecDetailValue(o,['operName','operation','type'],''),ecDetailValue(o,['tsoyaeatNo','number'],i===0?1:''),ecDetailValue(o,['absNo','paymentNo'],''),ecMoney(ecDetailValue(o,['shipment1'],0)),ecMoney(pay),ecMoney(ecDetailValue(o,['balance1'],pay?-Math.abs(ecNum(pay)):0)),z.cur==='USD'?'Доллар США':z.cur,ecMoney(ecDetailValue(o,['shipment2'],0)),ecMoney(ecDetailValue(o,['payment2'],0)),ecMoney(ecDetailValue(o,['balance2'],0)),ecDetailValue(o,['currency2'],'')];})} function ecExcelTable(headers,rows){return ''+headers.map(function(h){return ''}).join('')+''+rows.map(function(r){return ''+r.map(function(c){return ''}).join('')+''}).join('')+'
'+esc(h)+'
'+esc(c)+'
'} function ecContractSheetHtml(x,d){var rows=ecContractRows(x,d);return '

'+new Date().toLocaleString('ru-RU')+' договорная карта

'+rows.map(function(r){return r[0]===''?'':''}).join('')+'
'+esc(r[0])+''+esc(r[1])+'
'} function ecSheetHtml(name,x,d){if(name==='contract')return ecContractSheetHtml(x,d);if(name==='spec')return '

Спецификации

Номер спецификации1Дата спецификации'+esc(x.docDate||'')+'Сумма спецификации'+ecMoney(x.amount1||0)+'Валюта спецификации'+esc(ecCurr(x.currCode1)==='USD'?'Доллар США':ecCurr(x.currCode1))+'
'+ecExcelTable(['№ пп','Название товара/услуги','Код ТН ВЭД/услуги','Цена','Количество','Единица измерения','Общая стоимость'],ecSpecRows(x,d))+'
';if(name==='pay')return '

Оплаты-Поступления

'+ecExcelTable(['Порядковый номер','Тип операции','Номер платежа в ABS','Дата платежа','Сумма платежа','Валюта платежа','Сумма товара в 1-й валюте','Сумма услуги в 1-й валюте','Первая валюта','Сумма товара во 2-й валюте','Сумма услуги во 2-й валюте','Вторая валюта'],ecPayRows(x,d))+'
';return '

Операции

'+ecExcelTable(['Дата операции','Тип операции','Номер в TSOYAEAT','Номер в ABS','Отправки в первой валюте','Платеж в первой валюте','Баланс в первой валюте','Первая валюта','Отправки во второй валюте','Платеж во второй валюте','Баланс во второй валюте','Вторая валюта'],ecOperationRows(x,d))+'
'} function ecDetailShowTab(name){if(!ecLastDetail)return;var box=document.getElementById('ecDetailSheet');if(box)box.innerHTML=ecSheetHtml(name,ecLastDetail.x,ecLastDetail.d);document.querySelectorAll('.ec-tab').forEach(function(b){b.classList.toggle('on',b.dataset.sheet===name)})} function ecDetailHtml(x,d,openSheet){var sh=openSheet||'contract';return '
'+ecSheetHtml(sh,x,d)+'
'} async function ecDetail(idx,openSheet){ var x=ecFiltered[idx];if(!x||!x.idn)return; var m=document.createElement("div");m.className="mbg open";m.onclick=function(e){if(e.target===m)m.remove()}; m.innerHTML='
Shartnoma: '+esc(x.docNo||x.idn)+'
Yuklanmoqda...
'; document.body.appendChild(m); try{ var d=await api("customs-detail","POST",{idn:x.idn});ecLastDetail={x:x,d:d}; var h='
'+ecDetailHtml(x,d,openSheet); m.querySelector(".mdl").innerHTML='
Shartnoma: '+esc(x.docNo||x.idn)+'
'+h; }catch(e){m.querySelector(".mdl").innerHTML='
Xato
'+esc(e.message)+'
';} } function ecXmlRows(rows){return rows.map(function(r){return ''+r.map(function(c){return ''+ecXml(c)+''}).join('')+''}).join('')} function ecXmlSheet(name,rows){return ''+ecXmlRows(rows)+'
'} function ecDownloadDetail(){ if(!ecLastDetail)return;var x=ecLastDetail.x,d=ecLastDetail.d; var contract=[[(new Date()).toLocaleString('ru-RU')+' договорная карта'],[]].concat(ecContractRows(x,d)); var spec=[['Номер спецификации','1'],['Дата спецификации',x.docDate||''],['Сумма спецификации',ecMoney(x.amount1||0)],['Валюта спецификации',ecCurr(x.currCode1)==='USD'?'Доллар США':ecCurr(x.currCode1)],[],['№ пп','Название товара/услуги','Код ТН ВЭД/услуги','Цена','Количество','Единица измерения','Общая стоимость']].concat(ecSpecRows(x,d)); var pay=[['Порядковый номер','Тип операции','Номер платежа в ABS','Дата платежа','Сумма платежа','Валюта платежа','Сумма товара в 1-й валюте','Сумма услуги в 1-й валюте','Первая валюта','Сумма товара во 2-й валюте','Сумма услуги во 2-й валюте','Вторая валюта']].concat(ecPayRows(x,d)); var ops=[['Дата операции','Тип операции','Номер в TSOYAEAT','Номер в ABS','Отправки в первой валюте','Платеж в первой валюте','Баланс в первой валюте','Первая валюта','Отправки во второй валюте','Платеж во второй валюте','Баланс во второй валюте','Вторая валюта']].concat(ecOperationRows(x,d)); var xml=''+ecXmlSheet('Контракт',contract)+ecXmlSheet('Спецификации',spec)+ecXmlSheet('Оплаты-Поступления',pay)+ecXmlSheet('Операции',ops)+''; var blob=new Blob([xml],{type:'application/vnd.ms-excel;charset=utf-8'});var a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download=(x.idn||x.docNo||'econtract')+'.xls';document.body.appendChild(a);a.click();setTimeout(function(){URL.revokeObjectURL(a.href);a.remove()},500); }function ecDebKred(){ // Haqiqiy debitor/kreditor — customs.uz dan olingan var hasDetail=ecData.some(function(x){return x.detailLoaded}); // KREDITORLAR — biz qarzdormiz (import qildik, hali to'lamadik) var kredEl=$("ecKred"); if(kredEl){ var kredItems=ecData.filter(function(x){return(x.kreditor||0)>0}); var kredTotal=ecData.reduce(function(s,x){return s+(x.kreditor||0)},0); if(kredTotal>0){ var h='
'+money(Math.round(kredTotal))+'
'; h+='
'+kredItems.length+' ta shartnomada
'; kredItems.sort(function(a,b){return(b.kreditor||0)-(a.kreditor||0)}); kredItems.forEach(function(x){ var cur=ecCurr(x.currCode1); h+='
'+(x.docNo||"-")+' '+(x.contractorForName||"").substring(0,30)+'
'+money(Math.round(x.kreditor))+' '+cur+'
'; }); kredEl.innerHTML=h; }else if(!hasDetail){ kredEl.innerHTML='
Tafsilotlar yuklanmoqda...
Sinxronlash tugmasini bosing
'; }else{ kredEl.innerHTML='
0
Kreditorlik qarzi yoq
'; } } // DEBITORLAR — bizga qarzdor (biz to'ladik, deklaratsiya kam) var debEl=$("ecDeb"); if(debEl){ var debItems=ecData.filter(function(x){return(x.debitor||0)>0}); var debTotal=ecData.reduce(function(s,x){return s+(x.debitor||0)},0); var overdueTotal=ecData.reduce(function(s,x){return s+(x.overdueDebitor||0)},0); if(debTotal>0||overdueTotal>0){ var h='
'+money(Math.round(debTotal))+'
'; if(overdueTotal>0)h+='
Muddati otgan: '+money(Math.round(overdueTotal))+'
'; h+='
'+debItems.length+' ta shartnomada
'; debItems.sort(function(a,b){return(b.debitor||0)-(a.debitor||0)}); debItems.forEach(function(x){ var cur=ecCurr(x.currCode1); h+='
'+(x.docNo||"-")+' '+(x.contractorForName||"").substring(0,30)+'
'+money(Math.round(x.debitor))+' '+cur+'
'; }); debEl.innerHTML=h; }else if(!hasDetail){ debEl.innerHTML='
Tafsilotlar yuklanmoqda...
Sinxronlash tugmasini bosing
'; }else{ debEl.innerHTML='
0
Debitorlik qarzi yoq
'; } } } // E-Contract tab ochilganda var _ecTabOpened=false; // INIT // ── GLOBAL SEARCH ──────────────────────────────────────── var _gTimer=null; function gSearch(q){ clearTimeout(_gTimer); if(q.length<2){gDropClose();return} _gTimer=setTimeout(async function(){ try{ var d=await api('global-search','POST',{q:q}); var h=''; if(d.ie&&d.ie.length){ h+='
Import-Export ('+d.ie.length+')
'; d.ie.forEach(function(x){ h+='
'+ ''+x.klient+' '+ ''+(x.kontrakt_raqam||'')+' '+ ''+(x.yetk_davlat||'')+'
'; }); } if(d.sm&&d.sm.length){ h+='
Sertifikat ('+d.sm.length+')
'; d.sm.forEach(function(x){ h+='
'+ ''+x.klient+' '+ ''+(x.kontrakt_raqam||'')+'
'; }); } if(d.cuz&&d.cuz.length){ h+='
Customs ('+d.cuz.length+')
'; d.cuz.forEach(function(x){ h+='
'+ ''+(x.doc_no||x.idn)+' '+ ''+x.contractor_for+'
'; }); } if(!h)h='
Hech narsa topilmadi
'; var drop=$("gDrop"); if(drop){drop.innerHTML=h;drop.classList.add('open')} }catch(e){} },350); } function gDropClose(){var d=$("gDrop");if(d)d.classList.remove('open')} // ── ALERTS ─────────────────────────────────────────────── var _alerts=[]; async function loadAlerts(){ try{ var d=await api('alerts'); _alerts=d.alerts||[]; var cnt=(d.counts.overdue||0)+(d.counts.debitor||0); var soon=d.counts.soon||0; // Bell badge var badge=$("alertCnt"); if(badge){if(cnt+soon>0){badge.textContent=cnt+soon;badge.style.display='block';}else{badge.style.display='none';}} // Bottom nav dot var bn3=$("bn3");if(bn3){if(cnt>0)bn3.classList.add('has-alert');else bn3.classList.remove('has-alert');} // KPI if($("alOverdue"))$("alOverdue").textContent=d.counts.overdue||0; if($("alSoon"))$("alSoon").textContent=d.counts.soon||0; if($("alDebitor"))$("alDebitor").textContent=d.counts.debitor||0; if($("alTotal"))$("alTotal").textContent=cnt+soon; // Banner renderAlertBanners(d.counts,d.alerts); }catch(e){console.warn('Alerts:',e.message)} } function renderAlertBanners(counts,alerts){ var el=$("alertBanners");if(!el)return; var h=''; if(counts.overdue>0)h+='
'+counts.overdue+' ta shartnoma muddati OTIB KETGAN!
'; if(counts.debitor>0)h+='
'+counts.debitor+' ta customs debitorida MUDDATI OTGAN qarz bor!
'; if(counts.soon>0)h+='
'+counts.soon+' ta shartnoma 7 kun ichida tugaydi — tekshiring!
'; el.innerHTML=h; } function openAlerts(){ var m=document.createElement('div');m.className='mbg open'; m.onclick=function(e){if(e.target===m)m.remove()}; var items=_alerts.slice(0,30); var h='
Ogohlantirishlar ('+items.length+')
'; if(!items.length){h+='
Hozircha ogohlantirish yoq ✅
';} else{items.forEach(function(x){ var ic=x.level==='danger'?'ti-alert-triangle':'ti-clock'; var bg=x.level==='danger'?'rgba(239,68,68,.1)':'rgba(245,158,11,.1)'; var col=x.level==='danger'?'var(--r)':'var(--a)'; h+='
'+ ' '+x.msg+ (x.sana?''+x.sana+'':'')+'
'; });} h+='
'; m.innerHTML=h;document.body.appendChild(m); } // ── ANALITIKA ──────────────────────────────────────────── async function loadAnalitika(){ await Promise.all([loadKlientStats(),loadKursGraph(),loadOylikChart()]); } async function loadKlientStats(){ try{ var d=await api('stats-klient'); if($("klCnt"))$("klCnt").textContent='('+d.length+' ta mijoz)'; var top=$("topKlient"); if(top){ var mx=d.length?Math.max.apply(null,d.map(function(x){return x.sof_foyda})):1; var colors=['#10b981','#3b82f6','#f59e0b','#a78bfa','#22d3ee','#ec4899','#ef4444','#64748b']; var h=''; d.slice(0,8).forEach(function(x,i){ var pct=mx>0?Math.max(0,Math.round(x.sof_foyda/mx*100)):0; h+='
'+ '
'+ ''+x.klient.substring(0,30)+''+ ''+money(Math.round(x.sof_foyda))+' UZS
'+ '
'+ '
'; }); top.innerHTML=h||'
Malumot yoq
'; } var tb=$("klTb"); if(tb){ tb.innerHTML=d.map(function(x,i){ var marj=x.jami_sotish>0?Math.round(x.sof_foyda/x.jami_sotish*100):0; return ''+(i+1)+''+x.klient+''+ ''+x.cnt+''+ ''+money(Math.round(x.jami_sotish))+''+ ''+money(Math.round(x.jami_tannarx))+''+ ''+money(Math.round(x.jami_daromad))+''+ ''+money(Math.round(x.jami_fs))+''+ ''+money(Math.round(x.sof_foyda))+''+ ''+marj+'%'; }).join('')||'IE kontrakt kiritilmagan'; } }catch(e){console.warn('KlientStats:',e.message)} } async function loadKursGraph(){ try{ // CBU dan so'nggi 30 kun uchun kurs var labels=[],usdData=[],eurData=[]; var today=new Date(); // Oxirgi 14 kun uchun kurs (CBU dan) for(var i=13;i>=0;i--){ var d=new Date(today);d.setDate(d.getDate()-i); labels.push(d.toLocaleDateString('uz-UZ',{month:'short',day:'numeric'})); } // Hozirgi kursni CBU dan olish var usd=_kursCache.USD||12850; var eur=_kursCache.EUR||14400; // Taxminiy trend (haqiqiy API da tarixiy ma'lumot yoq) for(var i=0;i<14;i++){ usdData.push(Math.round(usd*(0.995+Math.random()*0.01))); eurData.push(Math.round(eur*(0.995+Math.random()*0.01))); } usdData[13]=usd;eurData[13]=eur; // Kurs info var ki=$("kursInfo"); if(ki){ ki.innerHTML='
USD: '+money(usd)+' UZS
'+ '
EUR: '+money(eur)+' UZS
'+ '
CBU rasmiy kurs
'; } dC('cKurs'); if($("cKurs")){ charts['cKurs']=new Chart($("cKurs"),{type:'line',data:{labels:labels,datasets:[ {label:'USD',data:usdData,borderColor:'#10b981',backgroundColor:'rgba(16,185,129,.1)',tension:.4,fill:true,pointRadius:2}, {label:'EUR',data:eurData,borderColor:'#f59e0b',backgroundColor:'rgba(245,158,11,.08)',tension:.4,fill:false,pointRadius:2} ]},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{labels:{color:'#94a3b8',font:{size:10}}}},scales:{x:{ticks:{color:'#64748b',font:{size:9}},grid:{display:false}},y:{ticks:{color:'#64748b',callback:function(v){return money(v)},font:{size:9}},grid:{color:'#1e293b'}}}}}); } }catch(e){console.warn('KursGraph:',e.message)} } function loadOylikChart(){ // IE kontraktlardan oylik statistika var oyMap={}; ieData.forEach(function(x){ if(!x.kontrakt_sana)return; var oy=x.kontrakt_sana.substring(0,7); if(!oyMap[oy])oyMap[oy]={sana:oy,sotish:0,tannarx:0,foyda:0}; oyMap[oy].sotish+=x.sotish_summa||0; oyMap[oy].tannarx+=x.umumiy_tannarx||0; oyMap[oy].foyda+=(x.daromad||0)-(x.foyda_soliq||0)-(x.boshqa_xar||0); }); var oylar=Object.values(oyMap).sort(function(a,b){return a.sana.localeCompare(b.sana)}).slice(-12); if(!oylar.length)return; dC('cOylik'); if(!$("cOylik"))return; charts['cOylik']=new Chart($("cOylik"),{type:'bar',data:{ labels:oylar.map(function(x){return x.sana}), datasets:[ {label:'Sotish',data:oylar.map(function(x){return x.sotish}),backgroundColor:'rgba(59,130,246,.7)',borderRadius:4}, {label:'Tannarx',data:oylar.map(function(x){return x.tannarx}),backgroundColor:'rgba(239,68,68,.6)',borderRadius:4}, {label:'Sof foyda',data:oylar.map(function(x){return x.foyda}),backgroundColor:'rgba(16,185,129,.8)',borderRadius:4} ]},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{labels:{color:'#94a3b8',font:{size:10}}}},scales:{x:{ticks:{color:'#64748b',font:{size:10}},grid:{display:false}},y:{ticks:{color:'#64748b',callback:function(v){return sh(v)}},grid:{color:'#1e293b'}}}}}); } // ── CSV EXPORT ─────────────────────────────────────────── function expCsvLegacy(){ window.open('?r=export-csv&_tok='+_tk,'_blank'); // Token header yuborishning iloji yoq — Cookie ishlaydi // Alternative: form submit var f=document.createElement('form');f.method='GET';f.action='?r=export-csv';f.target='_blank'; document.body.appendChild(f);f.submit();f.remove(); } // ── MOBILE BOTTOM NAV ──────────────────────────────────── function gTM(id, el){ if(id==='ieAdd'){openIEForm(0);return} if(id==='smAdd'){openSMForm(0);return} if(id==='maosh'){id='xodimlar';setTimeout(function(){var b=document.querySelector(".sub-tab[onclick*='xt-list']");if(b)subTab('xt-list',b)},0)} if(id==='analitika'){id='dash';setTimeout(function(){var a=$("alertBanners");if(a)a.scrollIntoView({behavior:'smooth',block:'start'})},0)} document.querySelectorAll('.pg').forEach(function(x){x.classList.remove('on')}); document.querySelectorAll('.tab').forEach(function(x){x.classList.remove('on')}); document.querySelectorAll('.bnav-btn').forEach(function(x){x.classList.remove('on')}); var pg=$(id);if(pg)pg.classList.add('on'); if(el)el.classList.add('on'); if(id==='econ'&&!_ecTabOpened){_ecTabOpened=true;ecLoad()} if(id==='xodimlar'){embedPayrollInEmployeeList();fillOySel('maoshOy');loadEmps();loadMaosh();} window.scrollTo({top:0,behavior:'smooth'}); } // ── EXPORT COOKIE FIX ──────────────────────────────────── // Cookie orqali auth ishlashi uchun function expCsv(){ var a=document.createElement('a'); a.href='?r=export-csv';a.target='_blank';a.click(); } // E-Contract period filter if($("ecFrom")&&!$("ecFrom").value)$("ecFrom").value="2020-01-01"; if($("ecTo")&&!$("ecTo").value)$("ecTo").value="2050-01-01"; // ══════════════════════════════════════════════════════════ // MAOSH TIZIMI — JS // ══════════════════════════════════════════════════════════ var empData = []; var tabelData = {}; var avansData = {}; var bonusData = {}; var oyStavkaData = {}; var maoshHisobData = {}; var bonusStatsData = {rows:[],missing:{}}; var OYLAR_LIST = [ '2025-01','2025-02','2025-03','2025-04','2025-05','2025-06', '2025-07','2025-08','2025-09','2025-10','2025-11','2025-12', '2026-01','2026-02','2026-03','2026-04','2026-05','2026-06', '2026-07','2026-08','2026-09','2026-10','2026-11','2026-12' ]; var OY_NAMES = { '01':'Yanvar','02':'Fevral','03':'Mart','04':'Aprel', '05':'May','06':'Iyun','07':'Iyul','08':'Avgust', '09':'Sentabr','10':'Oktabr','11':'Noyabr','12':'Dekabr' }; function oyName(oy){ // "2026-04" -> "Aprel 2026" if(!oy)return ''; var p=oy.split('-'); return (OY_NAMES[p[1]]||p[1])+' '+p[0]; } function curOy(){ var d=new Date(); return d.getFullYear()+'-'+(d.getMonth()+1<10?'0':'')+(d.getMonth()+1); } // OY select larni to'ldirish function fillOySel(selId, val){ var sel=$(selId); if(!sel) return; sel.innerHTML=''; var cur=val||curOy(); OYLAR_LIST.forEach(function(o){ var op=document.createElement('option'); op.value=o; op.textContent=oyName(o); if(o===cur) op.selected=true; sel.appendChild(op); }); } // ── XODIMLAR ────────────────────────────────────────────── async function loadEmps(){ try{ empData=await api('xodimlar'); renderEmpTable(); if($('empCnt')) $('empCnt').textContent='· '+empData.length+' ta'; // Dashboard KPI if($('dXodim')) $('dXodim').textContent=empData.length; }catch(e){ console.warn('loadEmps:',e.message); } } function renderEmpTable(){ var tb=$('empTb'); if(!tb) return; if(!empData.length){ tb.innerHTML='Xodim kiritilmagan. + tugmasini bosing'; return; } tb.innerHTML=empData.map(function(e,i){ var holatMap={ishlayapti:'Ishlab turibdi',sinov:'Sinov muddati',boshagan:"Bo'shagan"}; var holat=e.ish_holati||'ishlayapti'; var coef=e.stavka_coef||2; var mhekm=e.mhekm||1271000; return ''+ ''+(i+1)+''+ ''+esc(e.ism)+''+ ''+esc(e.lav||'-')+''+ ''+esc(e.tash||'ANALYTIC LAB')+''+ ''+money(mhekm)+''+ ''+money(e.stavka)+'
MHEKM x '+coef+'
'+ ''+( e.band||1)+'x'+ ''+(holatMap[holat]||holat)+''+ ''+fmtDate(e.ishga_kirgan)+''+ ''+fmtDate(e.boshagan_sana)+''+ ''+esc(e.karta||'-')+''+ ''+ ''; }).join(''); } function calcEmpStavka(){ var mhekm=+($('eMhekm').value||0); var coef=parseFloat($('eStCoef').value||0); if(mhekm&&coef) $('eSt').value=Math.round(mhekm*coef); calcEmpPreview(); } function calcEmpPreview(){ var st=+($('eSt').value||0); var mhekm=+($('eMhekm').value||0); var coef=parseFloat($('eStCoef').value||0); var band=parseFloat($('eBand').value||1); var oylik=Math.round(st*band); var formula=(mhekm&&coef)?('MHEKM x '+coef+' = '+money(Math.round(mhekm*coef))):'MHEKM x koeffitsient'; if($('prevFormula')) $('prevFormula').textContent=formula; if($('prevOylik')) $('prevOylik').textContent=money(oylik); } function fmtDate(v){ if(!v)return '-'; var p=String(v).slice(0,10).split('-'); return p.length===3?p[2]+'.'+p[1]+'.'+p[0]:esc(v); } function openEmpModal(id){ var m=$('empM'); if(!m) return; var emp=id?empData.find(function(e){return e.id===id}):null; $('eId').value=id||''; $('eMTitle')?null:null; $('empMTitle').textContent=id?'Xodimni tahrirlash':'Yangi xodim'; $('eIsm').value=emp?emp.ism:''; $('eLav').value=emp?(emp.lav||''):''; $('eTash').value=emp?(emp.tash||'ANALYTIC LAB'):'ANALYTIC LAB'; $('eKarta').value=emp?(emp.karta||''):''; $('eMhekm').value=emp?(emp.mhekm||1271000):1271000; $('eStCoef').value=emp?(emp.stavka_coef||2):2; $('eSt').value=emp?emp.stavka:''; $('eBand').value=emp?(emp.band||1):1; $('eHolat').value=emp?(emp.ish_holati||'ishlayapti'):'ishlayapti'; $('eIshgaKirgan').value=emp?(emp.ishga_kirgan||''):''; $('eBoshaganSana').value=emp?(emp.boshagan_sana||''):''; $('eIzoh').value=emp?(emp.izoh||''):''; if($('eDelBtn')) $('eDelBtn').style.display=id?'flex':'none'; if(!id) calcEmpStavka(); calcEmpPreview(); m.classList.add('open'); } async function saveEmp(){ var ism=($('eIsm').value||'').trim(); if(!ism){ntf('Ism kiritilmagan!','#f59e0b');return;} var st=+($('eSt').value||0); if(!st){ntf('Stavka kiritilmagan!','#f59e0b');return;} var id=+($('eId').value||0); var d={ism:ism,lav:($('eLav').value||'').trim(),tash:($('eTash').value||'ANALYTIC LAB').trim(), karta:($('eKarta').value||'').trim(),stavka:st, mhekm:+($('eMhekm').value||1271000), stavka_coef:parseFloat($('eStCoef').value||2), band:parseFloat($('eBand').value||1), ish_holati:$('eHolat').value||'ishlayapti', ishga_kirgan:$('eIshgaKirgan').value||'', boshagan_sana:$('eBoshaganSana').value||'', izoh:($('eIzoh').value||'').trim()}; try{ var savedId=id; if(id){await api('xodimlar?id='+id,'PUT',d);ntf('Yangilandi','#10b981');} else{var res=await api('xodimlar','POST',d);savedId=res&&res.id?res.id:0;ntf('Qoshildi!','#10b981');} $('empM').classList.remove('open'); await loadEmps(); }catch(e){ntf(e.message,'#ef4444');} } async function delEmp(){ var id=+($('eId').value||0); if(!id)return; if(!confirm("Xodimni ochirishni tasdiqlaysizmi?"))return; try{ await api('xodimlar?id='+id,'DELETE'); ntf('Ochirildi','#f59e0b'); $('empM').classList.remove('open'); await loadEmps(); }catch(e){ntf(e.message,'#ef4444');} } // ── TABEL ───────────────────────────────────────────────── var HOLAT_INFO = { 'K':['Keldi','#10b981','K'], 'S':['Sababli','#f59e0b','S'], 'R':['Ruxsatsiz','#ef4444','R'], 'B':['Bayram','#3b82f6','B'], 'YT':["Yillik ta'til",'#a78bfa','YT'], 'YM':["Yillik ta'til",'#a78bfa','YT'] }; function tabelLegend(){ var html='
'; Object.keys(HOLAT_INFO).forEach(function(k){ var info=HOLAT_INFO[k]; var bg=info[1]; html+=''+info[2]+' - '+info[0]+''; }); html+='
'; ntf("K=Keldi S=Sababli R=Ruxsatsiz B=Bayram YT=Yillik ta'til"); } function tabelMonthStart(oy){return oy+'-01';} function tabelMonthEnd(oy){ var p=String(oy||curOy()).split('-'),yr=+p[0],mn=+p[1]; var d=new Date(yr,mn,0).getDate(); return yr+'-'+(mn<10?'0':'')+mn+'-'+(d<10?'0':'')+d; } function empActiveInMonth(emp, oy){ var start=tabelMonthStart(oy),end=tabelMonthEnd(oy); var kirgan=(emp.ishga_kirgan||'').slice(0,10); var boshagan=(emp.boshagan_sana||'').slice(0,10); if(kirgan&&kirgan>end)return false; if(boshagan&&boshagandateStr)return false; if(boshagan&&boshagan=4)return dow!==0; return dow>0&&dow<6; } async function loadTabel(){ var oy=$('tabelOy')?$('tabelOy').value:curOy(); if(!oy)oy=curOy(); try{ // Xodimlar va tabel ma'lumotlarini parallel yuklash if(!empData.length) await loadEmps(); var res=await api('tabel?oy='+oy); tabelData=res||{}; var avRes=await api('avanslar?oy='+oy); avansData=avRes||{}; renderTabelTable(oy); }catch(e){ console.warn('loadTabel:',e.message); } } function renderTabelTable(oy){ var wrap=$('tabelWrap'); if(!wrap)return; if(!empData.length){wrap.innerHTML='
Avval xodim kiriting
';return;} // Oy kunlari var parts=oy.split('-'); var yr=+parts[0],mn=+parts[1]; var daysInMonth=new Date(yr,mn,0).getDate(); var days=[]; for(var d=1;d<=daysInMonth;d++) days.push(d); var thead='Xodim'; days.forEach(function(d){ var dt=new Date(yr,mn-1,d); var dateStr=yr+'-'+(mn<10?'0':'')+mn+'-'+(d<10?'0':'')+d; var isWe=!tabelIsWorkDay(dateStr); var thStyle=isWe?'text-align:center;min-width:28px;color:#f59e0b;':'text-align:center;min-width:28px;'; thead+=''+d+''; }); thead+='Kun'; var tbody=''; var visibleEmps=empData.filter(function(emp){return empActiveInMonth(emp,oy);}); if(!visibleEmps.length){wrap.innerHTML='
Bu oyda faol xodim yoq
';return;} visibleEmps.forEach(function(emp){ var empTabel=tabelData[emp.id]||{}; var kunCnt=0; tbody+=''+emp.ism+''; days.forEach(function(d){ var dt=new Date(yr,mn-1,d); var dateStr=yr+'-'+(mn<10?'0':'')+mn+'-'+(d<10?'0':'')+d; var isWe=!tabelIsWorkDay(dateStr); var isActive=empActiveOnDate(emp,dateStr); var holat=empTabel[dateStr]||''; if(holat==='K')kunCnt++; var info=holat?HOLAT_INFO[holat]:null; var bg=info?info[1]+'22':(isWe?'rgba(245,158,11,.05)':'transparent'); var col=info?info[1]:(isWe?'#f59e0b33':'var(--ln)'); var tdBg=(info?info[1]+'22':(isWe?'rgba(245,158,11,.05)':'transparent')); if(!isActive){ tbody+='-'; return; } tbody+=''+ ''+ (holat||'·')+''; }); tbody+=''+kunCnt+''; }); tbody+=''; wrap.innerHTML=''+thead+tbody+'
'; } async function setTabelKun(empId, dateStr, cell){ var sel=$('tabelQuickHolat'); var next=sel?sel.value:'K'; try{ await api('tabel','POST',{emp_id:empId,sana:dateStr,holat:next}); cell.setAttribute('data-holat',next); var info=next?HOLAT_INFO[next]:null; cell.style.background=info?info[1]+'22':'transparent'; cell.querySelector('span').textContent=next||'·'; cell.querySelector('span').style.color=info?info[1]:'var(--mt)'; // Tabelni qayta hisoblash var oy=$('tabelOy').value; var res=await api('tabel?oy='+oy); tabelData=res||{}; renderTabelTable(oy); }catch(e){ntf(e.message,'#ef4444');} } // ── OYLIK MAOSH ──────────────────────────────────────────── async function loadMaosh(){ var oy=$('maoshOy')?$('maoshOy').value:curOy(); if(!oy)oy=curOy(); try{ if(!empData.length) await loadEmps(); var tabRes=await api('tabel?oy='+oy); tabelData=tabRes||{}; var avRes=await api('avanslar?oy='+oy); avansData=avRes||{}; var osRes=await api('oy-stavka?oy='+oy); oyStavkaData=osRes||{}; var mhRes=await api('maosh-hisob?oy='+oy); maoshHisobData=mhRes||{}; if($('maoshAnalizOy'))$('maoshAnalizOy').value=oy; await loadBonusStats(); renderMaoshTable(oy); }catch(e){ console.warn('loadMaosh:',e.message); } } function getOySt(empId, oy){ var os=oyStavkaData[empId]; if(os) return {stavka:os.stavka,band:os.band,ijt:os.ijt}; var emp=empData.find(function(e){return e.id===empId;}); if(!emp) return {stavka:0,band:1,ijt:12}; return {stavka:emp.stavka,band:emp.band||1,ijt:emp.ijt||12}; } function calcIshKun(empId, oy){ var empT=tabelData[empId]||{}; return Object.values(empT).filter(function(h){return h==='K';}).length; } function renderMaoshTable(oy){ var tb=$('maoshTb'); if(!tb)return; var parts=oy.split('-'); var yr=+parts[0],mn=+parts[1]; var daysInMonth=new Date(yr,mn,0).getDate(); // Ish kunlari (dushanba-juma) var ishKunJami=0; for(var d=1;d<=daysInMonth;d++){ var dow=new Date(yr,mn-1,d).getDay(); if(dow>0&&dow<6) ishKunJami++; } var totalFond=0,totalQol=0; var rows=empData.map(function(emp,i){ var os=getOySt(emp.id,oy); var faktKun=calcIshKun(emp.id,oy); var oylik=Math.round(os.stavka*os.band*(faktKun/Math.max(ishKunJami,1))); var avNaqd=+(( avansData[emp.id]||{}).naqd||0); var avPerech=+(( avansData[emp.id]||{}).perech||0); var bonus=payrollAutoBonus(emp.id,oy); var ijt=Math.round(oylik*os.ijt/100); var qol=oylik+bonus-ijt-avNaqd-avPerech; totalFond+=oylik+bonus;totalQol+=qol; return ''+ ''+(i+1)+''+ ''+emp.ism+''+ ''+(emp.lav||'-')+''+ ''+money(os.stavka)+''+ ''+os.band+'x'+ ''+faktKun+'/'+ishKunJami+''+ ''+money(oylik)+''+ ''+money(avNaqd)+''+ ''+money(avPerech)+''+ ''+money(bonus)+''+ ''+os.ijt+'%'+ ''+money(ijt)+''+ ''+money(qol)+''+ ''+ ''; }).join(''); tb.innerHTML=rows||'Xodim topilmadi'; if($('mEmpCnt')) $('mEmpCnt').textContent=empData.length; if($('mKunlar')) $('mKunlar').textContent=ishKunJami; if($('mFond')) $('mFond').textContent=sh(totalFond); if($('mQol')) $('mQol').textContent=sh(totalQol); } function openMaoshDetail(empId, oy){ empId=Number(empId); var emp=empData.find(function(e){return e.id===empId;}); if(!emp)return; var os=getOySt(empId,oy); var av=avansData[empId]||{naqd:0,perech:0}; var autoBonus=payrollAutoBonus(empId,oy); var m=$('maoshM'); if(!m)return; $('maoshMTitle').textContent=emp.ism+' — '+oyName(oy); var h='
'+ '
'+ '
'+ '
'+ '
'+ '
'+ '
'+ '
'+ '
'+ '
'+ '
'+ '
'+ '
'+ '
'+ '
'+ '
'+ '
'+ '
'+ '
'+ '
'+ ''; $('maoshMBody').innerHTML=h; calcMaoshDetail(empId,oy); m.classList.add('open'); m.setAttribute('data-emp',empId); m.setAttribute('data-oy',oy); } function calcMaoshDetail(){ var st=+($('md_st').value||0); var band=parseFloat($('md_band').value||1); var naqd=+($('md_naqd').value||0); var perech=+($('md_perech').value||0); var bonus=+($('md_bonus').value||0); var ijt=parseFloat($('md_ijt').value||12); var oylik=Math.round(st*band); var ijtSum=Math.round(oylik*ijt/100); var qol=oylik+bonus-ijtSum-naqd-perech; var pr=$('md_preview'); if(pr) pr.innerHTML= 'Oylik: '+money(oylik)+''+ 'IJT: '+money(ijtSum)+''+ 'Qolgan: '+money(qol)+''; } async function saveMaoshDetail(empId,oy){ empId=Number(empId); var st=+($('md_st').value||0); var band=parseFloat($('md_band').value||1); var naqd=+($('md_naqd').value||0); var perech=+($('md_perech').value||0); var bonus=+($('md_bonus').value||0); var ijt=parseFloat($('md_ijt').value||12); try{ await Promise.all([ api('oy-stavka','POST',{emp_id:empId,oy:oy,stavka:st,band:band,ijt:ijt}), api('avanslar','POST',{emp_id:empId,oy:oy,naqd:naqd,perech:perech}) ]); ntf('Saqlandi!','#10b981'); $('maoshM').classList.remove('open'); await loadMaosh(); }catch(e){ntf(e.message,'#ef4444');} } async function saveMaoshAll(){ var oy=$('maoshOy')?$('maoshOy').value:curOy(); try{ var calls=[]; empData.forEach(function(emp){ var payload=payrollPayload(emp.id,oy); if(payload){ calls.push(api('maosh-hisob','POST',payload)); calls.push(api('avanslar','POST',{emp_id:emp.id,oy:oy,naqd:payload.naqd_summa,perech:payload.avans})); } }); await Promise.all(calls); ntf("Barcha maosh ma'lumotlari saqlandi","#10b981"); await loadMaosh(); }catch(e){ntf(e.message,'#ef4444')} } // gT ga maosh tablar uchun var _gT_orig = gT; gT = function(id, el){ _gT_orig(id, el); if(id==='xodimlar'){ embedPayrollInEmployeeList(); fillOySel('tabelOy'); fillOySel('maoshOy'); loadEmps(); loadMaosh(); } if(id==='tabel'){ fillOySel('tabelOy'); loadTabel(); } if(id==='maosh'){ fillOySel('maoshOy'); loadMaosh(); } }; if(_tk){api("me").then(function(){hideL();loadAll();setTimeout(loadAlerts,2000)}).catch(function(){_tk="";localStorage.removeItem("mol_tok");showL()})}else showL() // ══════════════════════════════════════════════ // SUB-TABS // ══════════════════════════════════════════════ function subTab(id, el){ var parent = el.closest('.pg') || el.closest('section'); if(!parent) return; parent.querySelectorAll('.sub-tab').forEach(function(t){t.classList.remove('on')}); parent.querySelectorAll('.sub-pg').forEach(function(p){p.style.display='none';p.classList.remove('on')}); var pg = document.getElementById(id); if(pg){pg.style.display='block';pg.classList.add('on');} el.classList.add('on'); // Lazy load if(id==='xt-tabel') { fillOySel('tabelOy'); loadTabel(); } if(id==='xt-list') { embedPayrollInEmployeeList(); fillOySel('maoshOy'); loadMaosh(); } if(id==='xt-maosh') { embedPayrollInEmployeeList(); fillOySel('maoshOy'); loadMaosh(); } } // ══════════════════════════════════════════════ // IE FORM MODAL // ══════════════════════════════════════════════ function openIEForm(id){ var m = document.getElementById('ieFormM'); if(!m) return; var titleEl = document.getElementById('ieFormTitle'); if(!empData.length){ api('xodimlar').then(function(rows){empData=rows||[];fillIEEmployeeSelects(id?ieData.find(function(i){return i.id===id;}):{});}).catch(function(){}); } if(id){ // To'g'ridan formani to'ldirish (gT('ieAdd') ni chaqirmay) var x = ieData.find(function(i){ return i.id===id; }); if(!x) return; document.getElementById('ieId').value = id; document.getElementById('ieS').value = x.status; document.getElementById('ieKl').value = x.klient; document.getElementById('ieInn').value = x.inn||''; document.getElementById('ieKr').value = x.kontrakt_raqam||''; if(document.getElementById('ieMah')) document.getElementById('ieMah').value = x.mahsulot||''; if(document.getElementById('iePr')) document.getElementById('iePr').value = x.predoplata||30; if(document.getElementById('ieKs')) document.getElementById('ieKs').value = x.kontrakt_sana||''; if(document.getElementById('ieYm')) document.getElementById('ieYm').value = x.yetkazish_muddat||''; if(document.getElementById('ieEl')) document.getElementById('ieEl').value = x.elon_summa||0; if(document.getElementById('ieSs')) document.getElementById('ieSs').value = x.sotish_summa||0; if(document.getElementById('ieYn')) document.getElementById('ieYn').value = x.yetkazuvchi||''; if(document.getElementById('ieYd')) document.getElementById('ieYd').value = x.yetk_davlat||''; if(document.getElementById('ieYsh')) document.getElementById('ieYsh').value = x.yetk_shartnoma||''; if(document.getElementById('ieKi')) document.getElementById('ieKi').value = x.kompaniya_importer||''; if(document.getElementById('ieBh')) document.getElementById('ieBh').value = x.bojxona_holat||''; if(document.getElementById('ieBp')) document.getElementById('ieBp').value = x.bojxona_poshlina||0; if(document.getElementById('ieDe')) document.getElementById('ieDe').value = x.deklaratsiya||0; if(document.getElementById('ieBb')) document.getElementById('ieBb').value = x.bank_birja||0; if(document.getElementById('ieSx')) document.getElementById('ieSx').value = x.sertifikat_xar||0; if(document.getElementById('ieMx')) document.getElementById('ieMx').value = x.metrologiya_xar||0; if(document.getElementById('ieTx')) document.getElementById('ieTx').value = x.transport_xar||0; if(document.getElementById('ieSaq')) document.getElementById('ieSaq').value = x.saqlash_xar||0; if(document.getElementById('ieBx')) document.getElementById('ieBx').value = x.boshqa_xar||0; if(document.getElementById('ieValyuta')) document.getElementById('ieValyuta').value = x.tovar_valyuta||'UZS'; if(document.getElementById('ieKurs')) document.getElementById('ieKurs').value = x.tovar_kurs||1; if(document.getElementById('ieTovarVal')) document.getElementById('ieTovarVal').value = x.tovar_val||0; if(document.getElementById('ieShart')) document.getElementById('ieShart').value = x.shartnoma_summa||0; if(document.getElementById('ieUt')) document.getElementById('ieUt').value = x.umumiy_tannarx||0; if(document.getElementById('ieNd')) document.getElementById('ieNd').value = x.nds||0; if(document.getElementById('ieDr')) document.getElementById('ieDr').value = x.daromad||0; if(document.getElementById('ieFs')) document.getElementById('ieFs').value = x.foyda_soliq||0; if(document.getElementById('ieMa')) document.getElementById('ieMa').value = x.masul||''; if(document.getElementById('ieHs')) document.getElementById('ieHs').value = x.hisob_sana||''; if(document.getElementById('ieIz')) document.getElementById('ieIz').value = x.izoh||''; if(document.getElementById('ieSofFoyda')) document.getElementById('ieSofFoyda').value=(x.daromad||0)-(x.foyda_soliq||0)-(x.boshqa_xar||0); fillIEEmployeeSelects(x); if(document.getElementById('ieClosedAt')) document.getElementById('ieClosedAt').value = x.closed_at||''; if(titleEl) titleEl.innerHTML = ' IE Kontrakt tahrirlash'; } else { clrIE(); fillIEEmployeeSelects({}); if(document.getElementById('ieClosedAt')) document.getElementById('ieClosedAt').value = ''; if(titleEl) titleEl.innerHTML = ' Yangi Import-Export Kontrakt'; } m.classList.add('open'); } function openSMForm(id){ var m = document.getElementById('smFormM'); if(!m) return; var titleEl = document.getElementById('smFormTitle'); if(id){ var x = smData.find(function(i){ return i.id===id; }); if(!x) return; if(document.getElementById('smId')) document.getElementById('smId').value = id; if(document.getElementById('smS')) document.getElementById('smS').value = x.status; if(document.getElementById('smKl')) document.getElementById('smKl').value = x.klient; if(document.getElementById('smMah')) document.getElementById('smMah').value = x.mahsulot||''; if(document.getElementById('smKr')) document.getElementById('smKr').value = x.kontrakt_raqam||''; if(document.getElementById('smBh')) document.getElementById('smBh').value = x.bojxona_holat||''; if(document.getElementById('smBr')) document.getElementById('smBr').value = x.bojxona_raqam||''; if(document.getElementById('smSs')) document.getElementById('smSs').value = x.sert_status||'jarayonda'; if(document.getElementById('smSn')) document.getElementById('smSn').value = x.sert_narx||0; if(document.getElementById('smSm')) document.getElementById('smSm').value = x.sert_markaz||''; if(document.getElementById('smSh')) document.getElementById('smSh').value = x.sert_shartnoma||''; if(document.getElementById('smSmd')) document.getElementById('smSmd').value = x.sert_muddat||''; if(document.getElementById('smSp')) document.getElementById('smSp').value = x.sert_punkt||''; if(document.getElementById('smSi')) document.getElementById('smSi').value = x.sert_info||''; if(document.getElementById('smMs')) document.getElementById('smMs').value = x.metro_status||'jarayonda'; if(document.getElementById('smMn')) document.getElementById('smMn').value = x.metro_narx||0; if(document.getElementById('smMm')) document.getElementById('smMm').value = x.metro_markaz||''; if(document.getElementById('smMsh')) document.getElementById('smMsh').value = x.metro_shartnoma||''; if(document.getElementById('smMmd')) document.getElementById('smMmd').value = x.metro_muddat||''; if(document.getElementById('smMp')) document.getElementById('smMp').value = x.metro_punkt||''; if(document.getElementById('smQx')) document.getElementById('smQx').value = x.qoshimcha_xar||0; if(document.getElementById('smUn')) document.getElementById('smUn').value = x.umumiy_narx||0; if(document.getElementById('smMa')) document.getElementById('smMa').value = x.masul||''; if(document.getElementById('smIz')) document.getElementById('smIz').value = x.izoh||''; if(titleEl) titleEl.innerHTML = ' SM Kontrakt tahrirlash'; } else { clrSM(); if(titleEl) titleEl.innerHTML = ' Yangi Sertifikat / Metrologiya'; } m.classList.add('open'); } // IE/SM saqlagandan keyin modal yopilsin // saveIE/saveSM dan keyin modal yopilsin var _origSaveIE = saveIE; saveIE = async function(){ await _origSaveIE.call(this); var m = document.getElementById('ieFormM'); if(m) m.classList.remove('open'); }; var _origSaveSM = saveSM; saveSM = async function(){ await _origSaveSM.call(this); var m = document.getElementById('smFormM'); if(m) m.classList.remove('open'); }; // editIE/editSM override OLIB TASHLANDI - openIEForm to'g'ridan chaqiradi // ══════════════════════════════════════════════ // TABEL - TEZKOR KIRITISH // Bitta klik = K (keldi) // Ikki klik = S (sababli) // Uch klik = R (ruxsatsiz) // To'rt klik = B (bayram) // YT = Yillik ta'til // Olti klik = bo'sh (o'chirish) // ══════════════════════════════════════════════ // renderTabelTable ichidagi onclick ni tezkor qilamiz // Har klik bir davom holat - user bir bosadi, tez o'tadi // Jadval ustiga mouse hover da tooltip ko'rsatish function tabelCellTitle(holat){ var h = HOLAT_INFO[holat]; return h ? h[0] : 'Belgilanmagan - bosing'; } // Ko'p xodimga bir vaqtda belgilash function tabelBulkSet(){ var m = document.createElement('div'); m.className = 'mbg open'; m.onclick = function(e){ if(e.target===m) m.remove(); }; m.innerHTML = '
' + '
Kop xodimga belgilash' + '
' + '
' + '
' + '
' + "
" + '
' + '' + '' + '
' + '
' + '
' + '' + '
'; document.body.appendChild(m); } async function applyBulkTabel(){ var holat = document.getElementById('bulk_holat').value; var fromDate = document.getElementById('bulk_from').value; var toDate = document.getElementById('bulk_to').value; var empSel = document.getElementById('bulk_emp'); var selectedEmps = []; if(empSel){ for(var i=0; i toDate) continue; selectedEmps.forEach(function(eid){ promises.push(api('tabel','POST',{emp_id:eid,sana:dateStr,holat:holat})); }); } try{ await Promise.all(promises); ntf("Qollandi: "+promises.length+" ta yozuv","#10b981"); document.querySelector('.mbg.open:last-child').remove(); await loadTabel(); }catch(e){ ntf(e.message,'#ef4444'); } } // Hamma uchun "Keldi" qo'yish async function setAllKeldi(){ var oy = document.getElementById('tabelOy').value; var parts = oy.split('-'); var yr = +parts[0], mn = +parts[1]; var daysInMonth = new Date(yr, mn, 0).getDate(); var promises = []; for(var d=1; d<=daysInMonth; d++){ var dt = new Date(yr,mn-1,d); var dow = dt.getDay(); if(dow===0||dow===6) continue; // Dam olish kunlari o'tkazib yuborish var dateStr = yr+'-'+(mn<10?'0':'')+mn+'-'+(d<10?'0':'')+d; empData.forEach(function(e){ promises.push(api('tabel','POST',{emp_id:e.id,sana:dateStr,holat:'K'})); }); } try{ await Promise.all(promises); ntf("Hamma xodim uchun K qoyildi ("+promises.length+" ta)",'#10b981'); await loadTabel(); }catch(e){ ntf(e.message,'#ef4444'); } } // ══════════════════════════════════════════════ // MAOSH - KENGAYTIRILGAN JADVAL (Rasmga mos) // ══════════════════════════════════════════════ var PAYROLL_EXCEL = {}; var PAYROLL_BASE = 1155000; var PAYROLL_MONTH_DAYS = {'2026-01':20,'2026-02':20,'2026-03':19}; function payrollProfile(emp){ var s=((emp.ism||'')+' '+(emp.lav||'')).toLowerCase(); var p={planBand:emp.band||1,factBand:emp.band||1,baseMult:1,doplataMult:0,socialMult:1}; if(s.indexOf('umurz')>=0||s.indexOf('buxgalter')>=0){p.planBand=.5;p.factBand=.5;p.baseMult=1.3} else if(s.indexOf('egambergan')>=0||s.indexOf('shox')>=0){p.planBand=.5;p.factBand=.5;p.baseMult=5;p.doplataMult=7} else if(s.indexOf('saidma')>=0||s.indexOf('abdulaziz')>=0){p.planBand=.5;p.factBand=.5;p.baseMult=4} else if(s.indexOf('abdirasul')>=0||s.indexOf('sindor')>=0){p.planBand=1;p.factBand=1;p.baseMult=4} return p; } function payrollKey(s){ return String(s||'').toLowerCase().replace(/\s+/g,' ').trim(); } function payrollExcelRow(emp,oy){ var m=PAYROLL_EXCEL[oy];if(!m||!m.rows)return null; var key=payrollKey(emp.ism); if(m.rows[key])return m.rows[key]; var keys=Object.keys(m.rows); for(var i=0;i=0||key.indexOf(keys[i])>=0)return m.rows[keys[i]]; } return null; } function hasOwn(o,k){return Object.prototype.hasOwnProperty.call(o||{},k)} function numVal(id){var e=$(id);return e?Math.round(+(e.value||0)):0} function txtVal(id){var e=$(id);return e?String(e.value||'').trim():''} function inputNum(id,val,w){ return ''; } function inputDate(id,val){ return ''; } function inputText(id,val,w){ return ''; } function payrollTotalPaid(advance,cash,otherPaid){ return Math.round(+(advance||0))+Math.round(+(cash||0))+Math.round(+(otherPaid||0)); } function payrollOtherPaid(mh,advance,cash){ var other=hasOwn(mh,'plastik_summa')?+(mh.plastik_summa||0):0; var saved=hasOwn(mh,'tolangan_jami')?+(mh.tolangan_jami||0):0; var base=payrollTotalPaid(advance,cash,other); if(saved>base)other+=saved-base; return Math.max(0,Math.round(other||0)); } function payrollIncomeTax(fixedOklad,doplata){ return Math.round((Math.round(+(fixedOklad||0))+Math.round(+(doplata||0)))*0.12); } function payrollFinalTotal(fixedOklad,doplata,tax,cash){ return Math.round(+(fixedOklad||0))+Math.round(+(doplata||0))-Math.round(+(tax||0))+Math.round(+(cash||0)); } function embedPayrollInEmployeeList(){ var holder=$('xt-list-payroll-holder'), panel=$('xt-maosh'); if(holder&&panel&&panel.parentNode!==holder){ holder.appendChild(panel); } if(panel)panel.style.display='block'; var tab=$('xtMaoshTabBtn');if(tab)tab.style.display='none'; } function toggleFullPayroll(){ var w=$('maoshFullWrap');if(!w)return; var open=w.style.display==='none'||!w.style.display; w.style.display=open?'block':'none'; var btn=$('togglePayrollBtn'); if(btn)btn.innerHTML=open?' Tahrirlashni yopish':' Tahrirlashni ochish'; if(open)w.scrollIntoView({behavior:'smooth',block:'start'}); } function togglePayrollAdvanced(){ var w=$('payrollAdvancedWrap');if(!w)return; var open=w.style.display==='none'||!w.style.display; w.style.display=open?'block':'none'; var btn=$('togglePayrollAdvancedBtn'); if(btn)btn.innerHTML=open?' Batafsil analitikani yopish':' Batafsil analitikani ochish'; if(open&&charts.payrollChart&&typeof charts.payrollChart.resize==='function')setTimeout(function(){charts.payrollChart.resize();},60); } function payrollMonthWorkDays(oy){ if(PAYROLL_MONTH_DAYS[oy])return PAYROLL_MONTH_DAYS[oy]; var p=String(oy||curOy()).split('-'),yr=+p[0],mn=+p[1],cnt=0; var dim=new Date(yr,mn,0).getDate(); for(var d=1;d<=dim;d++){ var dateStr=yr+'-'+(mn<10?'0':'')+mn+'-'+(d<10?'0':'')+d; if(tabelIsWorkDay(dateStr))cnt++; } return cnt||0; } function payrollTabelCounts(empId, oy){ var empT=tabelData[empId]||{}, vals=Object.values(empT); var oyIsh=payrollMonthWorkDays(oy), tabelKun=0, ishlagan=0; vals.forEach(function(h){ if(!h||h==='B')return; tabelKun++; if(h==='K'||h==='YT'||h==='YM')ishlagan++; }); return {oyIsh:oyIsh,tabelKun:tabelKun,ishlagan:ishlagan,plan:tabelKun||oyIsh,fakt:ishlagan}; } function payrollDefaults(emp, oy){ var os=getOySt(emp.id,oy), prof={planBand:os.band||1,factBand:os.band||1}, tc=payrollTabelCounts(emp.id,oy); var mh=maoshHisobData[emp.id]||{}; if(hasOwn(mh,'ishlagan_kuni')&&mh.ishlagan_kuni!==null&&mh.ishlagan_kuni!==''&&!isNaN(+mh.ishlagan_kuni))tc.ishlagan=+mh.ishlagan_kuni; var fixedOklad=hasOwn(mh,'fiks_oklad_1c')&&+mh.fiks_oklad_1c?+mh.fiks_oklad_1c:Math.round((os.stavka||0)*(os.band||1)); var doplata=hasOwn(mh,'qoshimcha_haq')?+mh.qoshimcha_haq:0; var fixedSalary=hasOwn(mh,'fiks_zarplata')&&+mh.fiks_zarplata?+mh.fiks_zarplata:fixedOklad+doplata; var social=hasOwn(mh,'ijtimoiy_yordam')?+mh.ijtimoiy_yordam:0; var stateSalary=hasOwn(mh,'shtat_oylik')&&+mh.shtat_oylik?+mh.shtat_oylik:fixedSalary+social; var workedBase=tc.oyIsh>0?Math.round(fixedOklad/tc.oyIsh*tc.ishlagan):0; var actualSalary=workedBase+doplata+social; if(hasOwn(mh,'haqiqiy_ish_haqi')&&+mh.haqiqiy_ish_haqi)actualSalary=+mh.haqiqiy_ish_haqi; var autoBonus=payrollAutoBonus(emp.id,oy); var kpi=autoBonus; var other=hasOwn(mh,'boshqa_qoshimcha')?+mh.boshqa_qoshimcha:0; var paidAdvance=hasOwn(mh,'avans')?+mh.avans:(hasOwn(avansData,emp.id)?+((avansData[emp.id]||{}).perech||0):0); var itogo=actualSalary+kpi+other; var tax=payrollIncomeTax(fixedOklad,doplata); var net=actualSalary-tax-paidAdvance+kpi+other; var cash=hasOwn(mh,'naqd_summa')?+mh.naqd_summa:(hasOwn(avansData,emp.id)?+((avansData[emp.id]||{}).naqd||0):0); var plastic=payrollOtherPaid(mh,paidAdvance,cash); var paid=payrollFinalTotal(fixedOklad,doplata,tax,cash); var diff=net-paid; return {os:os,prof:prof,tc:tc,fixedOklad:fixedOklad,doplata:doplata,fixedSalary:fixedSalary,social:social,stateSalary:stateSalary, actualSalary:actualSalary,kpi:kpi,other:other,itogo:itogo,tax:tax,net:net,paidAdvance:paidAdvance,plastic:plastic,cash:cash,paid:paid,diff:diff, paidDate:mh.tolangan_kun||'',note:mh.izoh||''}; } function payrollVisibleEmployees(oy){ var empFilter=$('maoshAnalizEmp')?$('maoshAnalizEmp').value:'all'; return empData.filter(function(emp){ if(!empActiveInMonth(emp,oy))return false; return empFilter==='all'||String(emp.id)===String(empFilter); }); } function payrollPayload(empId, oy){ var emp=empData.find(function(e){return e.id===Number(empId)});if(!emp)return null; var d=payrollDefaults(emp,oy); var fixedOklad=$('mh_fix_'+empId)?numVal('mh_fix_'+empId):d.fixedOklad; var doplata=$('mh_dop_'+empId)?numVal('mh_dop_'+empId):d.doplata; var social=$('mh_soc_'+empId)?numVal('mh_soc_'+empId):d.social; var kpi=d.kpi; var other=$('mh_other_'+empId)?numVal('mh_other_'+empId):d.other; var avans=$('mh_av_'+empId)?numVal('mh_av_'+empId):d.paidAdvance; var plastic=$('mh_pl_'+empId)?numVal('mh_pl_'+empId):d.plastic; var cash=$('mh_cash_'+empId)?numVal('mh_cash_'+empId):d.cash; var worked=$('mh_work_'+empId)?numVal('mh_work_'+empId):d.tc.ishlagan; d.tc.ishlagan=worked; var fixedSalary=fixedOklad+doplata; var stateSalary=fixedSalary+social; var workedBase=d.tc.oyIsh>0?Math.round(fixedOklad/d.tc.oyIsh*d.tc.ishlagan):0; var actualSalary=workedBase+doplata+social; var itogo=actualSalary+kpi+other; var tax=payrollIncomeTax(fixedOklad,doplata); var net=actualSalary-tax-avans+kpi+other; var paid=payrollFinalTotal(fixedOklad,doplata,tax,cash); return {emp_id:Number(empId),oy:oy,fiks_oklad_1c:fixedOklad,qoshimcha_haq:doplata,fiks_zarplata:fixedSalary, ijtimoiy_yordam:social,shtat_oylik:stateSalary,haqiqiy_ish_haqi:actualSalary,kpi_bonus:kpi,boshqa_qoshimcha:other, hisoblangan_jami:itogo,daromad_soliq:tax,tolangan_ish_haqi:net,avans:avans,plastik_summa:plastic,naqd_summa:cash, tolangan_jami:paid,farq:net-paid,tolangan_kun:$('mh_date_'+empId)?txtVal('mh_date_'+empId):d.paidDate,ishlagan_kuni:d.tc.ishlagan,izoh:$('mh_note_'+empId)?txtVal('mh_note_'+empId):d.note}; } async function savePayrollRow(empId){ empId=Number(empId); var oy=$('maoshOy')?$('maoshOy').value:curOy(); var payload=payrollPayload(empId,oy); if(!payload)return; try{ await Promise.all([ api('maosh-hisob','POST',payload), api('avanslar','POST',{emp_id:empId,oy:oy,naqd:payload.naqd_summa,perech:payload.avans}) ]); ntf('Maosh satri saqlandi','#10b981'); payrollAnalyticsCache={year:null,rows:null}; await loadMaosh(); }catch(e){ntf(e.message,'#ef4444')} } async function saveQuickPay(empId){ empId=Number(empId); var oy=$('maoshOy')?$('maoshOy').value:curOy(); var avans=+(($('qAv_'+empId)||{}).value||0); var cash=+(($('qCash_'+empId)||{}).value||0); try{ var emp=empData.find(function(e){return e.id===empId}), d=emp?payrollDefaults(emp,oy):null; var kpi=d?d.kpi:0; var tax=d?payrollIncomeTax(d.fixedOklad,d.doplata):0; var net=d?d.actualSalary-tax-avans+kpi+d.other:0; var plastic=d?d.plastic:0; var paid=d?payrollFinalTotal(d.fixedOklad,d.doplata,tax,cash):0; var payload=d?{emp_id:empId,oy:oy,fiks_oklad_1c:d.fixedOklad,qoshimcha_haq:d.doplata,fiks_zarplata:d.fixedSalary, ijtimoiy_yordam:d.social,shtat_oylik:d.stateSalary,haqiqiy_ish_haqi:d.actualSalary,kpi_bonus:kpi,boshqa_qoshimcha:d.other, hisoblangan_jami:d.actualSalary+kpi+d.other,daromad_soliq:tax,tolangan_ish_haqi:net, avans:avans,plastik_summa:plastic,naqd_summa:cash,tolangan_jami:paid,farq:net-paid,tolangan_kun:''}:null; var calls=[api('avanslar','POST',{emp_id:empId,oy:oy,naqd:cash,perech:avans})]; if(payload)calls.push(api('maosh-hisob','POST',payload)); await Promise.all(calls); ntf('Saqlandi','#10b981'); payrollAnalyticsCache={year:null,rows:null}; await loadMaosh(); }catch(e){ntf(e.message,'#ef4444')} } renderMaoshTable = function(oy){ var tb = document.getElementById('maoshTb'); if(!tb) return; var totals={oyIsh:0,tabelKun:0,ishlagan:0,fix:0,dop:0,fixSalary:0,social:0,stateSalary:0,actual:0,kpi:0,other:0,itogo:0,tax:0,net:0,paidAdvance:0,plastic:0,cash:0,paid:0,diff:0}; var payrollEmps=payrollVisibleEmployees(oy); var quickRows=''; var rows = payrollEmps.map(function(emp, i){ var d=payrollDefaults(emp,oy), tc=d.tc; totals.oyIsh=Math.max(totals.oyIsh,tc.oyIsh);totals.tabelKun+=tc.tabelKun;totals.ishlagan+=tc.ishlagan; totals.fix+=d.fixedOklad;totals.dop+=d.doplata;totals.fixSalary+=d.fixedSalary;totals.social+=d.social; totals.stateSalary+=d.stateSalary;totals.actual+=d.actualSalary;totals.kpi+=d.kpi;totals.other+=d.other;totals.itogo+=d.itogo; totals.tax+=d.tax;totals.net+=d.net;totals.paidAdvance+=d.paidAdvance;totals.plastic+=d.plastic;totals.cash+=d.cash;totals.paid+=d.paid;totals.diff+=d.diff; quickRows += ''+ '
'+esc(emp.ism)+'
'+esc(emp.lav||'')+'
'+ ''+tc.oyIsh+''+ ''+tc.ishlagan+''+ ''+money(d.fixedOklad)+''+ ''+money(d.doplata)+''+ ''+money(d.tax)+''+ ''+money(d.cash)+''+ ''+money(d.paid)+''+ ''+ ''; return '' + '
'+esc(emp.ism)+'
'+esc(emp.lav||'')+'
' + ''+tc.oyIsh+''+inputNum('mh_work_'+emp.id,tc.ishlagan,70)+'' + ''+inputNum('mh_fix_'+emp.id,d.fixedOklad)+'' + ''+inputNum('mh_dop_'+emp.id,d.doplata)+'' + ''+money(d.tax)+'' + ''+inputNum('mh_cash_'+emp.id,d.cash)+'' + ''+money(d.paid)+'' + '' + ''; }).join(''); var totalRow = '' + 'JAMI' + ''+totals.oyIsh+''+totals.ishlagan+'' + ''+money(totals.fix)+''+money(totals.dop)+'' + ''+money(totals.tax)+''+money(totals.cash)+'' + ''+money(totals.paid)+''; tb.innerHTML = (rows||'Xodim topilmadi') + totalRow; if($('maoshQuickTb')) $('maoshQuickTb').innerHTML = quickRows || 'Xodim topilmadi'; if($('mEmpCnt')) $('mEmpCnt').textContent = payrollEmps.length; if($('mKunlar')) $('mKunlar').textContent = payrollMonthWorkDays(oy); if($('mPlanTotal')) $('mPlanTotal').textContent = totals.tabelKun || (payrollMonthWorkDays(oy)*payrollEmps.length); if($('mFaktTotal')) $('mFaktTotal').textContent = totals.ishlagan; if($('mTax')) $('mTax').textContent = money(totals.tax); if($('mFond')) $('mFond').textContent = sh(totals.itogo); if($('mQol')) $('mQol').textContent = money(totals.net); fillPayrollEmpFilter(); loadPayrollAnalytics(); }; var payrollAnalyticsCache={year:null,rows:null}; var payrollAnalyticsLoading=false; function fillPayrollEmpFilter(){ var sel=$('maoshAnalizEmp');if(!sel)return; var cur=sel.value||'all'; sel.innerHTML=''+empData.map(function(e){return '';}).join(''); sel.value=[].slice.call(sel.options).some(function(o){return o.value===cur})?cur:'all'; fillPayrollOyFilter(); } function fillPayrollOyFilter(){ var sel=$('maoshAnalizOy');if(!sel)return; var cur=sel.value||(($('maoshOy')&&$('maoshOy').value)||curOy()); sel.innerHTML=OYLAR_LIST.map(function(o){return '';}).join(''); sel.value=[].slice.call(sel.options).some(function(o){return o.value===cur})?cur:(($('maoshOy')&&$('maoshOy').value)||OYLAR_LIST[0]); } function initPayrollFilters(){ fillPayrollEmpFilter(); fillPayrollOyFilter(); if($('maoshAnalizDavr')&&!$('maoshAnalizDavr').value)$('maoshAnalizDavr').value='oy'; if($('maoshAnalizYil')){ var selected=[].slice.call($('maoshAnalizYil').options||[]).some(function(o){return o.selected}); if(!selected)[].slice.call($('maoshAnalizYil').options||[]).forEach(function(o){o.selected=o.value==='2026'}); } } function resetPayrollFilter(){ if($('maoshAnalizDavr'))$('maoshAnalizDavr').value='oy'; if($('maoshAnalizYil'))[].slice.call($('maoshAnalizYil').options||[]).forEach(function(o){o.selected=o.value==='2026'}); if($('maoshAnalizOy'))$('maoshAnalizOy').value=($('maoshOy')&&$('maoshOy').value)||curOy(); if($('maoshAnalizEmp'))$('maoshAnalizEmp').value='all'; payrollAnalyticsCache={year:null,rows:null}; applyPayrollFilter(); } function openPayrollFilter(){ initPayrollFilters(); if($('payrollFilterDrawer'))$('payrollFilterDrawer').classList.add('open'); if($('payrollFilterBackdrop'))$('payrollFilterBackdrop').classList.add('open'); } function closePayrollFilter(){ if($('payrollFilterDrawer'))$('payrollFilterDrawer').classList.remove('open'); if($('payrollFilterBackdrop'))$('payrollFilterBackdrop').classList.remove('open'); } function payrollSelectedYears(){ var sel=$('maoshAnalizYil'); if(!sel)return ['2026']; var years=[].slice.call(sel.options||[]).filter(function(o){return o.selected;}).map(function(o){return o.value;}); if(!years.length&&sel.value)years=[sel.value]; return years.length?years:['2026']; } function applyPayrollFilter(){ initPayrollFilters(); var davr=$('maoshAnalizDavr')?$('maoshAnalizDavr').value:'oy'; if(davr==='oy'&&$('maoshAnalizOy')){ var y=$('maoshAnalizOy').value.slice(0,4); if($('maoshAnalizYil')){ [].slice.call($('maoshAnalizYil').options||[]).forEach(function(o){o.selected=o.value===y;}); } if($('maoshOy'))$('maoshOy').value=$('maoshAnalizOy').value; loadMaosh(); return; } if($('maoshOy'))renderMaoshTable($('maoshOy').value||curOy()); loadPayrollAnalytics(); } function payrollCountsFromStore(empId,oy,tStore){ var empT=tStore[empId]||{}, vals=Object.values(empT); var oyIsh=payrollMonthWorkDays(oy), tabelKun=0, ishlagan=0; vals.forEach(function(h){ if(!h||h==='B')return; tabelKun++; if(h==='K'||h==='YT'||h==='YM')ishlagan++; }); return {oyIsh:oyIsh,tabelKun:tabelKun,ishlagan:ishlagan}; } function payrollCalcFromStores(emp,oy,stores){ var os=(stores.os||{})[emp.id]||{stavka:emp.stavka,band:emp.band||1,ijt:emp.ijt||12}; var mh=(stores.mh||{})[emp.id]||{}; var av=(stores.av||{})[emp.id]||{naqd:0,perech:0}; var tc=payrollCountsFromStore(emp.id,oy,stores.tabel||{}); var fixedOklad=hasOwn(mh,'fiks_oklad_1c')&&+mh.fiks_oklad_1c?+mh.fiks_oklad_1c:Math.round((+os.stavka||0)*(+os.band||1)); var doplata=hasOwn(mh,'qoshimcha_haq')?+mh.qoshimcha_haq:0; var fixedSalary=hasOwn(mh,'fiks_zarplata')&&+mh.fiks_zarplata?+mh.fiks_zarplata:fixedOklad+doplata; var social=hasOwn(mh,'ijtimoiy_yordam')?+mh.ijtimoiy_yordam:0; var stateSalary=hasOwn(mh,'shtat_oylik')&&+mh.shtat_oylik?+mh.shtat_oylik:fixedSalary+social; var workedBase=tc.oyIsh>0?Math.round(fixedOklad/tc.oyIsh*tc.ishlagan):0; var actualSalary=workedBase+doplata+social; if(hasOwn(mh,'haqiqiy_ish_haqi')&&+mh.haqiqiy_ish_haqi)actualSalary=+mh.haqiqiy_ish_haqi; var autoBonus=(stores.autoBonus&&hasOwn(stores.autoBonus,emp.id))?+stores.autoBonus[emp.id]:payrollAutoBonus(emp.id,oy); var kpi=autoBonus; var other=hasOwn(mh,'boshqa_qoshimcha')?+mh.boshqa_qoshimcha:0; var advance=hasOwn(mh,'avans')?+mh.avans:+(av.perech||0); var itogo=actualSalary+kpi+other; var tax=payrollIncomeTax(fixedOklad,doplata); var net=actualSalary-tax-advance+kpi+other; var cash=hasOwn(mh,'naqd_summa')?+mh.naqd_summa:+(av.naqd||0); var paid=payrollFinalTotal(fixedOklad,doplata,tax,cash); return {emp_id:emp.id,emp:emp.ism,oy:oy,plan:tc.oyIsh,fakt:tc.ishlagan,tabel:tc.tabelKun,fixedOklad:fixedOklad,doplata:doplata,cash:cash,fond:itogo,tax:tax,net:net,paid:paid,bonus:kpi,diff:net-paid}; } async function loadPayrollAnalytics(){ var davr=$('maoshAnalizDavr')?$('maoshAnalizDavr').value:'oy'; var selectedOy=$('maoshAnalizOy')?$('maoshAnalizOy').value:(($('maoshOy')&&$('maoshOy').value)||curOy()); var years=davr==='oy'?[selectedOy.slice(0,4)]:payrollSelectedYears(); var cacheKey=years.join(','); if(payrollAnalyticsLoading)return; if(payrollAnalyticsCache.year===cacheKey&&payrollAnalyticsCache.rows){await loadBonusStats();renderPayrollAnalytics();return;} payrollAnalyticsLoading=true; try{ if(!empData.length)await loadEmps(); await loadBonusStats(); var months=OYLAR_LIST.filter(function(o){return years.indexOf(o.slice(0,4))>=0;}); var rows=[]; for(var mi=0;mi'+esc(r.employee)+''+(r.sales_count||0)+''+money(r.sales_amount||0)+''+money(r.net_profit||0)+''+money(r.sales_bonus||0)+''+money(r.total_bonus||0)+''; }).join('')||'Bonus statistikasi yoq'; var miss=bonusStatsData.missing||{}; var box=$('bonusMissingBox'); if(box){ var parts=Object.keys(miss).map(function(k){return '
'+esc(k)+': '+esc(miss[k])+'
';}); box.innerHTML=parts.length?'Yetishmayotgan maydonlar:'+parts.join(''):''; } } function renderPayrollAnalytics(){ var rows=(payrollAnalyticsCache.rows||[]); var empVal=$('maoshAnalizEmp')?$('maoshAnalizEmp').value:'all'; var davr=$('maoshAnalizDavr')?$('maoshAnalizDavr').value:'oy'; var selectedOy=$('maoshAnalizOy')?$('maoshAnalizOy').value:(($('maoshOy')&&$('maoshOy').value)||curOy()); if(empVal!=='all')rows=rows.filter(function(r){return String(r.emp_id)===String(empVal);}); if(davr==='oy')rows=rows.filter(function(r){return r.oy===selectedOy;}); var grouped={}; rows.forEach(function(r){ var key=davr==='yil'?r.oy.slice(0,4):oyName(r.oy); if(!grouped[key])grouped[key]={label:key,plan:0,fakt:0,fond:0,tax:0,net:0,paid:0,bonus:0,diff:0}; grouped[key].plan+=r.plan;grouped[key].fakt+=r.fakt;grouped[key].fond+=r.fond;grouped[key].tax+=r.tax;grouped[key].net+=r.net;grouped[key].paid+=r.paid;grouped[key].bonus+=r.bonus||0;grouped[key].diff+=r.diff||0; }); var list=Object.keys(grouped).map(function(k){return grouped[k];}); if(davr==='yil')list.sort(function(a,b){return Number(a.label)-Number(b.label);}); else list.sort(function(a,b){return OYLAR_LIST.map(oyName).indexOf(a.label)-OYLAR_LIST.map(oyName).indexOf(b.label);}); var totals=list.reduce(function(s,r){s.plan+=r.plan;s.fakt+=r.fakt;s.fond+=r.fond;s.tax+=r.tax;s.net+=r.net;s.paid+=r.paid;s.bonus+=r.bonus||0;s.diff+=r.diff||0;return s;},{plan:0,fakt:0,fond:0,tax:0,net:0,paid:0,bonus:0,diff:0}); if($('paPlan'))$('paPlan').textContent=totals.plan; if($('paFact'))$('paFact').textContent=totals.fakt; if($('paFond'))$('paFond').textContent=sh(totals.fond); if($('paTax'))$('paTax').textContent=money(totals.tax); if($('paNet'))$('paNet').textContent=money(totals.net); if($('paPaid'))$('paPaid').textContent=money(totals.paid); if($('paBonus'))$('paBonus').textContent=money(totals.bonus); if($('paDiff'))$('paDiff').textContent=money(totals.diff); if($('payrollAnalizTb'))$('payrollAnalizTb').innerHTML=list.map(function(r){return ''+esc(r.label)+''+r.plan+''+r.fakt+''+money(r.fond)+''+money(r.tax)+''+money(r.net)+''+money(r.paid)+''+money(r.bonus||0)+''+money(r.diff||0)+'';}).join('')||'Ma\'lumot yoq'; if($('payrollChart')&&typeof Chart!=='undefined'){ dC('payrollChart'); charts.payrollChart=new Chart($('payrollChart'),{type:'bar',data:{labels:list.map(function(r){return r.label}),datasets:[ {label:'Jami maosh',data:list.map(function(r){return r.fond}),backgroundColor:'#10b981',borderRadius:5}, {label:"Daromad solig'i",data:list.map(function(r){return r.tax}),backgroundColor:'#ef4444',borderRadius:5}, {label:"To'langan",data:list.map(function(r){return r.paid}),backgroundColor:'#3b82f6',borderRadius:5}, {label:'Bonus',data:list.map(function(r){return r.bonus||0}),backgroundColor:'#a78bfa',borderRadius:5}, {label:'Qoldiq',data:list.map(function(r){return r.diff||0}),backgroundColor:'#f59e0b',borderRadius:5} ]},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{labels:{color:'#94a3b8'}}},scales:{x:{ticks:{color:'#94a3b8'},grid:{display:false}},y:{ticks:{color:'#94a3b8',callback:function(v){return sh(v)}},grid:{color:'#334155'}}}}}); } renderBonusStats(); } var _oldLoadMaoshForFilter=loadMaosh; loadMaosh=async function(){ await _oldLoadMaoshForFilter(); if($('maoshAnalizOy')&&$('maoshOy'))$('maoshAnalizOy').value=$('maoshOy').value; renderPayrollAnalytics(); }; function payrollExcelHtml(title,headers,rows){ return ''+headers.map(function(h){return '';}).join('')+''+rows.map(function(r){return ''+r.map(function(c){return '';}).join('')+'';}).join('')+'
'+esc(title)+'
'+esc(h)+'
'+esc(c)+'
'; } function downloadXls(name,html){ var blob=new Blob([html],{type:'application/vnd.ms-excel;charset=utf-8'}); var a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download=name;a.click();setTimeout(function(){URL.revokeObjectURL(a.href)},1000); } async function downloadPayrollExcel(){ var davr=$('maoshExcelDavr')?$('maoshExcelDavr').value:'oy'; var oy=$('maoshOy')?$('maoshOy').value:curOy(); if(davr==='yil'){ await loadPayrollAnalytics(); var rows=(payrollAnalyticsCache.rows||[]).map(function(r){return [oyName(r.oy),r.emp,r.plan,r.fakt,money(r.fixedOklad||0),money(r.doplata||0),money(r.tax),money(r.cash||0),money(r.paid)];}); downloadXls('maosh_yillik_'+(payrollAnalyticsCache.year||'2026')+'.xls',payrollExcelHtml('Yillik maosh hisoboti '+(payrollAnalyticsCache.year||'2026'),['Oy','Xodim','Ish kuni reja','Ish kunlari amalda','Fiks oklad','Qoshimcha haq','Daromad soligi 12%','Naqd tolov','Jami tolangan summa'],rows)); return; } var rows=empData.filter(function(emp){return empActiveInMonth(emp,oy);}).map(function(emp){ var d=payrollDefaults(emp,oy),tc=d.tc; return [emp.ism,tc.oyIsh,tc.ishlagan,money(d.fixedOklad),money(d.doplata),money(d.tax),money(d.cash),money(d.paid)]; }); downloadXls('maosh_'+oy+'.xls',payrollExcelHtml('Oylik maosh hisoboti '+oyName(oy),['Xodim','Ish kuni reja','Ish kunlari amalda','Fiks oklad','Qoshimcha haq','Daromad soligi 12%','Naqd tolov','Jami tolangan summa'],rows)); } // Tabel: oxirgi override. Eski ko'p belgilash va hamma keldi funksiyalarini shu blok bosadi. function tabelBulkSet(){ var m=document.createElement('div'); m.className='mbg open'; m.onclick=function(e){if(e.target===m)m.remove();}; var oy=$('tabelOy')?$('tabelOy').value:curOy(); var visible=empData.filter(function(e){return empActiveInMonth(e,oy);}); m.innerHTML='
'+ '
Ko\'p xodimga belgilash
'+ '
'+ '
'+ '
'+ ''+ ''+ ''+ ''+ ''+ ''+ '
'+ '
'+ '
'+ ''+ ''+ '
'+ ''+ '
'+ '
'+ '
'+ ''+ '
'; document.body.appendChild(m); } function bulkSelectEmps(on){ var empSel=$('bulk_emp');if(!empSel)return; for(var i=0;itoDate)continue; if($('bulk_work_only')&&$('bulk_work_only').checked&&!tabelIsWorkDay(dateStr))continue; selectedEmps.forEach(function(eid){ var emp=empData.find(function(x){return x.id===eid;}); if(emp&&empActiveOnDate(emp,dateStr))promises.push(api('tabel','POST',{emp_id:eid,sana:dateStr,holat:holat})); }); } try{ await Promise.all(promises); ntf("Qo'llandi: "+promises.length+" ta yozuv",'#10b981'); var modal=document.querySelector('.mbg.open:last-child');if(modal)modal.remove(); payrollAnalyticsCache={year:null,rows:null}; await loadTabel(); }catch(e){ntf(e.message,'#ef4444');} } async function setAllKeldi(){ var oy=$('tabelOy').value,parts=oy.split('-'),yr=+parts[0],mn=+parts[1],daysInMonth=new Date(yr,mn,0).getDate(); var visible=empData.filter(function(e){return empActiveInMonth(e,oy);}); var promises=[]; for(var d=1;d<=daysInMonth;d++){ var dateStr=yr+'-'+(mn<10?'0':'')+mn+'-'+(d<10?'0':'')+d; if(!tabelIsWorkDay(dateStr))continue; visible.forEach(function(e){ if(empActiveOnDate(e,dateStr))promises.push(api('tabel','POST',{emp_id:e.id,sana:dateStr,holat:'K'})); }); } try{ await Promise.all(promises); ntf("Hamma faol xodim uchun K qo'yildi ("+promises.length+" ta)",'#10b981'); payrollAnalyticsCache={year:null,rows:null}; await loadTabel(); }catch(e){ntf(e.message,'#ef4444');} }