diff --git a/agencias.txt b/agencias.txt index d695f0a..26cb4d2 100644 --- a/agencias.txt +++ b/agencias.txt @@ -202,4 +202,43 @@ CREATE INDEX [IX_agencias_activo] ON [dbo].[agencias_aduanales] ([activo]); CREATE INDEX [IX_agencias_administrador] ON [dbo].[agencias_aduanales] ([id_administrador]); -CREATE INDEX [IX_solicitudes_estado] ON [dbo].[solicitudes_vinculacion] ([estado], [id_agencia]); \ No newline at end of file +CREATE INDEX [IX_solicitudes_estado] ON [dbo].[solicitudes_vinculacion] ([estado], [id_agencia]); + + +== MODIFICACIONES MULLTI-AGENCIA == +ALTER TABLE usuarios_sistema +ADD id_agencia_en_uso INT NULL; + +ALTER TABLE usuarios_sistema +ADD CONSTRAINT FK_usuario_agencia_uso +FOREIGN KEY (id_agencia_en_uso) REFERENCES agencias_aduanales(id_agencia); + + +-- 1. Modificar la tabla de solicitudes para incluir la relación con agencia +ALTER TABLE [dbo].[solicitud_importacion_factura] +ADD [id_agencia] [int] NULL; + +-- Agregar foreign key para la agencia +ALTER TABLE [dbo].[solicitud_importacion_factura] +ADD CONSTRAINT [FK_solicitud_agencia] +FOREIGN KEY ([id_agencia]) REFERENCES [dbo].[agencias_aduanales]([id_agencia]); + +-- 2. Crear índices para mejorar el rendimiento +CREATE INDEX [IX_solicitud_importador_agencia] +ON [dbo].[solicitud_importacion_factura] ([id_importador], [id_agencia]); + +CREATE INDEX [IX_solicitud_agencia_status] +ON [dbo].[solicitud_importacion_factura] ([id_agencia], [status]); + + +-- 3. Agregar campos adicionales a la tabla expediente_archivos existente para mejor control +ALTER TABLE [dbo].[expediente_archivos] +ADD [estado_archivo] [varchar](20) NULL DEFAULT 'ACTIVO', -- ACTIVO, INACTIVO, ELIMINADO + [subido_por] [int] NULL, -- ID del usuario que subió el archivo + [observaciones] [nvarchar](500) NULL, + [fecha_modificacion] [datetime] NULL; + +-- Agregar foreign key para el usuario que subió el archivo +ALTER TABLE [dbo].[expediente_archivos] +ADD CONSTRAINT [FK_expediente_archivos_usuario] +FOREIGN KEY ([subido_por]) REFERENCES [dbo].[usuarios_sistema]([id_usuario]); \ No newline at end of file diff --git a/app/controllers/importadores.php b/app/controllers/importadores.php index 1dfbb9e..5481345 100644 --- a/app/controllers/importadores.php +++ b/app/controllers/importadores.php @@ -203,4 +203,56 @@ function desvincularUsuario() header('Location: /IMPORTADORES/vinculaciones/vinculacionesUsuario?error=unlinked_failed&msg=' . urlencode($e->getMessage())); exit; } +} + +/** Función para cambiar la agencia activa del usuario **/ +function cambiarAgenciaActiva() +{ + if (!isset($_SESSION['usuario_id']) || $_SESSION['tipo_usuario'] !== 'importador') { + header('Location: /IMPORTADORES/login'); + exit; + } + + if (!isset($_GET['id']) || !is_numeric($_GET['id'])) { + header("Location: /IMPORTADORES/vinculaciones/vinculacionesusuario?error=invalid_id"); + exit; + } + + $id_agencia = intval($_GET['id']); + $id_usuario = $_SESSION['usuario_id']; + + $conn = getConnection(); + + // Validar que el importador está vinculado a esta agencia + $sqlVerificacion = " + SELECT 1 + FROM importador_agencia + WHERE id_importador = ? AND id_agencia = ? AND activo = 1 + "; + $stmtVerificacion = sqlsrv_query($conn, $sqlVerificacion, [$id_usuario, $id_agencia]); + + if ($stmtVerificacion === false || !sqlsrv_fetch($stmtVerificacion)) { + header("Location: /IMPORTADORES/vinculaciones/vinculacionesusuario?error=invalid_agency"); + exit; + } + + // Actualizar campo id_agencia_en_uso + $sqlUpdate = " + UPDATE usuarios_sistema + SET id_agencia_en_uso = ? + WHERE id_usuario = ? + "; + $stmtUpdate = sqlsrv_query($conn, $sqlUpdate, [$id_agencia, $id_usuario]); + + if ($stmtUpdate === false) { + header("Location: /IMPORTADORES/vinculaciones/vinculacionesusuario?error=agency_changed_failed"); + exit; + } + + // Opcional: actualizar también la sesión si lo usas en tu lógica + $_SESSION['id_agencia_en_uso'] = $id_agencia; + + // Redirigir con éxito + header("Location: /IMPORTADORES/vinculaciones/vinculacionesusuario?success=agency_changed"); + exit; } \ No newline at end of file diff --git a/app/controllers/solicitud_importacion.php b/app/controllers/solicitud_importacion.php index fcf8d8f..7c94f24 100644 --- a/app/controllers/solicitud_importacion.php +++ b/app/controllers/solicitud_importacion.php @@ -71,6 +71,13 @@ function lista() { $id_importador = $_SESSION['usuario_id']; $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]); + $id_agencia = null; + if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { + $id_agencia = $row['id_agencia_en_uso']; + } + $sql = " SELECT f.*, @@ -86,10 +93,11 @@ function lista() { LEFT JOIN dbo.paises p ON f.pais_proveedor = p.id_pais WHERE f.id_importador = ? + AND f.id_agencia = ? AND f.status >= 1 ORDER BY f.created_at DESC "; - $stmt = sqlsrv_query($conn, $sql, [$id_importador]); + $stmt = sqlsrv_query($conn, $sql, [$id_importador, $id_agencia]); if ($stmt === false) { die("Error en lista(): " . print_r(sqlsrv_errors(), true)); } @@ -115,6 +123,13 @@ function crear() $id_importador = $_SESSION['usuario_id']; $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]); + $id_agencia = null; + if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { + $id_agencia = $row['id_agencia_en_uso']; + } + // Carga de datos para selects $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]); @@ -151,7 +166,22 @@ function guardar() if (!($_SESSION['usuario_id'] ?? false)) { die("⚠️ No autorizado."); } - $id_importador = $_SESSION['usuario_id']; + + $id_importador = $_SESSION['usuario_id']; + $conn = getConnection(); + + // ✅ Obtener id_agencia_en_uso del usuario + $stmtAgencia = sqlsrv_query($conn, "SELECT id_agencia_en_uso FROM dbo.usuarios_sistema WHERE id_usuario = ?", [$id_importador]); + $id_agencia = null; + if ($stmtAgencia && $row = sqlsrv_fetch_array($stmtAgencia, SQLSRV_FETCH_ASSOC)) { + $id_agencia = $row['id_agencia_en_uso']; + } + + if (!$id_agencia) { + die("❌ No se pudo determinar la agencia en uso para guardar la solicitud."); + } + + // Obtener y validar campos del formulario $aduana_seccion = $_POST['anexo22_apendice'] ?? null; $num_factura = trim($_POST['numero_factura'] ?? ''); $fecha = $_POST['fecha_factura'] ?? null; @@ -179,11 +209,10 @@ function guardar() $fotoUrl="/IMPORTADORES/public/uploads/".basename($dest); } } - - $conn = getConnection(); $params = [ $id_importador, + $id_agencia, $aduana_seccion, $aduana_seccion, $num_factura, @@ -201,12 +230,12 @@ function guardar() ]; $sql = "INSERT INTO dbo.solicitud_importacion_factura - (id_importador, 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) - OUTPUT INSERTED.id_solicitud - VALUES(?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + (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) + OUTPUT INSERTED.id_solicitud + VALUES(?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; $stmt = sqlsrv_query($conn, $sql, $params, ['Scrollable' => SQLSRV_CURSOR_KEYSET]); if ($stmt === false) { @@ -435,19 +464,29 @@ function enviarNotificacionNuevaSolicitud($email, $nombreUsuario, $datosSolicitu } /** Formulario de edición de factura **/ -function editar() { +function editar() +{ if (!($_SESSION['usuario_id'] ?? false)) { - header('Location: /IMPORTADORES/login'); exit; + header('Location: /IMPORTADORES/login'); + exit; } $id_solicitud = $_GET['id']??null; if(!$id_solicitud || !is_numeric($id_solicitud)) { die("❌ ID inválido."); } + $id_importador = $_SESSION['usuario_id']; $conn = getConnection(); - $stmt = sqlsrv_query($conn,"SELECT * FROM dbo.solicitud_importacion_factura WHERE id_solicitud=? AND id_importador=?",[(int)$id_solicitud,$id_importador]); + // ✅ Obtener id_agencia_en_uso del usuario + $stmtAgencia = sqlsrv_query($conn, "SELECT id_agencia_en_uso FROM dbo.usuarios_sistema WHERE id_usuario = ?", [$id_importador]); + $id_agencia = null; + if ($stmtAgencia && $row = sqlsrv_fetch_array($stmtAgencia, SQLSRV_FETCH_ASSOC)) { + $id_agencia = $row['id_agencia_en_uso']; + } + + $stmt = sqlsrv_query($conn,"SELECT * FROM dbo.solicitud_importacion_factura WHERE id_solicitud=? AND id_importador=? AND id_agencia=?", [(int)$id_solicitud, $id_importador, $id_agencia]); if($stmt === false) { die(print_r(sqlsrv_errors(),true)); } @@ -508,8 +547,8 @@ function editar() { } /** Procesa la actualización de una factura y sus partidas **/ -function actualizar() { - session_start(); +function actualizar() +{ if (!($_SESSION['usuario_id'] ?? false)) { die("⚠️ No autorizado."); } @@ -522,14 +561,21 @@ function actualizar() { // 1) Conexión $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]); + $id_agencia = null; + if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { + $id_agencia = $row['id_agencia_en_uso']; + } + // 2) Obtener URL de foto actual desde BD para conservar si no suben nueva $fotoUrl = null; $stmtFoto = sqlsrv_query( $conn, "SELECT foto_solicitud_url FROM dbo.solicitud_importacion_factura - WHERE id_solicitud = ? AND id_importador = ?", - [ $id_solicitud, $_SESSION['usuario_id'] ] + WHERE id_solicitud = ? AND id_importador = ? AND id_agencia = ?", + [ $id_solicitud, $_SESSION['usuario_id'], $id_agencia ] ); if ($stmtFoto !== false && ($row = sqlsrv_fetch_array($stmtFoto, SQLSRV_FETCH_ASSOC))) { $fotoUrl = $row['foto_solicitud_url']; @@ -549,17 +595,17 @@ function actualizar() { } // 4) Extraer campos del formulario - $aduana_seccion = $_POST['anexo22_apendice'] ?? null; - $num_factura = trim($_POST['numero_factura'] ?? ''); - $fecha = $_POST['fecha_factura'] ?? null; - $incoterm = $_POST['incoterm'] ?? null; - $pais_proveedor = $_POST['pais_proveedor'] ?? null; - $tipo_moneda = $_POST['tipo_moneda'] ?? null; - $valor_factura = $_POST['valor_factura'] ?? null; - $vinculacion = $_POST['vinculacion'] ?? 0; + $aduana_seccion = $_POST['anexo22_apendice'] ?? null; + $num_factura = trim($_POST['numero_factura'] ?? ''); + $fecha = $_POST['fecha_factura'] ?? null; + $incoterm = $_POST['incoterm'] ?? null; + $pais_proveedor = $_POST['pais_proveedor'] ?? null; + $tipo_moneda = $_POST['tipo_moneda'] ?? null; + $valor_factura = $_POST['valor_factura'] ?? null; + $vinculacion = $_POST['vinculacion'] ?? 0; $transportista_id = (int)($_POST['transportista_id'] ?? 0); - $chofer_id = (int)($_POST['chofer_id'] ?? 0); - $status = isset($_POST['status']) ?? 1; + $chofer_id = (int)($_POST['chofer_id'] ?? 0); + $status = isset($_POST['status']) ?? 1; // 5) Validar obligatorios if (empty($num_factura) || empty($fecha) || $transportista_id <= 0 || $chofer_id <= 0) { @@ -585,6 +631,7 @@ function actualizar() { updated_at = GETDATE() WHERE id_solicitud = ? AND id_importador = ? + AND id_agencia = ? "; $paramsU = [ $aduana_seccion, @@ -601,7 +648,8 @@ function actualizar() { $fotoUrl, $status, $id_solicitud, - $_SESSION['usuario_id'] + $_SESSION['usuario_id'], + $id_agencia ]; $stmtU = sqlsrv_query($conn, $sqlU, $paramsU); if ($stmtU === false) { @@ -1553,6 +1601,9 @@ function pdf() { $options = new Options(); $options->set('defaultFont', 'Arial'); $options->set('isRemoteEnabled', true); // Permite cargar imágenes remotas si es necesario + $options->set('isHtml5ParserEnabled', true); // Habilita el parser HTML5 + $options->set('isPhpEnabled', true); // Habilita PHP dentro del HTML si es necesario + $options->set('chroot', $_SERVER['DOCUMENT_ROOT']); // Asegura que las rutas relativas funcionen correctamente $dompdf = new Dompdf($options); $dompdf->loadHtml($html); @@ -1772,8 +1823,7 @@ function generarHTMLPDF($solicitud, $partidas, $configuracion, $proveedor_info = /** Encabezado **/ .header { padding-bottom: 50px; } .logo-section { width: 20%; text-align: left; } - .logo { max-width: 100px; height: auto; vertical-align: center; } - .siglas { font-size: 15px; } + .logo { max-width: 125px; height: auto; vertical-align: top; } .company-info { width: 60%; text-align: center; vertical-align: top; font-size: 12px; } .company-name { font-weight: bold; font-size: 25px; margin-bottom: 3px; } .invoice-info { width: 20%; text-align: right; vertical-align: top; font-size: 12px; } @@ -1811,7 +1861,6 @@ function generarHTMLPDF($solicitud, $partidas, $configuracion, $proveedor_info =
-
' . htmlspecialchars($configuracion['siglas'] ?? 'SIIH') . '
' . htmlspecialchars($solicitud['importador_nombre']) . '
diff --git a/app/controllers/vinculaciones.php b/app/controllers/vinculaciones.php index 874462a..857f1c2 100644 --- a/app/controllers/vinculaciones.php +++ b/app/controllers/vinculaciones.php @@ -21,8 +21,10 @@ function vinculacionesUsuario() $sql = " SELECT * FROM importador_agencia ia - INNER JOIN agencias_aduanales aa ON ia.id_agencia = aa.id_agencia - WHERE ia.id_importador = ? AND ia.activo = 1 + INNER JOIN agencias_aduanales aa + ON ia.id_agencia = aa.id_agencia + WHERE ia.id_importador = ? + AND ia.activo = 1 ORDER BY ia.fecha_vinculacion DESC "; $stmt = sqlsrv_query($conn, $sql, [$_SESSION['usuario_id']]); @@ -37,7 +39,6 @@ function vinculacionesUsuario() include __DIR__ . '/../../views/vinculaciones/vinculaciones_importador.php'; } - function nuevaVinculacion() { if (!isset($_SESSION['usuario_id']) || $_SESSION['tipo_usuario'] !== 'importador') { diff --git a/views/vinculaciones/vinculaciones_importador.php b/views/vinculaciones/vinculaciones_importador.php index 07093a5..453ae34 100644 --- a/views/vinculaciones/vinculaciones_importador.php +++ b/views/vinculaciones/vinculaciones_importador.php @@ -46,6 +46,7 @@ # + Agencia Nombre RFC Teléfono @@ -59,12 +60,18 @@ + format('Y-m-d H:i') : '' ?> + + En uso + + Usar Agencia + Desvincular @@ -93,6 +100,10 @@ Swal.fire({ icon: 'success', title: 'Usuario desvinculado', text: 'El usuario se ha desvinculado correctamente.', confirmButtonColor: '#198754' }); + + Swal.fire({ icon: 'success', title: 'Agencia cambiada', + text: 'La agencia activa se ha cambiado correctamente.', + confirmButtonColor: '#198754' }); @@ -103,6 +114,12 @@ Swal.fire({ icon: 'error', title: 'Desvinculación fallida', text: 'No se ha podido desvincular el usuario.', confirmButtonColor: '#dc3545' }); Swal.fire({ icon: 'error', title: 'ID inválido', text: 'El identificador de la relación no es válido.', confirmButtonColor: '#dc3545' }); + + Swal.fire({ icon: 'error', title: 'Agencia inválida', text: 'El ID de agencia proporcionado no es válido.', confirmButtonColor: '#dc3545' }); + + Swal.fire({ icon: 'error', title: 'Error al cargar agencias', text: 'No se han podido cargar las agencias.', confirmButtonColor: '#dc3545' }); + + Swal.fire({ icon: 'error', title: 'Error al cambiar agencia', text: 'No se ha podido cambiar la agencia activa.', confirmButtonColor: '#dc3545' });