From a3e2f8e45e42574a3034e19be2a73e359e904dd3 Mon Sep 17 00:00:00 2001 From: Alexeer Date: Fri, 4 Jul 2025 17:00:08 -0600 Subject: [PATCH] =?UTF-8?q?Filtro=20de=20choferes=20pertenecientes=20a=20t?= =?UTF-8?q?ransportista=20en=20solicitudes=20de=20importaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/solicitud_importacion.php | 254 +++++++----- views/solicitud_importacion/crear.php | 125 +++++- views/solicitud_importacion/editar.php | 468 +++++++++++++++------- views/solicitud_importacion/lista.php | 14 +- 4 files changed, 620 insertions(+), 241 deletions(-) diff --git a/app/controllers/solicitud_importacion.php b/app/controllers/solicitud_importacion.php index 4351f48..64d8023 100644 --- a/app/controllers/solicitud_importacion.php +++ b/app/controllers/solicitud_importacion.php @@ -126,7 +126,7 @@ function crear() } $id_importador = $_SESSION['usuario_id']; - $conn = getConnection(); + $conn = getConnection(); // ✅ NUEVO: Obtener la agencia actual del usuario $stmt = sqlsrv_query($conn, "SELECT id_agencia_en_uso FROM dbo.usuarios_sistema WHERE id_usuario = ?", [$id_importador]); @@ -140,11 +140,12 @@ function crear() while ($r = sqlsrv_fetch_array($stmtP, SQLSRV_FETCH_ASSOC)) { $patentes[] = $r; } $transportistas = []; - $stmtT = sqlsrv_query($conn, "SELECT id_transportista, clave_identificador, nombre FROM dbo.transportistas WHERE id_usuario = ? AND activo=1 ORDER BY nombre",[$id_importador]); + $stmtT = sqlsrv_query($conn, "SELECT id_transportista, clave_identificador, nombre FROM dbo.transportistas WHERE id_usuario = ? AND activo = 1 ORDER BY nombre",[$id_importador]); while ($r = sqlsrv_fetch_array($stmtT, SQLSRV_FETCH_ASSOC)) { $transportistas[] = $r; } + // ✅ MODIFICADO: Obtener choferes con su transportista_id para el filtro $choferes = []; - $stmtC = sqlsrv_query($conn, "SELECT c.id_chofer, c.nombre+' '+c.apellido AS nombre FROM dbo.choferes c JOIN dbo.transportistas t ON c.transportista_id=t.id_transportista WHERE t.id_usuario=? AND c.status=1 ORDER BY c.nombre",[$id_importador]); + $stmtC = sqlsrv_query($conn, "SELECT c.id_chofer, c.nombre+' '+c.apellido AS nombre, c.transportista_id FROM dbo.choferes c JOIN dbo.transportistas t ON c.transportista_id=t.id_transportista WHERE t.id_usuario=? AND c.status=1 ORDER BY c.nombre",[$id_importador]); while ($r = sqlsrv_fetch_array($stmtC, SQLSRV_FETCH_ASSOC)) { $choferes[] = $r; } $paises = []; @@ -161,13 +162,74 @@ function crear() $unidades_medida = []; $stmtU = sqlsrv_query($conn, "SELECT id, descripcion FROM dbo.unidades_medida_apendice7 ORDER BY id"); - while ($r = sqlsrv_fetch_array($stmtU, SQLSRV_FETCH_ASSOC)) { - $unidades_medida[] = $r; - } + while ($r = sqlsrv_fetch_array($stmtU, SQLSRV_FETCH_ASSOC)) { $unidades_medida[] = $r; } include __DIR__ . '/../../views/solicitud_importacion/crear.php'; } +// ✅ NUEVO: Endpoint AJAX para obtener choferes por transportista +function obtenerChoferesPorTransportista() +{ + // Configurar headers para JSON desde el inicio + header('Content-Type: application/json'); + + try { + if (!($_SESSION['usuario_id'] ?? false)) { + http_response_code(401); + echo json_encode(['error' => 'No autorizado']); + exit; + } + + $id_importador = $_SESSION['usuario_id']; + $transportista_id = $_GET['transportista_id'] ?? null; + + if (!$transportista_id || !is_numeric($transportista_id)) { + http_response_code(400); + echo json_encode(['error' => 'ID de transportista requerido']); + exit; + } + + $conn = getConnection(); + + // Validar que el transportista pertenezca al usuario + $stmtValidate = sqlsrv_query($conn, + "SELECT id_transportista FROM dbo.transportistas WHERE id_transportista = ? AND id_usuario = ? AND activo = 1", + [intval($transportista_id), $id_importador]); + + if (!$stmtValidate || !sqlsrv_fetch_array($stmtValidate, SQLSRV_FETCH_ASSOC)) { + http_response_code(403); + echo json_encode(['error' => 'Transportista no válido']); + exit; + } + + // Obtener choferes del transportista + $choferes = []; + $stmtC = sqlsrv_query($conn, + "SELECT c.id_chofer, c.nombre+' '+c.apellido AS nombre + FROM dbo.choferes c + WHERE c.transportista_id = ? AND c.status = 1 + ORDER BY c.nombre", + [intval($transportista_id)]); + + if ($stmtC) { + while ($r = sqlsrv_fetch_array($stmtC, SQLSRV_FETCH_ASSOC)) { + $choferes[] = [ + 'id_chofer' => $r['id_chofer'], + 'nombre' => $r['nombre'] + ]; + } + } + + echo json_encode($choferes); + exit; + + } catch (Exception $e) { + http_response_code(500); + echo json_encode(['error' => 'Error interno del servidor']); + exit; + } +} + /** Procesa la creación de una nueva factura y sus partidas **/ function guardar() { @@ -250,13 +312,15 @@ function guardar() $patente_id ? (int)$patente_id : null ]; - $sql = "INSERT INTO dbo.solicitud_importacion_factura - (id_importador, id_agencia, aduana, anexo22_apendice, numero_factura, fecha_factura, - numero_pedimento, incoterm, pais_proveedor, tipo_moneda, - valor_factura, vinculacion, transportista_id, chofer_id, - foto_solicitud_url, status, proveedor_clave, patente_id) - OUTPUT INSERTED.id_solicitud - VALUES(?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + $sql = " + INSERT INTO dbo.solicitud_importacion_factura + (id_importador, id_agencia, aduana, anexo22_apendice, numero_factura, + fecha_factura, numero_pedimento, incoterm, pais_proveedor, tipo_moneda, + valor_factura, vinculacion, transportista_id, chofer_id, + foto_solicitud_url, status, proveedor_clave, patente_id) + OUTPUT INSERTED.id_solicitud + VALUES(?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + "; $stmt = sqlsrv_query($conn, $sql, $params, ['Scrollable' => SQLSRV_CURSOR_KEYSET]); if ($stmt === false) { @@ -281,9 +345,12 @@ function guardar() COALESCE(p.nuevas_solicitudes, 0) as nuevas_solicitudes, ce.correo as correo_extra FROM usuarios_sistema u - LEFT JOIN preferencias_notificaciones_usuario p ON u.id_usuario = p.id_usuario - LEFT JOIN correo_extra ce ON u.id_usuario = ce.id_usuario - WHERE u.id_usuario = ?"; + LEFT JOIN preferencias_notificaciones_usuario p + ON u.id_usuario = p.id_usuario + LEFT JOIN correo_extra ce + ON u.id_usuario = ce.id_usuario + WHERE u.id_usuario = ? + "; $stmtNotif = sqlsrv_prepare($conn, $sqlNotif, [$id_importador]); @@ -306,11 +373,11 @@ function guardar() // Preparar datos para la notificación $datosNotificacion = [ - 'id_solicitud' => $id_solicitud, + 'id_solicitud' => $id_solicitud, 'numero_factura' => $num_factura, - 'fecha_factura' => $fecha, - 'valor_factura' => $valor_factura, - 'tipo_moneda' => $tipo_moneda + 'fecha_factura' => $fecha, + 'valor_factura' => $valor_factura, + 'tipo_moneda' => $tipo_moneda ]; // Enviar al correo principal @@ -356,15 +423,13 @@ function guardar() error_log("Partida $i: " . print_r($p, true)); $params = [ $id_solicitud, - trim($p['descripcion'] ?? ''), - + trim($p['descripcion'] ?? ''), floatval($p['cantidad_comercial'] ?? 0), - floatval($p['cantidad_tarifa'] ?? 0), - floatval($p['valor_factura'] ?? 0), - floatval($p['peso_bruto'] ?? 0), - intval($p['unidad_comercial_id'] ?? 0) ?: null, - - trim($p['tasa_preferencial'] ?? '') + floatval($p['cantidad_tarifa'] ?? 0), + floatval($p['valor_factura'] ?? 0), + floatval($p['peso_bruto'] ?? 0), + intval($p['unidad_comercial_id'] ?? 0) ?: null, + trim($p['tasa_preferencial'] ?? '') ]; if ($params[1] !== '' && $params[2] > 0) { @@ -396,13 +461,13 @@ function enviarNotificacionNuevaSolicitud($email, $nombreUsuario, $datosSolicitu try { // Configuración SMTP $mail->isSMTP(); - $mail->Host = 'secure.emailsrvr.com'; - $mail->SMTPAuth = true; - $mail->Username = 'noreply@aduanasoft.com.mx'; - $mail->Password = $_ENV['SMTP_PASS'] ?? ''; + $mail->Host = 'secure.emailsrvr.com'; + $mail->SMTPAuth = true; + $mail->Username = 'noreply@aduanasoft.com.mx'; + $mail->Password = $_ENV['SMTP_PASS'] ?? ''; $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; - $mail->Port = 587; - $mail->CharSet = 'UTF-8'; + $mail->Port = 587; + $mail->CharSet = 'UTF-8'; // Configuración del mensaje $mail->setFrom('noreply@aduanasoft.com.mx', 'SIIH | AduanaSoft'); @@ -414,11 +479,11 @@ function enviarNotificacionNuevaSolicitud($email, $nombreUsuario, $datosSolicitu $mail->Subject = $subjectPrefix . '📦 Nueva Solicitud de Importación Registrada'; // Formatear datos para el email - $idSolicitud = $datosSolicitud['id_solicitud']; + $idSolicitud = $datosSolicitud['id_solicitud']; $numeroFactura = htmlspecialchars($datosSolicitud['numero_factura']); - $fechaFactura = htmlspecialchars($datosSolicitud['fecha_factura']); - $valorFactura = number_format($datosSolicitud['valor_factura'], 2); - $tipoMoneda = htmlspecialchars($datosSolicitud['tipo_moneda']); + $fechaFactura = htmlspecialchars($datosSolicitud['fecha_factura']); + $valorFactura = number_format($datosSolicitud['valor_factura'], 2); + $tipoMoneda = htmlspecialchars($datosSolicitud['tipo_moneda']); $tipoNotificacion = $esCorreoExtra ? '
@@ -498,7 +563,7 @@ function editar() } $id_importador = $_SESSION['usuario_id']; - $conn = getConnection(); + $conn = getConnection(); // ✅ NUEVO: Obtener la agencia actual del usuario $stmtAg = sqlsrv_query($conn, "SELECT id_agencia_en_uso FROM dbo.usuarios_sistema WHERE id_usuario = ?", [$id_importador]); @@ -528,36 +593,30 @@ function editar() while ($r = sqlsrv_fetch_array($stmtP, SQLSRV_FETCH_ASSOC)) { $patentes[] = $r; } // Transportistas - $transportistas = []; $stmtT = sqlsrv_query($conn,"SELECT id_transportista, nombre FROM dbo.transportistas WHERE id_usuario=? AND activo=1 ORDER BY nombre",[$id_importador]); - while($r = sqlsrv_fetch_array($stmtT,SQLSRV_FETCH_ASSOC)) { - $transportistas[] = $r; - } + $transportistas = []; + $stmtT = sqlsrv_query($conn, "SELECT id_transportista, clave_identificador, nombre FROM dbo.transportistas WHERE id_usuario = ? AND activo = 1 ORDER BY nombre",[$id_importador]); + while($r = sqlsrv_fetch_array($stmtT,SQLSRV_FETCH_ASSOC)) { $transportistas[] = $r; } // Choferes - $choferes = []; $stmtC = sqlsrv_query($conn,"SELECT c.id_chofer, c.nombre+' '+c.apellido AS nombre FROM dbo.choferes c JOIN dbo.transportistas t ON c.transportista_id=t.id_transportista + $choferes = []; + $stmtC = sqlsrv_query($conn, "SELECT c.id_chofer, c.nombre+' '+c.apellido AS nombre, c.transportista_id FROM dbo.choferes c JOIN dbo.transportistas t ON c.transportista_id=t.id_transportista WHERE t.id_usuario=? AND c.status=1 ORDER BY c.nombre",[$id_importador]); - while($r=sqlsrv_fetch_array($stmtC,SQLSRV_FETCH_ASSOC)) { - $choferes[] = $r; - } + while($r=sqlsrv_fetch_array($stmtC,SQLSRV_FETCH_ASSOC)) { $choferes[] = $r; } // Paises - $paises = []; $stmtP = sqlsrv_query($conn,"SELECT id_pais, nombre FROM dbo.paises ORDER BY nombre"); - while($r=sqlsrv_fetch_array($stmtP,SQLSRV_FETCH_ASSOC)) { - $paises[] = $r; - } + $paises = []; + $stmtP = sqlsrv_query($conn, "SELECT id_pais, nombre FROM dbo.paises ORDER BY nombre"); + while($r=sqlsrv_fetch_array($stmtP,SQLSRV_FETCH_ASSOC)) { $paises[] = $r;} // Aduanas - $aduanas = []; $stmtA = sqlsrv_query($conn,"SELECT DISTINCT RIGHT(REPLICATE('0', 3) + CAST(aduana_seccion AS VARCHAR), 3) AS aduana_seccion, nombre FROM dbo.aduanas ORDER BY aduana_seccion"); - while($r = sqlsrv_fetch_array($stmtA,SQLSRV_FETCH_ASSOC)) { - $aduanas[] = $r; - } + $aduanas = []; + $stmtA = sqlsrv_query($conn, "SELECT DISTINCT RIGHT(REPLICATE('0', 3) + CAST(aduana_seccion AS VARCHAR), 3) AS aduana_seccion, nombre FROM dbo.aduanas ORDER BY aduana_seccion"); + while($r = sqlsrv_fetch_array($stmtA,SQLSRV_FETCH_ASSOC)) { $aduanas[] = $r; } // Incoterms - $incoterms = []; $stmtI = sqlsrv_query($conn,"SELECT INCOTERM,DESCESPANOL FROM dbo.gIncoterms ORDER BY INCOTERM"); - while($r = sqlsrv_fetch_array($stmtI,SQLSRV_FETCH_ASSOC)) { - $incoterms[] = $r; - } + $incoterms = []; + $stmtI = sqlsrv_query($conn, "SELECT INCOTERM, DESCESPANOL FROM dbo.gIncoterms ORDER BY INCOTERM"); + while($r = sqlsrv_fetch_array($stmtI,SQLSRV_FETCH_ASSOC)) { $incoterms[] = $r; } // Unidades de Medida - $unidades_medida = []; $stmtU = sqlsrv_query($conn, "SELECT id, descripcion FROM dbo.unidades_medida_apendice7 ORDER BY id"); - while ($r = sqlsrv_fetch_array($stmtU, SQLSRV_FETCH_ASSOC)) { - $unidades_medida[] = $r; - } + $unidades_medida = []; + $stmtU = sqlsrv_query($conn, "SELECT id, descripcion FROM dbo.unidades_medida_apendice7 ORDER BY id"); + while ($r = sqlsrv_fetch_array($stmtU, SQLSRV_FETCH_ASSOC)) { $unidades_medida[] = $r; } // Partidas existentes $partidas = []; @@ -634,6 +693,7 @@ function actualizar() $chofer_id = (int)($_POST['chofer_id'] ?? 0); $status = isset($_POST['status']) ?? 1; $patente_id = $_POST['patente'] ?? null; + $proveedor_clave = $_POST['proveedor_clave'] ?? null; // ✅ NUEVO: Validar que la patente pertenezca a la agencia del usuario (si se seleccionó una) if ($patente_id) { @@ -653,27 +713,6 @@ function actualizar() } // 6) UPDATE de la cabecera - $sqlU = " - UPDATE dbo.solicitud_importacion_factura - SET aduana = ?, - anexo22_apendice = ?, - numero_factura = ?, - fecha_factura = ?, - incoterm = ?, - pais_proveedor = ?, - tipo_moneda = ?, - valor_factura = ?, - vinculacion = ?, - transportista_id = ?, - chofer_id = ?, - foto_solicitud_url = ?, - status = ?, - patente_id = ?, - updated_at = GETDATE() - WHERE id_solicitud = ? - AND id_importador = ? - AND id_agencia = ? - "; $paramsU = [ $aduana_seccion, $aduana_seccion, @@ -684,26 +723,47 @@ function actualizar() $tipo_moneda, $valor_factura, $vinculacion, - $transportista_id, - $chofer_id, + (int)$transportista_id, + (int)$chofer_id, $fotoUrl, $status, + $proveedor_clave, $patente_id ? (int)$patente_id : null, $id_solicitud, $_SESSION['usuario_id'], $id_agencia ]; + + $sqlU = " + UPDATE dbo.solicitud_importacion_factura + SET aduana = ?, + anexo22_apendice = ?, + numero_factura = ?, + fecha_factura = ?, + incoterm = ?, + pais_proveedor = ?, + tipo_moneda = ?, + valor_factura = ?, + vinculacion = ?, + transportista_id = ?, + chofer_id = ?, + foto_solicitud_url = ?, + status = ?, + proveedor_clave = ?, + patente_id = ?, + updated_at = GETDATE() + WHERE id_solicitud = ? + AND id_importador = ? + AND id_agencia = ? + "; + $stmtU = sqlsrv_query($conn, $sqlU, $paramsU); if ($stmtU === false) { die("❌ Error ejecutando UPDATE: " . print_r(sqlsrv_errors(), true)); } // 7) Borrar partidas anteriores - $del = sqlsrv_query( - $conn, - "DELETE FROM dbo.solicitud_importacion_partidas WHERE id_solicitud = ?", - [ $id_solicitud ] - ); + $del = sqlsrv_query($conn, "DELETE FROM dbo.solicitud_importacion_partidas WHERE id_solicitud = ?", [ $id_solicitud ]); if ($del === false) { die("❌ Error borrando partidas previas: " . print_r(sqlsrv_errors(), true)); } @@ -717,13 +777,13 @@ function actualizar() VALUES (?, ?, ?, ?, ?, ?, ?, ?) "; foreach ($_POST['partidas'] as $i => $p) { - $desc = trim($p['descripcion'] ?? ''); + $desc = trim($p['descripcion'] ?? ''); $cantCom = floatval($p['cantidad_comercial'] ?? 0); - $cantTar = floatval($p['cantidad_tarifa'] ?? 0); - $valPart = floatval($p['valor_factura'] ?? 0); - $peso = floatval($p['peso_bruto'] ?? 0); - $umId = intval($p['unidad_comercial_id'] ?? 0) ?: null; - $tasaPref = trim($p['tasa_preferencial'] ?? ''); + $cantTar = floatval($p['cantidad_tarifa'] ?? 0); + $valPart = floatval($p['valor_factura'] ?? 0); + $peso = floatval($p['peso_bruto'] ?? 0); + $umId = intval($p['unidad_comercial_id'] ?? 0) ?: null; + $tasaPref = trim($p['tasa_preferencial'] ?? ''); // Sólo inserta si descripción y cantidad comercial válidos if ($desc !== '' && $cantCom > 0) { diff --git a/views/solicitud_importacion/crear.php b/views/solicitud_importacion/crear.php index 4fceae5..72613af 100644 --- a/views/solicitud_importacion/crear.php +++ b/views/solicitud_importacion/crear.php @@ -35,8 +35,8 @@ .card-hover:hover { transform: translateY(-8px) scale(1.02); box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.15) !important; } .btn-pulse { animation: pulse 2s infinite; } @keyframes pulse { - 0% { transform: scale(1); } - 50% { transform: scale(1.05); } + 0% { transform: scale(1); } + 50% { transform: scale(1.05); } 100% { transform: scale(1); } } .fade-in-up { animation: fadeInUp 0.8s ease-out; } @@ -63,10 +63,16 @@ -
-
⚠️ No tienes una agencia activa vinculada.
-

