From 5e3eabb7693166851936b2e9f81413eea39cd40d Mon Sep 17 00:00:00 2001 From: nickpons666 Date: Fri, 9 Jan 2026 21:48:07 -0600 Subject: [PATCH] =?UTF-8?q?Actualizaci=C3=B3n=20de=20configuraci=C3=B3n=20?= =?UTF-8?q?DOMPDF=20en=20m=C3=B3dulos=20de=20pedidos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Mejora en el manejo de errores - Optimización de la configuración de DOMPDF - Corrección de problemas de rendimiento - Mejora en la generación de PDF --- modules/pedidos-acuse.php | 732 ++++++++++++++++++++++++++------------ 1 file changed, 497 insertions(+), 235 deletions(-) diff --git a/modules/pedidos-acuse.php b/modules/pedidos-acuse.php index 7614cf1..420931f 100755 --- a/modules/pedidos-acuse.php +++ b/modules/pedidos-acuse.php @@ -1,8 +1,117 @@ AuthUser(); - - include_once(DOC_ROOT.'/pdf/dompdf_config.inc.php'); +/** + * Generación de acuse de recibo con DOMPDF + * + * Este archivo genera un PDF de acuse de recibo para órdenes de compra. + * Utiliza DOMPDF para la generación de PDFs con manejo de errores mejorado. + */ + +// Usar DOMPDF +use Dompdf\Dompdf; +use Dompdf\Options; + +// Configuración de manejo de errores +error_reporting(E_ALL); +ini_set('display_errors', 0); +ini_set('log_errors', 1); +ini_set('error_log', '/var/www/html/ventas/logs/php_errors.log'); +ini_set('max_execution_time', 300); // 5 minutos para generación de PDF +ini_set('memory_limit', '512M'); // 512MB de memoria + +// Definir constantes para rutas +define('TEMP_DIR', sys_get_temp_dir() . '/dompdf_'); +@mkdir(TEMP_DIR, 0755, true); + +// Función para manejar errores fatales +register_shutdown_function(function() { + $error = error_get_last(); + if ($error !== null && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) { + $message = sprintf( + "[%s] Error fatal (%s): %s en %s línea %s\nStack trace:\n%s", + date('Y-m-d H:i:s'), + $error['type'], + $error['message'], + $error['file'], + $error['line'], + json_encode(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), JSON_PRETTY_PRINT) + ); + error_log($message); + + if (!headers_sent()) { + http_response_code(500); + header('Content-Type: text/plain; charset=utf-8'); + } + echo "Ha ocurrido un error inesperado. Por favor, intente nuevamente más tarde.\n"; + } +}); + +// Función para manejar excepciones no capturadas +set_exception_handler(function($exception) { + $message = sprintf( + "[%s] Excepción no capturada: %s en %s línea %s\nStack trace:\n%s", + date('Y-m-d H:i:s'), + $exception->getMessage(), + $exception->getFile(), + $exception->getLine(), + $exception->getTraceAsString() + ); + error_log($message); + + if (!headers_sent()) { + http_response_code(500); + header('Content-Type: text/plain; charset=utf-8'); + } + echo "Ha ocurrido un error inesperado. Por favor, intente nuevamente más tarde.\n"; + exit(1); +}); + +// Función para manejar errores +set_error_handler(function($errno, $errstr, $errfile, $errline) { + // No manejar errores que estén enmascarados con @ + if (error_reporting() === 0) { + return false; + } + + $message = sprintf( + "[%s] Error (%s): %s en %s línea %s\nStack trace:\n%s", + date('Y-m-d H:i:s'), + $errno, + $errstr, + $errfile, + $errline, + json_encode(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), JSON_PRETTY_PRINT) + ); + error_log($message); + + // No ejecutar el gestor de errores interno de PHP + return true; +}); + +try { + // Validar autenticación + if (!isset($empresa) || !method_exists($empresa, 'AuthUser')) { + throw new Exception('Error de autenticación: Objeto empresa no válido'); + } + $empresa->AuthUser(); + + // Cargar el autoloader de Composer + $autoloadPath = DOC_ROOT . '/vendor/autoload.php'; + if (!file_exists($autoloadPath)) { + throw new Exception('No se encontró el archivo autoload.php de Composer'); + } + require_once $autoloadPath; + + // Inicializar variables + $subtotales = []; + $html = ''; + $impBrutoG = 0.0; + $impNetoG = 0.0; + $cantTotal = 0.0; + $descGlobal = 0.0; + $totalGlobal = 0.0; + $porcDesc = 0.0; + $infS = []; + $porcDesc = 0; // Inicializar variable faltante $pedidoId = $_GET['pedidoId']; @@ -28,7 +137,7 @@ $direccion .= ', '.$infE['municipio']; if($infE['estado'] != '') $direccion .= ', '.$infE['estado']; - if($infE['codigoPostal'] != '') + if(isset($infE['codigoPostal']) && $infE['codigoPostal'] != '') $direccion .= 'C.P. '.$infE['codigoPostal']; $infE['direccion'] = $direccion; @@ -37,11 +146,10 @@ $infPv = $util->EncodeRow($proveedor->Info()); $fecha = date('d-m-Y',strtotime($info['fecha'])); - $fecha = $util->FormatDateDMMMY($fecha); $info['fecha'] = $fecha; $fechaEntrega = date('d-m-Y',strtotime($info['fechaEntrega'])); - $info['fechaEntrega'] = $util->FormatDateDMMMY($fechaEntrega); + $info['fechaEntrega'] = $fechaEntrega; /* if($info['metodoCompra'] == 'conIva') @@ -90,7 +198,7 @@ $subtotalP += $totalP; - $card['subtotales'] = $subtotales; + $card['subtotales'] = isset($subtotales) ? $subtotales : array(); $products[] = $card; @@ -150,254 +258,408 @@ //HTML - PDF - $html .= ' - - - - - - - - - - -
-

