'+ticketHTML+'<\/body><\/html>'; var btnReimp=$('#p101-btn-reimp'); if(btnReimp) btnReimp.disabled=false; try{ var w=window.open('','_blank','width=320,height=640,scrollbars=yes'); if(w && w.document){ w.document.write(docHTML); w.document.close(); setTimeout(function(){ try{ w.focus(); w.print(); setTimeout(function(){ try{w.close();}catch(e){} },900); }catch(e){} },350); toast('Ticket #'+(venta.numero||venta.id||'---')+' impreso',{icon:'🖨️'}); return; } }catch(e){ console.warn('[P101] popup:',e); } try{ var prev=$('.p101-print-frame'); if(prev) prev.remove(); var iframe=document.createElement('iframe'); iframe.className='p101-print-frame'; document.body.appendChild(iframe); var idoc=iframe.contentDocument||iframe.contentWindow.document; idoc.open(); idoc.write(docHTML); idoc.close(); setTimeout(function(){ try{ iframe.contentWindow.focus(); iframe.contentWindow.print(); toast('Ticket #'+(venta.numero||venta.id||'---')+' impreso',{icon:'🖨️'}); } catch(e){ toast('Permite popups o usa Ctrl+P',{error:true}); } },400); }catch(e){ console.error('[P101] print:',e); toast('Error al imprimir',{error:true}); } } P101.imprimir=imprimirTicket; function reimprimirUltimo(){ if(!P101.ultimo_ticket){ toast('No hay ticket reciente',{error:true}); return; } imprimirTicket(P101.ultimo_ticket); } P101.reimprimir=reimprimirUltimo; function detectarMetodo(){ var sel=document.querySelector('input[name="metodo_pago"]:checked, input[name="metodo"]:checked, .pos-pay-btn.active'); if(sel) return sel.dataset.pay||sel.value||sel.textContent.trim().toLowerCase(); return 'efectivo'; } function construirVenta(data, init, formData){ var payload={}; try{ if(formData && formData.entries){ var it=formData.entries(); var p; while(!(p=it.next()).done){ payload[p.value[0]]=p.value[1]; } }else if(init && init.body){ if(typeof init.body==='string'){ try{ payload=JSON.parse(init.body); } catch(e){ init.body.split('&').forEach(function(kv){ var pp=kv.split('='); if(pp[0]) payload[decodeURIComponent(pp[0])]=decodeURIComponent((pp[1]||'').replace(/\+/g,' ')); }); } } } }catch(e){} var cart=(window.POS && window.POS.cart)?window.POS.cart:[]; var totales={}; try{ if(window.POS && window.POS.calcularTotales) totales=window.POS.calcularTotales()||{}; }catch(e){} var metodo=payload.metodo_pago||payload.metodo||detectarMetodo(); var efIn=$('#posCash')||$('#posCashInput'); var efectivo=parseFloat((efIn && efIn.value)||payload.efectivo||0)||0; var totalNum=parseFloat(totales.total||payload.total||(data && data.total)||0)||0; return { id:(data && (data.id||data.pedido_id||data.venta_id))||('TMP-'+Date.now().toString().slice(-6)), numero:(data && (data.numero||data.numero_pedido))||'', cliente:payload.cliente_nombre||($('#posClienteNombre') && $('#posClienteNombre').value)||P101.cliente_default, vendedor:payload.vendedor||payload.asesor||'', metodo_pago:String(metodo).toLowerCase(), items:(cart||[]).map(function(it){ return {nombre:it.nombre||it.descripcion||it.titulo||'',cantidad:it.cantidad||it.qty||1,precio:it.precio||it.precio_unit||0,subtotal:(it.cantidad||it.qty||1)*(it.precio||it.precio_unit||0)}; }), subtotal:totales.subtotal||payload.subtotal||0, descuento:totales.descuento||payload.descuento||0, total:totalNum, efectivo:efectivo, cambio:efectivo>totalNum?(efectivo-totalNum):0 }; } function manejarCobro(data, init, formData){ try{ var venta=construirVenta(data,init,formData); setTimeout(function(){ imprimirTicket(venta); },280); setTimeout(cargarVentasHoy,700); }catch(e){ console.error('[P101] cobro:',e); } } function interceptar(){ var origFetch=window.fetch; if(origFetch && !origFetch.__p101){ window.fetch=function(){ var args=arguments; var url=(args[0]||'').toString(); var init=args[1]||{}; var resp=origFetch.apply(this,args); try{ if(url.indexOf('/admin/pos/api/cobrar')>=0){ resp.then(function(r){ try{ r.clone().json().then(function(data){ if(data && (data.ok||data.success||data.id||data.numero)){ var fd=(init.body && init.body instanceof FormData)?init.body:null; manejarCobro(data,init,fd); } }).catch(function(){}); }catch(e){} }).catch(function(){}); } }catch(e){} return resp; }; window.fetch.__p101=true; } var OrigXHR=window.XMLHttpRequest; if(OrigXHR && !OrigXHR.__p101){ var Patched=function(){ var xhr=new OrigXHR(); var origOpen=xhr.open; var origSend=xhr.send; var capURL='', capBody=null; xhr.open=function(method,url){ capURL=url||''; return origOpen.apply(xhr,arguments); }; xhr.send=function(body){ capBody=body; xhr.addEventListener('load',function(){ try{ if(capURL.indexOf('/admin/pos/api/cobrar')>=0 && xhr.status>=200 && xhr.status<300){ var data={}; try{ data=JSON.parse(xhr.responseText||'{}'); }catch(e){} if(data && (data.ok||data.success||data.id||data.numero)){ var fd=(capBody && capBody instanceof FormData)?capBody:null; var fakeInit=(fd?null:{body:capBody}); manejarCobro(data,fakeInit,fd); } } }catch(e){} }); return origSend.apply(xhr,arguments); }; return xhr; }; Patched.__p101=true; window.XMLHttpRequest=Patched; } document.addEventListener('pos:venta-completada',function(ev){ try{ manejarCobro((ev && ev.detail)||{},null,null); }catch(e){} }); } function setupAtajos(){ document.addEventListener('keydown',function(ev){ if(ev.key==='F8'){ ev.preventDefault(); togglePanel(); return; } if(ev.key==='Escape' && P101.abierto){ ev.preventDefault(); cerrarPanel(); return; } if((ev.ctrlKey||ev.metaKey) && ev.shiftKey && (ev.key==='p'||ev.key==='P')){ if(P101.ultimo_ticket){ ev.preventDefault(); reimprimirUltimo(); } } }); } function init(){ if(location.pathname.indexOf('/admin/pos')!==0) return; setClienteMostrador(); inyectarTrigger(); inyectarPanel(); interceptar(); setupAtajos(); cargarVentasHoy(); var n=0; var iv=setInterval(function(){ n++; setClienteMostrador(); if(!$('.p101-trigger')) inyectarTrigger(); if(n>=30) clearInterval(iv); },600); console.log('%c[P101] POS Command Center listo','background:#fbbf24;color:#0a0a0a;padding:3px 9px;border-radius:5px;font-weight:900','· F8 panel · Ctrl+Shift+P reimprimir'); } if(document.readyState==='loading'){ document.addEventListener('DOMContentLoaded',init); } else{ setTimeout(init,120); } })();
💬 Habla con nosotros