Para poder gestionar tus solicitudes de importación, primero debes vincularte a una agencia.

- Ir a Vinculaciones +
+
+
+
+
⚠️ No tienes una agencia activa vinculada.
+

Para poder gestionar tus solicitudes de importación, primero debes vincularte a una agencia.

+ Ir a Vinculaciones +
+
+
@@ -399,6 +405,113 @@ } }); } + document.addEventListener('DOMContentLoaded', function() { + const transportistaSelect = document.getElementById('transportista_id'); + const choferSelect = document.getElementById('chofer_id'); + + // Inicializar Choices.js si está disponible + let choferChoices = null; + if (typeof Choices !== 'undefined') { + choferChoices = new Choices(choferSelect, { + searchEnabled: true, + placeholderValue: '-- Selecciona Transportista primero --', + noResultsText: 'No se encontraron resultados', + itemSelectText: '', + searchPlaceholderValue: 'Buscar chofer...' + }); + } + + transportistaSelect.addEventListener('change', function() { + const transportistaId = this.value; + + // Limpiar opciones del chofer + if (choferChoices) { + choferChoices.clearStore(); + choferChoices.setChoices([{ + value: '', + label: transportistaId ? '-- Cargando choferes... --' : '-- Selecciona Transportista primero --', + disabled: true + }], 'value', 'label', true); + } else { + choferSelect.innerHTML = ''; + } + + if (!transportistaId) { + return; + } + + // Hacer petición AJAX para obtener choferes + fetch(`/IMPORTADORES/solicitud_importacion/obtenerChoferesPorTransportista?transportista_id=${transportistaId}`) + .then(response => { + console.log('Response status:', response.status); + console.log('Response headers:', response.headers.get('content-type')); + + if (!response.ok) { + return response.text().then(text => { + console.error('Error response:', text); + throw new Error(`Error ${response.status}: ${text}`); + }); + } + + // Verificar que la respuesta sea JSON + const contentType = response.headers.get('content-type'); + if (!contentType || !contentType.includes('application/json')) { + return response.text().then(text => { + console.error('Non-JSON response:', text); + throw new Error('La respuesta no es JSON válido'); + }); + } + + return response.json(); + }) + .then(choferes => { + const opciones = [{ + value: '', + label: '-- Selecciona Chofer --', + disabled: false + }]; + + choferes.forEach(chofer => { + opciones.push({ + value: chofer.id_chofer, + label: chofer.nombre, + disabled: false + }); + }); + + if (choferChoices) { + choferChoices.clearStore(); + choferChoices.setChoices(opciones, 'value', 'label', true); + } else { + choferSelect.innerHTML = ''; + opciones.forEach(opcion => { + const option = document.createElement('option'); + option.value = opcion.value; + option.textContent = opcion.label; + if (opcion.disabled) option.disabled = true; + choferSelect.appendChild(option); + }); + } + }) + .catch(error => { + console.error('Error al cargar choferes:', error); + + const errorMessage = '-- Error al cargar choferes --'; + if (choferChoices) { + choferChoices.clearStore(); + choferChoices.setChoices([{ + value: '', + label: errorMessage, + disabled: true + }], 'value', 'label', true); + } else { + choferSelect.innerHTML = ``; + } + }); + }); + }); diff --git a/views/solicitud_importacion/editar.php b/views/solicitud_importacion/editar.php index 671ca38..deae253 100644 --- a/views/solicitud_importacion/editar.php +++ b/views/solicitud_importacion/editar.php @@ -165,7 +165,7 @@
- +
@@ -173,7 +173,7 @@ @@ -183,7 +183,9 @@