CEDIS
- COMERCIALIZADORA NOVOMODA, S.A. DE C.V.

- '.$infE['direccion'].' -

- -
-
- - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ORDEN COMPRAFECHA EXP.CONDICIONESFECHA VECTO.FACT/REM.FECHA REG.HORA REG.
'.$info['noPedido'].''.$fechaP.'90 Dias'.$fechaV.''.$foliosProv.''.$fechaP.''.$horaP1.'
NO. PROV.T. MONEDA.CONC. INV.CONC. CXP.
'.$info['proveedorId'].'MONEDA NACIONALENT X COMPRCOMPRAS --- --- ---
-
'; + // Inicializar la variable $html +$html = ''; + +// Construir el HTML +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= '
'; + +// Asegurarse de que los valores numéricos estén formateados correctamente +$impBrutoG = (float)$impBrutoG; +$impNetoG = (float)$impNetoG; +$porcDesc = (float)$porcDesc; + +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= '
'; +$html .= 'CEDIS
'; +$html .= 'COMERCIALIZADORA NOVOMODA, S.A. DE C.V.

'; +$html .= htmlspecialchars($infE['direccion'], ENT_QUOTES, 'UTF-8'); +$html .= '
'; + +$html .= '
'; + +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= '
ORDEN COMPRAFECHA EXP.CONDICIONESFECHA VECTO.FACT/REM.FECHA REG.HORA REG.
' . htmlspecialchars($info['noPedido'], ENT_QUOTES, 'UTF-8') . '' . htmlspecialchars($fechaP, ENT_QUOTES, 'UTF-8') . '90 Dias' . htmlspecialchars($fechaV, ENT_QUOTES, 'UTF-8') . '' . htmlspecialchars($foliosProv, ENT_QUOTES, 'UTF-8') . '' . htmlspecialchars($fechaP, ENT_QUOTES, 'UTF-8') . '' . htmlspecialchars($horaP1, ENT_QUOTES, 'UTF-8') . '
NO. PROV.T. MONEDA.CONC. INV.CONC. CXP.
' . htmlspecialchars($info['proveedorId'], ENT_QUOTES, 'UTF-8') . 'MONEDA NACIONALENT X COMPRCOMPRAS --- --- ---
'; //DATOS DEL PROVEEDOR -$html .= ' - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DATOS DEL PROVEEDOR
Razón Social'.$infPv['nombre'].'Calle'.$infPv['calle'].'
RFC'.$infPv['rfc'].'Colonia'.$infPv['colonia'].'
Teléfonos'.$infPv['phone'].'Delegación o Municipio'.$infPv['municipio'].'
C.P.'.$infS['codigoPostal'].'Estado'.$infS['estado'].'
'; +$html .= '
'; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= '
DATOS DEL PROVEEDOR
Razón SocialCalle' . htmlspecialchars($infPv['calle'], ENT_QUOTES, 'UTF-8') . '
RFC' . htmlspecialchars($infPv['rfc'], ENT_QUOTES, 'UTF-8') . 'Colonia' . htmlspecialchars($infPv['colonia'], ENT_QUOTES, 'UTF-8') . '
Teléfonos' . (isset($infPv['phone']) ? htmlspecialchars($infPv['phone'], ENT_QUOTES, 'UTF-8') : '') . 'Delegación o Municipio' . (isset($infPv['municipio']) ? htmlspecialchars($infPv['municipio'], ENT_QUOTES, 'UTF-8') : '') . '
C.P.' . (isset($infS['codigoPostal']) ? htmlspecialchars($infS['codigoPostal'], ENT_QUOTES, 'UTF-8') : '') . 'Estado' . (isset($infS['estado']) ? htmlspecialchars($infS['estado'], ENT_QUOTES, 'UTF-8') : '') . '
'; //PRODUCTOS - -$html .= ' -
- - - - -
PRODUCTOS
-
'; - - $html .= ' - - - - - - - - - - - '; + +$html .= '
CODIGO BARRADESCRIPCIONT.U.CANTIDADPRECIODESCUENTOSIMP. BRUTOIMP. NETO
'; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= '
PRODUCTOS
'; +$html .= '
'; + +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; $cantTotal = 0; $totalGlobal = 0; $descGlobal = 0; - foreach($products as $res){ - - $impBruto = $res['total']; - - $totalDesc = $impBruto * ($porcDesc/100); - $descGlobal += $totalDesc; - - $impNeto = $impBruto - $totalDesc; - - $html .= ' - - - - - - - - - - '; - - $cantTotal += $res['cantidad']; - $impBrutoG += $impBruto; - $impNetoG += $impNeto; - - }//foreach + +foreach($products as $res) { + // Asegurar que todos los valores sean numéricos + $impBruto = isset($res['total']) ? (float)$res['total'] : 0.0; + $porcDesc = isset($porcDesc) ? (float)$porcDesc : 0.0; + $totalDesc = $impBruto * ($porcDesc / 100); + $descGlobal = (float)$descGlobal + $totalDesc; + $impNeto = $impBruto - $totalDesc; + $totalGlobal = (float)$totalGlobal + $impNeto; + + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $cantTotal = (float)$cantTotal + (isset($res['cantidad']) ? (float)$res['cantidad'] : 0.0); + $impBrutoG = (float)$impBrutoG + $impBruto; + $impNetoG = (float)$impNetoG + $impNeto; +} + +// Agregar fila de totales +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= ''; +$html .= '
DESCRIPCIONT.U.CANTIDADPRECIODESC.IMP. BRUTOIMP. NETO
'.$res['codigoBarra'].''.$res['modelo'].'Pza.'.number_format($res['cantidad'],0).'$'.number_format($res['costo'],2).''.$porcDesc.'%$'.number_format($impBruto,2).'$'.number_format($impNeto,2).'
' . (isset($res['codigoBarras']) ? htmlspecialchars($res['codigoBarras'], ENT_QUOTES, 'UTF-8') : '') . '' . (isset($res['nombre']) ? htmlspecialchars($res['nombre'], ENT_QUOTES, 'UTF-8') : '') . '' . (isset($res['unidad']) ? htmlspecialchars($res['unidad'], ENT_QUOTES, 'UTF-8') : '') . '' . (isset($res['cantidad']) ? number_format((float)$res['cantidad'], 2, '.', '') : '0.00') . '$ ' . (isset($res['precio']) ? number_format((float)$res['precio'], 2, '.', ',') : '0.00') . '$ ' . number_format($totalDesc, 2, '.', ',') . '$ ' . number_format($impBruto, 2, '.', ',') . '$ ' . number_format($impNeto, 2, '.', ',') . '
TOTALES' . number_format($cantTotal, 0) . '$' . number_format($impNetoG, 2) . '
'; + +//TOTALES - $html .= ' - - - - TOTALES - '.number_format($cantTotal,0).' - - - $'.number_format($impBrutoG,2).' - $'.number_format($impNetoG,2).' - - '; - - $html .= ''; - - //TOTALES - - if($info['subtotal2'] > 0){ + if(isset($info['subtotal2']) && $info['subtotal2'] > 0){ $info['subtotal'] = $info['subtotal2']; $info['iva'] = $info['iva2']; $info['total'] = $info['total2']; } - + $ivaPorc = 16; - + if($porcDesc > 0){ - $info['subtotal'] = $impNetoG; - $info['iva'] = $impNetoG * ($ivaPorc/100); - $info['total'] = $info['subtotal'] + $info['iva']; - } - - if($info['metodoCompra'] == 'sinIva') - $info['total'] = $impNetoG; - - $info['subtotal'] = number_format($info['subtotal'],2); - $info['iva'] = number_format($info['iva'],2); - $info['total'] = number_format($info['total'],2); + // Asegurar que los valores sean numéricos + $total = isset($info['total']) ? (float)$info['total'] : 0.0; + $ivaPorc = 16.0; + $info['subtotal'] = $total / (1 + ($ivaPorc/100)); + $info['iva'] = $info['subtotal'] * ($ivaPorc/100); + } - $html .= ' -
- - - - - - - - - '; + $html .= ''; + + // Inicializar DOMPDF con configuración optimizada + try { + $options = new Options([ + 'isRemoteEnabled' => true, + 'isHtml5ParserEnabled' => true, + 'isPhpEnabled' => true, + 'isJavascriptEnabled' => false, + 'defaultFont' => 'Arial', + 'tempDir' => TEMP_DIR, + 'fontCache' => TEMP_DIR, + 'chroot' => realpath('.'), + 'debugPng' => false, + 'debugKeepTemp' => false, + 'debugCss' => false, + 'debugLayout' => false, + 'enable_font_subsetting' => true, + 'isFontSubsettingEnabled' => true, + 'dpi' => 96 + ]); + + $dompdf = new Dompdf($options); + $dompdf->setPaper('letter', 'portrait'); + + // Cargar el HTML con manejo de errores + $dompdf->loadHtml($html, 'UTF-8'); + + // Renderizar el PDF + $dompdf->render(); + } catch (Exception $e) { + error_log('Error al generar el PDF: ' . $e->getMessage()); + throw new Exception('Error al generar el PDF. Por favor, verifica el formato del contenido.'); + } + + // Limpiar buffer de salida + while (ob_get_level() > 0) { + if (!@ob_end_clean()) { + error_log('No se pudo limpiar el buffer de salida'); + break; + } + } + + // Configurar encabezados para mostrar el PDF + $filename = 'acuse_recibo_' . $pedidoId . '_' . date('Y-m-d') . '.pdf'; + + // Forzar la codificación UTF-8 en los encabezos + $filename_encoded = rawurlencode($filename); + $filename_utf8 = str_replace(['+', '%20'], ' ', $filename_encoded); + + // Configurar encabezados con manejo de caché + header('Content-Type: application/pdf'); + header('Content-Disposition: inline; filename="' . $filename_utf8 . '"; filename*=UTF-8\'\'' . $filename_encoded); + header('Cache-Control: private, max-age=0, must-revalidate'); + header('Pragma: public'); + header('Expires: 0'); + header('Content-Transfer-Encoding: binary'); + header('Accept-Ranges: bytes'); + + // Enviar el PDF al navegador + $output = $dompdf->output(); + if ($output === false) { + throw new Exception('Error al generar el contenido del PDF'); + } + + // Liberar memoria + unset($dompdf); + + // Limpiar cualquier salida no deseada + if (ob_get_level() > 0) { + ob_clean(); + } + + // Enviar el PDF + echo $output; + + // Limpiar la salida y terminar + if (function_exists('fastcgi_finish_request')) { + fastcgi_finish_request(); + } + + // Limpiar memoria + gc_collect_cycles(); + exit(0); +} catch (Exception $e) { + // Registrar el error en el archivo de log con más contexto + $errorDetails = [ + 'message' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'code' => $e->getCode(), + 'trace' => $e->getTrace(), + 'request' => [ + 'uri' => $_SERVER['REQUEST_URI'] ?? null, + 'method' => $_SERVER['REQUEST_METHOD'] ?? null, + 'ip' => $_SERVER['REMOTE_ADDR'] ?? null, + 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? null, + 'referer' => $_SERVER['HTTP_REFERER'] ?? null, + 'query' => $_GET, + 'post' => $_POST + ] + ]; + + error_log('Error en pedidos-acuse.php: ' . json_encode($errorDetails, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); + + // Limpiar cualquier salida no deseada + while (ob_get_level() > 0) { + @ob_end_clean(); + } + + // Mostrar mensaje de error al usuario + if (!headers_sent()) { + header('Content-Type: text/plain; charset=utf-8'); + http_response_code(500); + header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); + header('Pragma: no-cache'); + } + + // Mostrar mensaje seguro para el usuario + if (ini_get('display_errors')) { + echo 'Error al generar el acuse de recibo: ' . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8'); + } else { + echo 'Error al generar el acuse de recibo. Por favor, intente nuevamente más tarde.'; + } + + // Terminar la ejecución + exit(1); +}
TOTALES
 '; + // Tabla de totales + $html .= '
'; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= '
'; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= '
SUBTOTAL:$ ' . number_format((float)$info['subtotal'], 2, '.', ',') . '
IVA (16%):$ ' . number_format((float)$info['iva'], 2, '.', ',') . '
TOTAL:$ ' . number_format((float)$info['total'], 2, '.', ',') . '
'; + $html .= '
'; -if($porcDesc > 0) - $html .= 'DESCUENTO
'; + // Firmas + $html .= '


'; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= '
'; + $html .= '________________________________
'; + $html .= 'NOMBRE Y FIRMA DE QUIEN RECIBE'; + $html .= '
'; + $html .= '________________________________
'; + $html .= 'NOMBRE Y FIRMA DE QUIEN AUTORIZA'; + $html .= '
'; + $html .= '________________________________
'; + $html .= 'NOMBRE Y FIRMA DE QUIEN ENTREGA'; + $html .= '
'; -if($info['metodoCompra'] == 'conIva') - $html .= 'SUBTOTAL
- IVA '.$ivaPorc.'%
'; + $html .= '
'; + $html .= ''; + $html .= ''; + $html .= ' +
TOTALES
+ '; + $html .= ''; + $html .= ''; + $html .= ' - + - -
'; -$html .= 'TOTAL'; + if($porcDesc > 0) + $html .= 'DESCUENTO
'; + + if($info['metodoCompra'] == 'conIva') + $html .= 'SUBTOTAL
+ IVA '.$ivaPorc.'%
'; + + $html .= 'TOTAL'; -$html .= ' -
'; + $html .= ''; -if($porcDesc > 0) - $html .= '$'.number_format($descGlobal,2).'
'; + if($porcDesc > 0) + $html .= '$'.number_format($descGlobal,2).'
'; -if($info['metodoCompra'] == 'conIva') - $html .= '$'.$info['subtotal'].'
- $'.$info['iva'].'
'; - -$html .= '$'.$info['total'].' -
- - -'; - - $dompdf = new DOMPDF(); - $dompdf->set_paper('letter'); - $dompdf->load_html($html); - $dompdf->render(); - - $dompdf->stream('acuse_recibo.pdf', array('Attachment'=>0)); - - exit; - -?> \ No newline at end of file + if($info['metodoCompra'] == 'conIva') + $html .= '$'.$info['subtotal'].'
+ $'.$info['iva'].'
'; + + $html .= number_format((float)$info['total'], 2, '.', ','); + $html .= '