getMessage()); if (isset($conn)) { sqlsrv_close($conn); } return false; } } /** Función para verificar si es hora de enviar el resumen para un usuario específico **/ function esHoraDeEnvio($usuario, $horaActual, $diaActual) { $horaConfigurada = $usuario['resumen_diario_hora'] ?: '08:00'; $diasConfigurados = $usuario['resumen_diario_dias'] ?: 'L-V'; // Verificar hora (con margen de 5 minutos) $horaActualMinutos = horaAMinutos($horaActual); $horaConfiguradaMinutos = horaAMinutos($horaConfigurada); if (abs($horaActualMinutos - $horaConfiguradaMinutos) > 5) { return false; } // Verificar día if ($diasConfigurados === 'TODOS') { return true; } elseif ($diasConfigurados === 'L-V') { return in_array($diaActual, ['L', 'M', 'X', 'J', 'V']); } else { // Días personalizados $diasArray = array_map('trim', explode(',', $diasConfigurados)); return in_array($diaActual, $diasArray); } } /** Función auxiliar para convertir hora a minutos **/ function horaAMinutos($hora) { list($h, $m) = explode(':', $hora); return ($h * 60) + $m; } /** Función auxiliar para obtener el día de la semana **/ function obtenerDiaSemana() { $dias = ['D', 'L', 'M', 'X', 'J', 'V', 'S']; return $dias[date('w')]; } /** Función para enviar el resumen diario a un usuario específico **/ function enviarResumenDiarioUsuario($usuario, $fechaFiltro) { try { // Obtener datos del importador $datosImportador = obtenerDatosImportador($usuario['id_usuario']); if (!$datosImportador) { error_log("⚠️ No se encontraron datos del importador para usuario ID: {$usuario['id_usuario']}"); return false; } // Obtener operaciones del día anterior $operaciones = obtenerOperacionesDiarias($usuario['id_usuario'], $fechaFiltro); // Si no hay operaciones, no enviar resumen (opcional: enviar notificación de "sin actividad") if (empty($operaciones)) { error_log("ℹ️ Sin operaciones para enviar resumen a: {$usuario['email']} en fecha: $fechaFiltro"); return false; } // Generar PDF $rutaPdf = generarPdfResumenDiario($datosImportador, $operaciones, $fechaFiltro); if (!$rutaPdf) { error_log("❌ Error al generar PDF para usuario: {$usuario['email']}"); return false; } $resultadoEnvio = false; // Enviar al correo principal $resultadoPrincipal = enviarEmailResumenDiario( $usuario['email'], $usuario['nombre'], $datosImportador, $fechaFiltro, count($operaciones), $rutaPdf ); if ($resultadoPrincipal) { $resultadoEnvio = true; error_log("✅ Resumen diario enviado a: {$usuario['email']}"); } // Enviar al correo adicional si está configurado if ($usuario['notificaciones_extra'] == 1 && !empty($usuario['correo_extra'])) { $resultadoExtra = enviarEmailResumenDiario( $usuario['correo_extra'], $usuario['nombre'], $datosImportador, $fechaFiltro, count($operaciones), $rutaPdf, true ); if ($resultadoExtra) { $resultadoEnvio = true; error_log("✅ Resumen diario enviado a correo adicional: {$usuario['correo_extra']}"); } } // Limpiar archivo temporal if (file_exists($rutaPdf)) { unlink($rutaPdf); } return $resultadoEnvio; } catch (Exception $e) { error_log("❌ Error al procesar resumen diario para usuario {$usuario['email']}: " . $e->getMessage()); return false; } } /** Función para obtener datos del importador **/ function obtenerDatosImportador($idUsuario) { $conn = getConnection(); if (!$conn) { return null; } $sql = " SELECT ig.nombre, ig.rfc, CONCAT(ig.calle, ' ', CASE WHEN ig.num_exterior IS NOT NULL THEN CONCAT('#', ig.num_exterior) ELSE '' END, CASE WHEN ig.num_interior IS NOT NULL AND ig.num_interior != '' THEN CONCAT(' Int. ', ig.num_interior) ELSE '' END, CASE WHEN ig.colonia IS NOT NULL AND ig.colonia != '' THEN CONCAT(', ', ig.colonia) ELSE '' END, CASE WHEN ig.ciudad IS NOT NULL AND ig.ciudad != '' THEN CONCAT(', ', ig.ciudad) ELSE '' END, CASE WHEN ig.estado IS NOT NULL AND ig.estado != '' THEN CONCAT(', ', ig.estado) ELSE '' END, CASE WHEN ig.codigo_postal IS NOT NULL THEN CONCAT(' C.P. ', ig.codigo_postal) ELSE '' END ) as direccion, ig.correo as correo_contacto, ig.telefono, u.email as email_usuario FROM informacion_general ig INNER JOIN usuarios_sistema u ON ig.id_usuario = u.id_usuario WHERE u.id_usuario = ? "; $stmt = sqlsrv_prepare($conn, $sql, [$idUsuario]); if (!$stmt || !sqlsrv_execute($stmt)) { sqlsrv_close($conn); return null; } $datos = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); sqlsrv_free_stmt($stmt); sqlsrv_close($conn); if ($datos) { // Desencriptar datos sensibles $datos['nombre_importador'] = decrypt($datos['nombre']); // Mapear nombre a nombre_importador para compatibilidad $datos['direccion'] = $datos['direccion']; // Ya concatenada en la consulta $datos['correo_contacto'] = decrypt($datos['correo_contacto']); $datos['email_usuario'] = decrypt($datos['email_usuario']); $datos['rfc'] = $datos['rfc']; // RFC generalmente no se encripta } return $datos; } /** Función para obtener operaciones diarias **/ function obtenerOperacionesDiarias($idUsuario, $fecha) { $conn = getConnection(); if (!$conn) { return []; } $sql = " SELECT sif.numero_factura, sif.valor_factura, sif.tipo_moneda, sif.fecha_factura, sif.numero_pedimento, sif.pais_proveedor, sif.aduana, CASE WHEN sif.status = 0 THEN 'Pendiente' WHEN sif.status = 1 THEN 'En Proceso' WHEN sif.status = 2 THEN 'Completado' WHEN sif.status = 3 THEN 'Cancelado' ELSE 'Sin Estado' END as status FROM solicitud_importacion_factura sif INNER JOIN usuarios_sistema u ON sif.id_importador = u.id_importador WHERE u.id_usuario = ? AND CAST(sif.fecha_factura AS DATE) = ? ORDER BY sif.fecha_factura DESC "; $stmt = sqlsrv_prepare($conn, $sql, [$idUsuario, $fecha]); if (!$stmt || !sqlsrv_execute($stmt)) { sqlsrv_close($conn); return []; } $operaciones = []; while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { // Desencriptar datos si es necesario $row['numero_factura'] = decrypt($row['numero_factura']); $row['numero_pedimento'] = $row['numero_pedimento'] ? decrypt($row['numero_pedimento']) : 'N/A'; $operaciones[] = $row; } sqlsrv_free_stmt($stmt); sqlsrv_close($conn); return $operaciones; } /** Función para generar el PDF del resumen **/ function generarPdfResumenDiario($datosImportador, $operaciones, $fecha) { require_once 'vendor/autoload.php'; // Asumiendo que usas TCPDF o similar try { $pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false); // Configuración del documento $pdf->SetCreator('SIIH | AduanaSoft'); $pdf->SetAuthor('Sistema de Importaciones'); $pdf->SetTitle('Resumen Diario de Importaciones - ' . $fecha); $pdf->SetSubject('Resumen de Operaciones'); // Configurar margenes $pdf->SetMargins(15, 20, 15); $pdf->SetHeaderMargin(10); $pdf->SetFooterMargin(10); // Agregar página $pdf->AddPage(); // Encabezado $html = '
Nombre: ' . htmlspecialchars($datosImportador['nombre_importador']) . '
'; $html .= 'RFC: ' . htmlspecialchars($datosImportador['rfc'] ?? 'N/A') . '
'; $html .= 'Dirección: ' . htmlspecialchars($datosImportador['direccion']) . '
'; $html .= 'Correo: ' . htmlspecialchars($datosImportador['correo_contacto']) . '
'; $html .= 'Total de Operaciones: ' . $totalOperaciones . '
'; $html .= 'Valor Total: $' . number_format($valorTotal, 2) . '
'; $html .= '| No. Factura | '; $html .= 'Valor | '; $html .= 'Moneda | '; $html .= 'Estado | '; $html .= 'Fecha | '; $html .= '
|---|---|---|---|---|
| ' . htmlspecialchars($op['numero_factura']) . ' | '; $html .= '$' . number_format($op['valor_factura'], 2) . ' | '; $html .= '' . htmlspecialchars($op['tipo_moneda']) . ' | '; $html .= '' . htmlspecialchars($op['status']) . ' | '; $html .= '' . date('d/m/Y H:i', strtotime($op['fecha_factura'])) . ' | '; $html .= '
Este documento fue generado automáticamente el ' . date('d/m/Y H:i:s') . '
'; $html .= 'SIIH | AduanaSoft - Sistema Integral de Importaciones
'; $html .= 'Te enviamos el resumen de tus operaciones de importación correspondientes al día $fechaFormateada.
📧 Correo: " . htmlspecialchars($datosImportador['correo_contacto']) . "
📍 Dirección: " . htmlspecialchars($datosImportador['direccion']) . "
Total de Operaciones: $totalOperaciones
📎 Adjunto: Reporte detallado en formato PDF con todas tus operaciones
Puedes modificar la frecuencia y horario de estos resúmenes desde tu panel de Preferencias de Notificaciones en el sistema.
Este resumen se genera automáticamente según tus preferencias de notificación.
SIIH | AduanaSoft - Sistema Integral de Importaciones
Generado el " . date('d/m/Y H:i:s') . "