This commit is contained in:
2025-07-09 16:14:22 -06:00
parent 91b6806898
commit 287ad27274
39 changed files with 2517 additions and 2000 deletions

View File

@@ -525,7 +525,7 @@ function aprobar_agencia()
$sqlGetAgenciaId = "SELECT SCOPE_IDENTITY() AS id_agencia"; $sqlGetAgenciaId = "SELECT SCOPE_IDENTITY() AS id_agencia";
$stmtGetAgenciaId = sqlsrv_query($conn, $sqlGetAgenciaId); $stmtGetAgenciaId = sqlsrv_query($conn, $sqlGetAgenciaId);
$agenciaIdRow = sqlsrv_fetch_array($stmtGetAgenciaId, SQLSRV_FETCH_ASSOC); $agenciaIdRow = sqlsrv_fetch_array($stmtGetAgenciaId, SQLSRV_FETCH_ASSOC);
$id_agencia = $idUsuarioRow['id_agencia'] ?? null; $id_agencia = $agenciaIdRow['id_agencia'] ?? null;
if (!$id_agencia) { if (!$id_agencia) {
die("❌ No se pudo obtener el ID de la agencia recién creada."); die("❌ No se pudo obtener el ID de la agencia recién creada.");
@@ -535,9 +535,7 @@ function aprobar_agencia()
$sqlInsert2 = "INSERT INTO usuarios_sistema (nombre, email, password_hash, tipo_usuario, activo, creado_en, dos_factores, creado_por) $sqlInsert2 = "INSERT INTO usuarios_sistema (nombre, email, password_hash, tipo_usuario, activo, creado_en, dos_factores, creado_por)
VALUES (?, ?, ?, ?, 1, GETDATE(), 0, ?) VALUES (?, ?, ?, ?, 1, GETDATE(), 0, ?)
"; ";
$stmtInsert2 = sqlsrv_query($conn, $sqlInsert, [ $stmtInsert2 = sqlsrv_query($conn, $sqlInsert, [$admin_name_encrypt, $admin_email_encrypt, $password_hash, $tipo, $usuario_id]);
$admin_name_encrypt, $admin_email_encrypt, $password_hash, $tipo, $usuario_id
]);
if (!$stmtInsert2) { if (!$stmtInsert2) {
die("❌ Error al crear usuario administrador: " . print_r(sqlsrv_errors(), true)); die("❌ Error al crear usuario administrador: " . print_r(sqlsrv_errors(), true));
@@ -576,7 +574,8 @@ function aprobar_agencia()
SET request_status = 'approved', SET request_status = 'approved',
approval_date = GETDATE(), approval_date = GETDATE(),
approved_by = ? approved_by = ?
WHERE request_id = ?"; WHERE request_id = ?
";
$stmtUpdate = sqlsrv_query($conn, $sqlUpdate, [$usuario_id, $id]); $stmtUpdate = sqlsrv_query($conn, $sqlUpdate, [$usuario_id, $id]);
if (!$stmtUpdate) { if (!$stmtUpdate) {

View File

@@ -1,6 +1,5 @@
<?php <?php
require_once __DIR__ . '/../../vendor/autoload.php'; require_once __DIR__ . '/../../vendor/autoload.php';
require_once __DIR__ . '/../helpers/session.php'; require_once __DIR__ . '/../helpers/session.php';
require_once __DIR__ . '/../../config/database.php'; require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../helpers/crypto.php'; require_once __DIR__ . '/../helpers/crypto.php';
@@ -66,19 +65,10 @@ function alta()
$rowCountActive = sqlsrv_fetch_array($stmtCountActive, SQLSRV_FETCH_ASSOC); $rowCountActive = sqlsrv_fetch_array($stmtCountActive, SQLSRV_FETCH_ASSOC);
// Consulta de agentes vinculados ACTIVOS a MI agencia // Consulta de agentes vinculados ACTIVOS a MI agencia
$sql = " $sql = "SELECT
SELECT u.id_usuario, u.nombre, u.email, u.tipo_usuario as tipo_usuario_sistema, u.activo,
u.id_usuario, u.creado_en, u.creado_por, creador.nombre as nombre_creador,
u.nombre, aa.fecha_asignacion as fecha_vinculacion, aa.id_relacion, 'agente' as tipo_vinculacion
u.email,
u.tipo_usuario as tipo_usuario_sistema,
u.activo,
u.creado_en,
u.creado_por,
creador.nombre as nombre_creador,
aa.fecha_asignacion as fecha_vinculacion,
aa.id_relacion,
'agente' as tipo_vinculacion
FROM agente_agencia aa FROM agente_agencia aa
INNER JOIN usuarios_sistema u INNER JOIN usuarios_sistema u
ON aa.id_agente = u.id_usuario ON aa.id_agente = u.id_usuario
@@ -157,10 +147,11 @@ function guardarAgente()
} }
// 4. Insertar usuario // 4. Insertar usuario
$sqlInsert = " $sqlInsert = "INSERT INTO usuarios_sistema
INSERT INTO usuarios_sistema (nombre, email, password_hash, tipo_usuario, activo, creado_en, dos_factores, creado_por) (nombre, email, password_hash, tipo_usuario, activo, creado_en, dos_factores, creado_por)
OUTPUT INSERTED.id_usuario OUTPUT INSERTED.id_usuario
VALUES (?, ?, ?, ?, 1, GETDATE(), 0, ?)"; VALUES (?, ?, ?, ?, 1, GETDATE(), 0, ?)
";
$params = [$nombre_encrypted, $email_encrypted, $password_hash, $tipo, $_SESSION['usuario_id']]; $params = [$nombre_encrypted, $email_encrypted, $password_hash, $tipo, $_SESSION['usuario_id']];
$stmtInsert = sqlsrv_query($conn, $sqlInsert, $params); $stmtInsert = sqlsrv_query($conn, $sqlInsert, $params);
@@ -190,8 +181,10 @@ function guardarAgente()
} }
// 7. Crear la relación agente-agencia // 7. Crear la relación agente-agencia
$sqlRelacion = "INSERT INTO agente_agencia (id_agente, id_agencia, fecha_asignacion, activo, asignado_por) $sqlRelacion = "INSERT INTO agente_agencia
VALUES (?, ?, GETDATE(), 1, ?)"; (id_agente, id_agencia, fecha_asignacion, activo, asignado_por)
VALUES (?, ?, GETDATE(), 1, ?)
";
$paramsRelacion = [$id_usuario, $id_agencia, $_SESSION['usuario_id']]; $paramsRelacion = [$id_usuario, $id_agencia, $_SESSION['usuario_id']];
$stmtRelacion = sqlsrv_query($conn, $sqlRelacion, $paramsRelacion); $stmtRelacion = sqlsrv_query($conn, $sqlRelacion, $paramsRelacion);

View File

@@ -1,6 +1,5 @@
<?php <?php
require_once __DIR__ . '/../../vendor/autoload.php'; require_once __DIR__ . '/../../vendor/autoload.php';
require_once __DIR__ . '/../helpers/session.php'; require_once __DIR__ . '/../helpers/session.php';
require_once __DIR__ . '/../../config/database.php'; require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../helpers/crypto.php'; require_once __DIR__ . '/../helpers/crypto.php';
@@ -65,19 +64,19 @@ function vinculados()
$stmtCountActive = sqlsrv_query($conn, $sqlCountActive, [$id_agencia]); $stmtCountActive = sqlsrv_query($conn, $sqlCountActive, [$id_agencia]);
$rowCountActive = sqlsrv_fetch_array($stmtCountActive, SQLSRV_FETCH_ASSOC); $rowCountActive = sqlsrv_fetch_array($stmtCountActive, SQLSRV_FETCH_ASSOC);
// Consulta corregida: solo usuarios vinculados ACTIVOS a MI agencia // Solo usuarios vinculados ACTIVOS a MI agencia
$sql = " $sql = "SELECT
SELECT ia.*, u.nombre as importador_nombre, ig.rfc, ig.telefono, aa.nombre_agencia
ia.*,
u.nombre as importador_nombre,
ig.rfc,
ig.telefono,
aa.nombre_agencia
FROM importador_agencia ia FROM importador_agencia ia
INNER JOIN usuarios_sistema u ON ia.id_importador = u.id_usuario INNER JOIN usuarios_sistema u
LEFT JOIN informacion_general ig ON u.id_usuario = ig.id_usuario ON ia.id_importador = u.id_usuario
LEFT JOIN agencias_aduanales aa ON ia.id_agencia = aa.id_agencia LEFT JOIN informacion_general ig
WHERE ia.id_agencia = ? AND ia.activo = 1 AND ia.estado = 'APROBADO' ON u.id_usuario = ig.id_usuario
LEFT JOIN agencias_aduanales aa
ON ia.id_agencia = aa.id_agencia
WHERE ia.id_agencia = ?
AND ia.activo = 1
AND ia.estado = 'APROBADO'
ORDER BY ia.fecha_vinculacion DESC ORDER BY ia.fecha_vinculacion DESC
"; ";
$stmt = sqlsrv_query($conn, $sql, [$id_agencia]); $stmt = sqlsrv_query($conn, $sql, [$id_agencia]);
@@ -118,30 +117,30 @@ function desvincularAgente()
sqlsrv_begin_transaction($conn); sqlsrv_begin_transaction($conn);
// 1. Primero obtener la agencia del agente aduanal // 1. Primero obtener la agencia del agente aduanal
$sqlAgenciaAgente = " $sqlAgenciaAgente = "SELECT id_agencia
SELECT id_agencia
FROM agente_agencia FROM agente_agencia
WHERE id_agente = ? AND activo = 1 WHERE id_agente = ?
AND activo = 1
"; ";
$stmtAgenciaAgente = sqlsrv_query($conn, $sqlAgenciaAgente, [$_SESSION['usuario_id']]); $stmtAgenciaAgente = sqlsrv_query($conn, $sqlAgenciaAgente, [$_SESSION['usuario_id']]);
$agenciaAgente = sqlsrv_fetch_array($stmtAgenciaAgente, SQLSRV_FETCH_ASSOC);
if ($stmtAgenciaAgente === false) { if ($stmtAgenciaAgente === false) {
throw new Exception('Error en la consulta de agencia-agente: ' . print_r(sqlsrv_errors(), true)); throw new Exception('Error en la consulta de agencia-agente: ' . print_r(sqlsrv_errors(), true));
} }
$agenciaAgente = sqlsrv_fetch_array($stmtAgenciaAgente, SQLSRV_FETCH_ASSOC);
$id_agencia_agente = $agenciaAgente['id_agencia']; $id_agencia_agente = $agenciaAgente['id_agencia'];
// 2. Verificar que la relación existe y pertenece a la MISMA agencia del agente // 2. Verificar que la relación existe y pertenece a la MISMA agencia del agente
$sqlVerificar = " $sqlVerificar = "SELECT
SELECT ia.*, u.id_usuario, u.nombre as importador_nombre, aa.nombre_agencia
ia.*,
u.id_usuario, u.nombre as importador_nombre, aa.nombre_agencia
FROM importador_agencia ia FROM importador_agencia ia
INNER JOIN usuarios_sistema u ON ia.id_importador = u.id_usuario INNER JOIN usuarios_sistema u
INNER JOIN agencias_aduanales aa ON ia.id_agencia = aa.id_agencia ON ia.id_importador = u.id_usuario
WHERE ia.id_relacion = ? AND ia.id_agencia = ? INNER JOIN agencias_aduanales aa
ON ia.id_agencia = aa.id_agencia
WHERE ia.id_relacion = ?
AND ia.id_agencia = ?
"; ";
$stmtVerificar = sqlsrv_query($conn, $sqlVerificar, [$id_relacion, $id_agencia_agente]); $stmtVerificar = sqlsrv_query($conn, $sqlVerificar, [$id_relacion, $id_agencia_agente]);
@@ -151,10 +150,8 @@ function desvincularAgente()
$relacion = sqlsrv_fetch_array($stmtVerificar, SQLSRV_FETCH_ASSOC); $relacion = sqlsrv_fetch_array($stmtVerificar, SQLSRV_FETCH_ASSOC);
// 4. Desactivar la relación (no eliminar, mantener historial) // 4. Desactivar la relación (no eliminar, mantener historial)
$sqlDesactivar = " $sqlDesactivar = "UPDATE importador_agencia
UPDATE importador_agencia
SET activo = 0, SET activo = 0,
estado = 'DESVINCULADO' estado = 'DESVINCULADO'
WHERE id_relacion = ? WHERE id_relacion = ?
@@ -166,10 +163,10 @@ function desvincularAgente()
} }
// NUEVO: Verificar si el importador desvinculado tenía esta agencia como activa // NUEVO: Verificar si el importador desvinculado tenía esta agencia como activa
$sqlVerificarAgenciaActiva = " $sqlVerificarAgenciaActiva = "SELECT id_agencia_en_uso
SELECT id_agencia_en_uso
FROM usuarios_sistema FROM usuarios_sistema
WHERE id_usuario = ? AND id_agencia_en_uso = ? WHERE id_usuario = ?
AND id_agencia_en_uso = ?
"; ";
$stmtVerificarActiva = sqlsrv_query($conn, $sqlVerificarAgenciaActiva, $stmtVerificarActiva = sqlsrv_query($conn, $sqlVerificarAgenciaActiva,
[$relacion['id_importador'], $relacion['id_agencia']]); [$relacion['id_importador'], $relacion['id_agencia']]);
@@ -180,8 +177,7 @@ function desvincularAgente()
if ($stmtVerificarActiva && sqlsrv_fetch_array($stmtVerificarActiva, SQLSRV_FETCH_ASSOC)) { if ($stmtVerificarActiva && sqlsrv_fetch_array($stmtVerificarActiva, SQLSRV_FETCH_ASSOC)) {
// Si tenía esta agencia como activa, quitársela // Si tenía esta agencia como activa, quitársela
$sqlQuitarAgenciaActiva = " $sqlQuitarAgenciaActiva = "UPDATE usuarios_sistema
UPDATE usuarios_sistema
SET id_agencia_en_uso = NULL SET id_agencia_en_uso = NULL
WHERE id_usuario = ? WHERE id_usuario = ?
"; ";

View File

@@ -17,11 +17,13 @@ function sistema()
} }
$conn = getConnection(); $conn = getConnection();
$sql = "SELECT bl.*, u.nombre $sql = "SELECT bl.*, u.nombre
FROM bitacora_login bl FROM bitacora_login bl
INNER JOIN usuarios_sistema u INNER JOIN usuarios_sistema u
ON bl.id_usuario = u.id_usuario ON bl.id_usuario = u.id_usuario
ORDER BY fecha DESC"; ORDER BY fecha DESC
";
$stmt = sqlsrv_query($conn, $sql); $stmt = sqlsrv_query($conn, $sql);
if ($stmt === false) { if ($stmt === false) {
@@ -44,6 +46,7 @@ function sistemaAgencia()
} }
$conn = getConnection(); $conn = getConnection();
$id_usuario = $_SESSION['usuario_id']; $id_usuario = $_SESSION['usuario_id'];
// Obtener ID de agencia asociada // Obtener ID de agencia asociada
@@ -60,13 +63,12 @@ function sistemaAgencia()
} }
// Obtener todos los usuarios ligados a la misma agencia (agentes + importadores) // Obtener todos los usuarios ligados a la misma agencia (agentes + importadores)
$sql_usuarios = " $sql_usuarios = "SELECT DISTINCT id_usuario
SELECT DISTINCT id_usuario FROM usuarios_sistema FROM usuarios_sistema
WHERE id_usuario IN ( WHERE id_usuario IN (
SELECT id_agente FROM agente_agencia WHERE id_agencia = ? AND activo = 1 SELECT id_agente FROM agente_agencia WHERE id_agencia = ? AND activo = 1
UNION UNION
SELECT id_importador FROM importador_agencia WHERE id_agencia = ? AND activo = 1 SELECT id_importador FROM importador_agencia WHERE id_agencia = ? AND activo = 1)
)
"; ";
$stmt_usuarios = sqlsrv_query($conn, $sql_usuarios, [$id_agencia, $id_agencia]); $stmt_usuarios = sqlsrv_query($conn, $sql_usuarios, [$id_agencia, $id_agencia]);
@@ -80,14 +82,13 @@ function sistemaAgencia()
if (!empty($usuarios)) { if (!empty($usuarios)) {
$placeholders = implode(',', array_fill(0, count($usuarios), '?')); $placeholders = implode(',', array_fill(0, count($usuarios), '?'));
$sql_bitacora = " $sql_bitacora = "SELECT bl.*, u.nombre
SELECT bl.*, u.nombre
FROM bitacora_login bl FROM bitacora_login bl
INNER JOIN usuarios_sistema u ON bl.id_usuario = u.id_usuario INNER JOIN usuarios_sistema u
ON bl.id_usuario = u.id_usuario
WHERE bl.id_usuario IN ($placeholders) WHERE bl.id_usuario IN ($placeholders)
ORDER BY fecha DESC ORDER BY fecha DESC
"; ";
$stmt = sqlsrv_query($conn, $sql_bitacora, $usuarios); $stmt = sqlsrv_query($conn, $sql_bitacora, $usuarios);
if ($stmt === false) { if ($stmt === false) {
@@ -110,6 +111,7 @@ function cambios()
} }
$conn = getConnection(); $conn = getConnection();
$sql = "SELECT * FROM bitacora_usuarios ORDER BY fecha DESC"; $sql = "SELECT * FROM bitacora_usuarios ORDER BY fecha DESC";
$stmt = sqlsrv_query($conn, $sql); $stmt = sqlsrv_query($conn, $sql);
@@ -133,10 +135,13 @@ function usuarios()
} }
$conn = getConnection(); $conn = getConnection();
$sql = "SELECT u.*, creador.nombre AS nombre_creador $sql = "SELECT u.*, creador.nombre AS nombre_creador
FROM usuarios_sistema u FROM usuarios_sistema u
LEFT JOIN usuarios_sistema creador ON u.creado_por = creador.id_usuario LEFT JOIN usuarios_sistema creador
ORDER BY creado_en DESC"; ON u.creado_por = creador.id_usuario
ORDER BY creado_en DESC
";
$stmt = sqlsrv_query($conn, $sql); $stmt = sqlsrv_query($conn, $sql);
if ($stmt === false) { if ($stmt === false) {
@@ -159,6 +164,7 @@ function vinculaciones()
} }
$conn = getConnection(); $conn = getConnection();
$usuario_id = $_SESSION['usuario_id']; $usuario_id = $_SESSION['usuario_id'];
// 1. Obtener la agencia asociada al usuario actual // 1. Obtener la agencia asociada al usuario actual
@@ -175,19 +181,20 @@ function vinculaciones()
} }
// 2. Consulta de vinculaciones SOLO de esa agencia // 2. Consulta de vinculaciones SOLO de esa agencia
$sql = " $sql = "SELECT ia.*,
SELECT ia.*,
u.nombre AS nombre_importador, u.nombre AS nombre_importador,
aa.nombre_agencia, aa.nombre_agencia,
ap.nombre AS nombre_aprobador ap.nombre AS nombre_aprobador
FROM importador_agencia ia FROM importador_agencia ia
INNER JOIN usuarios_sistema u ON ia.id_importador = u.id_usuario INNER JOIN usuarios_sistema u
INNER JOIN agencias_aduanales aa ON ia.id_agencia = aa.id_agencia ON ia.id_importador = u.id_usuario
LEFT JOIN usuarios_sistema ap ON ia.aprobado_por = ap.id_usuario INNER JOIN agencias_aduanales aa
ON ia.id_agencia = aa.id_agencia
LEFT JOIN usuarios_sistema ap
ON ia.aprobado_por = ap.id_usuario
WHERE ia.id_agencia = ? WHERE ia.id_agencia = ?
ORDER BY ia.fecha_vinculacion DESC ORDER BY ia.fecha_vinculacion DESC
"; ";
$stmt = sqlsrv_query($conn, $sql, [$id_agencia]); $stmt = sqlsrv_query($conn, $sql, [$id_agencia]);
if ($stmt === false) { if ($stmt === false) {
@@ -217,22 +224,24 @@ function vinculacionesUsuario()
} }
$conn = getConnection(); $conn = getConnection();
$id_importador = $_SESSION['usuario_id']; $id_importador = $_SESSION['usuario_id'];
// Traer todas las relaciones del importador actual // Traer todas las relaciones del importador actual
$sql = " $sql = "SELECT ia.*,
SELECT ia.*,
u.nombre AS nombre_importador, u.nombre AS nombre_importador,
aa.nombre_agencia, aa.nombre_agencia,
ap.nombre AS nombre_aprobador ap.nombre AS nombre_aprobador
FROM importador_agencia ia FROM importador_agencia ia
INNER JOIN usuarios_sistema u ON ia.id_importador = u.id_usuario INNER JOIN usuarios_sistema u
INNER JOIN agencias_aduanales aa ON ia.id_agencia = aa.id_agencia ON ia.id_importador = u.id_usuario
LEFT JOIN usuarios_sistema ap ON ia.aprobado_por = ap.id_usuario INNER JOIN agencias_aduanales aa
ON ia.id_agencia = aa.id_agencia
LEFT JOIN usuarios_sistema ap
ON ia.aprobado_por = ap.id_usuario
WHERE ia.id_importador = ? WHERE ia.id_importador = ?
ORDER BY ia.fecha_vinculacion DESC ORDER BY ia.fecha_vinculacion DESC
"; ";
$stmt = sqlsrv_query($conn, $sql, [$id_importador]); $stmt = sqlsrv_query($conn, $sql, [$id_importador]);
if ($stmt === false) { if ($stmt === false) {
@@ -249,7 +258,6 @@ function vinculacionesUsuario()
$row['accion'] = 'Vinculación'; $row['accion'] = 'Vinculación';
$row['fecha'] = $row['fecha_vinculacion']; $row['fecha'] = $row['fecha_vinculacion'];
} }
$registros[] = $row; $registros[] = $row;
} }
@@ -264,13 +272,15 @@ function agencias()
} }
$conn = getConnection(); $conn = getConnection();
$sql = "SELECT ba.*, aa.nombre_agencia, u.nombre $sql = "SELECT ba.*, aa.nombre_agencia, u.nombre
FROM bitacora_agencias ba FROM bitacora_agencias ba
INNER JOIN agencias_aduanales aa INNER JOIN agencias_aduanales aa
ON ba.id_agencia = aa.id_agencia ON ba.id_agencia = aa.id_agencia
INNER JOIN usuarios_sistema u INNER JOIN usuarios_sistema u
ON ba.realizado_por = u.id_usuario ON ba.realizado_por = u.id_usuario
ORDER BY fecha DESC"; ORDER BY fecha DESC
";
$stmt = sqlsrv_query($conn, $sql); $stmt = sqlsrv_query($conn, $sql);
if ($stmt === false) { if ($stmt === false) {
@@ -292,6 +302,7 @@ function miAcceso()
} }
$conn = getConnection(); $conn = getConnection();
$id_usuario = $_SESSION['usuario_id']; $id_usuario = $_SESSION['usuario_id'];
$sql = "SELECT bl.id, bl.id_usuario, bl.email, bl.ip, bl.fecha, bl.exito, bl.detalle, u.nombre $sql = "SELECT bl.id, bl.id_usuario, bl.email, bl.ip, bl.fecha, bl.exito, bl.detalle, u.nombre
@@ -299,7 +310,8 @@ function miAcceso()
INNER JOIN usuarios_sistema u INNER JOIN usuarios_sistema u
ON bl.id_usuario = u.id_usuario ON bl.id_usuario = u.id_usuario
WHERE bl.id_usuario = ? WHERE bl.id_usuario = ?
ORDER BY bl.fecha DESC"; ORDER BY bl.fecha DESC
";
$stmt = sqlsrv_query($conn, $sql, [$id_usuario]); $stmt = sqlsrv_query($conn, $sql, [$id_usuario]);
if ($stmt === false) { if ($stmt === false) {

View File

@@ -3,19 +3,18 @@ require_once __DIR__ . '/../helpers/session.php';
require_once __DIR__ . '/../../config/database.php'; require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../helpers/env.php'; require_once __DIR__ . '/../helpers/env.php';
function lista() { function lista()
{
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login'); header('Location: /IMPORTADORES/login');
exit; exit;
} }
$usr = $_SESSION['usuario_id']; $usr = $_SESSION['usuario_id'];
$conn = getConnection(); $conn = getConnection();
$sql = " $sql = "SELECT
SELECT c.*, (c.nombre + ' ' + c.apellido) AS nombre_completo, (tr.clave_identificador + ' - ' + tr.nombre) AS transportista
c.*,
(c.nombre + ' ' + c.apellido) AS nombre_completo,
(tr.clave_identificador + ' - ' + tr.nombre) AS transportista
FROM dbo.choferes c FROM dbo.choferes c
JOIN dbo.transportistas tr JOIN dbo.transportistas tr
ON c.transportista_id = tr.id_transportista ON c.transportista_id = tr.id_transportista
@@ -24,9 +23,11 @@ function lista() {
ORDER BY c.created_at DESC ORDER BY c.created_at DESC
"; ";
$stmt = sqlsrv_query($conn, $sql, [$usr]); $stmt = sqlsrv_query($conn, $sql, [$usr]);
if ($stmt === false) { if ($stmt === false) {
die("Error en lista(): " . print_r(sqlsrv_errors(), true)); die("Error en lista(): " . print_r(sqlsrv_errors(), true));
} }
$choferes = []; $choferes = [];
while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$choferes[] = $r; $choferes[] = $r;
@@ -35,27 +36,33 @@ function lista() {
include __DIR__ . '/../../views/choferes/lista.php'; include __DIR__ . '/../../views/choferes/lista.php';
} }
function crear() { function crear()
{
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login'); header('Location: /IMPORTADORES/login');
exit; exit;
} }
$usr = $_SESSION['usuario_id']; $usr = $_SESSION['usuario_id'];
$conn = getConnection(); $conn = getConnection();
// OJO: aquí usamos "activo" según tu esquema original // OJO: aquí usamos "activo" según tu esquema original
$sql = " $sql = "SELECT
SELECT t.id_transportista, t.clave_identificador, t.nombre, t.ciudad, t.domicilio, t.id_transportista, t.clave_identificador, t.nombre, t.ciudad, t.domicilio,
c.nombre AS ciudad_nombre c.nombre AS ciudad_nombre
FROM dbo.transportistas t FROM dbo.transportistas t
LEFT JOIN dbo.ciudades c ON t.ciudad = c.id_ciudad LEFT JOIN dbo.ciudades c
WHERE id_usuario = ? AND activo = 1 ON t.ciudad = c.id_ciudad
WHERE id_usuario = ?
AND activo = 1
ORDER BY nombre ORDER BY nombre
"; ";
$stmt = sqlsrv_query($conn, $sql, [$usr]); $stmt = sqlsrv_query($conn, $sql, [$usr]);
if ($stmt === false) { if ($stmt === false) {
die("Error en crear(): " . print_r(sqlsrv_errors(), true)); die("Error en crear(): " . print_r(sqlsrv_errors(), true));
} }
$transportistas = []; $transportistas = [];
while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$transportistas[] = $r; $transportistas[] = $r;
@@ -64,10 +71,12 @@ function crear() {
include __DIR__ . '/../../views/choferes/crear.php'; include __DIR__ . '/../../views/choferes/crear.php';
} }
function guardar() { function guardar()
{
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
die("⚠️ No autorizado."); die("⚠️ No autorizado.");
} }
$transportista_id = $_POST['transportista_id'] ?? null; $transportista_id = $_POST['transportista_id'] ?? null;
$nombre = trim($_POST['nombre'] ?? ''); $nombre = trim($_POST['nombre'] ?? '');
$apellido = trim($_POST['apellido'] ?? ''); $apellido = trim($_POST['apellido'] ?? '');
@@ -87,6 +96,7 @@ function guardar() {
// ✅ CRÍTICO: Verificar que el transportista pertenece al usuario // ✅ CRÍTICO: Verificar que el transportista pertenece al usuario
$sqlVerify = "SELECT id_transportista FROM dbo.transportistas WHERE id_transportista = ? AND id_usuario = ?"; $sqlVerify = "SELECT id_transportista FROM dbo.transportistas WHERE id_transportista = ? AND id_usuario = ?";
$stmtVerify = sqlsrv_query($conn, $sqlVerify, [(int)$transportista_id, $_SESSION['usuario_id']]); $stmtVerify = sqlsrv_query($conn, $sqlVerify, [(int)$transportista_id, $_SESSION['usuario_id']]);
if (!$stmtVerify || !sqlsrv_fetch($stmtVerify)) { if (!$stmtVerify || !sqlsrv_fetch($stmtVerify)) {
die("❌ Transportista no autorizado."); die("❌ Transportista no autorizado.");
} }
@@ -94,6 +104,7 @@ function guardar() {
// ✅ CRÍTICO: Verificar que el número de gafete no existe // ✅ CRÍTICO: Verificar que el número de gafete no existe
$sqlCheckGafete = "SELECT id_chofer FROM dbo.choferes WHERE numero_gafete = ? AND status = 1"; $sqlCheckGafete = "SELECT id_chofer FROM dbo.choferes WHERE numero_gafete = ? AND status = 1";
$stmtCheck = sqlsrv_query($conn, $sqlCheckGafete, [$gafete]); $stmtCheck = sqlsrv_query($conn, $sqlCheckGafete, [$gafete]);
if ($stmtCheck && sqlsrv_fetch($stmtCheck)) { if ($stmtCheck && sqlsrv_fetch($stmtCheck)) {
die("❌ El número de gafete '{$gafete}' ya está en uso. Por favor, use otro número."); die("❌ El número de gafete '{$gafete}' ya está en uso. Por favor, use otro número.");
} }
@@ -125,8 +136,7 @@ function guardar() {
} }
} }
$sql = " $sql = "INSERT INTO dbo.choferes
INSERT INTO dbo.choferes
(transportista_id, nombre, apellido, numero_licencia, numero_gafete, telefono, email, fecha_ingreso, foto_url, status) (transportista_id, nombre, apellido, numero_licencia, numero_gafete, telefono, email, fecha_ingreso, foto_url, status)
VALUES (?, ?, ?, ?, ?, ?, ?, GETDATE(), ?, 1) VALUES (?, ?, ?, ?, ?, ?, ?, GETDATE(), ?, 1)
"; ";
@@ -141,8 +151,8 @@ function guardar() {
$fecha_ingreso, $fecha_ingreso,
$fotoUrl $fotoUrl
]; ];
$stmt = sqlsrv_query($conn, $sql, $params); $stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt === false) { if ($stmt === false) {
$errors = sqlsrv_errors(); $errors = sqlsrv_errors();
// ✅ Manejo específico de error de duplicado // ✅ Manejo específico de error de duplicado
@@ -158,32 +168,39 @@ function guardar() {
exit; exit;
} }
function editar() { function editar()
{
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login'); header('Location: /IMPORTADORES/login');
exit; exit;
} }
$id = $_GET['id'] ?? null; $id = $_GET['id'] ?? null;
if (!$id || !is_numeric($id)) { if (!$id || !is_numeric($id)) {
die("❌ ID inválido."); die("❌ ID inválido.");
} }
$conn = getConnection(); $conn = getConnection();
$sql = " $sql = "SELECT
SELECT
ch.*, tr.clave_identificador, tr.nombre AS transportista_nombre, tr.ciudad, tr.domicilio, ch.*, tr.clave_identificador, tr.nombre AS transportista_nombre, tr.ciudad, tr.domicilio,
ciu.nombre AS ciudad_nombre ciu.nombre AS ciudad_nombre
FROM dbo.choferes ch FROM dbo.choferes ch
LEFT JOIN dbo.transportistas tr ON ch.transportista_id = tr.id_transportista LEFT JOIN dbo.transportistas tr
LEFT JOIN dbo.ciudades ciu ON tr.ciudad = ciu.id_ciudad ON ch.transportista_id = tr.id_transportista
LEFT JOIN dbo.ciudades ciu
ON tr.ciudad = ciu.id_ciudad
WHERE ch.id_chofer = ? WHERE ch.id_chofer = ?
AND tr.id_usuario = ? AND tr.id_usuario = ?
AND ch.status = 1 AND ch.status = 1
"; ";
$stmt = sqlsrv_query($conn, $sql, [(int)$id, $_SESSION['usuario_id']]); $stmt = sqlsrv_query($conn, $sql, [(int)$id, $_SESSION['usuario_id']]);
if ($stmt === false) { if ($stmt === false) {
die("Error en editar(): " . print_r(sqlsrv_errors(), true)); die("Error en editar(): " . print_r(sqlsrv_errors(), true));
} }
$chofer = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); $chofer = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
if (!$chofer) { if (!$chofer) {
die("❌ Chofer no encontrado o no autorizado."); die("❌ Chofer no encontrado o no autorizado.");
@@ -195,18 +212,22 @@ function editar() {
} }
// Lista de transportistas // Lista de transportistas
$sql2 = " $sql2 = "SELECT
SELECT tr.id_transportista, tr.clave_identificador, tr.nombre, tr.domicilio, tr.id_transportista, tr.clave_identificador, tr.nombre, tr.domicilio,
ciu.nombre AS ciudad_nombre ciu.nombre AS ciudad_nombre
FROM dbo.transportistas tr FROM dbo.transportistas tr
LEFT JOIN dbo.ciudades ciu ON tr.ciudad = ciu.id_ciudad LEFT JOIN dbo.ciudades ciu
WHERE tr.id_usuario = ? AND tr.activo = 1 ON tr.ciudad = ciu.id_ciudad
WHERE tr.id_usuario = ?
AND tr.activo = 1
ORDER BY tr.nombre ORDER BY tr.nombre
"; ";
$stmt2 = sqlsrv_query($conn, $sql2, [$_SESSION['usuario_id']]); $stmt2 = sqlsrv_query($conn, $sql2, [$_SESSION['usuario_id']]);
if ($stmt2 === false) { if ($stmt2 === false) {
die("Error en editar() [transportistas]: " . print_r(sqlsrv_errors(), true)); die("Error en editar() [transportistas]: " . print_r(sqlsrv_errors(), true));
} }
$transportistas = []; $transportistas = [];
while ($r = sqlsrv_fetch_array($stmt2, SQLSRV_FETCH_ASSOC)) { while ($r = sqlsrv_fetch_array($stmt2, SQLSRV_FETCH_ASSOC)) {
$transportistas[] = $r; $transportistas[] = $r;
@@ -216,7 +237,8 @@ function editar() {
} }
/** Valida que el número de gafete sea único **/ /** Valida que el número de gafete sea único **/
function validarNumeroGafete() { function validarNumeroGafete()
{
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
http_response_code(403); http_response_code(403);
echo json_encode(['success' => false, 'message' => 'No autorizado']); echo json_encode(['success' => false, 'message' => 'No autorizado']);
@@ -252,7 +274,8 @@ function validarNumeroGafete() {
} }
/** Procesa la actualización de un chofer **/ /** Procesa la actualización de un chofer **/
function actualizar() { function actualizar()
{
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
die("⚠️ No autorizado."); die("⚠️ No autorizado.");
} }
@@ -261,8 +284,8 @@ function actualizar() {
$transportista_id = $_POST['transportista_id'] ?? null; $transportista_id = $_POST['transportista_id'] ?? null;
$nombre = trim($_POST['nombre'] ?? ''); $nombre = trim($_POST['nombre'] ?? '');
$apellido = trim($_POST['apellido'] ?? ''); $apellido = trim($_POST['apellido'] ?? '');
$licencia = trim($_POST['numero_licencia']?? ''); $licencia = trim($_POST['numero_licencia'] ?? '');
$gafete = trim($_POST['numero_gafete']?? ''); $gafete = trim($_POST['numero_gafete'] ?? '');
$telefono = trim($_POST['telefono'] ?? ''); $telefono = trim($_POST['telefono'] ?? '');
$email = trim($_POST['email'] ?? ''); $email = trim($_POST['email'] ?? '');
$fecha_ingreso = $_POST['fecha_ingreso'] ?: null; $fecha_ingreso = $_POST['fecha_ingreso'] ?: null;
@@ -282,6 +305,7 @@ function actualizar() {
// ✅ CRÍTICO: Verificar que el número de gafete no existe (excluyendo el chofer actual) // ✅ CRÍTICO: Verificar que el número de gafete no existe (excluyendo el chofer actual)
$sqlCheckGafete = "SELECT id_chofer FROM dbo.choferes WHERE numero_gafete = ? AND id_chofer <> ? AND status = 1"; $sqlCheckGafete = "SELECT id_chofer FROM dbo.choferes WHERE numero_gafete = ? AND id_chofer <> ? AND status = 1";
$stmtCheck = sqlsrv_query($conn, $sqlCheckGafete, [$gafete, $id_chofer]); $stmtCheck = sqlsrv_query($conn, $sqlCheckGafete, [$gafete, $id_chofer]);
if ($stmtCheck && sqlsrv_fetch($stmtCheck)) { if ($stmtCheck && sqlsrv_fetch($stmtCheck)) {
die("❌ El número de gafete '{$gafete}' ya está en uso. Por favor, use otro número."); die("❌ El número de gafete '{$gafete}' ya está en uso. Por favor, use otro número.");
} }
@@ -314,8 +338,7 @@ function actualizar() {
} }
if ($fotoUrl) { if ($fotoUrl) {
$sql = " $sql = "UPDATE dbo.choferes SET
UPDATE dbo.choferes SET
transportista_id = ?, transportista_id = ?,
nombre = ?, nombre = ?,
apellido = ?, apellido = ?,
@@ -343,8 +366,7 @@ function actualizar() {
(int)$id (int)$id
]; ];
} else { } else {
$sql = " $sql = "UPDATE dbo.choferes SET
UPDATE dbo.choferes SET
transportista_id = ?, transportista_id = ?,
nombre = ?, nombre = ?,
apellido = ?, apellido = ?,
@@ -370,8 +392,8 @@ function actualizar() {
(int)$id (int)$id
]; ];
} }
$stmt = sqlsrv_query($conn, $sql, $params); $stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt === false) { if ($stmt === false) {
$errors = sqlsrv_errors(); $errors = sqlsrv_errors();
// ✅ Manejo específico de error de duplicado // ✅ Manejo específico de error de duplicado
@@ -388,25 +410,28 @@ function actualizar() {
} }
/** “Soft-delete” (status = 0) de un chofer **/ /** “Soft-delete” (status = 0) de un chofer **/
function eliminar() { function eliminar()
{
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login'); header('Location: /IMPORTADORES/login');
exit; exit;
} }
$id = $_GET['id'] ?? null; $id = $_GET['id'] ?? null;
if (!$id || !is_numeric($id)) { if (!$id || !is_numeric($id)) {
die("❌ ID inválido."); die("❌ ID inválido.");
} }
$conn = getConnection(); $conn = getConnection();
$sql = "
UPDATE dbo.choferes $sql = "UPDATE dbo.choferes
SET status = 0, SET status = 0,
updated_at = GETDATE() updated_at = GETDATE()
WHERE id_chofer = ? WHERE id_chofer = ?
"; ";
$stmt = sqlsrv_query($conn, $sql, [(int)$id]); $stmt = sqlsrv_query($conn, $sql, [(int)$id]);
if ($stmt === false) { if ($stmt === false) {
die("❌ Error en eliminar(): " . print_r(sqlsrv_errors(), true)); die("❌ Error en eliminar(): " . print_r(sqlsrv_errors(), true));
} }

View File

@@ -6,6 +6,7 @@ require_once __DIR__ . '/../helpers/crypto.php';
function index() function index()
{ {
$conn = getConnection(); $conn = getConnection();
$id_usuario = $_SESSION['usuario_id'] ?? null; $id_usuario = $_SESSION['usuario_id'] ?? null;
if (!$id_usuario) { if (!$id_usuario) {
@@ -48,15 +49,17 @@ function index()
case 'admin_agencia': case 'admin_agencia':
case 'agente_aduanal': case 'agente_aduanal':
$sql_agencia = " $sql_agencia = "SELECT
SELECT aa.id_agencia, aa.nombre_agencia, aa.rfc_agencia, aa.id_agencia, aa.nombre_agencia, aa.rfc_agencia,
aa.direccion AS direccion_agencia, aa.telefono AS telefono_agencia, aa.direccion AS direccion_agencia, aa.telefono AS telefono_agencia,
aa.email AS email_agencia, aga.fecha_asignacion aa.email AS email_agencia, aga.fecha_asignacion
FROM agente_agencia aga FROM agente_agencia aga
INNER JOIN agencias_aduanales aa ON aga.id_agencia = aa.id_agencia INNER JOIN agencias_aduanales aa
WHERE aga.id_agente = ? AND aga.activo = 1 AND aa.activo = 1 ON aga.id_agencia = aa.id_agencia
WHERE aga.id_agente = ?
AND aga.activo = 1
AND aa.activo = 1
"; ";
$stmt_agencia = sqlsrv_query($conn, $sql_agencia, [$id_usuario]); $stmt_agencia = sqlsrv_query($conn, $sql_agencia, [$id_usuario]);
if ($stmt_agencia !== false) { if ($stmt_agencia !== false) {
@@ -89,6 +92,7 @@ function index()
function editar() function editar()
{ {
$conn = getConnection(); $conn = getConnection();
$id_usuario = $_SESSION['usuario_id'] ?? null; $id_usuario = $_SESSION['usuario_id'] ?? null;
if (!$id_usuario) { if (!$id_usuario) {
@@ -112,6 +116,7 @@ function editar()
function guardar() function guardar()
{ {
$conn = getConnection(); $conn = getConnection();
$id_usuario = $_SESSION['usuario_id'] ?? null; $id_usuario = $_SESSION['usuario_id'] ?? null;
if (!$id_usuario) { if (!$id_usuario) {
@@ -146,8 +151,8 @@ function guardar()
// 1. Actualiza la tabla informacion_general // 1. Actualiza la tabla informacion_general
$sql = "UPDATE informacion_general SET " . implode(", ", $sql_parts) . " WHERE id_usuario = ?"; $sql = "UPDATE informacion_general SET " . implode(", ", $sql_parts) . " WHERE id_usuario = ?";
$params[] = $id_usuario; $params[] = $id_usuario;
$stmt = sqlsrv_query($conn, $sql, $params); $stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt === false) { if ($stmt === false) {
throw new Exception(print_r(sqlsrv_errors(), true)); throw new Exception(print_r(sqlsrv_errors(), true));
} }
@@ -176,7 +181,6 @@ function guardar()
// Actualizar solicitudes_importadores usando el company_name encriptado // Actualizar solicitudes_importadores usando el company_name encriptado
$sql_solicitud = "UPDATE solicitudes_importadores SET phone = ? WHERE company_name = ?"; $sql_solicitud = "UPDATE solicitudes_importadores SET phone = ? WHERE company_name = ?";
$params_solicitud = [$telefono, $nombre_encriptado]; $params_solicitud = [$telefono, $nombre_encriptado];
$stmt_solicitud = sqlsrv_query($conn, $sql_solicitud, $params_solicitud); $stmt_solicitud = sqlsrv_query($conn, $sql_solicitud, $params_solicitud);
if ($stmt_solicitud === false) { if ($stmt_solicitud === false) {
@@ -198,7 +202,6 @@ function guardar()
if ($rfc_data && !empty($rfc_data['rfc'])) { if ($rfc_data && !empty($rfc_data['rfc'])) {
$sql_solicitud_rfc = "UPDATE solicitudes_importadores SET phone = ? WHERE rfc = ?"; $sql_solicitud_rfc = "UPDATE solicitudes_importadores SET phone = ? WHERE rfc = ?";
$params_solicitud_rfc = [$telefono, $rfc_data['rfc']]; $params_solicitud_rfc = [$telefono, $rfc_data['rfc']];
$stmt_solicitud_rfc = sqlsrv_query($conn, $sql_solicitud_rfc, $params_solicitud_rfc); $stmt_solicitud_rfc = sqlsrv_query($conn, $sql_solicitud_rfc, $params_solicitud_rfc);
if ($stmt_solicitud_rfc === false) { if ($stmt_solicitud_rfc === false) {

View File

@@ -4,33 +4,33 @@ require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../helpers/env.php'; require_once __DIR__ . '/../helpers/env.php';
// Mostrar tabla de expedientes // Mostrar tabla de expedientes
function index() { function index()
{
if (!isset($_SESSION['usuario_id'])) { if (!isset($_SESSION['usuario_id'])) {
header('Location: /IMPORTADORES/login'); header('Location: /IMPORTADORES/login');
exit; exit;
} }
$conn = getConnection(); $conn = getConnection();
$id_importador = $_SESSION['usuario_id']; $id_importador = $_SESSION['usuario_id'];
$sql = " $sql = "SELECT
SELECT sif.id_solicitud, sif.numero_pedimento, sif.fecha_factura, sif.aduana, sif.proveedor_clave,
sif.id_solicitud,
sif.numero_pedimento,
sif.fecha_factura,
sif.aduana,
sif.proveedor_clave,
COUNT(ea.id) AS total_archivos, COUNT(ea.id) AS total_archivos,
ISNULL(SUM(ea.tamano_archivo), 0) AS total_tamano ISNULL(SUM(ea.tamano_archivo), 0) AS total_tamano
FROM solicitud_importacion_factura sif FROM solicitud_importacion_factura sif
LEFT JOIN expediente_archivos ea ON ea.id_solicitud = sif.id_solicitud LEFT JOIN expediente_archivos ea
WHERE sif.numero_pedimento IS NOT NULL AND sif.id_importador = ? and sif.status > 0 ON ea.id_solicitud = sif.id_solicitud
WHERE sif.numero_pedimento IS NOT NULL
AND sif.id_importador = ?
AND sif.status > 0
GROUP BY sif.id_solicitud, sif.numero_pedimento, sif.fecha_factura, sif.aduana, sif.proveedor_clave GROUP BY sif.id_solicitud, sif.numero_pedimento, sif.fecha_factura, sif.aduana, sif.proveedor_clave
ORDER BY sif.fecha_factura DESC ORDER BY sif.fecha_factura DESC
"; ";
$stmt = sqlsrv_query($conn, $sql, [$id_importador]); $stmt = sqlsrv_query($conn, $sql, [$id_importador]);
$expedientes = [];
$expedientes = [];
if ($stmt) { if ($stmt) {
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$expedientes[] = $row; $expedientes[] = $row;
@@ -40,16 +40,19 @@ function index() {
include __DIR__ . '/../../views/expediente/index.php'; include __DIR__ . '/../../views/expediente/index.php';
} }
function subir($id_solicitud) { function subir($id_solicitud)
{
include __DIR__ . '/../../views/expediente/subir.php'; include __DIR__ . '/../../views/expediente/subir.php';
} }
function subir_handler() { function subir_handler()
{
if (!isset($_POST['id_solicitud']) || !isset($_FILES['archivos']) || !isset($_SESSION['usuario_id'])) { if (!isset($_POST['id_solicitud']) || !isset($_FILES['archivos']) || !isset($_SESSION['usuario_id'])) {
die("❌ Solicitud inválida."); die("❌ Solicitud inválida.");
} }
$conn = getConnection(); $conn = getConnection();
$id_solicitud = (int) $_POST['id_solicitud']; $id_solicitud = (int) $_POST['id_solicitud'];
$id_importador = $_SESSION['usuario_id']; $id_importador = $_SESSION['usuario_id'];
@@ -80,9 +83,10 @@ function subir_handler() {
$tamanoKb = round(filesize($rutaFinal) / 1024, 2); $tamanoKb = round(filesize($rutaFinal) / 1024, 2);
$tipoArchivo = mime_content_type($rutaFinal); $tipoArchivo = mime_content_type($rutaFinal);
$sql = "INSERT INTO expediente_archivos (id_solicitud, nombre_archivo, ruta_archivo, tipo_archivo, tamano_archivo, creado_por) $sql = "INSERT INTO expediente_archivos
VALUES (?, ?, ?, ?, ?, ?)"; (id_solicitud, nombre_archivo, ruta_archivo, tipo_archivo, tamano_archivo, creado_por)
VALUES (?, ?, ?, ?, ?, ?)
";
$params = [$id_solicitud, $nombreOriginal, $rutaDb, $tipoArchivo, $tamanoKb, $usuario]; $params = [$id_solicitud, $nombreOriginal, $rutaDb, $tipoArchivo, $tamanoKb, $usuario];
sqlsrv_query($conn, $sql, $params); sqlsrv_query($conn, $sql, $params);
} }
@@ -99,12 +103,13 @@ function ver($id_solicitud)
} }
$conn = getConnection(); $conn = getConnection();
$id_importador = $_SESSION['usuario_id']; $id_importador = $_SESSION['usuario_id'];
$archivos = [];
$sql = "SELECT * FROM expediente_archivos WHERE id_solicitud = ? AND id_solicitud IN (SELECT id_solicitud FROM solicitud_importacion_factura WHERE id_importador = ?) ORDER BY creado_en DESC"; $sql = "SELECT * FROM expediente_archivos WHERE id_solicitud = ? AND id_solicitud IN (SELECT id_solicitud FROM solicitud_importacion_factura WHERE id_importador = ?) ORDER BY creado_en DESC";
$stmt = sqlsrv_query($conn, $sql, [$id_solicitud, $id_importador]); $stmt = sqlsrv_query($conn, $sql, [$id_solicitud, $id_importador]);
$archivos = [];
if ($stmt) { if ($stmt) {
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
if (is_string($row['creado_en'])) { if (is_string($row['creado_en'])) {
@@ -117,13 +122,15 @@ function ver($id_solicitud)
include __DIR__ . '/../../views/expediente/ver.php'; include __DIR__ . '/../../views/expediente/ver.php';
} }
function ver_archivo($id_archivo) { function ver_archivo($id_archivo)
{
if (!isset($_SESSION['usuario_id'])) { if (!isset($_SESSION['usuario_id'])) {
header('Location: /IMPORTADORES/login'); header('Location: /IMPORTADORES/login');
exit; exit;
} }
$conn = getConnection(); $conn = getConnection();
$sql = "SELECT ea.*, sif.id_importador FROM expediente_archivos ea JOIN solicitud_importacion_factura sif ON sif.id_solicitud = ea.id_solicitud WHERE ea.id = ?"; $sql = "SELECT ea.*, sif.id_importador FROM expediente_archivos ea JOIN solicitud_importacion_factura sif ON sif.id_solicitud = ea.id_solicitud WHERE ea.id = ?";
$stmt = sqlsrv_query($conn, $sql, [$id_archivo]); $stmt = sqlsrv_query($conn, $sql, [$id_archivo]);
$archivo = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); $archivo = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
@@ -160,16 +167,19 @@ function descargar_zip($id_solicitud)
} }
$conn = getConnection(); $conn = getConnection();
$id_importador = $_SESSION['usuario_id']; $id_importador = $_SESSION['usuario_id'];
$sql = " $sql = "SELECT
SELECT ea.nombre_archivo, ea.ruta_archivo ea.nombre_archivo, ea.ruta_archivo
FROM expediente_archivos ea FROM expediente_archivos ea
JOIN solicitud_importacion_factura sif ON sif.id_solicitud = ea.id_solicitud JOIN solicitud_importacion_factura sif
WHERE ea.id_solicitud = ? AND sif.id_importador = ? ON sif.id_solicitud = ea.id_solicitud
WHERE ea.id_solicitud = ?
AND sif.id_importador = ?
"; ";
$stmt = sqlsrv_query($conn, $sql, [$id_solicitud, $id_importador]); $stmt = sqlsrv_query($conn, $sql, [$id_solicitud, $id_importador]);
if (!$stmt) { if (!$stmt) {
http_response_code(500); http_response_code(500);
echo "Error al consultar archivos."; echo "Error al consultar archivos.";

View File

@@ -4,7 +4,8 @@ require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../helpers/crypto.php'; require_once __DIR__ . '/../helpers/crypto.php';
// Función para obtener catálogos visibles del usuario // Función para obtener catálogos visibles del usuario
function obtenerCatalogosVisibles($idUsuario) { function obtenerCatalogosVisibles($idUsuario)
{
$conn = getConnection(); $conn = getConnection();
// Obtener configuración general y tipo de usuario // Obtener configuración general y tipo de usuario
@@ -132,7 +133,8 @@ function obtenerCatalogosVisibles($idUsuario) {
} }
// Función para obtener icono según el nombre del catálogo // Función para obtener icono según el nombre del catálogo
function obtenerIconoCatalogo($nombre) { function obtenerIconoCatalogo($nombre)
{
$iconos = [ $iconos = [
'Locaciones' => '📍', 'Locaciones' => '📍',
'Vinculación' => '🔗', 'Vinculación' => '🔗',
@@ -169,21 +171,22 @@ function dashboard()
function lista() function lista()
{ {
$conn = getConnection(); $conn = getConnection();
$locaciones = [];
// Consulta conjunta para evitar múltiples queries anidadas // Consulta conjunta para evitar múltiples queries anidadas
$sql = " $sql = "SELECT
SELECT
p.id_pais, p.nombre AS nombre_pais, p.iso2, p.iso3, p.id_pais, p.nombre AS nombre_pais, p.iso2, p.iso3,
e.id_estado, e.nombre AS nombre_estado, e.abreviatura, e.id_estado, e.nombre AS nombre_estado, e.abreviatura,
c.id_ciudad, c.nombre AS nombre_ciudad c.id_ciudad, c.nombre AS nombre_ciudad
FROM paises p FROM paises p
LEFT JOIN estados e ON p.id_pais = e.pais_id LEFT JOIN estados e
LEFT JOIN ciudades c ON e.id_estado = c.estado_id ON p.id_pais = e.pais_id
LEFT JOIN ciudades c
ON e.id_estado = c.estado_id
ORDER BY p.id_pais, e.id_estado, c.id_ciudad ORDER BY p.id_pais, e.id_estado, c.id_ciudad
"; ";
$stmt = sqlsrv_query($conn, $sql); $stmt = sqlsrv_query($conn, $sql);
$locaciones = [];
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$locaciones[] = $row; $locaciones[] = $row;
} }
@@ -191,6 +194,7 @@ function lista()
// Obtener países para los selects del modal // Obtener países para los selects del modal
$sql_paises_select = "SELECT id_pais, nombre FROM paises ORDER BY nombre"; $sql_paises_select = "SELECT id_pais, nombre FROM paises ORDER BY nombre";
$stmt_paises_select = sqlsrv_query($conn, $sql_paises_select); $stmt_paises_select = sqlsrv_query($conn, $sql_paises_select);
$paises = []; $paises = [];
while ($row = sqlsrv_fetch_array($stmt_paises_select, SQLSRV_FETCH_ASSOC)) { while ($row = sqlsrv_fetch_array($stmt_paises_select, SQLSRV_FETCH_ASSOC)) {
$paises[] = $row; $paises[] = $row;
@@ -225,7 +229,10 @@ function vincular()
} }
// Insertar la nueva solicitud // Insertar la nueva solicitud
$sql = "INSERT INTO solicitudes_vinculacion (id_importador, id_agencia, mensaje, estado, fecha_solicitud) VALUES (?, ?, 'Solicitud de vinculación', 'PENDIENTE', GETDATE())"; $sql = "INSERT INTO solicitudes_vinculacion
(id_importador, id_agencia, mensaje, estado, fecha_solicitud)
VALUES (?, ?, 'Solicitud de vinculación', 'PENDIENTE', GETDATE())
";
$params = [$id_importador, $id_agencia]; $params = [$id_importador, $id_agencia];
$stmt = sqlsrv_prepare($conn, $sql, $params); $stmt = sqlsrv_prepare($conn, $sql, $params);
@@ -252,8 +259,10 @@ function cancelarVinculacion()
$sql = "UPDATE solicitudes_vinculacion $sql = "UPDATE solicitudes_vinculacion
SET estado = 'CANCELADA', fecha_respuesta = GETDATE() SET estado = 'CANCELADA', fecha_respuesta = GETDATE()
WHERE id_importador = ? AND id_agencia = ? AND estado = 'PENDIENTE'"; WHERE id_importador = ?
AND id_agencia = ?
AND estado = 'PENDIENTE'
";
$params = [$id_importador, $id_agencia]; $params = [$id_importador, $id_agencia];
$stmt = sqlsrv_prepare($conn, $sql, $params); $stmt = sqlsrv_prepare($conn, $sql, $params);
@@ -284,14 +293,15 @@ function desvincularUsuario()
sqlsrv_begin_transaction($conn); sqlsrv_begin_transaction($conn);
// 1. Verificar que la relación existe y pertenece a la agencia del admin // 1. Verificar que la relación existe y pertenece a la agencia del admin
$sqlVerificar = " $sqlVerificar = "SELECT
SELECT ia.*, u.id_usuario, u.nombre as importador_nombre, aa.nombre_agencia
ia.*,
u.id_usuario, u.nombre as importador_nombre, aa.nombre_agencia
FROM importador_agencia ia FROM importador_agencia ia
INNER JOIN usuarios_sistema u ON ia.id_importador = u.id_usuario INNER JOIN usuarios_sistema u
INNER JOIN agencias_aduanales aa ON ia.id_agencia = aa.id_agencia ON ia.id_importador = u.id_usuario
WHERE ia.id_relacion = ? AND ia.id_importador = ? INNER JOIN agencias_aduanales aa
ON ia.id_agencia = aa.id_agencia
WHERE ia.id_relacion = ?
AND ia.id_importador = ?
"; ";
$stmtVerificar = sqlsrv_query($conn, $sqlVerificar, [$id_relacion, $_SESSION['usuario_id']]); $stmtVerificar = sqlsrv_query($conn, $sqlVerificar, [$id_relacion, $_SESSION['usuario_id']]);
@@ -313,14 +323,13 @@ function desvincularUsuario()
} }
// 2. Desactivar la relación (no eliminar, mantener historial) // 2. Desactivar la relación (no eliminar, mantener historial)
$sqlDesactivar = " $sqlDesactivar = "UPDATE importador_agencia
UPDATE importador_agencia
SET activo = 0, SET activo = 0,
fecha_desvinculacion = GETDATE(), fecha_desvinculacion = GETDATE(),
estado = 'DESVINCULADO' estado = 'DESVINCULADO'
WHERE id_relacion = ? AND id_importador = ? WHERE id_relacion = ?
AND id_importador = ?
"; ";
$stmtDesactivar = sqlsrv_query($conn, $sqlDesactivar, [$id_relacion, $_SESSION['usuario_id']]); $stmtDesactivar = sqlsrv_query($conn, $sqlDesactivar, [$id_relacion, $_SESSION['usuario_id']]);
if ($stmtDesactivar === false) { if ($stmtDesactivar === false) {
@@ -337,11 +346,7 @@ function desvincularUsuario()
// 3. Actualizar el campo id_agencia_en_uso del usuario si es necesario // 3. Actualizar el campo id_agencia_en_uso del usuario si es necesario
if ($_SESSION['id_agencia_en_uso'] == $relacion['id_agencia']) { if ($_SESSION['id_agencia_en_uso'] == $relacion['id_agencia']) {
$sqlActualizarAgencia = " $sqlActualizarAgencia = "UPDATE usuarios_sistema SET id_agencia_en_uso = NULL WHERE id_usuario = ?";
UPDATE usuarios_sistema
SET id_agencia_en_uso = NULL
WHERE id_usuario = ?
";
$stmtActualizarAgencia = sqlsrv_query($conn, $sqlActualizarAgencia, [$_SESSION['usuario_id']]); $stmtActualizarAgencia = sqlsrv_query($conn, $sqlActualizarAgencia, [$_SESSION['usuario_id']]);
if ($stmtActualizarAgencia === false) { if ($stmtActualizarAgencia === false) {
@@ -392,11 +397,7 @@ function cambiarAgenciaActiva()
$conn = getConnection(); $conn = getConnection();
// Validar que el importador está vinculado a esta agencia // Validar que el importador está vinculado a esta agencia
$sqlVerificacion = " $sqlVerificacion = "SELECT 1 FROM importador_agencia WHERE id_importador = ? AND id_agencia = ? AND activo = 1";
SELECT 1
FROM importador_agencia
WHERE id_importador = ? AND id_agencia = ? AND activo = 1
";
$stmtVerificacion = sqlsrv_query($conn, $sqlVerificacion, [$id_usuario, $id_agencia]); $stmtVerificacion = sqlsrv_query($conn, $sqlVerificacion, [$id_usuario, $id_agencia]);
if ($stmtVerificacion === false || !sqlsrv_fetch($stmtVerificacion)) { if ($stmtVerificacion === false || !sqlsrv_fetch($stmtVerificacion)) {
@@ -405,11 +406,7 @@ function cambiarAgenciaActiva()
} }
// Actualizar campo id_agencia_en_uso // Actualizar campo id_agencia_en_uso
$sqlUpdate = " $sqlUpdate = "UPDATE usuarios_sistema SET id_agencia_en_uso = ? WHERE id_usuario = ?";
UPDATE usuarios_sistema
SET id_agencia_en_uso = ?
WHERE id_usuario = ?
";
$stmtUpdate = sqlsrv_query($conn, $sqlUpdate, [$id_agencia, $id_usuario]); $stmtUpdate = sqlsrv_query($conn, $sqlUpdate, [$id_agencia, $id_usuario]);
if ($stmtUpdate === false) { if ($stmtUpdate === false) {

View File

@@ -1,6 +1,5 @@
<?php <?php
require_once __DIR__ . '/../../vendor/autoload.php'; require_once __DIR__ . '/../../vendor/autoload.php';
require_once __DIR__ . '/../helpers/session.php'; require_once __DIR__ . '/../helpers/session.php';
require_once __DIR__ . '/../../config/database.php'; require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../helpers/crypto.php'; require_once __DIR__ . '/../helpers/crypto.php';
@@ -10,20 +9,19 @@ require_once __DIR__ . '/../helpers/env.php';
function lista() function lista()
{ {
$conn = getConnection(); $conn = getConnection();
$locaciones = [];
// CONSULTA CORREGIDA - Agregamos abreviatura e iso2 // CONSULTA CORREGIDA - Agregamos abreviatura e iso2
$sql = " $sql = "SELECT
SELECT
p.id_pais, p.nombre AS nombre_pais, p.iso2, p.iso3, p.id_pais, p.nombre AS nombre_pais, p.iso2, p.iso3,
e.id_estado, e.nombre AS nombre_estado, e.abreviatura, e.id_estado, e.nombre AS nombre_estado, e.abreviatura,
c.id_ciudad, c.nombre AS nombre_ciudad c.id_ciudad, c.nombre AS nombre_ciudad
FROM paises p FROM paises p
LEFT JOIN estados e ON p.id_pais = e.pais_id LEFT JOIN estados e
LEFT JOIN ciudades c ON e.id_estado = c.estado_id ON p.id_pais = e.pais_id
LEFT JOIN ciudades c
ON e.id_estado = c.estado_id
ORDER BY p.id_pais, e.id_estado, c.id_ciudad ORDER BY p.id_pais, e.id_estado, c.id_ciudad
"; ";
$stmt = sqlsrv_query($conn, $sql); $stmt = sqlsrv_query($conn, $sql);
if (!$stmt) { if (!$stmt) {
@@ -32,6 +30,7 @@ function lista()
die("Error en la consulta"); die("Error en la consulta");
} }
$locaciones = [];
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$locaciones[] = $row; $locaciones[] = $row;
} }
@@ -39,6 +38,7 @@ function lista()
// Obtener países para los selects del modal // Obtener países para los selects del modal
$sql_paises_select = "SELECT id_pais, nombre FROM paises ORDER BY nombre"; $sql_paises_select = "SELECT id_pais, nombre FROM paises ORDER BY nombre";
$stmt_paises_select = sqlsrv_query($conn, $sql_paises_select); $stmt_paises_select = sqlsrv_query($conn, $sql_paises_select);
$paises = []; $paises = [];
while ($row = sqlsrv_fetch_array($stmt_paises_select, SQLSRV_FETCH_ASSOC)) { while ($row = sqlsrv_fetch_array($stmt_paises_select, SQLSRV_FETCH_ASSOC)) {
$paises[] = $row; $paises[] = $row;
@@ -50,9 +50,11 @@ function lista()
function alta() function alta()
{ {
$conn = getConnection(); $conn = getConnection();
// 1) Cargar países // 1) Cargar países
$sql = "SELECT id_pais, nombre FROM paises ORDER BY nombre"; $sql = "SELECT id_pais, nombre FROM paises ORDER BY nombre";
$stmt = sqlsrv_query($conn, $sql); $stmt = sqlsrv_query($conn, $sql);
$paises = []; $paises = [];
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$paises[] = $row; $paises[] = $row;
@@ -65,14 +67,18 @@ function alta()
function estados() function estados()
{ {
header('Content-Type: application/json; charset=utf-8'); header('Content-Type: application/json; charset=utf-8');
$pais = $_GET['pais'] ?? '';
$conn = getConnection(); $conn = getConnection();
$pais = $_GET['pais'] ?? '';
$sql = "SELECT id_estado, nombre FROM estados WHERE pais_id = ? ORDER BY nombre"; $sql = "SELECT id_estado, nombre FROM estados WHERE pais_id = ? ORDER BY nombre";
$stmt = sqlsrv_query($conn, $sql, [$pais]); $stmt = sqlsrv_query($conn, $sql, [$pais]);
$out = []; $out = [];
while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$out[] = $r; $out[] = $r;
} }
echo json_encode($out); echo json_encode($out);
exit; exit;
} }
@@ -83,15 +89,9 @@ function guardarEstado()
header('Content-Type: application/json; charset=utf-8'); header('Content-Type: application/json; charset=utf-8');
try { try {
// Debug: Verificar qué se está recibiendo
error_log("POST data: " . print_r($_POST, true));
$pais_id = $_POST['pais'] ?? ''; $pais_id = $_POST['pais'] ?? '';
$entidad = trim($_POST['entidad'] ?? ''); $entidad = trim($_POST['entidad'] ?? '');
// Debug: Verificar valores específicos
error_log("pais_id: '$pais_id', entidad: '$entidad'");
// Validaciones más específicas // Validaciones más específicas
if (empty($pais_id)) { if (empty($pais_id)) {
echo json_encode(['success' => false, 'message' => 'Debe seleccionar un país']); echo json_encode(['success' => false, 'message' => 'Debe seleccionar un país']);
@@ -211,6 +211,7 @@ function obtenerPaisPorEstado()
} }
$conn = getConnection(); $conn = getConnection();
$sql = "SELECT pais_id FROM estados WHERE id_estado = ?"; $sql = "SELECT pais_id FROM estados WHERE id_estado = ?";
$stmt = sqlsrv_query($conn, $sql, [$estado_id]); $stmt = sqlsrv_query($conn, $sql, [$estado_id]);
@@ -270,6 +271,7 @@ function actualizarPais()
} }
$conn = getConnection(); $conn = getConnection();
if (!$conn) { if (!$conn) {
echo json_encode(['success' => false, 'message' => 'Error de conexión a la base de datos']); echo json_encode(['success' => false, 'message' => 'Error de conexión a la base de datos']);
exit; exit;
@@ -296,7 +298,6 @@ function actualizarPais()
$sql = "UPDATE paises SET nombre = ?, iso2 = ?, iso3 = ? WHERE id_pais = ?"; $sql = "UPDATE paises SET nombre = ?, iso2 = ?, iso3 = ? WHERE id_pais = ?";
$params = [$nombre, $iso2_val, $iso3_val, $id]; $params = [$nombre, $iso2_val, $iso3_val, $id];
$stmt = sqlsrv_query($conn, $sql, $params); $stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt && sqlsrv_rows_affected($stmt) > 0) { if ($stmt && sqlsrv_rows_affected($stmt) > 0) {
@@ -329,6 +330,7 @@ function actualizarEstado()
} }
$conn = getConnection(); $conn = getConnection();
if (!$conn) { if (!$conn) {
echo json_encode(['success' => false, 'message' => 'Error de conexión a la base de datos']); echo json_encode(['success' => false, 'message' => 'Error de conexión a la base de datos']);
exit; exit;
@@ -354,7 +356,6 @@ function actualizarEstado()
$sql = "UPDATE estados SET nombre = ?, abreviatura = ?, pais_id = ? WHERE id_estado = ?"; $sql = "UPDATE estados SET nombre = ?, abreviatura = ?, pais_id = ? WHERE id_estado = ?";
$params = [$nombre, $abreviatura_val, $pais_id, $id]; $params = [$nombre, $abreviatura_val, $pais_id, $id];
$stmt = sqlsrv_query($conn, $sql, $params); $stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt && sqlsrv_rows_affected($stmt) > 0) { if ($stmt && sqlsrv_rows_affected($stmt) > 0) {
@@ -386,6 +387,7 @@ function actualizarCiudad()
} }
$conn = getConnection(); $conn = getConnection();
if (!$conn) { if (!$conn) {
echo json_encode(['success' => false, 'message' => 'Error de conexión a la base de datos']); echo json_encode(['success' => false, 'message' => 'Error de conexión a la base de datos']);
exit; exit;
@@ -409,7 +411,6 @@ function actualizarCiudad()
// Actualizar // Actualizar
$sql = "UPDATE ciudades SET nombre = ?, estado_id = ? WHERE id_ciudad = ?"; $sql = "UPDATE ciudades SET nombre = ?, estado_id = ? WHERE id_ciudad = ?";
$params = [$nombre, $estado_id, $id]; $params = [$nombre, $estado_id, $id];
$stmt = sqlsrv_query($conn, $sql, $params); $stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt && sqlsrv_rows_affected($stmt) > 0) { if ($stmt && sqlsrv_rows_affected($stmt) > 0) {

View File

@@ -4,8 +4,8 @@ require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../helpers/crypto.php'; require_once __DIR__ . '/../helpers/crypto.php';
require_once __DIR__ . '/../helpers/bitacoras.php'; require_once __DIR__ . '/../helpers/bitacoras.php';
require_once __DIR__ . '/../helpers/env.php'; require_once __DIR__ . '/../helpers/env.php';
require_once __DIR__ . '/../../vendor/autoload.php'; require_once __DIR__ . '/../../vendor/autoload.php';
use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception; use PHPMailer\PHPMailer\Exception;
@@ -33,9 +33,7 @@ function validar()
$emailEncrypted = encrypt($email); $emailEncrypted = encrypt($email);
// Obtenemos el usuario incluyendo el campo dos_factores // Obtenemos el usuario incluyendo el campo dos_factores
$sql = "SELECT id_usuario, nombre, email, password_hash, tipo_usuario, activo, dos_factores $sql = "SELECT id_usuario, nombre, email, password_hash, tipo_usuario, activo, dos_factores FROM usuarios_sistema WHERE email = ?";
FROM usuarios_sistema WHERE email = ?";
$stmt = sqlsrv_query($conn, $sql, [$emailEncrypted]); $stmt = sqlsrv_query($conn, $sql, [$emailEncrypted]);
if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
@@ -225,9 +223,7 @@ function confirmarAcceso()
exit; exit;
} }
$sql = "SELECT codigo, expiracion FROM verificaciones $sql = "SELECT codigo, expiracion FROM verificaciones WHERE id_usuario = ? AND codigo = ? ORDER BY id DESC";
WHERE id_usuario = ? AND codigo = ?
ORDER BY id DESC";
$stmt = sqlsrv_query($conn, $sql, [$usuarioId, $codigoIngresado]); $stmt = sqlsrv_query($conn, $sql, [$usuarioId, $codigoIngresado]);
if (!$stmt || !($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC))) { if (!$stmt || !($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC))) {
@@ -282,7 +278,9 @@ function recuperar()
function enviarCodigo() function enviarCodigo()
{ {
header('Content-Type: application/json'); header('Content-Type: application/json');
$conn = getConnection(); $conn = getConnection();
if (!$conn) { if (!$conn) {
echo json_encode(['success' => false, 'message' => '❌ Error de conexión con la base de datos.']); echo json_encode(['success' => false, 'message' => '❌ Error de conexión con la base de datos.']);
exit; exit;
@@ -314,8 +312,7 @@ function enviarCodigo()
} }
$now = (new DateTime())->format('Y-m-d H:i:s'); $now = (new DateTime())->format('Y-m-d H:i:s');
$sqlCheck = "SELECT COUNT(*) AS total FROM recuperacion_password $sqlCheck = "SELECT COUNT(*) AS total FROM recuperacion_password WHERE email = ? AND estatus = 0 AND expiracion > ?";
WHERE email = ? AND estatus = 0 AND expiracion > ?";
$checkStmt = sqlsrv_query($conn, $sqlCheck, [$emailEncrypted, $now]); $checkStmt = sqlsrv_query($conn, $sqlCheck, [$emailEncrypted, $now]);
$checkRow = sqlsrv_fetch_array($checkStmt, SQLSRV_FETCH_ASSOC); $checkRow = sqlsrv_fetch_array($checkStmt, SQLSRV_FETCH_ASSOC);
@@ -458,6 +455,7 @@ function reenviarCodigo()
} }
$conn = getConnection(); $conn = getConnection();
if (!$conn) { if (!$conn) {
echo json_encode(['success' => false, 'message' => '❌ Error de conexión con la base de datos.']); echo json_encode(['success' => false, 'message' => '❌ Error de conexión con la base de datos.']);
exit; exit;
@@ -468,9 +466,7 @@ function reenviarCodigo()
// Obtener el último código activo de recuperación // Obtener el último código activo de recuperación
$now = (new DateTime())->format('Y-m-d H:i:s'); $now = (new DateTime())->format('Y-m-d H:i:s');
$sql = "SELECT TOP 1 codigo FROM recuperacion_password $sql = "SELECT TOP 1 codigo FROM recuperacion_password WHERE email = ? AND estatus = 0 AND expiracion > ? ORDER BY expiracion DESC";
WHERE email = ? AND estatus = 0 AND expiracion > ?
ORDER BY expiracion DESC";
$stmt = sqlsrv_query($conn, $sql, [$emailEncrypted, $now]); $stmt = sqlsrv_query($conn, $sql, [$emailEncrypted, $now]);
if (!$stmt || !($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC))) { if (!$stmt || !($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC))) {
@@ -530,8 +526,7 @@ function verificarCodigo()
$emailEncrypted = encrypt($email); $emailEncrypted = encrypt($email);
// Consulta el último código válido para ese email // Consulta el último código válido para ese email
$sql = "SELECT TOP 1 id, codigo, expiracion FROM recuperacion_password $sql = "SELECT TOP 1 id, codigo, expiracion FROM recuperacion_password WHERE email = ? AND estatus = 0 ORDER BY id DESC";
WHERE email = ? AND estatus = 0 ORDER BY id DESC";
$stmt = sqlsrv_query($conn, $sql, [$emailEncrypted]); $stmt = sqlsrv_query($conn, $sql, [$emailEncrypted]);
if ($stmt === false) { if ($stmt === false) {
@@ -639,25 +634,25 @@ function verificarCodigo()
function enviarNotificacionIntentosExcedidos($email) function enviarNotificacionIntentosExcedidos($email)
{ {
$conn = getConnection(); $conn = getConnection();
if (!$conn) { if (!$conn) {
throw new Exception("No se pudo conectar a la base de datos"); throw new Exception("No se pudo conectar a la base de datos");
} }
// Buscar información del usuario por email // Buscar información del usuario por email
$emailEncrypted = encrypt($email); $emailEncrypted = encrypt($email);
$sqlNotif = "
SELECT $sqlNotif = "SELECT
u.nombre, u.nombre, u.email, u.notificaciones, u.notificaciones_extra,
u.email,
u.notificaciones,
u.notificaciones_extra,
COALESCE(p.intentos_fallidos, 0) as intentos_fallidos, COALESCE(p.intentos_fallidos, 0) as intentos_fallidos,
ce.correo as correo_extra ce.correo as correo_extra
FROM usuarios_sistema u FROM usuarios_sistema u
LEFT JOIN preferencias_notificaciones_usuario p ON u.id_usuario = p.id_usuario LEFT JOIN preferencias_notificaciones_usuario p
LEFT JOIN correo_extra ce ON u.id_usuario = ce.id_usuario ON u.id_usuario = p.id_usuario
WHERE u.email = ?"; LEFT JOIN correo_extra ce
ON u.id_usuario = ce.id_usuario
WHERE u.email = ?
";
$stmtUsuario = sqlsrv_query($conn, $sqlNotif, [$emailEncrypted]); $stmtUsuario = sqlsrv_query($conn, $sqlNotif, [$emailEncrypted]);
if ($stmtUsuario === false) { if ($stmtUsuario === false) {
@@ -822,23 +817,21 @@ function enviarNotificacionSeguridadIntentos($emailDestino, $nombreUsuario, $dat
function enviarNotificacionCuentaBloqueada($email) function enviarNotificacionCuentaBloqueada($email)
{ {
$conn = getConnection(); $conn = getConnection();
if (!$conn) { if (!$conn) {
throw new Exception("No se pudo conectar a la base de datos"); throw new Exception("No se pudo conectar a la base de datos");
} }
// Buscar información del usuario por email (incluyendo correo extra) // Buscar información del usuario por email (incluyendo correo extra)
$emailEncrypted = encrypt($email); $emailEncrypted = encrypt($email);
$sqlNotif = " $sqlNotif = "SELECT
SELECT u.nombre, u.email, u.notificaciones, u.notificaciones_extra,
u.nombre,
u.email,
u.notificaciones,
u.notificaciones_extra,
ce.correo as correo_extra ce.correo as correo_extra
FROM usuarios_sistema u FROM usuarios_sistema u
LEFT JOIN correo_extra ce ON u.id_usuario = ce.id_usuario LEFT JOIN correo_extra ce
WHERE u.email = ?"; ON u.id_usuario = ce.id_usuario
WHERE u.email = ?
";
$stmtUsuario = sqlsrv_query($conn, $sqlNotif, [$emailEncrypted]); $stmtUsuario = sqlsrv_query($conn, $sqlNotif, [$emailEncrypted]);
if ($stmtUsuario === false) { if ($stmtUsuario === false) {
@@ -1020,6 +1013,7 @@ function cambiarPassword()
} }
$conn = getConnection(); $conn = getConnection();
$password = $_POST['password'] ?? ''; $password = $_POST['password'] ?? '';
$confirmar = $_POST['confirmar'] ?? ''; $confirmar = $_POST['confirmar'] ?? '';

View File

@@ -1,6 +1,5 @@
<?php <?php
require_once __DIR__ . '/../../vendor/autoload.php'; require_once __DIR__ . '/../../vendor/autoload.php';
require_once __DIR__ . '/../helpers/session.php'; require_once __DIR__ . '/../helpers/session.php';
require_once __DIR__ . '/../../config/database.php'; require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../helpers/crypto.php'; require_once __DIR__ . '/../helpers/crypto.php';
@@ -20,17 +19,20 @@ function lista()
} }
$conn = getConnection(); $conn = getConnection();
$id_agencia = null; $id_agencia = null;
if ($_SESSION['tipo_usuario'] === 'agente_aduanal') { if ($_SESSION['tipo_usuario'] === 'agente_aduanal') {
$id_agente = $_SESSION['usuario_id']; $id_agente = $_SESSION['usuario_id'];
$stmt = sqlsrv_query($conn, "SELECT id_agencia FROM dbo.agente_agencia WHERE id_agente = ?", [$id_agente]); $stmt = sqlsrv_query($conn, "SELECT id_agencia FROM dbo.agente_agencia WHERE id_agente = ?", [$id_agente]);
if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$id_agencia = $row['id_agencia']; $id_agencia = $row['id_agencia'];
} }
} elseif ($_SESSION['tipo_usuario'] === 'admin_agencia') { } elseif ($_SESSION['tipo_usuario'] === 'admin_agencia') {
$id_admin = $_SESSION['usuario_id']; $id_admin = $_SESSION['usuario_id'];
$stmt = sqlsrv_query($conn, "SELECT id_agencia FROM dbo.agente_agencia WHERE id_agente = ?", [$id_admin]); $stmt = sqlsrv_query($conn, "SELECT id_agencia FROM dbo.agente_agencia WHERE id_agente = ?", [$id_admin]);
if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$id_agencia = $row['id_agencia']; $id_agencia = $row['id_agencia'];
} }
@@ -41,8 +43,7 @@ function lista()
} }
// Obtener todas las patentes registradas por usuarios de esa agencia // Obtener todas las patentes registradas por usuarios de esa agencia
$sql = " $sql = "SELECT DISTINCT
SELECT DISTINCT
aa.*, aga.id_agencia aa.*, aga.id_agencia
FROM dbo.agentes_aduanales aa FROM dbo.agentes_aduanales aa
INNER JOIN dbo.usuarios_sistema u INNER JOIN dbo.usuarios_sistema u
@@ -53,8 +54,8 @@ function lista()
AND aa.activo = 1 AND aa.activo = 1
ORDER BY aa.creado_en DESC ORDER BY aa.creado_en DESC
"; ";
$stmt = sqlsrv_query($conn, $sql, [$id_agencia]); $stmt = sqlsrv_query($conn, $sql, [$id_agencia]);
if ($stmt === false) { if ($stmt === false) {
die("Error en lista(): " . print_r(sqlsrv_errors(), true)); die("Error en lista(): " . print_r(sqlsrv_errors(), true));
} }
@@ -75,17 +76,20 @@ function alta()
} }
$conn = getConnection(); $conn = getConnection();
$id_agencia = null; $id_agencia = null;
if ($_SESSION['tipo_usuario'] === 'agente_aduanal') { if ($_SESSION['tipo_usuario'] === 'agente_aduanal') {
$id_agente = $_SESSION['usuario_id']; $id_agente = $_SESSION['usuario_id'];
$stmt = sqlsrv_query($conn, "SELECT id_agencia FROM dbo.agente_agencia WHERE id_agente = ?", [$id_agente]); $stmt = sqlsrv_query($conn, "SELECT id_agencia FROM dbo.agente_agencia WHERE id_agente = ?", [$id_agente]);
if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$id_agencia = $row['id_agencia']; $id_agencia = $row['id_agencia'];
} }
} elseif ($_SESSION['tipo_usuario'] === 'admin_agencia') { } elseif ($_SESSION['tipo_usuario'] === 'admin_agencia') {
$id_admin = $_SESSION['usuario_id']; $id_admin = $_SESSION['usuario_id'];
$stmt = sqlsrv_query($conn, "SELECT id_agencia FROM dbo.agente_agencia WHERE id_agente = ?", [$id_admin]); $stmt = sqlsrv_query($conn, "SELECT id_agencia FROM dbo.agente_agencia WHERE id_agente = ?", [$id_admin]);
if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$id_agencia = $row['id_agencia']; $id_agencia = $row['id_agencia'];
} }
@@ -100,11 +104,13 @@ function guardar()
die("⚠️ No autorizado."); die("⚠️ No autorizado.");
} }
$id_agente = $_SESSION['usuario_id'];
$conn = getConnection(); $conn = getConnection();
$id_agente = $_SESSION['usuario_id'];
// ✅ NUEVO: Obtener la agencia actual del usuario // ✅ NUEVO: Obtener la agencia actual del usuario
$stmt = sqlsrv_query($conn, "SELECT id_agencia FROM dbo.agente_agencia WHERE id_agente = ?", [$id_agente]); $stmt = sqlsrv_query($conn, "SELECT id_agencia FROM dbo.agente_agencia WHERE id_agente = ?", [$id_agente]);
$id_agencia = null; $id_agencia = null;
if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$id_agencia = $row['id_agencia']; $id_agencia = $row['id_agencia'];
@@ -159,7 +165,7 @@ function guardar()
if (!empty($valor)) { if (!empty($valor)) {
if (strlen($valor) > 10) die("❌ El campo {$campo} no puede exceder 10 caracteres."); if (strlen($valor) > 10) die("❌ El campo {$campo} no puede exceder 10 caracteres.");
// Opcional: Si quieres mantener solo números, descomenta la siguiente línea // Opcional: Si quieres mantener solo números, descomenta la siguiente línea
// if (!is_numeric($valor)) die("❌ El campo {$campo} debe ser numérico."); if (!is_numeric($valor)) die("❌ El campo {$campo} debe ser numérico.");
} }
} }
@@ -217,8 +223,8 @@ function guardar()
vat_pb_inicio, vat_pb_final, vat_pb_siguiente, vat_pb_inicio, vat_pb_final, vat_pb_siguiente,
vcc_inicio, vcc_final, vcc_siguiente, vcc_inicio, vcc_final, vcc_siguiente,
vae_inicio, vae_final, vae_siguiente) vae_inicio, vae_final, vae_siguiente)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
";
$params = [ $params = [
$id_agencia, $aduana, $patente, $agente_aduanal, $rfc, $curp, $razon_social, $id_usuario, $id_agencia, $aduana, $patente, $agente_aduanal, $rfc, $curp, $razon_social, $id_usuario,
$mf_nombre, $mf_paterno, $mf_materno, $mf_nombre, $mf_paterno, $mf_materno,
@@ -228,8 +234,8 @@ function guardar()
$vcc_inicio, $vcc_final, $vcc_siguiente, $vcc_inicio, $vcc_final, $vcc_siguiente,
$vae_inicio, $vae_final, $vae_siguiente $vae_inicio, $vae_final, $vae_siguiente
]; ];
$stmt = sqlsrv_query($conn, $sql, $params); $stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt === false) die("❌ Error al guardar agente aduanal."); if ($stmt === false) die("❌ Error al guardar agente aduanal.");
sqlsrv_free_stmt($stmt); sqlsrv_free_stmt($stmt);
@@ -314,6 +320,7 @@ function actualizar()
// ✅ NUEVO: Obtener la agencia actual del usuario // ✅ NUEVO: Obtener la agencia actual del usuario
$stmt = sqlsrv_query($conn, "SELECT id_agencia FROM dbo.agente_agencia WHERE id_agente = ?", [$id_usuario]); $stmt = sqlsrv_query($conn, "SELECT id_agencia FROM dbo.agente_agencia WHERE id_agente = ?", [$id_usuario]);
$id_agencia = null; $id_agencia = null;
if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$id_agencia = $row['id_agencia']; $id_agencia = $row['id_agencia'];
@@ -354,13 +361,13 @@ function actualizar()
if (strlen($curp) > 18) die("❌ El CURP no puede exceder 18 caracteres."); if (strlen($curp) > 18) die("❌ El CURP no puede exceder 18 caracteres.");
// Validar duplicado (excepto el propio id) // Validar duplicado (excepto el propio id)
$sqlCheck = "SELECT COUNT(*) as count FROM dbo.agentes_aduanales $sqlCheck = "SELECT COUNT(*) as count FROM dbo.agentes_aduanales WHERE aduana = ? AND patente = ? AND id_usuario = ? AND id_agente != ?";
WHERE aduana = ? AND patente = ? AND id_usuario = ? AND id_agente != ?";
$stmtCheck = sqlsrv_query($conn, $sqlCheck, [$aduana, $patente, $id_usuario, $id_agente]); $stmtCheck = sqlsrv_query($conn, $sqlCheck, [$aduana, $patente, $id_usuario, $id_agente]);
if ($stmtCheck === false) die("❌ Error al verificar duplicados."); if ($stmtCheck === false) die("❌ Error al verificar duplicados.");
$row = sqlsrv_fetch_array($stmtCheck, SQLSRV_FETCH_ASSOC); $row = sqlsrv_fetch_array($stmtCheck, SQLSRV_FETCH_ASSOC);
if ($row['count'] > 0) die("❌ Ya existe un agente aduanal con esta combinación de aduana y patente."); if ($row['count'] > 0) die("❌ Ya existe un agente aduanal con esta combinación de aduana y patente.");
sqlsrv_free_stmt($stmtCheck); sqlsrv_free_stmt($stmtCheck);
@@ -391,8 +398,9 @@ function actualizar()
vat_pb_inicio = ?, vat_pb_final = ?, vat_pb_siguiente = ?, vat_pb_inicio = ?, vat_pb_final = ?, vat_pb_siguiente = ?,
vcc_inicio = ?, vcc_final = ?, vcc_siguiente = ?, vcc_inicio = ?, vcc_final = ?, vcc_siguiente = ?,
vae_inicio = ?, vae_final = ?, vae_siguiente = ?, id_agencia = ? vae_inicio = ?, vae_final = ?, vae_siguiente = ?, id_agencia = ?
WHERE id_agente = ? AND id_usuario = ?"; WHERE id_agente = ?
AND id_usuario = ?
";
$params = [ $params = [
$aduana, $patente, $agente_aduanal, $rfc, $curp, $razon_social, $aduana, $patente, $agente_aduanal, $rfc, $curp, $razon_social,
$mf_nombre, $mf_paterno, $mf_materno, $mf_nombre, $mf_paterno, $mf_materno,
@@ -403,8 +411,8 @@ function actualizar()
$vae_inicio, $vae_final, $vae_siguiente, $id_agencia, $vae_inicio, $vae_final, $vae_siguiente, $id_agencia,
$id_agente, $id_usuario $id_agente, $id_usuario
]; ];
$stmt = sqlsrv_query($conn, $sql, $params); $stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt === false) die("❌ Error al actualizar agente aduanal."); if ($stmt === false) die("❌ Error al actualizar agente aduanal.");
sqlsrv_free_stmt($stmt); sqlsrv_free_stmt($stmt);
@@ -424,6 +432,7 @@ function eliminar()
$usr = $_SESSION['usuario_id']; $usr = $_SESSION['usuario_id'];
$id = $_GET['id'] ?? null; $id = $_GET['id'] ?? null;
if (!$id || !is_numeric($id)) { if (!$id || !is_numeric($id)) {
die("❌ ID inválido."); die("❌ ID inválido.");
} }
@@ -431,17 +440,17 @@ function eliminar()
$conn = getConnection(); $conn = getConnection();
// Verificar que el transportista exista y pertenezca al usuario // Verificar que el transportista exista y pertenezca al usuario
$sqlChk = "SELECT COUNT(*) AS cnt $sqlChk = "SELECT COUNT(*) AS cnt FROM dbo.agentes_aduanales WHERE id_agente = ? AND id_usuario = ?";
FROM dbo.agentes_aduanales
WHERE id_agente = ? AND id_usuario = ?";
$stmtChk = sqlsrv_query($conn, $sqlChk, [$id, $usr]); $stmtChk = sqlsrv_query($conn, $sqlChk, [$id, $usr]);
$rowChk = sqlsrv_fetch_array($stmtChk, SQLSRV_FETCH_ASSOC); $rowChk = sqlsrv_fetch_array($stmtChk, SQLSRV_FETCH_ASSOC);
if ($rowChk['cnt'] == 0) { if ($rowChk['cnt'] == 0) {
die("❌ Agente no encontrado o no autorizado."); die("❌ Agente no encontrado o no autorizado.");
} }
$sql = "UPDATE dbo.agentes_aduanales SET activo = 0 WHERE id_agente = ?"; $sql = "UPDATE dbo.agentes_aduanales SET activo = 0 WHERE id_agente = ?";
$stmt = sqlsrv_query($conn, $sql, [(int)$id]); $stmt = sqlsrv_query($conn, $sql, [(int)$id]);
if ($stmt === false) { if ($stmt === false) {
die("❌ Error en eliminar(): " . print_r(sqlsrv_errors(), true)); die("❌ Error en eliminar(): " . print_r(sqlsrv_errors(), true));
} }

View File

@@ -11,6 +11,7 @@ function index()
function notificaciones() function notificaciones()
{ {
$conn = getConnection(); $conn = getConnection();
$idUsuario = $_SESSION['usuario_id'] ?? null; $idUsuario = $_SESSION['usuario_id'] ?? null;
if (!$idUsuario) { if (!$idUsuario) {
@@ -478,6 +479,7 @@ function guardarPreferenciasAjax()
// Verificar si existe el registro // Verificar si existe el registro
$query_exists = "SELECT COUNT(*) as count FROM $tabla_preferencias WHERE id_usuario = ?"; $query_exists = "SELECT COUNT(*) as count FROM $tabla_preferencias WHERE id_usuario = ?";
$stmt_exists = sqlsrv_prepare($conn, $query_exists, [$id_usuario]); $stmt_exists = sqlsrv_prepare($conn, $query_exists, [$id_usuario]);
$exists = false; $exists = false;
if ($stmt_exists && sqlsrv_execute($stmt_exists)) { if ($stmt_exists && sqlsrv_execute($stmt_exists)) {
$row = sqlsrv_fetch_array($stmt_exists, SQLSRV_FETCH_ASSOC); $row = sqlsrv_fetch_array($stmt_exists, SQLSRV_FETCH_ASSOC);
@@ -756,19 +758,23 @@ function getConfiguracionTipoUsuario($tipo_usuario) {
function obtenerCorreoExtra($id_usuario) function obtenerCorreoExtra($id_usuario)
{ {
$conn = getConnection(); $conn = getConnection();
$query = "
SELECT ce.correo $query = "SELECT ce.correo
FROM correo_extra ce FROM correo_extra ce
INNER JOIN usuarios_sistema us ON ce.id_usuario = us.id_usuario INNER JOIN usuarios_sistema us
WHERE ce.id_usuario = ? AND us.notificaciones_extra = 1 ON ce.id_usuario = us.id_usuario
WHERE ce.id_usuario = ?
AND us.notificaciones_extra = 1
"; ";
$stmt = sqlsrv_prepare($conn, $query, [$id_usuario]); $stmt = sqlsrv_prepare($conn, $query, [$id_usuario]);
$correo = null; $correo = null;
if ($stmt && sqlsrv_execute($stmt)) { if ($stmt && sqlsrv_execute($stmt)) {
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
$correo = $row ? $row['correo'] : null; $correo = $row ? $row['correo'] : null;
sqlsrv_free_stmt($stmt); sqlsrv_free_stmt($stmt);
} }
sqlsrv_close($conn); sqlsrv_close($conn);
return $correo; return $correo;
} }
@@ -781,10 +787,12 @@ function obtenerPreferenciasNotificacion($id_usuario)
// Obtener configuración general // Obtener configuración general
$query = "SELECT notificaciones, notificaciones_extra FROM usuarios_sistema WHERE id_usuario = ?"; $query = "SELECT notificaciones, notificaciones_extra FROM usuarios_sistema WHERE id_usuario = ?";
$stmt = sqlsrv_prepare($conn, $query, [$id_usuario]); $stmt = sqlsrv_prepare($conn, $query, [$id_usuario]);
if (!$stmt || !sqlsrv_execute($stmt)) { if (!$stmt || !sqlsrv_execute($stmt)) {
sqlsrv_close($conn); sqlsrv_close($conn);
return null; return null;
} }
$config = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); $config = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
sqlsrv_free_stmt($stmt); sqlsrv_free_stmt($stmt);
@@ -796,6 +804,7 @@ function obtenerPreferenciasNotificacion($id_usuario)
// Obtener preferencias específicas // Obtener preferencias específicas
$query = "SELECT * FROM preferencias_notificaciones_usuario WHERE id_usuario = ?"; $query = "SELECT * FROM preferencias_notificaciones_usuario WHERE id_usuario = ?";
$stmt = sqlsrv_prepare($conn, $query, [$id_usuario]); $stmt = sqlsrv_prepare($conn, $query, [$id_usuario]);
$preferencias = null; $preferencias = null;
if ($stmt && sqlsrv_execute($stmt)) { if ($stmt && sqlsrv_execute($stmt)) {
$preferencias = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); $preferencias = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
@@ -845,16 +854,18 @@ function obtenerConfigResumenDiario($id_usuario)
{ {
$conn = getConnection(); $conn = getConnection();
$query = " $query = "SELECT
SELECT pnu.resumen_diario, pnu.resumen_diario_hora, pnu.resumen_diario_dias pnu.resumen_diario, pnu.resumen_diario_hora, pnu.resumen_diario_dias
FROM preferencias_notificaciones_usuario pnu FROM preferencias_notificaciones_usuario pnu
INNER JOIN usuarios_sistema us ON pnu.id_usuario = us.id_usuario INNER JOIN usuarios_sistema us
WHERE pnu.id_usuario = ? AND us.notificaciones = 1 AND pnu.resumen_diario = 1 ON pnu.id_usuario = us.id_usuario
WHERE pnu.id_usuario = ?
AND us.notificaciones = 1
AND pnu.resumen_diario = 1
"; ";
$stmt = sqlsrv_prepare($conn, $query, [$id_usuario]); $stmt = sqlsrv_prepare($conn, $query, [$id_usuario]);
$config = null;
$config = null;
if ($stmt && sqlsrv_execute($stmt)) { if ($stmt && sqlsrv_execute($stmt)) {
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
if ($row) { if ($row) {
@@ -891,6 +902,7 @@ function esDiaResumen($config_dias)
function catalogos() function catalogos()
{ {
$conn = getConnection(); $conn = getConnection();
$idUsuario = $_SESSION['usuario_id'] ?? null; $idUsuario = $_SESSION['usuario_id'] ?? null;
if (!$idUsuario) { if (!$idUsuario) {
@@ -901,9 +913,11 @@ function catalogos()
// Obtener configuración general de catalogos y tipo de usuario // Obtener configuración general de catalogos y tipo de usuario
$query = "SELECT preferencias_catalogos, tipo_usuario FROM usuarios_sistema WHERE id_usuario = ?"; $query = "SELECT preferencias_catalogos, tipo_usuario FROM usuarios_sistema WHERE id_usuario = ?";
$stmt = sqlsrv_prepare($conn, $query, [$idUsuario]); $stmt = sqlsrv_prepare($conn, $query, [$idUsuario]);
if (!$stmt || !sqlsrv_execute($stmt)) { if (!$stmt || !sqlsrv_execute($stmt)) {
die("Error al obtener configuración: " . print_r(sqlsrv_errors(), true)); die("Error al obtener configuración: " . print_r(sqlsrv_errors(), true));
} }
$usuario = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); $usuario = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
if (!$usuario) { if (!$usuario) {
die("Usuario no encontrado"); die("Usuario no encontrado");
@@ -958,8 +972,8 @@ function catalogos()
// Si no existe registro, crear valores por defecto para agente aduanal // Si no existe registro, crear valores por defecto para agente aduanal
// if (!$preferenciasRow) { // if (!$preferenciasRow) {
// $preferencias = [ // $preferencias = [
// Aquí se definirán los campos específicos para agente aduanal // // Aquí se definirán los campos específicos para agente aduanal
// cuando se creen las tablas correspondientes // // cuando se creen las tablas correspondientes
// 'configuracion' => 0, // 'configuracion' => 0,
// 'cerrar_sesion' => 0 // 'cerrar_sesion' => 0
// ]; // ];
@@ -981,8 +995,8 @@ function catalogos()
// Si no existe registro, crear valores por defecto para admin agencia // Si no existe registro, crear valores por defecto para admin agencia
// if (!$preferenciasRow) { // if (!$preferenciasRow) {
// $preferencias = [ // $preferencias = [
// Aquí se definirán los campos específicos para admin agencia // // Aquí se definirán los campos específicos para admin agencia
// cuando se creen las tablas correspondientes // // cuando se creen las tablas correspondientes
// 'configuracion' => 0, // 'configuracion' => 0,
// 'cerrar_sesion' => 0 // 'cerrar_sesion' => 0
// ]; // ];
@@ -1004,8 +1018,8 @@ function catalogos()
// Si no existe registro, crear valores por defecto para super admin // Si no existe registro, crear valores por defecto para super admin
// if (!$preferenciasRow) { // if (!$preferenciasRow) {
// $preferencias = [ // $preferencias = [
// Aquí se definirán los campos específicos para super admin // // Aquí se definirán los campos específicos para super admin
// cuando se creen las tablas correspondientes // // cuando se creen las tablas correspondientes
// 'configuracion' => 0, // 'configuracion' => 0,
// 'cerrar_sesion' => 0 // 'cerrar_sesion' => 0
// ]; // ];
@@ -1026,6 +1040,7 @@ function catalogos()
// Obtener tipos de catalogos disponibles según el tipo de usuario // Obtener tipos de catalogos disponibles según el tipo de usuario
$query = "SELECT nombre, descripcion, color FROM tipos_catalogos WHERE tipo_usuario = ? ORDER BY id"; $query = "SELECT nombre, descripcion, color FROM tipos_catalogos WHERE tipo_usuario = ? ORDER BY id";
$stmt = sqlsrv_prepare($conn, $query, [$tipoUsuario]); $stmt = sqlsrv_prepare($conn, $query, [$tipoUsuario]);
if (!$stmt || !sqlsrv_execute($stmt)) { if (!$stmt || !sqlsrv_execute($stmt)) {
die("Error al obtener tipos: " . print_r(sqlsrv_errors(), true)); die("Error al obtener tipos: " . print_r(sqlsrv_errors(), true));
} }
@@ -1064,6 +1079,7 @@ function guardarCatalogosAjax()
} }
$conn = getConnection(); $conn = getConnection();
$idUsuario = $_SESSION['usuario_id'] ?? null; $idUsuario = $_SESSION['usuario_id'] ?? null;
if (!$idUsuario) { if (!$idUsuario) {
@@ -1075,11 +1091,13 @@ function guardarCatalogosAjax()
// Obtener tipo de usuario // Obtener tipo de usuario
$query = "SELECT tipo_usuario FROM usuarios_sistema WHERE id_usuario = ?"; $query = "SELECT tipo_usuario FROM usuarios_sistema WHERE id_usuario = ?";
$stmt = sqlsrv_prepare($conn, $query, [$idUsuario]); $stmt = sqlsrv_prepare($conn, $query, [$idUsuario]);
if (!$stmt || !sqlsrv_execute($stmt)) { if (!$stmt || !sqlsrv_execute($stmt)) {
http_response_code(500); http_response_code(500);
echo json_encode(['success' => false, 'message' => 'Error al obtener información del usuario']); echo json_encode(['success' => false, 'message' => 'Error al obtener información del usuario']);
exit; exit;
} }
$usuario = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); $usuario = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
$tipoUsuario = $usuario['tipo_usuario'] ?? 'importador'; $tipoUsuario = $usuario['tipo_usuario'] ?? 'importador';
sqlsrv_free_stmt($stmt); sqlsrv_free_stmt($stmt);
@@ -1091,13 +1109,13 @@ function guardarCatalogosAjax()
case 'catalogos_general': case 'catalogos_general':
// Actualizar preferencias generales de catálogos // Actualizar preferencias generales de catálogos
$valor = isset($input['valor']) && $input['valor'] ? 1 : 0; $valor = isset($input['valor']) && $input['valor'] ? 1 : 0;
$query = "UPDATE usuarios_sistema SET preferencias_catalogos = ? WHERE id_usuario = ?"; $query = "UPDATE usuarios_sistema SET preferencias_catalogos = ? WHERE id_usuario = ?";
$stmt = sqlsrv_prepare($conn, $query, [$valor, $idUsuario]); $stmt = sqlsrv_prepare($conn, $query, [$valor, $idUsuario]);
if (!$stmt || !sqlsrv_execute($stmt)) { if (!$stmt || !sqlsrv_execute($stmt)) {
throw new Exception('Error al actualizar preferencias generales'); throw new Exception('Error al actualizar preferencias generales');
} }
sqlsrv_free_stmt($stmt); sqlsrv_free_stmt($stmt);
break; break;
@@ -1132,6 +1150,7 @@ function guardarCatalogosAjax()
// Verificar si existe un registro para este usuario // Verificar si existe un registro para este usuario
$query = "SELECT id_preferencia FROM $tabla WHERE id_usuario = ?"; $query = "SELECT id_preferencia FROM $tabla WHERE id_usuario = ?";
$stmt = sqlsrv_prepare($conn, $query, [$idUsuario]); $stmt = sqlsrv_prepare($conn, $query, [$idUsuario]);
if (!$stmt || !sqlsrv_execute($stmt)) { if (!$stmt || !sqlsrv_execute($stmt)) {
throw new Exception('Error al verificar preferencias existentes'); throw new Exception('Error al verificar preferencias existentes');
} }

View File

@@ -1,6 +1,4 @@
<?php <?php
// app/controllers/productos_frecuentes.php
require_once __DIR__ . '/../helpers/session.php'; require_once __DIR__ . '/../helpers/session.php';
require_once __DIR__ . '/../../config/database.php'; require_once __DIR__ . '/../../config/database.php';
// 1) Composer autoload (phpdotenv y demás libs) // 1) Composer autoload (phpdotenv y demás libs)
@@ -26,9 +24,8 @@ function ajax_paises()
} }
$conn = getConnection(); $conn = getConnection();
$sql = "SELECT id_pais AS id, nombre AS text
FROM dbo.paises $sql = "SELECT id_pais AS id, nombre AS text FROM dbo.paises ORDER BY nombre";
ORDER BY nombre";
$stmt = sqlsrv_query($conn, $sql); $stmt = sqlsrv_query($conn, $sql);
$out = ['results' => []]; $out = ['results' => []];
@@ -93,6 +90,7 @@ function lista()
header('Location: /IMPORTADORES/login'); header('Location: /IMPORTADORES/login');
exit; exit;
} }
include __DIR__ . '/../../views/productos_frecuentes/lista.php'; include __DIR__ . '/../../views/productos_frecuentes/lista.php';
} }
@@ -100,11 +98,11 @@ function lista()
* Muestra el formulario de creación **/ * Muestra el formulario de creación **/
function alta() function alta()
{ {
if (empty($_SESSION['usuario_id'])) { if (empty($_SESSION['usuario_id'])) {
header('Location: /IMPORTADORES/login'); header('Location: /IMPORTADORES/login');
exit; exit;
} }
include __DIR__ . '/../../views/productos_frecuentes/alta.php'; include __DIR__ . '/../../views/productos_frecuentes/alta.php';
} }
@@ -112,7 +110,6 @@ function alta()
* Procesa alta de producto frecuente **/ * Procesa alta de producto frecuente **/
function guardar() function guardar()
{ {
if (empty($_SESSION['usuario_id'])) { if (empty($_SESSION['usuario_id'])) {
header('Location: /IMPORTADORES/login'); header('Location: /IMPORTADORES/login');
exit; exit;
@@ -153,38 +150,19 @@ function guardar()
} }
// INSERT // INSERT
$sql = " $sql = "INSERT INTO dbo.productos_frecuentes
INSERT INTO dbo.productos_frecuentes ( (sinonimo, fraccion, nico, numero_parte, descripcion, umc_id,
sinonimo, fraccion, nico, numero_parte, pais_origen_destino, pais_comprador_vendedor, uso_mercancia, estado_mercancia, vinculacion,
descripcion, umc_id, observaciones, preferencia, criterio_preferencia, uso_producto, descripcion_producto,
pais_origen_destino, pais_comprador_vendedor, certificado_origen, tipo_mercancia, documento_en_original, proveedor,
uso_mercancia, estado_mercancia, vinculacion, id_importador, fecha_alta, status, frecuencia_uso)
observaciones, preferencia, criterio_preferencia, VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, GETDATE(), ?, ?)
uso_producto, descripcion_producto,
certificado_origen, tipo_mercancia,
documento_en_original, proveedor,
id_importador, fecha_alta, status, frecuencia_uso
) VALUES (
?,?,?,?,
?,?,
?,?,
?,?,?,
?,?,?,
?,?,
?,?,
?,?,
?,GETDATE(),?,?
)
"; ";
$params = [ $params = [
$sinonimo, $fraccion, $nico, $numero_parte, $sinonimo, $fraccion, $nico, $numero_parte, $descripcion, $umc_id,
$descripcion, $umc_id, $pais_origen_destino, $pais_comprador_vendedor, $uso_mercancia, $estado_mercancia, $vinculacion,
$pais_origen_destino, $pais_comprador_vendedor, $observaciones, $preferencia, $criterio_preferencia, $uso_producto, $descripcion_producto,
$uso_mercancia, $estado_mercancia, $vinculacion, $certificado_origen, $tipo_mercancia, $documento_en_original, $proveedor,
$observaciones, $preferencia, $criterio_preferencia,
$uso_producto, $descripcion_producto,
$certificado_origen, $tipo_mercancia,
$documento_en_original, $proveedor,
$id_importador, $status, $frecuencia_uso $id_importador, $status, $frecuencia_uso
]; ];
$stmt = sqlsrv_query($conn, $sql, $params); $stmt = sqlsrv_query($conn, $sql, $params);
@@ -204,21 +182,23 @@ function guardar()
* Muestra el formulario de edición **/ * Muestra el formulario de edición **/
function editar() function editar()
{ {
if (empty($_SESSION['usuario_id'])) { if (empty($_SESSION['usuario_id'])) {
header('Location: /IMPORTADORES/login'); header('Location: /IMPORTADORES/login');
exit; exit;
} }
$id = intval($_GET['id'] ?? 0); $id = intval($_GET['id'] ?? 0);
if ($id <= 0) { if ($id <= 0) {
header('Location: /IMPORTADORES/productos_frecuentes'); header('Location: /IMPORTADORES/productos_frecuentes');
exit; exit;
} }
$conn = getConnection(); $conn = getConnection();
$sql = "SELECT * FROM dbo.productos_frecuentes WHERE id_producto_frecuente = ?"; $sql = "SELECT * FROM dbo.productos_frecuentes WHERE id_producto_frecuente = ?";
$stmt = sqlsrv_query($conn, $sql, [$id]); $stmt = sqlsrv_query($conn, $sql, [$id]);
if ($stmt === false || ($producto = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) === null) { if ($stmt === false || ($producto = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) === null) {
$_SESSION['flash_error'] = 'Producto frecuente no encontrado.'; $_SESSION['flash_error'] = 'Producto frecuente no encontrado.';
header('Location: /IMPORTADORES/productos_frecuentes'); header('Location: /IMPORTADORES/productos_frecuentes');
@@ -232,40 +212,28 @@ function editar()
* Procesa la actualización **/ * Procesa la actualización **/
function actualizar() function actualizar()
{ {
session_start();
if (empty($_SESSION['usuario_id'])) { if (empty($_SESSION['usuario_id'])) {
header('Location: /IMPORTADORES/login'); header('Location: /IMPORTADORES/login');
exit; exit;
} }
$conn = getConnection();
$id = intval($_POST['id_producto_frecuente'] ?? 0); $id = intval($_POST['id_producto_frecuente'] ?? 0);
$sinonimo = trim($_POST['sinonimo'] ?? ''); $sinonimo = trim($_POST['sinonimo'] ?? '');
// ... (resto de campos idénticos a guardar)
// Validaciones similares... $sql = "UPDATE dbo.productos_frecuentes SET
// UPDATE ... sinonimo = ?, fraccion = ?, nico = ?, numero_parte = ?, descripcion = ?, umc_id = ?,
$conn = getConnection(); pais_origen_destino = ?, pais_comprador_vendedor = ?, uso_mercancia = ?, estado_mercancia = ?, vinculacion = ?,
$sql = " observaciones = ?, preferencia = ?, criterio_preferencia = ?, uso_producto = ?, descripcion_producto = ?,
UPDATE dbo.productos_frecuentes SET certificado_origen = ?, tipo_mercancia = ?, documento_en_original = ?, proveedor = ?
sinonimo = ?, fraccion = ?, nico = ?, numero_parte = ?,
descripcion = ?, umc_id = ?,
pais_origen_destino = ?, pais_comprador_vendedor = ?,
uso_mercancia = ?, estado_mercancia = ?, vinculacion = ?,
observaciones = ?, preferencia = ?, criterio_preferencia = ?,
uso_producto = ?, descripcion_producto = ?,
certificado_origen = ?, tipo_mercancia = ?,
documento_en_original = ?, proveedor = ?
WHERE id_producto_frecuente = ? WHERE id_producto_frecuente = ?
"; ";
$params = [ $params = [
$sinonimo, $fraccion, $nico, $numero_parte, $sinonimo, $fraccion, $nico, $numero_parte, $descripcion, $umc_id,
$descripcion, $umc_id, $pais_origen_destino, $pais_comprador_vendedor, $uso_mercancia, $estado_mercancia, $vinculacion,
$pais_origen_destino, $pais_comprador_vendedor, $observaciones, $preferencia, $criterio_preferencia, $uso_producto, $descripcion_producto,
$uso_mercancia, $estado_mercancia, $vinculacion, $certificado_origen, $tipo_mercancia, $documento_en_original, $proveedor, $id
$observaciones, $preferencia, $criterio_preferencia,
$uso_producto, $descripcion_producto,
$certificado_origen, $tipo_mercancia,
$documento_en_original, $proveedor,
$id
]; ];
$stmt = sqlsrv_query($conn, $sql, $params); $stmt = sqlsrv_query($conn, $sql, $params);
@@ -300,6 +268,7 @@ function ajax_unidades()
} }
$conn = getConnection(); $conn = getConnection();
$sql = "SELECT id, descripcion FROM dbo.unidades_medida_apendice7 ORDER BY descripcion"; $sql = "SELECT id, descripcion FROM dbo.unidades_medida_apendice7 ORDER BY descripcion";
$stmt = sqlsrv_query($conn, $sql); $stmt = sqlsrv_query($conn, $sql);
@@ -332,7 +301,9 @@ function procesar_csv()
} }
$file = fopen($_FILES['csv_file']['tmp_name'], 'r'); $file = fopen($_FILES['csv_file']['tmp_name'], 'r');
$conn = getConnection(); $conn = getConnection();
$row = 0; $row = 0;
while (($data = fgetcsv($file, 0, ',')) !== false) { while (($data = fgetcsv($file, 0, ',')) !== false) {
$row++; $row++;

View File

@@ -1,13 +1,11 @@
<?php <?php
// app/controllers/proveedores.php
require_once __DIR__ . '/../helpers/session.php'; require_once __DIR__ . '/../helpers/session.php';
require_once __DIR__ . '/../../config/database.php'; require_once __DIR__ . '/../../config/database.php';
// 1) Composer autoload (phpdotenv y demás libs) // 1) Composer autoload (phpdotenv y demás libs)
require_once __DIR__ . '/../../vendor/autoload.php'; require_once __DIR__ . '/../../vendor/autoload.php';
// 2) Carga nuestro helper de entorno y dispara la carga de .env // 2) Carga nuestro helper de entorno y dispara la carga de .env
require_once __DIR__ . '/../helpers/env.php'; require_once __DIR__ . '/../helpers/env.php';
loadEnv(); loadEnv();
/** Obtiene (y cachea en sesión) el JWT de la API usando las credenciales de $_ENV **/ /** Obtiene (y cachea en sesión) el JWT de la API usando las credenciales de $_ENV **/
@@ -136,7 +134,7 @@ function ajax_lista()
htmlspecialchars($p['Nombre'] ?? '', ENT_QUOTES), htmlspecialchars($p['Nombre'] ?? '', ENT_QUOTES),
htmlspecialchars($p['RFC'] ?? '', ENT_QUOTES), htmlspecialchars($p['RFC'] ?? '', ENT_QUOTES),
htmlspecialchars($p['Ciudad'] ?? '', ENT_QUOTES), htmlspecialchars($p['Ciudad'] ?? '', ENT_QUOTES),
htmlspecialchars($p['Telefono']?? '', ENT_QUOTES), htmlspecialchars($p['Telefono'] ?? '', ENT_QUOTES),
htmlspecialchars($direccion ?? '', ENT_QUOTES), htmlspecialchars($direccion ?? '', ENT_QUOTES),
// Acciones // Acciones
"<a href=\"/IMPORTADORES/proveedores/editar?clave=" . rawurlencode($clave) . "\" class=\"btn btn-sm btn-primary\">✏️</a> "<a href=\"/IMPORTADORES/proveedores/editar?clave=" . rawurlencode($clave) . "\" class=\"btn btn-sm btn-primary\">✏️</a>
@@ -157,6 +155,7 @@ function eliminar()
{ {
$token = getApiToken(); $token = getApiToken();
$clave = $_GET['clave'] ?? ''; $clave = $_GET['clave'] ?? '';
if (!$token || !$clave) { if (!$token || !$clave) {
header('Location: /IMPORTADORES/proveedores'); header('Location: /IMPORTADORES/proveedores');
exit; exit;

View File

@@ -149,6 +149,7 @@ function enviarEmailConfirmacion($destinatario, $datosEmpresa, $esAgencia = fals
// Obtener configuración // Obtener configuración
$conn = getConnection(); $conn = getConnection();
$conf = obtenerConfiguracion($conn); $conf = obtenerConfiguracion($conn);
$nombrePlataforma = $conf['nombre_plataforma']; $nombrePlataforma = $conf['nombre_plataforma'];
@@ -230,8 +231,8 @@ function enviarSoliImportador()
// Insertar en base de datos // Insertar en base de datos
$sql = "INSERT INTO solicitudes_importadores $sql = "INSERT INTO solicitudes_importadores
(company_name, rfc, email, phone, opinion_file, request_status, request_date) (company_name, rfc, email, phone, opinion_file, request_status, request_date)
VALUES (?, ?, ?, ?, ?, 'pending', GETDATE())"; VALUES (?, ?, ?, ?, ?, 'pending', GETDATE())
";
$params = [$empresaEncriptada, $rfcEncriptado, $email, $telefono, $nombreArchivo]; $params = [$empresaEncriptada, $rfcEncriptado, $email, $telefono, $nombreArchivo];
$stmt = sqlsrv_query($conn, $sql, $params); $stmt = sqlsrv_query($conn, $sql, $params);
@@ -291,8 +292,8 @@ function enviarSoliAgencia()
// Insertar en base de datos // Insertar en base de datos
$sql = "INSERT INTO solicitudes_agencias $sql = "INSERT INTO solicitudes_agencias
(agencia_name, rfc, email, phone, direccion, opinion_file, admin_name, admin_email, request_status, request_date) (agencia_name, rfc, email, phone, direccion, opinion_file, admin_name, admin_email, request_status, request_date)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'pending', GETDATE())"; VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'pending', GETDATE())
";
$params = [$agenciaEncriptada, $rfcEncriptado, $correo, $telefono, $direccion, $nombreArchivo, $adminEncriptado, $admin_correo]; $params = [$agenciaEncriptada, $rfcEncriptado, $correo, $telefono, $direccion, $nombreArchivo, $adminEncriptado, $admin_correo];
$stmt = sqlsrv_query($conn, $sql, $params); $stmt = sqlsrv_query($conn, $sql, $params);

View File

@@ -4,8 +4,8 @@ require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../helpers/crypto.php'; require_once __DIR__ . '/../helpers/crypto.php';
require_once __DIR__ . '/../helpers/bitacoras.php'; require_once __DIR__ . '/../helpers/bitacoras.php';
require_once __DIR__ . '/../helpers/env.php'; require_once __DIR__ . '/../helpers/env.php';
require_once __DIR__ . '/../../vendor/autoload.php'; require_once __DIR__ . '/../../vendor/autoload.php';
use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception; use PHPMailer\PHPMailer\Exception;
@@ -22,6 +22,7 @@ function enviarCodigoInterno()
} }
$conn = getConnection(); $conn = getConnection();
if (!$conn) { if (!$conn) {
echo json_encode(['success' => false, 'message' => '❌ Error de conexión con la base de datos.']); echo json_encode(['success' => false, 'message' => '❌ Error de conexión con la base de datos.']);
exit; exit;
@@ -47,8 +48,7 @@ function enviarCodigoInterno()
// Verificar si ya existe un código activo // Verificar si ya existe un código activo
$now = (new DateTime())->format('Y-m-d H:i:s'); $now = (new DateTime())->format('Y-m-d H:i:s');
$sqlCheck = "SELECT COUNT(*) AS total FROM recuperacion_password $sqlCheck = "SELECT COUNT(*) AS total FROM recuperacion_password WHERE email = ? AND estatus = 0 AND expiracion > ?";
WHERE email = ? AND estatus = 0 AND expiracion > ?";
$checkStmt = sqlsrv_query($conn, $sqlCheck, [$emailEncrypted, $now]); $checkStmt = sqlsrv_query($conn, $sqlCheck, [$emailEncrypted, $now]);
$checkRow = sqlsrv_fetch_array($checkStmt, SQLSRV_FETCH_ASSOC); $checkRow = sqlsrv_fetch_array($checkStmt, SQLSRV_FETCH_ASSOC);
@@ -143,6 +143,7 @@ function reenviarCodigoInterno()
} }
$conn = getConnection(); $conn = getConnection();
if (!$conn) { if (!$conn) {
echo json_encode(['success' => false, 'message' => '❌ Error de conexión con la base de datos.']); echo json_encode(['success' => false, 'message' => '❌ Error de conexión con la base de datos.']);
exit; exit;
@@ -153,9 +154,7 @@ function reenviarCodigoInterno()
// Obtener el último código activo de recuperación // Obtener el último código activo de recuperación
$now = (new DateTime())->format('Y-m-d H:i:s'); $now = (new DateTime())->format('Y-m-d H:i:s');
$sql = "SELECT TOP 1 codigo FROM recuperacion_password $sql = "SELECT TOP 1 codigo FROM recuperacion_password WHERE email = ? AND estatus = 0 AND expiracion > ? ORDER BY expiracion DESC";
WHERE email = ? AND estatus = 0 AND expiracion > ?
ORDER BY expiracion DESC";
$stmt = sqlsrv_query($conn, $sql, [$emailEncrypted, $now]); $stmt = sqlsrv_query($conn, $sql, [$emailEncrypted, $now]);
if (!$stmt || !($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC))) { if (!$stmt || !($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC))) {
@@ -319,12 +318,14 @@ function verificarCodigoInterno()
} }
// Consulta principal para verificar el código // Consulta principal para verificar el código
$sql = "SELECT id, codigo, expiracion $sql = "SELECT
id, codigo, expiracion
FROM recuperacion_password FROM recuperacion_password
WHERE email = ? AND estatus = 0 AND expiracion > GETDATE() WHERE email = ?
AND estatus = 0
AND expiracion > GETDATE()
ORDER BY expiracion DESC ORDER BY expiracion DESC
"; ";
$stmt = sqlsrv_query($conn, $sql, [$emailEncrypted]); $stmt = sqlsrv_query($conn, $sql, [$emailEncrypted]);
if (!$stmt) { if (!$stmt) {
@@ -425,16 +426,27 @@ function cambiarPasswordInternoView()
function cambiarPasswordInterno() function cambiarPasswordInterno()
{ {
// Limpiar buffer de salida
if (ob_get_level()) {
ob_end_clean();
}
// Iniciar buffer limpio
ob_start();
header('Content-Type: application/json'); // ⬅️ AGREGAR ESTA LÍNEA header('Content-Type: application/json'); // ⬅️ AGREGAR ESTA LÍNEA
// Verificar autorización completa // Verificar autorización completa
if (!isset($_SESSION['usuario_id']) || !isset($_SESSION['usuario_email']) || if (!isset($_SESSION['usuario_id']) || !isset($_SESSION['usuario_email']) ||
!isset($_SESSION['cambio_interno']) || !isset($_SESSION['codigo_verificado_interno'])) { !isset($_SESSION['cambio_interno']) || !isset($_SESSION['codigo_verificado_interno'])) {
ob_end_clean(); // Limpiar buffer antes de enviar JSON
echo json_encode(['success' => false, 'message' => '❌ No tienes autorización para cambiar la contraseña.']); echo json_encode(['success' => false, 'message' => '❌ No tienes autorización para cambiar la contraseña.']);
exit; exit;
} }
$conn = getConnection(); $conn = getConnection();
if (!$conn) { if (!$conn) {
echo json_encode(['success' => false, 'message' => '❌ Error de conexión con la base de datos.']); echo json_encode(['success' => false, 'message' => '❌ Error de conexión con la base de datos.']);
exit; exit;
@@ -495,7 +507,7 @@ function cambiarPasswordInterno()
// Registrar en bitácora // Registrar en bitácora
$ip = $_SERVER['REMOTE_ADDR'] ?? 'N/A'; $ip = $_SERVER['REMOTE_ADDR'] ?? 'N/A';
registrarBitacora($conn, $id_usuario, $email, $ip, 1, 'Cambio de contraseña interno'); registrarBitacora($id_usuario, $email, $ip, 1, 'Cambio de contraseña interno');
// Enviar correo de confirmación // Enviar correo de confirmación
try { try {
@@ -547,6 +559,8 @@ function cambiarPasswordInterno()
unset($_SESSION['codigo_verificado_interno']); unset($_SESSION['codigo_verificado_interno']);
unset($_SESSION['codigo_timestamp']); unset($_SESSION['codigo_timestamp']);
// Al final, antes de cada echo json_encode:
ob_end_clean();
echo json_encode([ echo json_encode([
'success' => true, 'success' => true,
'message' => '✅ Contraseña actualizada exitosamente.', 'message' => '✅ Contraseña actualizada exitosamente.',
@@ -587,6 +601,7 @@ function obtenerEstadoDosFactores()
// CORRIGIDO: Cambiar id_usuario por usuario_id // CORRIGIDO: Cambiar id_usuario por usuario_id
$id_usuario = $_SESSION['usuario_id'] ?? null; $id_usuario = $_SESSION['usuario_id'] ?? null;
if (!$id_usuario) { if (!$id_usuario) {
return 0; // valor por defecto si no hay sesión return 0; // valor por defecto si no hay sesión
} }
@@ -596,7 +611,6 @@ function obtenerEstadoDosFactores()
$stmt_dos_factores = sqlsrv_prepare($conn, $sql_dos_factores, $params); $stmt_dos_factores = sqlsrv_prepare($conn, $sql_dos_factores, $params);
$dos_factores_estado = 0; // valor por defecto $dos_factores_estado = 0; // valor por defecto
if ($stmt_dos_factores && sqlsrv_execute($stmt_dos_factores)) { if ($stmt_dos_factores && sqlsrv_execute($stmt_dos_factores)) {
if ($row = sqlsrv_fetch_array($stmt_dos_factores, SQLSRV_FETCH_ASSOC)) { if ($row = sqlsrv_fetch_array($stmt_dos_factores, SQLSRV_FETCH_ASSOC)) {
$dos_factores_estado = (int)$row['dos_factores']; $dos_factores_estado = (int)$row['dos_factores'];

View File

@@ -25,6 +25,7 @@ function index()
function opciones() function opciones()
{ {
$conn = getConnection(); $conn = getConnection();
$id_usuario = $_SESSION['usuario_id'] ?? null; $id_usuario = $_SESSION['usuario_id'] ?? null;
// Asegúrate de que el usuario está autenticado // Asegúrate de que el usuario está autenticado
@@ -54,7 +55,6 @@ function obtenerEstadoDosFactores()
$stmt_dos_factores = sqlsrv_prepare($conn, $sql_dos_factores, $params); $stmt_dos_factores = sqlsrv_prepare($conn, $sql_dos_factores, $params);
$dos_factores_estado = 0; // valor por defecto $dos_factores_estado = 0; // valor por defecto
if ($stmt_dos_factores && sqlsrv_execute($stmt_dos_factores)) { if ($stmt_dos_factores && sqlsrv_execute($stmt_dos_factores)) {
if ($row = sqlsrv_fetch_array($stmt_dos_factores, SQLSRV_FETCH_ASSOC)) { if ($row = sqlsrv_fetch_array($stmt_dos_factores, SQLSRV_FETCH_ASSOC)) {
$dos_factores_estado = (int)$row['dos_factores']; $dos_factores_estado = (int)$row['dos_factores'];
@@ -90,7 +90,6 @@ function autenticacionDosFactores()
} }
$dos_factores = isset($_POST['dos_factores']) ? 1 : 0; $dos_factores = isset($_POST['dos_factores']) ? 1 : 0;
$sql = "UPDATE usuarios_sistema SET dos_factores = ? WHERE id_usuario = ?"; $sql = "UPDATE usuarios_sistema SET dos_factores = ? WHERE id_usuario = ?";
$params = [$dos_factores, $id_usuario]; $params = [$dos_factores, $id_usuario];
$stmt = sqlsrv_prepare($conn, $sql, $params); $stmt = sqlsrv_prepare($conn, $sql, $params);
@@ -125,7 +124,8 @@ function correoExtra()
exit; exit;
} }
$id_usuario = $_SESSION['usuario_id']; // CORRIGIDO $id_usuario = $_SESSION['usuario_id'];
$conn = getConnection(); $conn = getConnection();
$sql_check = "SELECT COUNT(*) AS total FROM correo_extra WHERE id_usuario = ?"; $sql_check = "SELECT COUNT(*) AS total FROM correo_extra WHERE id_usuario = ?";
@@ -164,6 +164,7 @@ function modificarCorreoExtra()
} }
$id_usuario = $_SESSION['usuario_id']; $id_usuario = $_SESSION['usuario_id'];
$conn = getConnection(); $conn = getConnection();
$correo = $_POST['email-extra'] ?? ''; $correo = $_POST['email-extra'] ?? '';
@@ -193,6 +194,7 @@ function eliminarCorreoExtra()
} }
$id_usuario = $_SESSION['usuario_id']; $id_usuario = $_SESSION['usuario_id'];
$conn = getConnection(); $conn = getConnection();
$query = "DELETE FROM correo_extra WHERE id_usuario = ?"; $query = "DELETE FROM correo_extra WHERE id_usuario = ?";
@@ -215,7 +217,8 @@ function correoRespaldo()
exit; exit;
} }
$id_usuario = $_SESSION['usuario_id']; // CORRIGIDO $id_usuario = $_SESSION['usuario_id'];
$conn = getConnection(); $conn = getConnection();
$sql_check = "SELECT COUNT(*) AS total FROM correo_respaldo WHERE id_usuario = ?"; $sql_check = "SELECT COUNT(*) AS total FROM correo_respaldo WHERE id_usuario = ?";
@@ -246,7 +249,7 @@ function correoRespaldo()
} }
} }
function modificarCorreoRspaldo() function modificarCorreoRespaldo()
{ {
if (!isset($_SESSION['usuario_id']) || ($_SESSION['pendiente_confirmacion'] ?? false)) { if (!isset($_SESSION['usuario_id']) || ($_SESSION['pendiente_confirmacion'] ?? false)) {
echo "Error: no se ha iniciado sesión o sesión incompleta."; echo "Error: no se ha iniciado sesión o sesión incompleta.";
@@ -254,6 +257,7 @@ function modificarCorreoRspaldo()
} }
$id_usuario = $_SESSION['usuario_id']; $id_usuario = $_SESSION['usuario_id'];
$conn = getConnection(); $conn = getConnection();
$correo = $_POST['email-respaldo'] ?? ''; $correo = $_POST['email-respaldo'] ?? '';
@@ -283,6 +287,7 @@ function eliminarCorreoRespaldo()
} }
$id_usuario = $_SESSION['usuario_id']; $id_usuario = $_SESSION['usuario_id'];
$conn = getConnection(); $conn = getConnection();
$query = "DELETE FROM correo_respaldo WHERE id_usuario = ?"; $query = "DELETE FROM correo_respaldo WHERE id_usuario = ?";
@@ -309,6 +314,7 @@ function obtenerCorreos($conn, $id_usuario)
$sql_dos_factores = "SELECT dos_factores FROM usuarios_sistema WHERE id_usuario = ?"; $sql_dos_factores = "SELECT dos_factores FROM usuarios_sistema WHERE id_usuario = ?";
$params = [$id_usuario]; $params = [$id_usuario];
$stmt_dos_factores = sqlsrv_prepare($conn, $sql_dos_factores, $params); $stmt_dos_factores = sqlsrv_prepare($conn, $sql_dos_factores, $params);
if ($stmt_dos_factores && sqlsrv_execute($stmt_dos_factores)) { if ($stmt_dos_factores && sqlsrv_execute($stmt_dos_factores)) {
if ($row = sqlsrv_fetch_array($stmt_dos_factores, SQLSRV_FETCH_ASSOC)) { if ($row = sqlsrv_fetch_array($stmt_dos_factores, SQLSRV_FETCH_ASSOC)) {
$correos['dos_factores'] = (int)$row['dos_factores']; // MEJORADO: Cast a int $correos['dos_factores'] = (int)$row['dos_factores']; // MEJORADO: Cast a int
@@ -318,6 +324,7 @@ function obtenerCorreos($conn, $id_usuario)
// Obtener correo_extra // Obtener correo_extra
$sql_extra = "SELECT correo FROM correo_extra WHERE id_usuario = ?"; $sql_extra = "SELECT correo FROM correo_extra WHERE id_usuario = ?";
$stmt_extra = sqlsrv_prepare($conn, $sql_extra, $params); $stmt_extra = sqlsrv_prepare($conn, $sql_extra, $params);
if ($stmt_extra && sqlsrv_execute($stmt_extra)) { if ($stmt_extra && sqlsrv_execute($stmt_extra)) {
if ($row = sqlsrv_fetch_array($stmt_extra, SQLSRV_FETCH_ASSOC)) { if ($row = sqlsrv_fetch_array($stmt_extra, SQLSRV_FETCH_ASSOC)) {
$correos['correo_extra'] = $row['correo']; $correos['correo_extra'] = $row['correo'];
@@ -327,6 +334,7 @@ function obtenerCorreos($conn, $id_usuario)
// Obtener correo_respaldo // Obtener correo_respaldo
$sql_respaldo = "SELECT correo FROM correo_respaldo WHERE id_usuario = ?"; $sql_respaldo = "SELECT correo FROM correo_respaldo WHERE id_usuario = ?";
$stmt_respaldo = sqlsrv_prepare($conn, $sql_respaldo, $params); $stmt_respaldo = sqlsrv_prepare($conn, $sql_respaldo, $params);
if ($stmt_respaldo && sqlsrv_execute($stmt_respaldo)) { if ($stmt_respaldo && sqlsrv_execute($stmt_respaldo)) {
if ($row = sqlsrv_fetch_array($stmt_respaldo, SQLSRV_FETCH_ASSOC)) { if ($row = sqlsrv_fetch_array($stmt_respaldo, SQLSRV_FETCH_ASSOC)) {
$correos['correo_respaldo'] = $row['correo']; $correos['correo_respaldo'] = $row['correo'];

View File

@@ -1,14 +1,19 @@
<?php <?php
require_once __DIR__ . '/../helpers/session.php'; require_once __DIR__ . '/../helpers/session.php';
require_once __DIR__ . '/../../config/database.php'; require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../helpers/crypto.php';
// 1) Composer autoload (phpdotenv y demás libs) // 1) Composer autoload (phpdotenv y demás libs)
require_once __DIR__ . '/../../vendor/autoload.php'; require_once __DIR__ . '/../../vendor/autoload.php';
// 2) Carga nuestro helper de entorno y dispara la carga de .env // 2) Carga nuestro helper de entorno y dispara la carga de .env
require_once __DIR__ . '/../helpers/env.php'; require_once __DIR__ . '/../helpers/env.php';
loadEnv();
require_once __DIR__ . '/../helpers/crypto.php'; use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use Dompdf\Dompdf;
use Dompdf\Options;
loadEnv();
/** Obtiene (y cachea en sesión) el JWT de la API usando las credenciales de $_ENV **/ /** Obtiene (y cachea en sesión) el JWT de la API usando las credenciales de $_ENV **/
/** Obtiene (y cachea) el JWT de la API usando credenciales de $_ENV /** Obtiene (y cachea) el JWT de la API usando credenciales de $_ENV
@@ -70,17 +75,18 @@ function lista()
exit; exit;
} }
$id_importador = $_SESSION['usuario_id']; $id_importador = $_SESSION['usuario_id'];
$conn = getConnection(); $conn = getConnection();
// ✅ NUEVO: Obtener la agencia actual del usuario // ✅ 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]); $stmt = sqlsrv_query($conn, "SELECT id_agencia_en_uso FROM dbo.usuarios_sistema WHERE id_usuario = ?", [$id_importador]);
$id_agencia = null; $id_agencia = null;
if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$id_agencia = $row['id_agencia_en_uso']; $id_agencia = $row['id_agencia_en_uso'];
} }
$sql = " $sql = "SELECT
SELECT
f.*, f.*,
tr.nombre AS transportista, tr.nombre AS transportista,
(c.nombre + ' ' + c.apellido) AS chofer, (c.nombre + ' ' + c.apellido) AS chofer,
@@ -102,6 +108,7 @@ function lista()
ORDER BY f.created_at DESC ORDER BY f.created_at DESC
"; ";
$stmt = sqlsrv_query($conn, $sql, [$id_importador, $id_agencia]); $stmt = sqlsrv_query($conn, $sql, [$id_importador, $id_agencia]);
if ($stmt === false) { if ($stmt === false) {
die("Error en lista(): " . print_r(sqlsrv_errors(), true)); die("Error en lista(): " . print_r(sqlsrv_errors(), true));
} }
@@ -126,11 +133,13 @@ function crear()
} }
$id_importador = $_SESSION['usuario_id']; $id_importador = $_SESSION['usuario_id'];
$conn = getConnection(); $conn = getConnection();
// ✅ NUEVO: Obtener la agencia actual del usuario // ✅ 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]); $stmt = sqlsrv_query($conn, "SELECT id_agencia_en_uso FROM dbo.usuarios_sistema WHERE id_usuario = ?", [$id_importador]);
if ($stmt === false) { die(print_r(sqlsrv_errors(), true)); } if ($stmt === false) { die(print_r(sqlsrv_errors(), true)); }
$id_agencia = null; $id_agencia = null;
if ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { $id_agencia = $row['id_agencia_en_uso']; } if ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { $id_agencia = $row['id_agencia_en_uso']; }
@@ -238,10 +247,12 @@ function guardar()
} }
$id_importador = $_SESSION['usuario_id']; $id_importador = $_SESSION['usuario_id'];
$conn = getConnection(); $conn = getConnection();
// ✅ Obtener id_agencia_en_uso del usuario // ✅ 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]); $stmtAgencia = sqlsrv_query($conn, "SELECT id_agencia_en_uso FROM dbo.usuarios_sistema WHERE id_usuario = ?", [$id_importador]);
$id_agencia = null; $id_agencia = null;
if ($stmtAgencia && $row = sqlsrv_fetch_array($stmtAgencia, SQLSRV_FETCH_ASSOC)) { if ($stmtAgencia && $row = sqlsrv_fetch_array($stmtAgencia, SQLSRV_FETCH_ASSOC)) {
$id_agencia = $row['id_agencia_en_uso']; $id_agencia = $row['id_agencia_en_uso'];
@@ -282,13 +293,13 @@ function guardar()
} }
// Foto solicitud // Foto solicitud
$fotoUrl=null; $fotoUrl = null;
if (!empty($_FILES['foto_solicitud']['tmp_name']) && $_FILES['foto_solicitud']['error']===UPLOAD_ERR_OK) { if (!empty($_FILES['foto_solicitud']['tmp_name']) && $_FILES['foto_solicitud']['error']===UPLOAD_ERR_OK) {
$ext=pathinfo($_FILES['foto_solicitud']['name'],PATHINFO_EXTENSION); $ext = pathinfo($_FILES['foto_solicitud']['name'], PATHINFO_EXTENSION);
$dest=__DIR__.'/../../public/uploads/solicitud_'.uniqid().".$ext"; $dest = __DIR__.'/../../public/uploads/solicitud_'.uniqid().".$ext";
if (!is_dir(dirname($dest))) mkdir(dirname($dest),0755,true); if (!is_dir(dirname($dest))) mkdir(dirname($dest),0755,true);
if(move_uploaded_file($_FILES['foto_solicitud']['tmp_name'],$dest)) { if(move_uploaded_file($_FILES['foto_solicitud']['tmp_name'],$dest)) {
$fotoUrl="/IMPORTADORES/public/uploads/".basename($dest); $fotoUrl = "/IMPORTADORES/public/uploads/".basename($dest);
} }
} }
@@ -311,9 +322,7 @@ function guardar()
$proveedor_clave, $proveedor_clave,
$patente_id ? (int)$patente_id : null $patente_id ? (int)$patente_id : null
]; ];
$sql = "INSERT INTO dbo.solicitud_importacion_factura
$sql = "
INSERT INTO dbo.solicitud_importacion_factura
(id_importador, id_agencia, aduana, anexo22_apendice, numero_factura, (id_importador, id_agencia, aduana, anexo22_apendice, numero_factura,
fecha_factura, numero_pedimento, incoterm, pais_proveedor, tipo_moneda, fecha_factura, numero_pedimento, incoterm, pais_proveedor, tipo_moneda,
valor_factura, vinculacion, transportista_id, chofer_id, valor_factura, vinculacion, transportista_id, chofer_id,
@@ -321,8 +330,8 @@ function guardar()
OUTPUT INSERTED.id_solicitud OUTPUT INSERTED.id_solicitud
VALUES(?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) VALUES(?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
"; ";
$stmt = sqlsrv_query($conn, $sql, $params, ['Scrollable' => SQLSRV_CURSOR_KEYSET]); $stmt = sqlsrv_query($conn, $sql, $params, ['Scrollable' => SQLSRV_CURSOR_KEYSET]);
if ($stmt === false) { if ($stmt === false) {
die("❌ Error ejecutando INSERT con OUTPUT: " . print_r(sqlsrv_errors(), true)); die("❌ Error ejecutando INSERT con OUTPUT: " . print_r(sqlsrv_errors(), true));
} }
@@ -336,12 +345,8 @@ function guardar()
try { try {
// Verificar configuración de notificaciones del usuario // Verificar configuración de notificaciones del usuario
$sqlNotif = " $sqlNotif = "SELECT
SELECT u.nombre, u.email, u.notificaciones, u.notificaciones_extra,
u.nombre,
u.email,
u.notificaciones,
u.notificaciones_extra,
COALESCE(p.nuevas_solicitudes, 0) as nuevas_solicitudes, COALESCE(p.nuevas_solicitudes, 0) as nuevas_solicitudes,
ce.correo as correo_extra ce.correo as correo_extra
FROM usuarios_sistema u FROM usuarios_sistema u
@@ -351,7 +356,6 @@ function guardar()
ON u.id_usuario = ce.id_usuario ON u.id_usuario = ce.id_usuario
WHERE u.id_usuario = ? WHERE u.id_usuario = ?
"; ";
$stmtNotif = sqlsrv_prepare($conn, $sqlNotif, [$id_importador]); $stmtNotif = sqlsrv_prepare($conn, $sqlNotif, [$id_importador]);
if ($stmtNotif && sqlsrv_execute($stmtNotif)) { if ($stmtNotif && sqlsrv_execute($stmtNotif)) {
@@ -452,10 +456,8 @@ function guardar()
} }
/** Función para generar la notificación **/ /** Función para generar la notificación **/
use PHPMailer\PHPMailer\PHPMailer; function enviarNotificacionNuevaSolicitud($email, $nombreUsuario, $datosSolicitud, $esCorreoExtra = false)
use PHPMailer\PHPMailer\Exception; {
function enviarNotificacionNuevaSolicitud($email, $nombreUsuario, $datosSolicitud, $esCorreoExtra = false) {
$mail = new PHPMailer(true); $mail = new PHPMailer(true);
try { try {
@@ -558,16 +560,19 @@ function editar()
} }
$id_solicitud = $_GET['id']??null; $id_solicitud = $_GET['id']??null;
if(!$id_solicitud || !is_numeric($id_solicitud)) { if(!$id_solicitud || !is_numeric($id_solicitud)) {
die("❌ ID inválido."); die("❌ ID inválido.");
} }
$id_importador = $_SESSION['usuario_id']; $id_importador = $_SESSION['usuario_id'];
$conn = getConnection(); $conn = getConnection();
// ✅ NUEVO: Obtener la agencia actual del usuario // ✅ 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]); $stmtAg = sqlsrv_query($conn, "SELECT id_agencia_en_uso FROM dbo.usuarios_sistema WHERE id_usuario = ?", [$id_importador]);
if ($stmtAg === false) { die(print_r(sqlsrv_errors(), true)); } if ($stmtAg === false) { die(print_r(sqlsrv_errors(), true)); }
$id_agencia = null; $id_agencia = null;
if ($row = sqlsrv_fetch_array($stmtAg, SQLSRV_FETCH_ASSOC)) { $id_agencia = $row['id_agencia_en_uso']; } if ($row = sqlsrv_fetch_array($stmtAg, SQLSRV_FETCH_ASSOC)) { $id_agencia = $row['id_agencia_en_uso']; }
@@ -575,10 +580,12 @@ function editar()
if($stmt === false) { if($stmt === false) {
die(print_r(sqlsrv_errors(),true)); die(print_r(sqlsrv_errors(),true));
} }
$factura = sqlsrv_fetch_array($stmt,SQLSRV_FETCH_ASSOC); $factura = sqlsrv_fetch_array($stmt,SQLSRV_FETCH_ASSOC);
if(!$factura) { if(!$factura) {
die("❌ No autorizado."); die("❌ No autorizado.");
} }
if($factura['fecha_factura'] instanceof DateTime) { if($factura['fecha_factura'] instanceof DateTime) {
$factura['fecha_factura'] = $factura['fecha_factura']->format('Y-m-d'); $factura['fecha_factura'] = $factura['fecha_factura']->format('Y-m-d');
} }
@@ -595,24 +602,24 @@ function editar()
// Transportistas // Transportistas
$transportistas = []; $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; } while ($r = sqlsrv_fetch_array($stmtT, SQLSRV_FETCH_ASSOC)) { $transportistas[] = $r; }
// Choferes // Choferes
$choferes = []; $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 $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]); 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
$paises = []; $paises = [];
$stmtP = sqlsrv_query($conn, "SELECT id_pais, nombre FROM dbo.paises ORDER BY nombre"); $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;} while ($r = sqlsrv_fetch_array($stmtP, SQLSRV_FETCH_ASSOC)) { $paises[] = $r;}
// Aduanas // Aduanas
$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"); $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; } while ($r = sqlsrv_fetch_array($stmtA, SQLSRV_FETCH_ASSOC)) { $aduanas[] = $r; }
// Incoterms // Incoterms
$incoterms = []; $incoterms = [];
$stmtI = sqlsrv_query($conn, "SELECT INCOTERM, DESCESPANOL FROM dbo.gIncoterms ORDER BY INCOTERM"); $stmtI = sqlsrv_query($conn, "SELECT INCOTERM, DESCESPANOL FROM dbo.gIncoterms ORDER BY INCOTERM");
while($r = sqlsrv_fetch_array($stmtI,SQLSRV_FETCH_ASSOC)) { $incoterms[] = $r; } while ($r = sqlsrv_fetch_array($stmtI, SQLSRV_FETCH_ASSOC)) { $incoterms[] = $r; }
// Unidades de Medida // Unidades de Medida
$unidades_medida = []; $unidades_medida = [];
$stmtU = sqlsrv_query($conn, "SELECT id, descripcion FROM dbo.unidades_medida_apendice7 ORDER BY id"); $stmtU = sqlsrv_query($conn, "SELECT id, descripcion FROM dbo.unidades_medida_apendice7 ORDER BY id");
@@ -620,12 +627,9 @@ function editar()
// Partidas existentes // Partidas existentes
$partidas = []; $partidas = [];
$stmtPar = sqlsrv_query($conn, $stmtPar = sqlsrv_query($conn, "SELECT id_partida, descripcion, cantidad_comercial, cantidad_tarifa, valor_factura, peso_bruto, unidad_comercial_id, tasa_preferencial
"SELECT id_partida, descripcion, cantidad_comercial, cantidad_tarifa, valor_factura, peso_bruto, unidad_comercial_id, tasa_preferencial FROM dbo.solicitud_importacion_partidas WHERE id_solicitud = ? ORDER BY id_partida", [(int)$id_solicitud]);
FROM dbo.solicitud_importacion_partidas WHERE id_solicitud=? ORDER BY id_partida", [(int)$id_solicitud]); while ($r = sqlsrv_fetch_array($stmtPar, SQLSRV_FETCH_ASSOC)) { $partidas[]=$r; }
while($r=sqlsrv_fetch_array($stmtPar,SQLSRV_FETCH_ASSOC)) {
$partidas[]=$r;
}
include __DIR__ . '/../../views/solicitud_importacion/editar.php'; include __DIR__ . '/../../views/solicitud_importacion/editar.php';
} }
@@ -638,8 +642,8 @@ function actualizar()
} }
$id_importador = $_SESSION['usuario_id']; $id_importador = $_SESSION['usuario_id'];
$id_solicitud = (int)($_POST['id_solicitud'] ?? 0); $id_solicitud = (int)($_POST['id_solicitud'] ?? 0);
if ($id_solicitud <= 0) { if ($id_solicitud <= 0) {
die("❌ ID inválido."); die("❌ ID inválido.");
} }
@@ -649,6 +653,7 @@ function actualizar()
// ✅ NUEVO: Obtener la agencia actual del usuario // ✅ 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]); $stmt = sqlsrv_query($conn, "SELECT id_agencia_en_uso FROM dbo.usuarios_sistema WHERE id_usuario = ?", [$id_importador]);
$id_agencia = null; $id_agencia = null;
if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$id_agencia = $row['id_agencia_en_uso']; $id_agencia = $row['id_agencia_en_uso'];
@@ -656,28 +661,20 @@ function actualizar()
// 2) Obtener URL de foto actual desde BD para conservar si no suben nueva // 2) Obtener URL de foto actual desde BD para conservar si no suben nueva
$fotoUrl = null; $fotoUrl = null;
$stmtFoto = sqlsrv_query( $stmtFoto = sqlsrv_query($conn, "SELECT foto_solicitud_url FROM dbo.solicitud_importacion_factura WHERE id_solicitud = ? AND id_importador = ? AND id_agencia = ?", [ $id_solicitud, $_SESSION['usuario_id'], $id_agencia ] );
$conn,
"SELECT foto_solicitud_url
FROM dbo.solicitud_importacion_factura
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))) { if ($stmtFoto !== false && ($row = sqlsrv_fetch_array($stmtFoto, SQLSRV_FETCH_ASSOC))) {
$fotoUrl = $row['foto_solicitud_url']; $fotoUrl = $row['foto_solicitud_url'];
} }
// 3) Procesar posible nueva foto // 3) Procesar posible nueva foto
if (!empty($_FILES['foto_solicitud']['tmp_name']) if (!empty($_FILES['foto_solicitud']['tmp_name']) && $_FILES['foto_solicitud']['error'] === UPLOAD_ERR_OK) {
&& $_FILES['foto_solicitud']['error'] === UPLOAD_ERR_OK) {
$ext = pathinfo($_FILES['foto_solicitud']['name'], PATHINFO_EXTENSION); $ext = pathinfo($_FILES['foto_solicitud']['name'], PATHINFO_EXTENSION);
$dest = __DIR__ . '/../../public/uploads/solicitud_' . uniqid() . ".$ext"; $dest = __DIR__ . '/../../public/uploads/solicitud_' . uniqid() . ".$ext";
if (!is_dir(dirname($dest))) {
mkdir(dirname($dest), 0755, true); if (!is_dir(dirname($dest))) { mkdir(dirname($dest), 0755, true); }
}
if (move_uploaded_file($_FILES['foto_solicitud']['tmp_name'], $dest)) { if (move_uploaded_file($_FILES['foto_solicitud']['tmp_name'], $dest)) { $fotoUrl = "/IMPORTADORES/public/uploads/" . basename($dest); }
$fotoUrl = "/IMPORTADORES/public/uploads/" . basename($dest);
}
} }
// 4) Extraer campos del formulario // 4) Extraer campos del formulario
@@ -697,9 +694,7 @@ function actualizar()
// ✅ NUEVO: Validar que la patente pertenezca a la agencia del usuario (si se seleccionó una) // ✅ NUEVO: Validar que la patente pertenezca a la agencia del usuario (si se seleccionó una)
if ($patente_id) { if ($patente_id) {
$stmtValidatePatente = sqlsrv_query($conn, $stmtValidatePatente = sqlsrv_query($conn, "SELECT id_agente FROM dbo.agentes_aduanales WHERE id_agente = ? AND id_agencia = ? AND activo = 1", [$patente_id, $id_agencia]);
"SELECT id_agente FROM dbo.agentes_aduanales WHERE id_agente = ? AND id_agencia = ? AND activo = 1",
[$patente_id, $id_agencia]);
if (!$stmtValidatePatente || !sqlsrv_fetch_array($stmtValidatePatente, SQLSRV_FETCH_ASSOC)) { if (!$stmtValidatePatente || !sqlsrv_fetch_array($stmtValidatePatente, SQLSRV_FETCH_ASSOC)) {
die("❌ La patente seleccionada no es válida para su agencia."); die("❌ La patente seleccionada no es válida para su agencia.");
@@ -733,10 +728,8 @@ function actualizar()
$_SESSION['usuario_id'], $_SESSION['usuario_id'],
$id_agencia $id_agencia
]; ];
$sqlU = "UPDATE dbo.solicitud_importacion_factura SET
$sqlU = " aduana = ?,
UPDATE dbo.solicitud_importacion_factura
SET aduana = ?,
anexo22_apendice = ?, anexo22_apendice = ?,
numero_factura = ?, numero_factura = ?,
fecha_factura = ?, fecha_factura = ?,
@@ -756,22 +749,22 @@ function actualizar()
AND id_importador = ? AND id_importador = ?
AND id_agencia = ? AND id_agencia = ?
"; ";
$stmtU = sqlsrv_query($conn, $sqlU, $paramsU); $stmtU = sqlsrv_query($conn, $sqlU, $paramsU);
if ($stmtU === false) { if ($stmtU === false) {
die("❌ Error ejecutando UPDATE: " . print_r(sqlsrv_errors(), true)); die("❌ Error ejecutando UPDATE: " . print_r(sqlsrv_errors(), true));
} }
// 7) Borrar partidas anteriores // 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) { if ($del === false) {
die("❌ Error borrando partidas previas: " . print_r(sqlsrv_errors(), true)); die("❌ Error borrando partidas previas: " . print_r(sqlsrv_errors(), true));
} }
// 8) Reinsertar partidas desde el formulario // 8) Reinsertar partidas desde el formulario
if (!empty($_POST['partidas']) && is_array($_POST['partidas'])) { if (!empty($_POST['partidas']) && is_array($_POST['partidas'])) {
$sqlP = " $sqlP = "INSERT INTO dbo.solicitud_importacion_partidas
INSERT INTO dbo.solicitud_importacion_partidas
(id_solicitud, descripcion, cantidad_comercial, cantidad_tarifa, (id_solicitud, descripcion, cantidad_comercial, cantidad_tarifa,
valor_factura, peso_bruto, unidad_comercial_id, tasa_preferencial) valor_factura, peso_bruto, unidad_comercial_id, tasa_preferencial)
VALUES (?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
@@ -798,6 +791,7 @@ function actualizar()
$tasaPref $tasaPref
]; ];
$stmtP = sqlsrv_query($conn, $sqlP, $paramsP); $stmtP = sqlsrv_query($conn, $sqlP, $paramsP);
if ($stmtP === false) { if ($stmtP === false) {
die("❌ Error insertando partida #$i: " . print_r(sqlsrv_errors(), true)); die("❌ Error insertando partida #$i: " . print_r(sqlsrv_errors(), true));
} }
@@ -811,19 +805,24 @@ function actualizar()
} }
/** “Soft-delete” de una factura **/ /** “Soft-delete” de una factura **/
function eliminar() { function eliminar()
{
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login'); header('Location: /IMPORTADORES/login');
exit; exit;
} }
$id = (int) ($_GET['id'] ?? 0); $id = (int) ($_GET['id'] ?? 0);
$conn = getConnection(); $conn = getConnection();
sqlsrv_query($conn, "UPDATE dbo.solicitud_importacion_factura SET status = 0, updated_at = GETDATE() WHERE id_solicitud = ? AND id_importador = ?",[$id,$_SESSION['usuario_id']]); sqlsrv_query($conn, "UPDATE dbo.solicitud_importacion_factura SET status = 0, updated_at = GETDATE() WHERE id_solicitud = ? AND id_importador = ?",[$id,$_SESSION['usuario_id']]);
header('Location: /IMPORTADORES/solicitud_importacion/lista?deleted=ok'); exit; header('Location: /IMPORTADORES/solicitud_importacion/lista?deleted=ok'); exit;
} }
function actualizar_masivo() { function actualizar_masivo()
{
header('Content-Type: application/json; charset=utf-8'); header('Content-Type: application/json; charset=utf-8');
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
@@ -847,6 +846,7 @@ function actualizar_masivo() {
} }
$conn = getConnection(); $conn = getConnection();
$usuarioId = $_SESSION['usuario_id']; $usuarioId = $_SESSION['usuario_id'];
$token = ($status === 2) ? getApiToken() : null; $token = ($status === 2) ? getApiToken() : null;
@@ -888,18 +888,20 @@ function actualizar_masivo() {
exit; exit;
} }
function generarPedimentoDesdeSolicitud($conn, $id, $usuarioId, $token) { function generarPedimentoDesdeSolicitud($conn, $id, $usuarioId, $token)
{
try { try {
// Consulta solicitud // Consulta solicitud
$sqlSel = "SELECT *, '9999' as patente FROM dbo.solicitud_importacion_factura WHERE id_solicitud = ? AND id_importador = ?"; $sqlSel = "SELECT *, '9999' as patente FROM dbo.solicitud_importacion_factura WHERE id_solicitud = ? AND id_importador = ?";
$stmtSel = sqlsrv_query($conn, $sqlSel, [$id, $usuarioId]); $stmtSel = sqlsrv_query($conn, $sqlSel, [$id, $usuarioId]);
$solicitud = sqlsrv_fetch_array($stmtSel, SQLSRV_FETCH_ASSOC); $solicitud = sqlsrv_fetch_array($stmtSel, SQLSRV_FETCH_ASSOC);
if (!$solicitud) return ['success' => false, 'error' => 'Solicitud no encontrada']; if (!$solicitud) return ['success' => false, 'error' => 'Solicitud no encontrada'];
// Fechas // Fechas
$solicitud['fecha_factura'] = $solicitud['fecha_factura'] instanceof DateTime ? $solicitud['fecha_factura']->format('Y-m-d') : $solicitud['fecha_factura']; $solicitud['fecha_factura'] = $solicitud['fecha_factura'] instanceof DateTime ? $solicitud['fecha_factura'] ->format('Y-m-d') : $solicitud['fecha_factura'];
$solicitud['created_at'] = $solicitud['created_at'] instanceof DateTime ? $solicitud['created_at']->format('Y-m-d\TH:i:s') : $solicitud['created_at']; $solicitud['created_at'] = $solicitud['created_at'] instanceof DateTime ? $solicitud['created_at'] ->format('Y-m-d\TH:i:s') : $solicitud['created_at'];
$solicitud['updated_at'] = $solicitud['updated_at'] instanceof DateTime ? $solicitud['updated_at']->format('Y-m-d\TH:i:s') : $solicitud['updated_at']; $solicitud['updated_at'] = $solicitud['updated_at'] instanceof DateTime ? $solicitud['updated_at'] ->format('Y-m-d\TH:i:s') : $solicitud['updated_at'];
// Partidas // Partidas
$partidas = []; $partidas = [];
@@ -1067,8 +1069,10 @@ function ajax_lista()
echo json_encode(['data' => $dataList]); echo json_encode(['data' => $dataList]);
} }
function update_status() { function update_status()
{
header('Content-Type: application/json; charset=utf-8'); header('Content-Type: application/json; charset=utf-8');
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
http_response_code(401); http_response_code(401);
echo json_encode(['error' => 'No autorizado']); echo json_encode(['error' => 'No autorizado']);
@@ -1082,11 +1086,10 @@ function update_status() {
$conn = getConnection(); $conn = getConnection();
// 2) Actualizar el status en la tabla solicitud_importacion_factura // 2) Actualizar el status en la tabla solicitud_importacion_factura
$sql = "UPDATE dbo.solicitud_importacion_factura $sql = "UPDATE dbo.solicitud_importacion_factura SET status = ? WHERE id_solicitud=? AND id_importador=?";
SET status=?
WHERE id_solicitud=? AND id_importador=?";
$params = [$status, $id, $_SESSION['usuario_id']]; $params = [$status, $id, $_SESSION['usuario_id']];
$stmt = sqlsrv_query($conn, $sql, $params); $stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt === false) { if ($stmt === false) {
http_response_code(500); http_response_code(500);
echo json_encode(['error' => 'Error al actualizar status']); echo json_encode(['error' => 'Error al actualizar status']);
@@ -1095,24 +1098,21 @@ function update_status() {
// 3) Obtener datos del usuario y solicitud para notificación // 3) Obtener datos del usuario y solicitud para notificación
try { try {
$sqlNotif = " $sqlNotif = "SELECT
SELECT u.nombre, u.email, u.notificaciones, u.notificaciones_extra,
u.nombre,
u.email,
u.notificaciones,
u.notificaciones_extra,
COALESCE(p.cambio_estado, 0) as cambio_estado, COALESCE(p.cambio_estado, 0) as cambio_estado,
ce.correo as correo_extra, ce.correo as correo_extra,
s.numero_factura, s.numero_factura, s.fecha_factura, s.valor_factura, s.tipo_moneda
s.fecha_factura,
s.valor_factura,
s.tipo_moneda
FROM usuarios_sistema u FROM usuarios_sistema u
LEFT JOIN preferencias_notificaciones_usuario p ON u.id_usuario = p.id_usuario LEFT JOIN preferencias_notificaciones_usuario p
LEFT JOIN correo_extra ce ON u.id_usuario = ce.id_usuario ON u.id_usuario = p.id_usuario
INNER JOIN solicitud_importacion_factura s ON s.id_importador = u.id_usuario LEFT JOIN correo_extra ce
WHERE u.id_usuario = ? AND s.id_solicitud = ?"; ON u.id_usuario = ce.id_usuario
INNER JOIN solicitud_importacion_factura s
ON s.id_importador = u.id_usuario
WHERE u.id_usuario = ?
AND s.id_solicitud = ?
";
$stmtNotif = sqlsrv_prepare($conn, $sqlNotif, [$_SESSION['usuario_id'], $id]); $stmtNotif = sqlsrv_prepare($conn, $sqlNotif, [$_SESSION['usuario_id'], $id]);
if ($stmtNotif && sqlsrv_execute($stmtNotif)) { if ($stmtNotif && sqlsrv_execute($stmtNotif)) {
@@ -1126,9 +1126,7 @@ function update_status() {
} }
// Verificar si debe enviar notificaciones de cambio de status // Verificar si debe enviar notificaciones de cambio de status
if ($notifConfig && if ($notifConfig && $notifConfig['notificaciones'] == 1 && $notifConfig['cambio_estado'] == 1) {
$notifConfig['notificaciones'] == 1 &&
$notifConfig['cambio_estado'] == 1) {
// Formatear fecha si es DateTime // Formatear fecha si es DateTime
$fechaFactura = ($notifConfig['fecha_factura'] instanceof DateTime) $fechaFactura = ($notifConfig['fecha_factura'] instanceof DateTime)
@@ -1225,36 +1223,24 @@ function update_status() {
} }
// 4.2) Leer de la BD todos los campos de la cabecera de la solicitud // 4.2) Leer de la BD todos los campos de la cabecera de la solicitud
$sqlSel = " $sqlSel = "SELECT
SELECT s.id_solicitud, s.id_importador, s.aduana, s.numero_pedimento, s.anexo22_apendice,
s.id_solicitud, s.numero_factura, s.fecha_factura, s.incoterm, s.pais_proveedor,
s.id_importador, s.tipo_moneda, s.valor_factura, s.vinculacion, s.transportista_id, s.chofer_id,
s.aduana, s.foto_solicitud_url, s.proveedor_clave, s.created_at, s.updated_at,
s.numero_pedimento,
s.anexo22_apendice,
s.numero_factura,
s.fecha_factura,
s.incoterm,
s.pais_proveedor,
s.tipo_moneda,
s.valor_factura,
s.vinculacion,
s.transportista_id,
s.chofer_id,
s.foto_solicitud_url,
s.proveedor_clave,
s.created_at,
s.updated_at,
'9999' as patente '9999' as patente
FROM dbo.solicitud_importacion_factura s FROM dbo.solicitud_importacion_factura s
WHERE s.id_solicitud = ? AND s.id_importador = ? WHERE s.id_solicitud = ?
AND s.id_importador = ?
"; ";
$stmtSel = sqlsrv_query($conn, $sqlSel, [$id, $_SESSION['usuario_id']]); $stmtSel = sqlsrv_query($conn, $sqlSel, [$id, $_SESSION['usuario_id']]);
if ($stmtSel === false) { if ($stmtSel === false) {
error_log("[update_status] Error al consultar solicitud: " . print_r(sqlsrv_errors(), true)); error_log("[update_status] Error al consultar solicitud: " . print_r(sqlsrv_errors(), true));
echo json_encode(['success' => true, 'warning' => 'Status actualizado, fallo al leer datos para pedimento']); echo json_encode(['success' => true, 'warning' => 'Status actualizado, fallo al leer datos para pedimento']);
exit; exit;
} }
$solicitud = sqlsrv_fetch_array($stmtSel, SQLSRV_FETCH_ASSOC); $solicitud = sqlsrv_fetch_array($stmtSel, SQLSRV_FETCH_ASSOC);
sqlsrv_free_stmt($stmtSel); sqlsrv_free_stmt($stmtSel);
@@ -1278,28 +1264,21 @@ function update_status() {
: $solicitud['updated_at']; : $solicitud['updated_at'];
// 4.4) Obtener todas las partidas asociadas a esta solicitud // 4.4) Obtener todas las partidas asociadas a esta solicitud
$sqlPart = " $sqlPart = "SELECT
SELECT p.id_partida, p.id_solicitud, p.descripcion, p.creado_en, p.cantidad_comercial,
p.id_partida, p.cantidad_tarifa, p.valor_factura, p.peso_bruto, p.unidad_comercial_id, p.tasa_preferencial
p.id_solicitud,
p.descripcion,
p.creado_en,
p.cantidad_comercial,
p.cantidad_tarifa,
p.valor_factura,
p.peso_bruto,
p.unidad_comercial_id,
p.tasa_preferencial
FROM dbo.solicitud_importacion_partidas p FROM dbo.solicitud_importacion_partidas p
WHERE p.id_solicitud = ? WHERE p.id_solicitud = ?
ORDER BY p.id_partida ORDER BY p.id_partida
"; ";
$stmtPart = sqlsrv_query($conn, $sqlPart, [$id]); $stmtPart = sqlsrv_query($conn, $sqlPart, [$id]);
if ($stmtPart === false) { if ($stmtPart === false) {
error_log("[update_status] Error al consultar partidas: " . print_r(sqlsrv_errors(), true)); error_log("[update_status] Error al consultar partidas: " . print_r(sqlsrv_errors(), true));
echo json_encode(['success' => true, 'warning' => 'Status actualizado, fallo al leer partidas para pedimento']); echo json_encode(['success' => true, 'warning' => 'Status actualizado, fallo al leer partidas para pedimento']);
exit; exit;
} }
$partidas = []; $partidas = [];
while ($row = sqlsrv_fetch_array($stmtPart, SQLSRV_FETCH_ASSOC)) { while ($row = sqlsrv_fetch_array($stmtPart, SQLSRV_FETCH_ASSOC)) {
if ($row['creado_en'] instanceof DateTime) { if ($row['creado_en'] instanceof DateTime) {
@@ -1330,7 +1309,6 @@ function update_status() {
"valor_factura" => floatval($solicitud['valor_factura']), "valor_factura" => floatval($solicitud['valor_factura']),
"vinculacion" => intval($solicitud['vinculacion']), "vinculacion" => intval($solicitud['vinculacion']),
"transportista_id" => intval($solicitud['transportista_id']), "transportista_id" => intval($solicitud['transportista_id']),
"created_at" => $createdAt, "created_at" => $createdAt,
"updated_at" => $updatedAt, "updated_at" => $updatedAt,
"transporte_id" => null, "transporte_id" => null,
@@ -1369,17 +1347,9 @@ function update_status() {
$numeroPedimento = $decoded['pedimento']['PEDIMENTO']; $numeroPedimento = $decoded['pedimento']['PEDIMENTO'];
// 3.8) Actualizar localmente el campo numero_pedimento // 3.8) Actualizar localmente el campo numero_pedimento
$sqlUpdPed = " $sqlUpdPed = "UPDATE dbo.solicitud_importacion_factura SET numero_pedimento = ? WHERE id_solicitud = ? AND id_importador = ?";
UPDATE dbo.solicitud_importacion_factura $stmtUpdPed = sqlsrv_query($conn, $sqlUpdPed, [$numeroPedimento, $id, $_SESSION['usuario_id']]);
SET numero_pedimento = ?
WHERE id_solicitud = ?
AND id_importador = ?
";
$stmtUpdPed = sqlsrv_query(
$conn,
$sqlUpdPed,
[$numeroPedimento, $id, $_SESSION['usuario_id']]
);
if ($stmtUpdPed === false) { if ($stmtUpdPed === false) {
error_log("[update_status] Error al actualizar numero_pedimento en BD: " . print_r(sqlsrv_errors(), true)); error_log("[update_status] Error al actualizar numero_pedimento en BD: " . print_r(sqlsrv_errors(), true));
} }
@@ -1408,7 +1378,8 @@ function update_status() {
} }
/** Envía notificación de cambio de estado de solicitud de importación **/ /** Envía notificación de cambio de estado de solicitud de importación **/
function enviarNotificacionCambioStatus($email, $nombreCompleto, $datosSolicitud, $esCorreoExtra = false) { function enviarNotificacionCambioStatus($email, $nombreCompleto, $datosSolicitud, $esCorreoExtra = false)
{
// Validar datos de entrada // Validar datos de entrada
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) { if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
error_log("❌ Email inválido para notificación: $email"); error_log("❌ Email inválido para notificación: $email");
@@ -1491,7 +1462,8 @@ function obtenerInfoStatus($status) {
} }
/** Prepara los datos para el template del email **/ /** Prepara los datos para el template del email **/
function prepararDatosTemplate($datosSolicitud, $nombreCompleto, $statusInfo, $esCorreoExtra) { function prepararDatosTemplate($datosSolicitud, $nombreCompleto, $statusInfo, $esCorreoExtra)
{
return [ return [
'nombreCompleto' => htmlspecialchars($nombreCompleto ?? 'Usuario'), 'nombreCompleto' => htmlspecialchars($nombreCompleto ?? 'Usuario'),
'idSolicitud' => intval($datosSolicitud['id_solicitud'] ?? 0), 'idSolicitud' => intval($datosSolicitud['id_solicitud'] ?? 0),
@@ -1509,7 +1481,8 @@ function prepararDatosTemplate($datosSolicitud, $nombreCompleto, $statusInfo, $e
} }
/** Genera el HTML para la notificación **/ /** Genera el HTML para la notificación **/
function generarHtmlNotificacion($datos) { function generarHtmlNotificacion($datos)
{
$tipoNotificacion = $datos['esCorreoExtra'] ? $tipoNotificacion = $datos['esCorreoExtra'] ?
'<div style="background: #fff3cd; padding: 10px; border-radius: 5px; margin-bottom: 15px; border-left: 4px solid #ffc107;"> '<div style="background: #fff3cd; padding: 10px; border-radius: 5px; margin-bottom: 15px; border-left: 4px solid #ffc107;">
<small><strong>📧 Copia enviada a correo adicional</strong></small> <small><strong>📧 Copia enviada a correo adicional</strong></small>
@@ -1596,9 +1569,6 @@ function generarHtmlNotificacion($datos) {
} }
// Función para generar el PDF // Función para generar el PDF
use Dompdf\Dompdf;
use Dompdf\Options;
function pdf() { function pdf() {
// Verificar que se recibió el ID // Verificar que se recibió el ID
if (!isset($_GET['id'])) { if (!isset($_GET['id'])) {
@@ -1614,29 +1584,20 @@ function pdf() {
$conn = getConnection(); $conn = getConnection();
// 2. Obtener datos de la solicitud principal // 2. Obtener datos de la solicitud principal
$sql = " $sql = "SELECT
SELECT s.*, i.nombre as importador_nombre, i.rfc as importador_rfc, i.calle, i.num_exterior,
s.*, i.num_interior, i.ciudad, i.colonia, i.codigo_postal, i.estado, i.telefono, i.correo,
i.nombre as importador_nombre,
i.rfc as importador_rfc,
i.calle,
i.num_exterior,
i.num_interior,
i.ciudad,
i.colonia,
i.codigo_postal,
i.estado,
i.telefono,
i.correo,
t.nombre as transportista_nombre, t.nombre as transportista_nombre,
c.nombre as chofer_nombre c.nombre as chofer_nombre
FROM solicitud_importacion_factura s FROM solicitud_importacion_factura s
LEFT JOIN informacion_general i ON s.id_importador = i.id_usuario LEFT JOIN informacion_general i
LEFT JOIN transportistas t ON s.transportista_id = t.id_transportista ON s.id_importador = i.id_usuario
LEFT JOIN choferes c ON s.chofer_id = c.id_chofer LEFT JOIN transportistas t
ON s.transportista_id = t.id_transportista
LEFT JOIN choferes c
ON s.chofer_id = c.id_chofer
WHERE s.id_solicitud = ? WHERE s.id_solicitud = ?
"; ";
$params = array($id_solicitud); $params = array($id_solicitud);
$stmt = sqlsrv_query($conn, $sql, $params); $stmt = sqlsrv_query($conn, $sql, $params);
@@ -1660,16 +1621,14 @@ function pdf() {
} }
// 3. Obtener partidas de la solicitud // 3. Obtener partidas de la solicitud
$sql = " $sql = "SELECT
SELECT p.*, u.descripcion as unidad_descripcion
p.*,
u.descripcion as unidad_descripcion
FROM solicitud_importacion_partidas p FROM solicitud_importacion_partidas p
LEFT JOIN unidades_medida_apendice7 u ON p.unidad_comercial_id = u.id LEFT JOIN unidades_medida_apendice7 u
ON p.unidad_comercial_id = u.id
WHERE p.id_solicitud = ? WHERE p.id_solicitud = ?
ORDER BY p.id_partida ORDER BY p.id_partida
"; ";
$params = array($id_solicitud); $params = array($id_solicitud);
$stmt = sqlsrv_query($conn, $sql, $params); $stmt = sqlsrv_query($conn, $sql, $params);
@@ -1693,7 +1652,6 @@ function pdf() {
$configuracion = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); $configuracion = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
// 5. Generar HTML del PDF // 5. Generar HTML del PDF
$html = generarHTMLPDF($solicitud, $partidas, $configuracion, $proveedor_info); $html = generarHTMLPDF($solicitud, $partidas, $configuracion, $proveedor_info);
@@ -1893,7 +1851,6 @@ function generarHTMLPDF($solicitud, $partidas, $configuracion, $proveedor_info =
'GBP' => ['nombre' => 'LIBRAS', 'sufijo' => 'GBP', 'centavos' => 'PENIQUES'], 'GBP' => ['nombre' => 'LIBRAS', 'sufijo' => 'GBP', 'centavos' => 'PENIQUES'],
'JPY' => ['nombre' => 'YENES', 'sufijo' => 'JPY', 'centavos' => 'SEN'] 'JPY' => ['nombre' => 'YENES', 'sufijo' => 'JPY', 'centavos' => 'SEN']
]; ];
$config_moneda = $monedas_config[$moneda_codigo] ?? $monedas_config['MXN']; $config_moneda = $monedas_config[$moneda_codigo] ?? $monedas_config['MXN'];
// Convertir total a texto // Convertir total a texto

View File

@@ -4,55 +4,62 @@ require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../helpers/env.php'; require_once __DIR__ . '/../helpers/env.php';
/** Listado de transportes (sólo activos) para el importador logueado **/ /** Listado de transportes (sólo activos) para el importador logueado **/
function lista() { function lista()
{
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login'); header('Location: /IMPORTADORES/login');
exit; exit;
} }
$usr = $_SESSION['usuario_id']; $usr = $_SESSION['usuario_id'];
$conn = getConnection(); $conn = getConnection();
// Sólo mostrar transportes de los transportistas que le pertenecen al usuario // Sólo mostrar transportes de los transportistas que le pertenecen al usuario
$sql = " $sql = "SELECT
SELECT t.*, (tr.clave_identificador + ' - ' + tr.nombre) AS transportista t.*, (tr.clave_identificador + ' - ' + tr.nombre) AS transportista
FROM dbo.transportes t FROM dbo.transportes t
JOIN dbo.transportistas tr JOIN dbo.transportistas tr
ON t.id_transportista = tr.id_transportista ON t.id_transportista = tr.id_transportista
WHERE tr.id_usuario = ? AND t.status = 1 WHERE tr.id_usuario = ?
AND t.status = 1
ORDER BY t.creado_en DESC ORDER BY t.creado_en DESC
"; ";
$stmt = sqlsrv_query($conn, $sql, [$usr]); $stmt = sqlsrv_query($conn, $sql, [$usr]);
$transportes = []; $transportes = [];
while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { $transportes[] = $r; }
$transportes[] = $r;
}
include __DIR__ . '/../../views/transportes/lista.php'; include __DIR__ . '/../../views/transportes/lista.php';
} }
/** Formulario de alta de transporte **/ /** Formulario de alta de transporte **/
function crear() { function crear()
{
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login'); header('Location: /IMPORTADORES/login');
exit; exit;
} }
$usr = $_SESSION['usuario_id']; $usr = $_SESSION['usuario_id'];
$conn = getConnection(); $conn = getConnection();
// Traer transportistas propios para el select // Traer transportistas propios para el select
$sql = " $sql = "SELECT
SELECT t.id_transportista, t.clave_identificador, t.nombre, t.ciudad, t.domicilio, t.id_transportista, t.clave_identificador, t.nombre, t.ciudad, t.domicilio,
c.nombre AS ciudad_nombre c.nombre AS ciudad_nombre
FROM dbo.transportistas t FROM dbo.transportistas t
LEFT JOIN dbo.ciudades c ON t.ciudad = c.id_ciudad LEFT JOIN dbo.ciudades c
WHERE id_usuario = ? AND activo = 1 ON t.ciudad = c.id_ciudad
WHERE id_usuario = ?
AND activo = 1
ORDER BY nombre ORDER BY nombre
"; ";
$stmt = sqlsrv_query($conn, $sql, [$usr]); $stmt = sqlsrv_query($conn, $sql, [$usr]);
$transportistas = []; $transportistas = [];
while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { $transportistas[] = $r; }
$transportistas[] = $r;
}
include __DIR__ . '/../../views/transportes/crear.php'; include __DIR__ . '/../../views/transportes/crear.php';
} }
@@ -74,11 +81,10 @@ function guardar()
// Validar que el transportista pertenece al usuario actual // Validar que el transportista pertenece al usuario actual
$conn = getConnection(); $conn = getConnection();
$sqlCheck = "
SELECT 1 FROM dbo.transportistas $sqlCheck = "SELECT 1 FROM dbo.transportistas WHERE id_transportista = ? AND id_usuario = ? AND activo = 1";
WHERE id_transportista = ? AND id_usuario = ? AND activo = 1
";
$stmtCheck = sqlsrv_query($conn, $sqlCheck, [$idTrans, $_SESSION['usuario_id']]); $stmtCheck = sqlsrv_query($conn, $sqlCheck, [$idTrans, $_SESSION['usuario_id']]);
if (!sqlsrv_fetch($stmtCheck)) { if (!sqlsrv_fetch($stmtCheck)) {
die("❌ Transportista no válido o no autorizado."); die("❌ Transportista no válido o no autorizado.");
} }
@@ -114,11 +120,7 @@ function guardar()
} }
// Insertar el nuevo transporte // Insertar el nuevo transporte
$sql = " $sql = "INSERT INTO dbo.transportes (vehiculo, identificador_fiscal, foto_url, status, id_transportista) VALUES (?, ?, ?, 1, ?)";
INSERT INTO dbo.transportes
(vehiculo, identificador_fiscal, foto_url, status, id_transportista)
VALUES (?, ?, ?, 1, ?)
";
$params = [$vehiculo, $identFiscal, $fotoUrl, $idTrans]; $params = [$vehiculo, $identFiscal, $fotoUrl, $idTrans];
$stmt = sqlsrv_query($conn, $sql, $params); $stmt = sqlsrv_query($conn, $sql, $params);
@@ -139,20 +141,24 @@ function guardar()
} }
/** Formulario de edición **/ /** Formulario de edición **/
function editar() { function editar()
{
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login'); header('Location: /IMPORTADORES/login');
exit; exit;
} }
$id = $_GET['id'] ?? null; $id = $_GET['id'] ?? null;
if (!$id || !is_numeric($id)) { if (!$id || !is_numeric($id)) {
die("❌ ID inválido."); die("❌ ID inválido.");
} }
$conn = getConnection(); $conn = getConnection();
// Validar pertenencia igual que en index() // Validar pertenencia igual que en index()
$sql = " $sql = "SELECT
SELECT t.*, tr.nombre AS transportista t.*, tr.nombre AS transportista
FROM dbo.transportes t FROM dbo.transportes t
JOIN dbo.transportistas tr JOIN dbo.transportistas tr
ON t.id_transportista = tr.id_transportista ON t.id_transportista = tr.id_transportista
@@ -161,30 +167,36 @@ function editar() {
AND t.status = 1 AND t.status = 1
"; ";
$stmt = sqlsrv_query($conn, $sql, [$id, $_SESSION['usuario_id']]); $stmt = sqlsrv_query($conn, $sql, [$id, $_SESSION['usuario_id']]);
$t = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); $t = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
if (!$t) die("❌ Transporte no encontrado o no autorizado."); if (!$t) die("❌ Transporte no encontrado o no autorizado.");
// Mismo select de transportistas que en crear() // Mismo select de transportistas que en crear()
$sql2 = " $sql2 = "SELECT
SELECT t.id_transportista, t.clave_identificador, t.nombre, t.ciudad, t.domicilio, t.id_transportista, t.clave_identificador, t.nombre, t.ciudad, t.domicilio,
c.nombre AS ciudad_nombre c.nombre AS ciudad_nombre
FROM dbo.transportistas t FROM dbo.transportistas t
LEFT JOIN dbo.ciudades c ON t.ciudad = c.id_ciudad LEFT JOIN dbo.ciudades c
WHERE id_usuario = ? AND activo = 1 ON t.ciudad = c.id_ciudad
WHERE id_usuario = ?
AND activo = 1
ORDER BY nombre ORDER BY nombre
"; ";
$stmt2 = sqlsrv_query($conn, $sql2, [$_SESSION['usuario_id']]); $stmt2 = sqlsrv_query($conn, $sql2, [$_SESSION['usuario_id']]);
$transportistas = []; $transportistas = [];
while ($r=sqlsrv_fetch_array($stmt2,SQLSRV_FETCH_ASSOC)) $transportistas[]=$r; while ($r = sqlsrv_fetch_array($stmt2, SQLSRV_FETCH_ASSOC)) { $transportistas[] = $r; }
include __DIR__ . '/../../views/transportes/editar.php'; include __DIR__ . '/../../views/transportes/editar.php';
} }
/** Procesa la actualización **/ /** Procesa la actualización **/
function actualizar() { function actualizar()
{
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
die("⚠️ No autorizado."); die("⚠️ No autorizado.");
} }
$id = $_POST['id_transporte'] ?? null; $id = $_POST['id_transporte'] ?? null;
$vehiculo = trim($_POST['vehiculo'] ?? ''); $vehiculo = trim($_POST['vehiculo'] ?? '');
$identFiscal = trim($_POST['identificador_fiscal'] ?? ''); $identFiscal = trim($_POST['identificador_fiscal'] ?? '');
@@ -197,17 +209,15 @@ function actualizar() {
$conn = getConnection(); $conn = getConnection();
// Antes del UPDATE, validar que el transporte pertenece al usuario // Antes del UPDATE, validar que el transporte pertenece al usuario
$sqlCheck = " $sqlCheck = "SELECT 1 FROM dbo.transportes t JOIN dbo.transportistas tr ON t.id_transportista = tr.id_transportista wHERE t.id_transporte = ? AND tr.id_usuario = ?";
SELECT 1 FROM dbo.transportes t
JOIN dbo.transportistas tr ON t.id_transportista = tr.id_transportista
wHERE t.id_transporte = ? AND tr.id_usuario = ?
";
$stmtCheck = sqlsrv_query($conn, $sqlCheck, [$id, $_SESSION['usuario_id']]); $stmtCheck = sqlsrv_query($conn, $sqlCheck, [$id, $_SESSION['usuario_id']]);
if ($stmtCheck === false) { if ($stmtCheck === false) {
$errors = sqlsrv_errors(); $errors = sqlsrv_errors();
error_log("Error SQL al validar transporte: " . print_r($errors, true)); error_log("Error SQL al validar transporte: " . print_r($errors, true));
die("❌ Error en la validación SQL."); die("❌ Error en la validación SQL.");
} }
if (!sqlsrv_fetch($stmtCheck)) { if (!sqlsrv_fetch($stmtCheck)) {
die("❌ No autorizado para modificar este transporte."); die("❌ No autorizado para modificar este transporte.");
} }
@@ -237,8 +247,7 @@ function actualizar() {
// —– Construye el UPDATE dinámico —– // —– Construye el UPDATE dinámico —–
if ($fotoUrl) { if ($fotoUrl) {
$sql = " $sql = "UPDATE dbo.transportes SET
UPDATE dbo.transportes SET
vehiculo = ?, vehiculo = ?,
identificador_fiscal = ?, identificador_fiscal = ?,
id_transportista = ?, id_transportista = ?,
@@ -247,8 +256,7 @@ function actualizar() {
"; ";
$params = [$vehiculo, $identFiscal, $idTrans, $fotoUrl, $id]; $params = [$vehiculo, $identFiscal, $idTrans, $fotoUrl, $id];
} else { } else {
$sql = " $sql = "UPDATE dbo.transportes SET
UPDATE dbo.transportes SET
vehiculo = ?, vehiculo = ?,
identificador_fiscal = ?, identificador_fiscal = ?,
id_transportista = ? id_transportista = ?
@@ -256,8 +264,8 @@ function actualizar() {
"; ";
$params = [$vehiculo, $identFiscal, $idTrans, $id]; $params = [$vehiculo, $identFiscal, $idTrans, $id];
} }
$stmt = sqlsrv_query($conn, $sql, $params); $stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt === false) { if ($stmt === false) {
$errors = sqlsrv_errors(); $errors = sqlsrv_errors();
error_log("Error SQL en actualizar transporte: " . print_r($errors, true)); error_log("Error SQL en actualizar transporte: " . print_r($errors, true));
@@ -275,28 +283,35 @@ function actualizar() {
} }
/** “Soft-delete” (status = 0) **/ /** “Soft-delete” (status = 0) **/
function eliminar() { function eliminar()
{
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login'); header('Location: /IMPORTADORES/login');
exit; exit;
} }
$id = $_GET['id'] ?? null; $id = $_GET['id'] ?? null;
if (!$id||!is_numeric($id)) { if (!$id||!is_numeric($id)) {
die("❌ ID inválido."); die("❌ ID inválido.");
} }
$conn = getConnection(); $conn = getConnection();
$sql = "UPDATE dbo.transportes SET status = 0 WHERE id_transporte = ?"; $sql = "UPDATE dbo.transportes SET status = 0 WHERE id_transporte = ?";
$stmt = sqlsrv_query($conn, $sql, [$id]); $stmt = sqlsrv_query($conn, $sql, [$id]);
if ($stmt === false) { if ($stmt === false) {
die("❌ Error al eliminar: ".print_r(sqlsrv_errors(),true)); die("❌ Error al eliminar: ".print_r(sqlsrv_errors(),true));
} }
header('Location: /IMPORTADORES/transportes/lista?deleted=ok'); header('Location: /IMPORTADORES/transportes/lista?deleted=ok');
exit; exit;
} }
/** Formulario de importación masiva **/ /** Formulario de importación masiva **/
function masivo() { function masivo()
{
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login'); header('Location: /IMPORTADORES/login');
exit; exit;
@@ -306,7 +321,8 @@ function masivo() {
} }
/** Procesa la importación masiva desde CSV **/ /** Procesa la importación masiva desde CSV **/
function importarGuardar() { function importarGuardar()
{
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
die("⚠️ No autorizado."); die("⚠️ No autorizado.");
} }
@@ -321,10 +337,11 @@ function importarGuardar() {
exit; exit;
} }
$conn = getConnection();
$tmp = $_FILES['csv']['tmp_name']; $tmp = $_FILES['csv']['tmp_name'];
$handle = fopen($tmp, 'r'); $handle = fopen($tmp, 'r');
$headers = fgetcsv($handle, 1000, ','); $headers = fgetcsv($handle, 1000, ',');
$conn = getConnection();
$usr = $_SESSION['usuario_id']; $usr = $_SESSION['usuario_id'];
$imported = 0; $imported = 0;
$errors = []; $errors = [];
@@ -345,21 +362,19 @@ function importarGuardar() {
} }
// Verificar que el transportista pertenezca al usuario // Verificar que el transportista pertenezca al usuario
$sqlCheck = "SELECT COUNT(*) AS cnt $sqlCheck = "SELECT COUNT(*) AS cnt FROM dbo.transportistas WHERE id_transportista = ? AND id_usuario = ?";
FROM dbo.transportistas
WHERE id_transportista = ? AND id_usuario = ?";
$stmtCheck = sqlsrv_query($conn, $sqlCheck, [$idTrans, $usr]); $stmtCheck = sqlsrv_query($conn, $sqlCheck, [$idTrans, $usr]);
$rCheck = sqlsrv_fetch_array($stmtCheck, SQLSRV_FETCH_ASSOC); $rCheck = sqlsrv_fetch_array($stmtCheck, SQLSRV_FETCH_ASSOC);
if ($rCheck['cnt'] == 0) { if ($rCheck['cnt'] == 0) {
$errors[] = "Fila $row: transportista $idTrans no válido."; $errors[] = "Fila $row: transportista $idTrans no válido.";
continue; continue;
} }
// Insertar sin foto // Insertar sin foto
$sql = "INSERT INTO dbo.transportes $sql = "INSERT INTO dbo.transportes (vehiculo, identificador_fiscal, foto_url, status, id_transportista) VALUES (?, ?, NULL, 1, ?)";
(vehiculo, identificador_fiscal, foto_url, status, id_transportista)
VALUES (?, ?, NULL, 1, ?)";
$stmt = sqlsrv_query($conn, $sql, [$vehiculo, $identFiscal, $idTrans]); $stmt = sqlsrv_query($conn, $sql, [$vehiculo, $identFiscal, $idTrans]);
if ($stmt === false) { if ($stmt === false) {
$errors[] = "Fila $row: error al insertar."; $errors[] = "Fila $row: error al insertar.";
continue; continue;

View File

@@ -2,9 +2,11 @@
require_once __DIR__ . '/../helpers/session.php'; require_once __DIR__ . '/../helpers/session.php';
require_once __DIR__ . '/../../config/database.php'; require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../helpers/env.php'; require_once __DIR__ . '/../helpers/env.php';
ob_clean(); ob_clean();
function guardar() { function guardar()
{
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
die("⚠️ No autorizado."); die("⚠️ No autorizado.");
} }
@@ -28,14 +30,11 @@ function guardar() {
$sql = "INSERT INTO dbo.transportistas $sql = "INSERT INTO dbo.transportistas
(clave_identificador, nombre, rfc, curp, domicilio, pais, (clave_identificador, nombre, rfc, curp, domicilio, pais,
entidad_federativa, ciudad, telefono, caat, id_usuario) entidad_federativa, ciudad, telefono, caat, id_usuario)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
$params = [ ";
$clave, $nombre, $rfc, $curp, $dom, $params = [$clave, $nombre, $rfc, $curp, $dom, $pais, $entidad, $ciudad, $tel, $caat, $usr_id];
$pais, $entidad, $ciudad, $tel, $caat,
$usr_id
];
$stmt = sqlsrv_query($conn, $sql, $params); $stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt === false) { if ($stmt === false) {
die("❌ Error al guardar transportista: " . print_r(sqlsrv_errors(), true)); die("❌ Error al guardar transportista: " . print_r(sqlsrv_errors(), true));
} }
@@ -45,11 +44,14 @@ function guardar() {
exit; exit;
} }
function alta() { function alta()
{
$conn = getConnection(); $conn = getConnection();
// 1) Cargar países // 1) Cargar países
$sql = "SELECT id_pais, nombre FROM paises ORDER BY nombre"; $sql = "SELECT id_pais, nombre FROM paises ORDER BY nombre";
$stmt = sqlsrv_query($conn, $sql); $stmt = sqlsrv_query($conn, $sql);
$paises = []; $paises = [];
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$paises[] = $row; $paises[] = $row;
@@ -59,48 +61,69 @@ function alta() {
} }
// AJAX: devuelve los estados de un país dado // AJAX: devuelve los estados de un país dado
function estados() { function estados()
{
header('Content-Type: application/json; charset=utf-8'); header('Content-Type: application/json; charset=utf-8');
$pais = $_GET['pais'] ?? ''; $pais = $_GET['pais'] ?? '';
$conn = getConnection(); $conn = getConnection();
$sql = "SELECT id_estado, nombre FROM estados WHERE pais_id = ? ORDER BY nombre"; $sql = "SELECT id_estado, nombre FROM estados WHERE pais_id = ? ORDER BY nombre";
$stmt = sqlsrv_query($conn, $sql, [$pais]); $stmt = sqlsrv_query($conn, $sql, [$pais]);
$out = []; $out = [];
while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$out[] = $r; $out[] = $r;
} }
echo json_encode($out); echo json_encode($out);
exit; exit;
} }
// AJAX: devuelve las ciudades de un estado dado // AJAX: devuelve las ciudades de un estado dado
function ciudades() { function ciudades()
{
header('Content-Type: application/json; charset=utf-8'); header('Content-Type: application/json; charset=utf-8');
$estado = $_GET['estado'] ?? ''; $estado = $_GET['estado'] ?? '';
$conn = getConnection(); $conn = getConnection();
$sql = "SELECT id_ciudad, nombre FROM ciudades WHERE estado_id = ? ORDER BY nombre"; $sql = "SELECT id_ciudad, nombre FROM ciudades WHERE estado_id = ? ORDER BY nombre";
$stmt = sqlsrv_query($conn, $sql, [$estado]); $stmt = sqlsrv_query($conn, $sql, [$estado]);
$out = []; $out = [];
while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$out[] = $r; $out[] = $r;
} }
echo json_encode($out); echo json_encode($out);
exit; exit;
} }
function lista() function lista()
{ {
// 1) Verificar sesión
if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login');
exit;
}
include __DIR__ . '/../../views/transportistas/lista.php'; include __DIR__ . '/../../views/transportistas/lista.php';
} }
/** Descarga la plantilla CSV para carga masiva **/ /** Descarga la plantilla CSV para carga masiva **/
function template() { function template()
{
$file = __DIR__ . '/../../public/downloads/transportistas_template.csv'; $file = __DIR__ . '/../../public/downloads/transportistas_template.csv';
if (!file_exists($file)) { if (!file_exists($file)) {
http_response_code(404); http_response_code(404);
echo "❌ Plantilla no encontrada."; echo "❌ Plantilla no encontrada.";
exit; exit;
} }
header('Content-Type: text/csv; charset=UTF-8'); header('Content-Type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename="transportistas_template.csv"'); header('Content-Disposition: attachment; filename="transportistas_template.csv"');
readfile($file); readfile($file);
@@ -108,18 +131,22 @@ function template() {
} }
/** Procesa la carga masiva desde un CSV **/ /** Procesa la carga masiva desde un CSV **/
function importar() { function importar()
{
// 1) Verificar sesión // 1) Verificar sesión
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
die("⚠️ No autorizado."); die("⚠️ No autorizado.");
} }
$usr_id = $_SESSION['usuario_id']; $usr_id = $_SESSION['usuario_id'];
// 2) Validar archivo subido // 2) Validar archivo subido
if (!isset($_FILES['archivo_csv']) || $_FILES['archivo_csv']['error'] !== UPLOAD_ERR_OK) { if (!isset($_FILES['archivo_csv']) || $_FILES['archivo_csv']['error'] !== UPLOAD_ERR_OK) {
die("❌ Debes subir un archivo CSV válido."); die("❌ Debes subir un archivo CSV válido.");
} }
$ext = pathinfo($_FILES['archivo_csv']['name'], PATHINFO_EXTENSION); $ext = pathinfo($_FILES['archivo_csv']['name'], PATHINFO_EXTENSION);
if (strtolower($ext) !== 'csv') { if (strtolower($ext) !== 'csv') {
die("❌ Solo se permiten archivos .csv"); die("❌ Solo se permiten archivos .csv");
} }
@@ -132,17 +159,15 @@ function importar() {
// 4) Encabezados esperados // 4) Encabezados esperados
$header = fgetcsv($fh, 1000, ','); $header = fgetcsv($fh, 1000, ',');
$expected = [ $expected = ['clave_identificador', 'nombre', 'rfc', 'curp', 'telefono', 'caat', 'pais_id', 'estado_id', 'ciudad_id', 'domicilio'];
'clave_identificador','nombre','rfc','curp',
'telefono','caat','pais_id','estado_id',
'ciudad_id','domicilio'
];
if ($header === false || array_map('trim', $header) !== $expected) { if ($header === false || array_map('trim', $header) !== $expected) {
fclose($fh); fclose($fh);
die("❌ Encabezado de CSV inválido. Debe contener: " . implode(',', $expected)); die("❌ Encabezado de CSV inválido. Debe contener: " . implode(',', $expected));
} }
$conn = getConnection(); $conn = getConnection();
$errors = []; $errors = [];
$rowNum = 1; $rowNum = 1;
@@ -154,7 +179,7 @@ function importar() {
continue; continue;
} }
// mapear valores y trim // mapear valores y trim
list($clave,$nombre,$rfc,$curp,$tel,$caat,$pais_id,$estado_id,$ciudad_id,$dom) = array_map('trim', $row); list($clave, $nombre, $rfc, $curp, $tel, $caat, $pais_id, $estado_id, $ciudad_id, $dom) = array_map('trim', $row);
// validar obligatorios // validar obligatorios
if ($clave==='' || $nombre==='' || $rfc==='' || $tel==='' || $caat==='' if ($clave==='' || $nombre==='' || $rfc==='' || $tel==='' || $caat===''
@@ -171,6 +196,7 @@ function importar() {
// Consultar nombre del país // Consultar nombre del país
$sql = "SELECT nombre FROM dbo.paises WHERE id_pais = ?"; $sql = "SELECT nombre FROM dbo.paises WHERE id_pais = ?";
$stmt = sqlsrv_query($conn, $sql, [$pais_id]); $stmt = sqlsrv_query($conn, $sql, [$pais_id]);
if ($row_pais = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { if ($row_pais = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$pais_nombre = $row_pais['nombre']; $pais_nombre = $row_pais['nombre'];
} else { } else {
@@ -181,6 +207,7 @@ function importar() {
// Consultar nombre del estado // Consultar nombre del estado
$sql = "SELECT nombre FROM dbo.estados WHERE id_estado = ?"; $sql = "SELECT nombre FROM dbo.estados WHERE id_estado = ?";
$stmt = sqlsrv_query($conn, $sql, [$estado_id]); $stmt = sqlsrv_query($conn, $sql, [$estado_id]);
if ($row_estado = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { if ($row_estado = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$estado_nombre = $row_estado['nombre']; $estado_nombre = $row_estado['nombre'];
} else { } else {
@@ -191,6 +218,7 @@ function importar() {
// Consultar nombre de la ciudad // Consultar nombre de la ciudad
$sql = "SELECT nombre FROM dbo.ciudades WHERE id_ciudad = ?"; $sql = "SELECT nombre FROM dbo.ciudades WHERE id_ciudad = ?";
$stmt = sqlsrv_query($conn, $sql, [$ciudad_id]); $stmt = sqlsrv_query($conn, $sql, [$ciudad_id]);
if ($row_ciudad = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { if ($row_ciudad = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$ciudad_nombre = $row_ciudad['nombre']; $ciudad_nombre = $row_ciudad['nombre'];
} else { } else {
@@ -202,13 +230,11 @@ function importar() {
$sql = "INSERT INTO dbo.transportistas $sql = "INSERT INTO dbo.transportistas
(clave_identificador, nombre, rfc, curp, telefono, caat, (clave_identificador, nombre, rfc, curp, telefono, caat,
pais, entidad_federativa, ciudad, domicilio, id_usuario) pais, entidad_federativa, ciudad, domicilio, id_usuario)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
$params = [ ";
$clave, $nombre, $rfc, $curp, $tel, $params = [$clave, $nombre, $rfc, $curp, $tel, $caat, $pais_nombre, $estado_nombre, $ciudad_nombre, $dom, $usr_id];
$caat, $pais_nombre, $estado_nombre, $ciudad_nombre, $dom,
$usr_id
];
$stmt = sqlsrv_query($conn, $sql, $params); $stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt === false) { if ($stmt === false) {
$errors[] = "Fila $rowNum: error al guardar → " . print_r(sqlsrv_errors(), true); $errors[] = "Fila $rowNum: error al guardar → " . print_r(sqlsrv_errors(), true);
} }
@@ -226,18 +252,20 @@ function importar() {
exit; exit;
} }
function bulk_upload() { function bulk_upload()
{
include __DIR__ . '/../../views/transportistas/bulk_upload.php'; include __DIR__ . '/../../views/transportistas/bulk_upload.php';
} }
function ajax_lista() { function ajax_lista()
{
// 1) Autorización // 1) Autorización
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
http_response_code(403); http_response_code(403);
echo json_encode([]); echo json_encode([]);
exit; exit;
} }
$usr = $_SESSION['usuario_id']; $usr = $_SESSION['usuario_id'];
$conn = getConnection(); $conn = getConnection();
@@ -249,7 +277,7 @@ function ajax_lista() {
$search = $_GET['search']['value'] ?? ''; $search = $_GET['search']['value'] ?? '';
// Mapeo columnas - ahora incluimos el nombre de la ciudad // Mapeo columnas - ahora incluimos el nombre de la ciudad
$cols = ['t.id_transportista','t.clave_identificador','t.nombre','t.rfc','c.nombre','t.creado_en']; $cols = ['t.id_transportista', 't.clave_identificador', 't.nombre', 't.rfc', 'c.nombre', 't.creado_en'];
$orderColIdx = intval($_GET['order'][0]['column'] ?? 5); $orderColIdx = intval($_GET['order'][0]['column'] ?? 5);
$orderDir = strtoupper($_GET['order'][0]['dir'] ?? 'ASC') === 'DESC' ? 'DESC' : 'ASC'; $orderDir = strtoupper($_GET['order'][0]['dir'] ?? 'ASC') === 'DESC' ? 'DESC' : 'ASC';
$orderCol = in_array($orderColIdx, range(0,5)) ? $cols[$orderColIdx] : 't.creado_en'; $orderCol = in_array($orderColIdx, range(0,5)) ? $cols[$orderColIdx] : 't.creado_en';
@@ -265,22 +293,20 @@ function ajax_lista() {
$params = [$usr]; $params = [$usr];
if ($search !== '') { if ($search !== '') {
$where .= " AND ( $where .= " AND (t.nombre LIKE ? OR t.rfc LIKE ? OR c.nombre LIKE ?)";
t.nombre LIKE ? OR
t.rfc LIKE ? OR
c.nombre LIKE ?
)";
$like = "%{$search}%"; $like = "%{$search}%";
$params = array_merge($params, array_fill(0, 3, $like)); $params = array_merge($params, array_fill(0, 3, $like));
} }
// 5) Total registros filtrados (CON JOIN) // 5) Total registros filtrados (CON JOIN)
$sqlFiltered = " $sqlFiltered = "SELECT COUNT(*) AS total
SELECT COUNT(*) AS total
FROM dbo.transportistas t FROM dbo.transportistas t
LEFT JOIN dbo.ciudades c ON t.ciudad = c.id_ciudad LEFT JOIN dbo.ciudades c
LEFT JOIN dbo.estados e ON c.estado_id = e.id_estado ON t.ciudad = c.id_ciudad
LEFT JOIN dbo.paises p ON e.pais_id = p.id_pais LEFT JOIN dbo.estados e
ON c.estado_id = e.id_estado
LEFT JOIN dbo.paises p
ON e.pais_id = p.id_pais
WHERE $where WHERE $where
"; ";
$stmtF = sqlsrv_query($conn, $sqlFiltered, $params); $stmtF = sqlsrv_query($conn, $sqlFiltered, $params);
@@ -288,24 +314,22 @@ function ajax_lista() {
$recordsFiltered = (int)$rowF['total']; $recordsFiltered = (int)$rowF['total'];
// 6) Datos de la página con JOIN completo // 6) Datos de la página con JOIN completo
$sqlData = " $sqlData = "SELECT
SELECT t.id_transportista, t.id_transportista, t.clave_identificador, t.nombre, t.rfc, t.creado_en,
t.clave_identificador,
t.nombre,
t.rfc,
COALESCE(c.nombre, 'Ciudad no encontrada') as ciudad_nombre, COALESCE(c.nombre, 'Ciudad no encontrada') as ciudad_nombre,
COALESCE(e.nombre, '') as estado_nombre, COALESCE(e.nombre, '') as estado_nombre,
COALESCE(p.nombre, '') as pais_nombre, COALESCE(p.nombre, '') as pais_nombre
t.creado_en
FROM dbo.transportistas t FROM dbo.transportistas t
LEFT JOIN dbo.ciudades c ON t.ciudad = c.id_ciudad LEFT JOIN dbo.ciudades c
LEFT JOIN dbo.estados e ON c.estado_id = e.id_estado ON t.ciudad = c.id_ciudad
LEFT JOIN dbo.paises p ON e.pais_id = p.id_pais LEFT JOIN dbo.estados e
ON c.estado_id = e.id_estado
LEFT JOIN dbo.paises p
ON e.pais_id = p.id_pais
WHERE $where WHERE $where
ORDER BY $orderCol $orderDir ORDER BY $orderCol $orderDir
OFFSET ? ROWS FETCH NEXT ? ROWS ONLY OFFSET ? ROWS FETCH NEXT ? ROWS ONLY
"; "; // Agregar offset/limit al final
// agregar offset/limit al final
$params[] = $start; $params[] = $start;
$params[] = $length; $params[] = $length;
$stmtD = sqlsrv_query($conn, $sqlData, $params); $stmtD = sqlsrv_query($conn, $sqlData, $params);
@@ -345,16 +369,19 @@ function ajax_lista() {
exit; exit;
} }
function editar() { function editar()
{
// 1) Verificar sesión // 1) Verificar sesión
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login'); header('Location: /IMPORTADORES/login');
exit; exit;
} }
$usr = $_SESSION['usuario_id']; $usr = $_SESSION['usuario_id'];
// 2) Obtener el ID y validarlo // 2) Obtener el ID y validarlo
$id = $_GET['id'] ?? null; $id = $_GET['id'] ?? null;
if (!$id || !is_numeric($id)) { if (!$id || !is_numeric($id)) {
die("❌ ID de transportista inválido."); die("❌ ID de transportista inválido.");
} }
@@ -362,9 +389,9 @@ function editar() {
$conn = getConnection(); $conn = getConnection();
// 3) Consultar el transportista (pertenece al usuario) // 3) Consultar el transportista (pertenece al usuario)
$sql = "SELECT * FROM dbo.transportistas $sql = "SELECT * FROM dbo.transportistas WHERE id_transportista = ? AND id_usuario = ?";
WHERE id_transportista = ? AND id_usuario = ?";
$stmt = sqlsrv_query($conn, $sql, [$id, $usr]); $stmt = sqlsrv_query($conn, $sql, [$id, $usr]);
$t = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); $t = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
if (!$t) { if (!$t) {
die("❌ Transportista no encontrado o no autorizado."); die("❌ Transportista no encontrado o no autorizado.");
@@ -402,19 +429,20 @@ function actualizar()
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
die("⚠️ No autorizado."); die("⚠️ No autorizado.");
} }
$usr = $_SESSION['usuario_id']; $usr = $_SESSION['usuario_id'];
// 1) Capturar y validar datos // 1) Capturar y validar datos
$id = $_POST['id_transportista'] ?? null; $id = $_POST['id_transportista'] ?? null;
$clave = trim($_POST['clave'] ?? ''); $clave = trim($_POST['clave'] ?? '');
$nombre= trim($_POST['nombre'] ?? ''); $nombre = trim($_POST['nombre'] ?? '');
$rfc = trim($_POST['rfc'] ?? ''); $rfc = trim($_POST['rfc'] ?? '');
$curp = trim($_POST['curp'] ?? ''); $curp = trim($_POST['curp'] ?? '');
$tel = trim($_POST['telefono'] ?? ''); $tel = trim($_POST['telefono'] ?? '');
$caat = trim($_POST['caat'] ?? ''); $caat = trim($_POST['caat'] ?? '');
$pais = $_POST['pais'] ?? ''; $pais = $_POST['pais'] ?? '';
$estado= $_POST['entidad'] ?? ''; $estado = $_POST['entidad'] ?? '';
$ciudad= $_POST['ciudad'] ?? ''; $ciudad = $_POST['ciudad'] ?? '';
$dom = trim($_POST['domicilio'] ?? ''); $dom = trim($_POST['domicilio'] ?? '');
if (!$id || !is_numeric($id) if (!$id || !is_numeric($id)
@@ -427,11 +455,10 @@ function actualizar()
$conn = getConnection(); $conn = getConnection();
// 2) Verificar que exista y pertenezca al usuario // 2) Verificar que exista y pertenezca al usuario
$sqlChk = "SELECT COUNT(*) AS cnt $sqlChk = "SELECT COUNT(*) AS cnt FROM dbo.transportistas WHERE id_transportista = ? AND id_usuario = ?";
FROM dbo.transportistas
WHERE id_transportista = ? AND id_usuario = ?";
$stmtChk = sqlsrv_query($conn, $sqlChk, [$id, $usr]); $stmtChk = sqlsrv_query($conn, $sqlChk, [$id, $usr]);
$rowChk = sqlsrv_fetch_array($stmtChk, SQLSRV_FETCH_ASSOC); $rowChk = sqlsrv_fetch_array($stmtChk, SQLSRV_FETCH_ASSOC);
if ($rowChk['cnt'] == 0) { if ($rowChk['cnt'] == 0) {
die("❌ Transportista no encontrado o no autorizado."); die("❌ Transportista no encontrado o no autorizado.");
} }
@@ -448,12 +475,9 @@ function actualizar()
entidad_federativa = ?, entidad_federativa = ?,
ciudad = ?, ciudad = ?,
domicilio = ? domicilio = ?
WHERE id_transportista = ?"; WHERE id_transportista = ?
$params = [ ";
$clave, $nombre, $rfc, $curp, $tel, $params = [$clave, $nombre, $rfc, $curp, $tel, $caat, $pais, $estado, $ciudad, $dom, $id];
$caat, $pais, $estado, $ciudad, $dom,
$id
];
$stmtUpd = sqlsrv_query($conn, $sqlUpd, $params); $stmtUpd = sqlsrv_query($conn, $sqlUpd, $params);
if ($stmtUpd === false) { if ($stmtUpd === false) {
die("❌ Error al actualizar: " . print_r(sqlsrv_errors(), true)); die("❌ Error al actualizar: " . print_r(sqlsrv_errors(), true));
@@ -464,13 +488,16 @@ function actualizar()
exit; exit;
} }
function eliminar() { function eliminar()
{
if (!($_SESSION['usuario_id'] ?? false)) { if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login'); header('Location: /IMPORTADORES/login');
exit; exit;
} }
$usr = $_SESSION['usuario_id']; $usr = $_SESSION['usuario_id'];
$id = $_GET['id'] ?? null; $id = $_GET['id'] ?? null;
if (!$id || !is_numeric($id)) { if (!$id || !is_numeric($id)) {
die("❌ ID inválido."); die("❌ ID inválido.");
} }
@@ -478,11 +505,10 @@ function eliminar() {
$conn = getConnection(); $conn = getConnection();
// Verificar que el transportista exista y pertenezca al usuario // Verificar que el transportista exista y pertenezca al usuario
$sqlChk = "SELECT COUNT(*) AS cnt $sqlChk = "SELECT COUNT(*) AS cnt FROM dbo.transportistas WHERE id_transportista = ? AND id_usuario = ?";
FROM dbo.transportistas
WHERE id_transportista = ? AND id_usuario = ?";
$stmtChk = sqlsrv_query($conn, $sqlChk, [$id, $usr]); $stmtChk = sqlsrv_query($conn, $sqlChk, [$id, $usr]);
$rowChk = sqlsrv_fetch_array($stmtChk, SQLSRV_FETCH_ASSOC); $rowChk = sqlsrv_fetch_array($stmtChk, SQLSRV_FETCH_ASSOC);
if ($rowChk['cnt'] == 0) { if ($rowChk['cnt'] == 0) {
die("❌ Transportista no encontrado o no autorizado."); die("❌ Transportista no encontrado o no autorizado.");
} }
@@ -490,6 +516,7 @@ function eliminar() {
// ELIMINACIÓN REAL - DELETE en lugar de UPDATE // ELIMINACIÓN REAL - DELETE en lugar de UPDATE
$sqlDel = "UPDATE dbo.transportistas SET activo = 0 WHERE id_transportista = ?"; $sqlDel = "UPDATE dbo.transportistas SET activo = 0 WHERE id_transportista = ?";
$stmtDel = sqlsrv_query($conn, $sqlDel, [$id]); $stmtDel = sqlsrv_query($conn, $sqlDel, [$id]);
if ($stmtDel === false) { if ($stmtDel === false) {
die("❌ Error al eliminar: " . print_r(sqlsrv_errors(), true)); die("❌ Error al eliminar: " . print_r(sqlsrv_errors(), true));
} }

View File

@@ -18,9 +18,7 @@ function vinculacionesUsuario()
} }
// Consulta de todas las relaciones del importador // Consulta de todas las relaciones del importador
$sql = " $sql = "SELECT * FROM importador_agencia ia
SELECT *
FROM importador_agencia ia
INNER JOIN agencias_aduanales aa INNER JOIN agencias_aduanales aa
ON ia.id_agencia = aa.id_agencia ON ia.id_agencia = aa.id_agencia
WHERE ia.id_importador = ? WHERE ia.id_importador = ?
@@ -48,13 +46,12 @@ function nuevaVinculacion()
$conn = getConnection(); $conn = getConnection();
$sql = " $sql = "SELECT
SELECT a.*, s.estado AS estado_solicitud
a.*,
s.estado AS estado_solicitud
FROM agencias_aduanales a FROM agencias_aduanales a
LEFT JOIN solicitudes_vinculacion s LEFT JOIN solicitudes_vinculacion s
ON s.id_agencia = a.id_agencia AND s.id_importador = ? ON s.id_agencia = a.id_agencia
AND s.id_importador = ?
AND s.estado = 'PENDIENTE' AND s.estado = 'PENDIENTE'
WHERE NOT EXISTS ( WHERE NOT EXISTS (
SELECT 1 SELECT 1
@@ -120,18 +117,17 @@ function vinculacionesAgencia()
$rowCountActive = sqlsrv_fetch_array($stmtCountActive, SQLSRV_FETCH_ASSOC); $rowCountActive = sqlsrv_fetch_array($stmtCountActive, SQLSRV_FETCH_ASSOC);
// Consulta de importadores vinculados ACTIVOS a MI agencia // Consulta de importadores vinculados ACTIVOS a MI agencia
$sql = " $sql = "SELECT
SELECT ia.*, u.nombre as importador_nombre, u.tipo_usuario as tipo_usuario_sistema,
ia.*, ig.rfc, ig.telefono, 'importador' as tipo_vinculacion
u.nombre as importador_nombre,
u.tipo_usuario as tipo_usuario_sistema,
ig.rfc,
ig.telefono,
'importador' as tipo_vinculacion
FROM importador_agencia ia FROM importador_agencia ia
INNER JOIN usuarios_sistema u ON ia.id_importador = u.id_usuario INNER JOIN usuarios_sistema u
LEFT JOIN informacion_general ig ON u.id_usuario = ig.id_usuario ON ia.id_importador = u.id_usuario
WHERE ia.id_agencia = ? AND ia.activo = 1 AND ia.estado = 'APROBADO' LEFT JOIN informacion_general ig
ON u.id_usuario = ig.id_usuario
WHERE ia.id_agencia = ?
AND ia.activo = 1
AND ia.estado = 'APROBADO'
ORDER BY ia.fecha_vinculacion DESC ORDER BY ia.fecha_vinculacion DESC
"; ";
$stmt = sqlsrv_query($conn, $sql, [$id_agencia]); $stmt = sqlsrv_query($conn, $sql, [$id_agencia]);
@@ -160,19 +156,17 @@ function vinculacionesAgencia()
$rowCountActive2 = sqlsrv_fetch_array($stmtCountActive2, SQLSRV_FETCH_ASSOC); $rowCountActive2 = sqlsrv_fetch_array($stmtCountActive2, SQLSRV_FETCH_ASSOC);
// Consulta de agentes vinculados ACTIVOS a MI agencia // Consulta de agentes vinculados ACTIVOS a MI agencia
$sql2 = " $sql2 = "SELECT
SELECT aa.*, aa.fecha_asignacion as fecha_vinculacion,
aa.*, u.nombre as importador_nombre, u.tipo_usuario as tipo_usuario_sistema,
aa.fecha_asignacion as fecha_vinculacion, ig.rfc, ig.telefono, 'agente' as tipo_vinculacion
u.nombre as importador_nombre,
u.tipo_usuario as tipo_usuario_sistema,
ig.rfc,
ig.telefono,
'agente' as tipo_vinculacion
FROM agente_agencia aa FROM agente_agencia aa
INNER JOIN usuarios_sistema u ON aa.id_agente = u.id_usuario INNER JOIN usuarios_sistema u
LEFT JOIN informacion_general ig ON u.id_usuario = ig.id_usuario ON aa.id_agente = u.id_usuario
WHERE aa.id_agencia = ? AND aa.activo = 1 LEFT JOIN informacion_general ig
ON u.id_usuario = ig.id_usuario
WHERE aa.id_agencia = ?
AND aa.activo = 1
ORDER BY aa.fecha_asignacion DESC ORDER BY aa.fecha_asignacion DESC
"; ";
$stmt2 = sqlsrv_query($conn, $sql2, [$id_agencia]); $stmt2 = sqlsrv_query($conn, $sql2, [$id_agencia]);
@@ -229,16 +223,16 @@ function desvincularAgencia()
if ($tipo === 'importador') { if ($tipo === 'importador') {
// Verificar relación de importador // Verificar relación de importador
$sqlVerificar = " $sqlVerificar = "SELECT
SELECT ia.*, aa.id_administrador, u.nombre as usuario_nombre, u.tipo_usuario
ia.*,
aa.id_administrador,
u.nombre as usuario_nombre,
u.tipo_usuario
FROM importador_agencia ia FROM importador_agencia ia
INNER JOIN agencias_aduanales aa ON ia.id_agencia = aa.id_agencia INNER JOIN agencias_aduanales aa
INNER JOIN usuarios_sistema u ON ia.id_importador = u.id_usuario ON ia.id_agencia = aa.id_agencia
WHERE ia.id_relacion = ? AND aa.id_administrador = ? AND u.tipo_usuario = 'importador' INNER JOIN usuarios_sistema u
ON ia.id_importador = u.id_usuario
WHERE ia.id_relacion = ?
AND aa.id_administrador = ?
AND u.tipo_usuario = 'importador'
"; ";
$stmtVerificar = sqlsrv_query($conn, $sqlVerificar, [$id_relacion, $_SESSION['usuario_id']]); $stmtVerificar = sqlsrv_query($conn, $sqlVerificar, [$id_relacion, $_SESSION['usuario_id']]);
$relacion = sqlsrv_fetch_array($stmtVerificar, SQLSRV_FETCH_ASSOC); $relacion = sqlsrv_fetch_array($stmtVerificar, SQLSRV_FETCH_ASSOC);
@@ -252,26 +246,20 @@ function desvincularAgencia()
} }
// Desactivar la relación de importador // Desactivar la relación de importador
$sqlDesactivar = " $sqlDesactivar = "UPDATE importador_agencia SET activo = 0, fecha_desvinculacion = GETDATE(), estado = 'DESVINCULADO' WHERE id_relacion = ?";
UPDATE importador_agencia
SET activo = 0,
fecha_desvinculacion = GETDATE(),
estado = 'DESVINCULADO'
WHERE id_relacion = ?
";
} else if ($tipo === 'agente') { } else if ($tipo === 'agente') {
// Verificar relación de agente aduanal // Verificar relación de agente aduanal
$sqlVerificar = " $sqlVerificar = "SELECT
SELECT aa.*, ag.id_administrador, u.nombre as usuario_nombre, u.tipo_usuario
aa.*,
ag.id_administrador,
u.nombre as usuario_nombre,
u.tipo_usuario
FROM agente_agencia aa FROM agente_agencia aa
INNER JOIN agencias_aduanales ag ON aa.id_agencia = ag.id_agencia INNER JOIN agencias_aduanales ag
INNER JOIN usuarios_sistema u ON aa.id_agente = u.id_usuario ON aa.id_agencia = ag.id_agencia
WHERE aa.id_relacion = ? AND ag.id_administrador = ? AND u.tipo_usuario = 'agente_aduanal' INNER JOIN usuarios_sistema u
ON aa.id_agente = u.id_usuario
WHERE aa.id_relacion = ?
AND ag.id_administrador = ?
AND u.tipo_usuario = 'agente_aduanal'
"; ";
$stmtVerificar = sqlsrv_query($conn, $sqlVerificar, [$id_relacion, $_SESSION['usuario_id']]); $stmtVerificar = sqlsrv_query($conn, $sqlVerificar, [$id_relacion, $_SESSION['usuario_id']]);
$relacion = sqlsrv_fetch_array($stmtVerificar, SQLSRV_FETCH_ASSOC); $relacion = sqlsrv_fetch_array($stmtVerificar, SQLSRV_FETCH_ASSOC);
@@ -285,11 +273,7 @@ function desvincularAgencia()
} }
// Desactivar la relación de agente // Desactivar la relación de agente
$sqlDesactivar = " $sqlDesactivar = "UPDATE agente_agencia SET activo = 0 WHERE id_relacion = ?";
UPDATE agente_agencia
SET activo = 0
WHERE id_relacion = ?
";
} }
$stmtDesactivar = sqlsrv_query($conn, $sqlDesactivar, [$id_relacion]); $stmtDesactivar = sqlsrv_query($conn, $sqlDesactivar, [$id_relacion]);
@@ -301,21 +285,12 @@ function desvincularAgencia()
// NUEVO: Verificar si el usuario desvinculado tenía esta agencia como activa // NUEVO: Verificar si el usuario desvinculado tenía esta agencia como activa
if ($tipo === 'importador') { if ($tipo === 'importador') {
// Verificar si el importador tenía esta agencia como activa // Verificar si el importador tenía esta agencia como activa
$sqlVerificarAgenciaActiva = " $sqlVerificarAgenciaActiva = "SELECT id_agencia_en_uso FROM usuarios_sistema WHERE id_usuario = ? AND id_agencia_en_uso = ?";
SELECT id_agencia_en_uso $stmtVerificarActiva = sqlsrv_query($conn, $sqlVerificarAgenciaActiva, [$relacion['id_importador'], $relacion['id_agencia']]);
FROM usuarios_sistema
WHERE id_usuario = ? AND id_agencia_en_uso = ?
";
$stmtVerificarActiva = sqlsrv_query($conn, $sqlVerificarAgenciaActiva,
[$relacion['id_importador'], $relacion['id_agencia']]);
if ($stmtVerificarActiva && sqlsrv_fetch_array($stmtVerificarActiva, SQLSRV_FETCH_ASSOC)) { if ($stmtVerificarActiva && sqlsrv_fetch_array($stmtVerificarActiva, SQLSRV_FETCH_ASSOC)) {
// Si tenía esta agencia como activa, quitársela // Si tenía esta agencia como activa, quitársela
$sqlQuitarAgenciaActiva = " $sqlQuitarAgenciaActiva = "UPDATE usuarios_sistema SET id_agencia_en_uso = NULL WHERE id_usuario = ?";
UPDATE usuarios_sistema
SET id_agencia_en_uso = NULL
WHERE id_usuario = ?
";
$stmtQuitarActiva = sqlsrv_query($conn, $sqlQuitarAgenciaActiva, [$relacion['id_importador']]); $stmtQuitarActiva = sqlsrv_query($conn, $sqlQuitarAgenciaActiva, [$relacion['id_importador']]);
if (!$stmtQuitarActiva) { if (!$stmtQuitarActiva) {
@@ -372,19 +347,18 @@ function solicitudesVinculacion()
$debugRow2 = sqlsrv_fetch_array($debugStmt2, SQLSRV_FETCH_ASSOC); $debugRow2 = sqlsrv_fetch_array($debugStmt2, SQLSRV_FETCH_ASSOC);
// Consulta principal // Consulta principal
$sql = " $sql = "SELECT
SELECT sv.id_solicitud, u.nombre AS importador_nombre, ig.rfc,
sv.id_solicitud, sv.mensaje, sv.fecha_solicitud, si.opinion_file
u.nombre AS importador_nombre,
ig.rfc,
sv.mensaje,
sv.fecha_solicitud,
si.opinion_file
FROM solicitudes_vinculacion sv FROM solicitudes_vinculacion sv
INNER JOIN usuarios_sistema u ON sv.id_importador = u.id_usuario INNER JOIN usuarios_sistema u
LEFT JOIN informacion_general ig ON u.id_usuario = ig.id_usuario ON sv.id_importador = u.id_usuario
LEFT JOIN solicitudes_importadores si ON LTRIM(RTRIM(LOWER(si.company_name))) = LTRIM(RTRIM(LOWER(u.nombre))) LEFT JOIN informacion_general ig
WHERE sv.estado = 'PENDIENTE' AND sv.id_agencia = ? ON u.id_usuario = ig.id_usuario
LEFT JOIN solicitudes_importadores si
ON LTRIM(RTRIM(LOWER(si.company_name))) = LTRIM(RTRIM(LOWER(u.nombre)))
WHERE sv.estado = 'PENDIENTE'
AND sv.id_agencia = ?
ORDER BY sv.fecha_solicitud DESC ORDER BY sv.fecha_solicitud DESC
"; ";
$params = [$id_agencia]; $params = [$id_agencia];
@@ -396,15 +370,13 @@ function solicitudesVinculacion()
// ✅ VERIFICAR SI LA CONSULTA FUNCIONÓ // ✅ VERIFICAR SI LA CONSULTA FUNCIONÓ
if ($stmt === false) { if ($stmt === false) {
// Usar consulta simplificada como backup // Usar consulta simplificada como backup
$sqlSimple = " $sqlSimple = "SELECT
SELECT sv.id_solicitud, u.nombre AS importador_nombre, sv.mensaje, sv.fecha_solicitud
sv.id_solicitud,
u.nombre AS importador_nombre,
sv.mensaje,
sv.fecha_solicitud
FROM solicitudes_vinculacion sv FROM solicitudes_vinculacion sv
INNER JOIN usuarios_sistema u ON sv.id_importador = u.id_usuario INNER JOIN usuarios_sistema u
WHERE sv.estado = 'PENDIENTE' AND sv.id_agencia = ? ON sv.id_importador = u.id_usuario
WHERE sv.estado = 'PENDIENTE'
AND sv.id_agencia = ?
ORDER BY sv.fecha_solicitud DESC ORDER BY sv.fecha_solicitud DESC
"; ";
$stmt = sqlsrv_query($conn, $sqlSimple, $params); $stmt = sqlsrv_query($conn, $sqlSimple, $params);
@@ -430,6 +402,7 @@ function aprobarVinculacion()
// Verificar que se recibió el ID de la solicitud // Verificar que se recibió el ID de la solicitud
$id_solicitud = $_GET['id'] ?? null; $id_solicitud = $_GET['id'] ?? null;
if (!$id_solicitud || !is_numeric($id_solicitud)) { if (!$id_solicitud || !is_numeric($id_solicitud)) {
header('Location: /IMPORTADORES/vinculaciones/solicitudesVinculacion?error=request_id_invalid'); header('Location: /IMPORTADORES/vinculaciones/solicitudesVinculacion?error=request_id_invalid');
exit; exit;
@@ -442,16 +415,13 @@ function aprobarVinculacion()
sqlsrv_begin_transaction($conn); sqlsrv_begin_transaction($conn);
// 1. Obtener datos de la solicitud y verificar que pertenece a la agencia del admin // 1. Obtener datos de la solicitud y verificar que pertenece a la agencia del admin
$sqlSolicitud = " $sqlSolicitud = "SELECT
SELECT sv.id_solicitud, sv.id_importador, sv.id_agencia, sv.estado, aa.id_administrador
sv.id_solicitud,
sv.id_importador,
sv.id_agencia,
sv.estado,
aa.id_administrador
FROM solicitudes_vinculacion sv FROM solicitudes_vinculacion sv
INNER JOIN agencias_aduanales aa ON sv.id_agencia = aa.id_agencia INNER JOIN agencias_aduanales aa
WHERE sv.id_solicitud = ? AND aa.id_administrador = ? ON sv.id_agencia = aa.id_agencia
WHERE sv.id_solicitud = ?
AND aa.id_administrador = ?
"; ";
$stmtSolicitud = sqlsrv_query($conn, $sqlSolicitud, [$id_solicitud, $_SESSION['usuario_id']]); $stmtSolicitud = sqlsrv_query($conn, $sqlSolicitud, [$id_solicitud, $_SESSION['usuario_id']]);
$solicitud = sqlsrv_fetch_array($stmtSolicitud, SQLSRV_FETCH_ASSOC); $solicitud = sqlsrv_fetch_array($stmtSolicitud, SQLSRV_FETCH_ASSOC);
@@ -465,11 +435,7 @@ function aprobarVinculacion()
} }
// 2. Verificar si ya existe una relación activa entre importador y agencia // 2. Verificar si ya existe una relación activa entre importador y agencia
$sqlVerificar = " $sqlVerificar = " SELECT id_relacion FROM importador_agencia WHERE id_importador = ? AND id_agencia = ? AND activo = 1";
SELECT id_relacion
FROM importador_agencia
WHERE id_importador = ? AND id_agencia = ? AND activo = 1
";
$stmtVerificar = sqlsrv_query($conn, $sqlVerificar, [$solicitud['id_importador'], $solicitud['id_agencia']]); $stmtVerificar = sqlsrv_query($conn, $sqlVerificar, [$solicitud['id_importador'], $solicitud['id_agencia']]);
$relacionExistente = sqlsrv_fetch_array($stmtVerificar, SQLSRV_FETCH_ASSOC); $relacionExistente = sqlsrv_fetch_array($stmtVerificar, SQLSRV_FETCH_ASSOC);
@@ -478,8 +444,7 @@ function aprobarVinculacion()
} }
// 3. Actualizar el estado de la solicitud a APROBADO // 3. Actualizar el estado de la solicitud a APROBADO
$sqlActualizar = " $sqlActualizar = "UPDATE solicitudes_vinculacion
UPDATE solicitudes_vinculacion
SET estado = 'APROBADO', SET estado = 'APROBADO',
fecha_respuesta = GETDATE(), fecha_respuesta = GETDATE(),
respondido_por = ?, respondido_por = ?,
@@ -493,23 +458,11 @@ function aprobarVinculacion()
} }
// 4. Crear la relación en importador_agencia // 4. Crear la relación en importador_agencia
$sqlRelacion = " $sqlRelacion = "INSERT INTO importador_agencia
INSERT INTO importador_agencia ( (id_importador, id_agencia, activo, fecha_vinculacion, creado_por, aprobado_por, estado)
id_importador, VALUES (?, ?, 1, GETDATE(), ?, ?, 'APROBADO')
id_agencia,
activo,
fecha_vinculacion,
creado_por,
aprobado_por,
estado
) VALUES (?, ?, 1, GETDATE(), ?, ?, 'APROBADO')
"; ";
$stmtRelacion = sqlsrv_query($conn, $sqlRelacion, [ $stmtRelacion = sqlsrv_query($conn, $sqlRelacion, [$solicitud['id_importador'], $solicitud['id_agencia'], $solicitud['id_importador'], $_SESSION['usuario_id']]);
$solicitud['id_importador'],
$solicitud['id_agencia'],
$solicitud['id_importador'], // creado_por (el importador que solicitó)
$_SESSION['usuario_id'] // aprobado_por (el admin de agencia)
]);
if (!$stmtRelacion) { if (!$stmtRelacion) {
throw new Exception('Error al crear la relación importador-agencia'); throw new Exception('Error al crear la relación importador-agencia');
@@ -539,6 +492,7 @@ function denegarVinculacion()
// Verificar que se recibió el ID de la solicitud // Verificar que se recibió el ID de la solicitud
$id_solicitud = $_GET['id'] ?? null; $id_solicitud = $_GET['id'] ?? null;
if (!$id_solicitud || !is_numeric($id_solicitud)) { if (!$id_solicitud || !is_numeric($id_solicitud)) {
header('Location: /IMPORTADORES/vinculaciones/solicitudesVinculacion?error=request_id_invalid'); header('Location: /IMPORTADORES/vinculaciones/solicitudesVinculacion?error=request_id_invalid');
exit; exit;
@@ -551,16 +505,13 @@ function denegarVinculacion()
sqlsrv_begin_transaction($conn); sqlsrv_begin_transaction($conn);
// 1. Obtener datos de la solicitud y verificar que pertenece a la agencia del admin // 1. Obtener datos de la solicitud y verificar que pertenece a la agencia del admin
$sqlSolicitud = " $sqlSolicitud = "SELECT
SELECT sv.id_solicitud, sv.id_importador, sv.id_agencia, sv.estado, aa.id_administrador
sv.id_solicitud,
sv.id_importador,
sv.id_agencia,
sv.estado,
aa.id_administrador
FROM solicitudes_vinculacion sv FROM solicitudes_vinculacion sv
INNER JOIN agencias_aduanales aa ON sv.id_agencia = aa.id_agencia INNER JOIN agencias_aduanales aa
WHERE sv.id_solicitud = ? AND aa.id_administrador = ? ON sv.id_agencia = aa.id_agencia
WHERE sv.id_solicitud = ?
AND aa.id_administrador = ?
"; ";
$stmtSolicitud = sqlsrv_query($conn, $sqlSolicitud, [$id_solicitud, $_SESSION['usuario_id']]); $stmtSolicitud = sqlsrv_query($conn, $sqlSolicitud, [$id_solicitud, $_SESSION['usuario_id']]);
$solicitud = sqlsrv_fetch_array($stmtSolicitud, SQLSRV_FETCH_ASSOC); $solicitud = sqlsrv_fetch_array($stmtSolicitud, SQLSRV_FETCH_ASSOC);
@@ -574,8 +525,7 @@ function denegarVinculacion()
} }
// 2. Actualizar el estado de la solicitud a DENEGADO // 2. Actualizar el estado de la solicitud a DENEGADO
$sqlActualizar = " $sqlActualizar = "UPDATE solicitudes_vinculacion
UPDATE solicitudes_vinculacion
SET estado = 'DENEGADO', SET estado = 'DENEGADO',
fecha_respuesta = GETDATE(), fecha_respuesta = GETDATE(),
respondido_por = ? respondido_por = ?

View File

@@ -214,8 +214,8 @@
</form> </form>
</div> </div>
<h4 class="mb-4">✅ Usuarios Activos</h4> <h4 class="mb-4 animate__animated animate__fadeInDown title_glow">✅ Usuarios Activos</h4>
<div class="card p-3 shadow-sm"> <div class="card p-3 shadow-sm bg-white card-hover position-relative h-auto">
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-striped table-hover align-middle" id="tabla-usuarios-activos"> <table class="table table-striped table-hover align-middle" id="tabla-usuarios-activos">
<thead class="table-dark"> <thead class="table-dark">

View File

@@ -94,20 +94,20 @@
?> --> ?> -->
<div class="col-md-4"> <div class="col-md-4">
<div class="card shadow-sm p-3"> <div class="card shadow-sm p-3">
<h5 class="text-primary">Aprobar agencias</h5> <h5 class="text-teal">Aprobar agencias</h5>
<p>Aprueba las agencias que solicitaron un registro.</p> <p>Aprueba las agencias que solicitaron un registro.</p>
<a href="/IMPORTADORES/administrador/aprobarAgencias" <a href="/IMPORTADORES/administrador/aprobarAgencias"
class="btn btn-primary btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/sistemas/aprobarAgencias' ? 'active' : '' ?>"> class="btn btn-teal btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/sistemas/aprobarAgencias' ? 'active' : '' ?>">
Ver agencias solicitantes</a> Ver agencias solicitantes</a>
</div> </div>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<div class="card shadow-sm p-3"> <div class="card shadow-sm p-3">
<h5 class="text-success">Alta de agencias</h5> <h5 class="text-lime">Alta de agencias</h5>
<p>Da de alta manualmente una agencia.</p> <p>Da de alta manualmente una agencia.</p>
<a href="/IMPORTADORES/administrador/altaAgencias" <a href="/IMPORTADORES/administrador/altaAgencias"
class="btn btn-success btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/sistemas/altaAgencias' ? 'active' : '' ?>"> class="btn btn-lime btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/sistemas/altaAgencias' ? 'active' : '' ?>">
Nueva agencia Nueva agencia
</a> </a>
</div> </div>
@@ -115,10 +115,10 @@
<div class="col-md-4"> <div class="col-md-4">
<div class="card shadow-sm p-3"> <div class="card shadow-sm p-3">
<h5 class="text-info">Aprobar de usuarios</h5> <h5 class="text-success">Aprobar de usuarios</h5>
<p>Aprueba los usuarios que solicitaron un registro.</p> <p>Aprueba los usuarios que solicitaron un registro.</p>
<a href="/IMPORTADORES/administrador/aprobarUsuarios" <a href="/IMPORTADORES/administrador/aprobarUsuarios"
class="btn btn-info btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/sistemas/aprobarUsuarios' ? 'active' : '' ?>"> class="btn btn-success btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/sistemas/aprobarUsuarios' ? 'active' : '' ?>">
Ver usuarios solicitantes Ver usuarios solicitantes
</a> </a>
</div> </div>
@@ -126,10 +126,10 @@
<div class="col-md-4"> <div class="col-md-4">
<div class="card shadow-sm p-3"> <div class="card shadow-sm p-3">
<h5 class="text-indigo">Alta de usuarios</h5> <h5 class="text-info">Alta de usuarios</h5>
<p>Da de alta manualmente a un usuario.</p> <p>Da de alta manualmente a un usuario.</p>
<a href="/IMPORTADORES/administrador/altaUsuarios" <a href="/IMPORTADORES/administrador/altaUsuarios"
class="btn btn-indigo btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/sistemas/altaUsuarios' ? 'active' : '' ?>"> class="btn btn-info btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/sistemas/altaUsuarios' ? 'active' : '' ?>">
Nuevo usuario Nuevo usuario
</a> </a>
</div> </div>

View File

@@ -94,10 +94,10 @@
?> --> ?> -->
<div class="col-md-4"> <div class="col-md-4">
<div class="card shadow-sm p-3"> <div class="card shadow-sm p-3">
<h5 class="text-primary">Solicitudes de vinculación</h5> <h5 class="text-teal">Solicitudes de vinculación</h5>
<p>Aprueba las solicitudes de vinculación de los importadores.</p> <p>Aprueba las solicitudes de vinculación de los importadores.</p>
<a href="/IMPORTADORES/vinculaciones/solicitudesVinculacion" <a href="/IMPORTADORES/vinculaciones/solicitudesVinculacion"
class="btn btn-primary btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/vinculaciones/solicitudesVinculacion' ? 'active' : '' ?>"> class="btn btn-teal btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/vinculaciones/solicitudesVinculacion' ? 'active' : '' ?>">
Ver solicitudes Ver solicitudes
</a> </a>
</div> </div>
@@ -105,10 +105,10 @@
<div class="col-md-4"> <div class="col-md-4">
<div class="card shadow-sm p-3"> <div class="card shadow-sm p-3">
<h5 class="text-success">Usuarios vinculados</h5> <h5 class="text-lime">Usuarios vinculados</h5>
<p>Consulta los que ya fueron autorizados.</p> <p>Consulta los que ya fueron autorizados.</p>
<a href="/IMPORTADORES/vinculaciones/vinculacionesAgencia" <a href="/IMPORTADORES/vinculaciones/vinculacionesAgencia"
class="btn btn-success btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/vinculaciones/vinculacionesAgencia' ? 'active' : '' ?>"> class="btn btn-lime btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/vinculaciones/vinculacionesAgencia' ? 'active' : '' ?>">
Ver usuarios Ver usuarios
</a> </a>
</div> </div>
@@ -116,10 +116,10 @@
<div class="col-md-4"> <div class="col-md-4">
<div class="card shadow-sm p-3"> <div class="card shadow-sm p-3">
<h5 class="text-info">Alta de agentes</h5> <h5 class="text-success">Alta de agentes</h5>
<p>Da de alta a tus agentes aduanales.</p> <p>Da de alta a tus agentes aduanales.</p>
<a href="/IMPORTADORES/agencias/alta" <a href="/IMPORTADORES/agencias/alta"
class="btn btn-info btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/agencias/alta' ? 'active' : '' ?>"> class="btn btn-success btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/agencias/alta' ? 'active' : '' ?>">
Nuevo agente Nuevo agente
</a> </a>
</div> </div>
@@ -127,15 +127,26 @@
<div class="col-md-4"> <div class="col-md-4">
<div class="card shadow-sm p-3"> <div class="card shadow-sm p-3">
<h5 class="text-indigo">Patentes</h5> <h5 class="text-info">Patentes</h5>
<p>Gestiona las patentes de la agencia.</p> <p>Gestiona las patentes de la agencia.</p>
<a href="/IMPORTADORES/patente/dashboard" <a href="/IMPORTADORES/patente/dashboard"
class="btn btn-indigo btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/patente/dashboard' ? 'active' : '' ?>"> class="btn btn-info btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/patente/dashboard' ? 'active' : '' ?>">
Ver agentes Ver agentes
</a> </a>
</div> </div>
</div> </div>
<div class="col-md-4">
<div class="card shadow-sm p-3">
<h5 class="text-cyan">Locaciones</h5>
<p>Gestiona la locaciones validas para nuevos registros.</p>
<a href="/IMPORTADORES/locaciones/lista"
class="btn btn-cyan btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/locaciones/lista' ? 'active' : '' ?>">
Gestionar locaciones
</a>
</div>
</div>
<div class="col-md-4"> <div class="col-md-4">
<div class="card shadow-sm p-3"> <div class="card shadow-sm p-3">
<h5 class="text-warning">Configuración</h5> <h5 class="text-warning">Configuración</h5>
@@ -147,17 +158,6 @@
</div> </div>
</div> </div>
<div class="col-md-4">
<div class="card shadow-sm p-3">
<h5 class="text-orange">Locaciones</h5>
<p>Gestiona la locaciones validas para nuevos registros.</p>
<a href="/IMPORTADORES/locaciones/lista"
class="btn btn-orange btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/locaciones/lista' ? 'active' : '' ?>">
Gestionar locaciones
</a>
</div>
</div>
<div class="col-md-4"> <div class="col-md-4">
<div class="card shadow-sm p-3"> <div class="card shadow-sm p-3">
<h5 class="text-danger">Cerrar sesión</h5> <h5 class="text-danger">Cerrar sesión</h5>

View File

@@ -97,10 +97,10 @@ include __DIR__ . '/../partials/sidebar_agente.php';
?> --> ?> -->
<div class="col-md-4"> <div class="col-md-4">
<div class="card shadow-sm p-3"> <div class="card shadow-sm p-3">
<h5 class="text-primary">Importadores vinculados</h5> <h5 class="text-teal">Importadores vinculados</h5>
<p>Consulta los que ya fueron autorizados.</p> <p>Consulta los que ya fueron autorizados.</p>
<a href="/IMPORTADORES/agentes/vinculados" <a href="/IMPORTADORES/agentes/vinculados"
class="btn btn-primary btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/agentes/vinculados' ? 'active' : '' ?>"> class="btn btn-teal btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/agentes/vinculados' ? 'active' : '' ?>">
Ver importadores Ver importadores
</a> </a>
</div> </div>
@@ -108,10 +108,10 @@ include __DIR__ . '/../partials/sidebar_agente.php';
<div class="col-md-4"> <div class="col-md-4">
<div class="card shadow-sm p-3"> <div class="card shadow-sm p-3">
<h5 class="text-success">Patentes</h5> <h5 class="text-lime">Patentes</h5>
<p>Gestiona las patentes de la agencia.</p> <p>Gestiona las patentes de la agencia.</p>
<a href="/IMPORTADORES/patente/dashboard" <a href="/IMPORTADORES/patente/dashboard"
class="btn btn-success btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES//patente/dashboard' ? 'active' : '' ?>"> class="btn btn-lime btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES//patente/dashboard' ? 'active' : '' ?>">
Ver solicitudes Ver solicitudes
</a> </a>
</div> </div>
@@ -119,10 +119,10 @@ include __DIR__ . '/../partials/sidebar_agente.php';
<div class="col-md-4"> <div class="col-md-4">
<div class="card shadow-sm p-3"> <div class="card shadow-sm p-3">
<h5 class="text-info">Locaciones</h5> <h5 class="text-success">Locaciones</h5>
<p>Gestiona la locaciones validas para nuevos registros.</p> <p>Gestiona la locaciones validas para nuevos registros.</p>
<a href="/IMPORTADORES/locaciones/lista" <a href="/IMPORTADORES/locaciones/lista"
class="btn btn-info btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/locaciones/lista' ? 'active' : '' ?>"> class="btn btn-success btn-sm mt-2 <?= $_SERVER['REQUEST_URI'] === '/IMPORTADORES/locaciones/lista' ? 'active' : '' ?>">
Gestionar locaciones Gestionar locaciones
</a> </a>
</div> </div>

View File

@@ -14,6 +14,12 @@
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<!-- Animate.css para animaciones adicionales --> <!-- Animate.css para animaciones adicionales -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">
<!-- CSS de Flatpickr -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<!-- JS de Flatpickr -->
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<!-- Idioma español -->
<script src="https://cdn.jsdelivr.net/npm/flatpickr/dist/l10n/es.js"></script>
<style> <style>
table.dataTable thead th { background: #343a40; color: #fff; } table.dataTable thead th { background: #343a40; color: #fff; }
body { font-family: 'Segoe UI', sans-serif; background-color: #f4f6f9; } body { font-family: 'Segoe UI', sans-serif; background-color: #f4f6f9; }
@@ -59,6 +65,114 @@
.btn-animated::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; .btn-animated::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); transition: left 0.5s; } background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); transition: left 0.5s; }
.btn-animated:hover::before { left: 100%; } .btn-animated:hover::before { left: 100%; }
/* ========== ANIMACIONES PARA INPUTS TEXTO ========== */
.form-control:not(.no-animation) { transition: all 0.3s ease; border: 2px solid #dee2e6; position: relative; }
.form-control:not(.no-animation):focus { border-color: #0d6efd; box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.25), 0 0 20px rgba(13, 110, 253, 0.3); transform: translateY(-2px); }
.form-control:not(.no-animation):not(:placeholder-shown) { border-color: #198754; background-color: #f8fff9; }
.form-control:not(.no-animation).shake { animation: shake 0.5s ease-in-out; }
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-5px); }
75% { transform: translateX(5px); }
}
/* Floating labels para inputs texto */
.form-floating-custom { position: relative; margin-bottom: 1.5rem; }
.form-floating-custom .form-control { padding: 1rem 0.75rem 0.5rem 0.75rem; height: auto; }
.form-floating-custom .form-label { position: absolute; top: 0.75rem; left: 0.75rem; transition: all 0.3s ease; pointer-events: none; color: #6c757d; z-index: 2; }
.form-floating-custom .form-control:focus ~ .form-label,
.form-floating-custom .form-control:not(:placeholder-shown) ~ .form-label { top: 0.25rem; font-size: 0.75rem; color: #0d6efd; font-weight: 600; }
.input-pulse:hover:not(.no-animation) { animation: inputPulse 0.6s ease-in-out; }
@keyframes inputPulse {
0% { transform: scale(1); }
50% { transform: scale(1.02); }
100% { transform: scale(1); }
}
.input-gradient:not(.no-animation) { position: relative; overflow: hidden; }
.input-gradient:not(.no-animation)::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%;
background: linear-gradient(90deg, transparent, rgba(13, 110, 253, 0.3), transparent); transition: left 0.5s; pointer-events: none; z-index: 1; }
.input-gradient:not(.no-animation):focus::before { left: 100%; }
.form-control.valid:not(.no-animation) { border-color: #198754; background: linear-gradient(45deg, #fff, #f8fff9); animation: successGlow 1s ease-in-out; }
@keyframes successGlow {
0% { box-shadow: 0 0 5px rgba(25, 135, 84, 0.5); }
50% { box-shadow: 0 0 20px rgba(25, 135, 84, 0.8); }
100% { box-shadow: 0 0 5px rgba(25, 135, 84, 0.5); }
}
.input-typing:not(.no-animation) { position: relative; }
.input-typing:not(.no-animation)::after { content: '|'; position: absolute; right: 10px; top: 50%; transform: translateY(-50%); opacity: 0; animation: blink 1s infinite; color: #0d6efd; }
.input-typing:not(.no-animation):focus::after { opacity: 1; }
@keyframes blink {
0%, 50% { opacity: 1; }
51%, 100% { opacity: 0; }
}
.input-ripple:not(.no-animation) { position: relative; overflow: hidden; }
.input-ripple:not(.no-animation)::before { content: ''; position: absolute; top: 50%; left: 50%; width: 0; height: 0;
background: rgba(13, 110, 253, 0.2); border-radius: 50%; transform: translate(-50%, -50%); transition: width 0.3s, height 0.3s; pointer-events: none; }
.input-ripple:not(.no-animation):focus::before { width: 300px; height: 300px; }
/* Animación para los campos del formulario */
.form-group-animated { opacity: 0; transform: translateY(20px); animation: slideUp 0.6s ease-out forwards; }
.form-group-animated:nth-child(1) { animation-delay: 0.1s; }
.form-group-animated:nth-child(2) { animation-delay: 0.2s; }
.form-group-animated:nth-child(3) { animation-delay: 0.3s; }
.form-group-animated:nth-child(4) { animation-delay: 0.4s; }
.form-group-animated:nth-child(5) { animation-delay: 0.5s; }
.form-group-animated:nth-child(6) { animation-delay: 0.6s; }
.form-group-animated:nth-child(7) { animation-delay: 0.7s; }
.form-group-animated:nth-child(8) { animation-delay: 0.8s; }
.form-group-animated:nth-child(9) { animation-delay: 0.9s; }
.form-group-animated:nth-child(10) { animation-delay: 1.0s; }
@keyframes slideUp { to { opacity: 1; transform: translateY(0); } }
/* ========== ANIMACIONES PARA SELECT ========== */
.form-select { transition: all 0.3s ease; border: 2px solid #dee2e6; position: relative; cursor: pointer;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m1 6 7 7 7-7'/%3e%3c/svg%3e");
background-repeat: no-repeat; background-position: right 0.75rem center; background-size: 16px 12px; padding: 1rem 2.5rem 0.5rem 0.75rem; height: auto; min-height: 3.5rem; }
.form-select:focus { border-color: #0d6efd; box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.25), 0 0 20px rgba(13, 110, 253, 0.3); transform: translateY(-2px);
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%230d6efd' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m1 6 7 7 7-7'/%3e%3c/svg%3e"); }
.form-select:not([value=""]):valid { border-color: #198754; background-color: #f8fff9;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23198754' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m1 6 7 7 7-7'/%3e%3c/svg%3e"); }
.form-select[value=""] { border-color: #dee2e6; background-color: #fff; }
/* Floating labels para select */
.form-floating-custom .form-select ~ .form-label { position: absolute; top: 50%; left: 0.75rem; transform: translateY(-50%); pointer-events: none;
transition: all 0.3s ease; color: #6c757d; font-size: 0.875rem; background: white; padding: 0 0.25rem; z-index: 1; opacity: 0; }
.form-floating-custom .form-select:focus ~ .form-label { opacity: 1; top: 0; transform: translateY(-50%) scale(0.85); color: #0d6efd; font-weight: 600; }
.form-floating-custom .form-select:not([value=""]):valid ~ .form-label { opacity: 1; top: 0; transform: translateY(-50%) scale(0.85); color: #0d6efd; font-weight: 600; }
.form-select.shake { animation: shake 0.5s ease-in-out; }
.select-pulse:hover { animation: inputPulse 0.6s ease-in-out; }
.select-gradient { position: relative; overflow: hidden; }
.select-gradient::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%;
background: linear-gradient(90deg, transparent, rgba(13, 110, 253, 0.3), transparent); transition: left 0.5s; pointer-events: none; z-index: 1; }
.select-gradient:focus::before { left: 100%; }
.form-select.valid { border-color: #198754; background-color: #f8fff9; animation: successGlow 1s ease-in-out; }
.select-arrow-rotate { transition: all 0.3s ease; }
.select-arrow-rotate:focus { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%230d6efd' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m1 10 7-7 7 7'/%3e%3c/svg%3e"); }
.select-ripple { position: relative; overflow: hidden; }
.select-ripple::after { content: ''; position: absolute; top: 50%; left: 50%; width: 0; height: 0;
background: rgba(13, 110, 253, 0.2); border-radius: 50%; transform: translate(-50%, -50%); transition: width 0.3s, height 0.3s; pointer-events: none; }
.select-ripple:focus::after { width: 300px; height: 300px; }
.select-scale { transition: transform 0.2s ease; }
.select-scale:hover {transform: scale(1.02); }
.select-scale:focus { transform: scale(1.02) translateY(-2px); }
.form-select option { padding: 0.5rem; transition: all 0.2s ease; }
.form-select option:hover { background-color: #f8f9fa; }
.select-status { position: relative; }
.select-status::after { content: ''; position: absolute; right: 2.5rem; top: 50%; transform: translateY(-50%);
width: 8px; height: 8px; border-radius: 50%; background-color: #dc3545; opacity: 0; transition: opacity 0.3s ease; }
.select-status.valid::after { background-color: #198754; opacity: 1; }
.select-status:invalid::after { background-color: #dc3545; opacity: 1; }
/* ========== ESTILOS PARA CAMPO FECHA ========== */
.form-floating-fecha { position: relative; margin-bottom: 1.5rem; }
.form-floating-fecha .form-control { padding: 1rem 0.75rem; transition: all 0.3s ease; border: 2px solid #dee2e6; }
.form-floating-fecha .form-control:focus { border-color: #0d6efd; box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.25), 0 0 20px rgba(13, 110, 253, 0.3); transform: translateY(-2px); }
.form-floating-fecha .form-control:not(:placeholder-shown) { border-color: #198754; background-color: #f8fff9; }
.form-floating-fecha .form-label { position: absolute; top: 50%; left: 0.75rem; transform: translateY(-50%);pointer-events: none;
transition: all 0.3s ease; color: #6c757d; opacity: 0; font-size: 0.875rem; background: white; padding: 0 0.25rem; z-index: 1; }
.form-floating-fecha .form-control:focus ~ .form-label,
.form-floating-fecha .form-control:not(:placeholder-shown) ~ .form-label { opacity: 1; top: 0; transform: translateY(-50%) scale(0.85); color: #0d6efd; font-weight: 600; }
.form-floating-fecha .form-control:focus, .form-floating-fecha .form-control:not(:placeholder-shown) { padding-top: 1.625rem; padding-bottom: 0.625rem; }
/* ========== ESTILOS PARA CAMPO FOTO (SIN ANIMACIONES) ========== */
.no-animation, .no-border-style { transition: none !important; border: 1px solid #ccc !important; box-shadow: none !important; background: #fff !important; }
.no-animation:focus { transform: none !important; border: 1px solid #0d6efd !important; box-shadow: none !important; }
.no-animation:hover { animation: none !important; }
.no-animation::before, .no-animation::after { display: none !important; }
</style> </style>
</head> </head>
<body> <body>
@@ -68,9 +182,11 @@
<div class="card p-4 shadow-sm bg-white card-hover position-relative h-auto"> <div class="card p-4 shadow-sm bg-white card-hover position-relative h-auto">
<!-- Se agrega enctype para subir archivos --> <!-- Se agrega enctype para subir archivos -->
<form action="/IMPORTADORES/choferes/guardar" method="POST" enctype="multipart/form-data" id="formAltaChoferes"> <form action="/IMPORTADORES/choferes/guardar" method="POST" enctype="multipart/form-data" id="formAltaChoferes">
<div class="mb-3"> <div class="row mb-3">
<label for="transportista_id" class="form-label">Transportista</label> <div class="col-md-12 form-group-animated">
<select name="transportista_id" id="transportista_id" class="form-select" required> <label for="" class="form-label">Transportista</label>
<div class="form-floating-custom">
<select name="transportista_id" id="transportista_id" class="form-select select-pulse select-gradient select-arrow-rotate select-status" required>
<option value="">-- Selecciona un transportista --</option> <option value="">-- Selecciona un transportista --</option>
<?php foreach ($transportistas as $t): ?> <?php foreach ($transportistas as $t): ?>
<option value="<?= $t['id_transportista'] ?>"> <option value="<?= $t['id_transportista'] ?>">
@@ -78,51 +194,79 @@
</option> </option>
<?php endforeach; ?> <?php endforeach; ?>
</select> </select>
<label for="transportista_id" class="form-label">Transportista</label>
</div>
</div> </div>
<div class="mb-3"> <div class="col-md-6 form-group-animated">
<label for="" class="form-label">Nombre</label>
<div class="form-floating-custom">
<input name="nombre" id="nombre" type="text" class="form-control input-pulse input-gradient" placeholder="" required>
<label for="nombre" class="form-label">Nombre</label> <label for="nombre" class="form-label">Nombre</label>
<input name="nombre" id="nombre" type="text" class="form-control" required> </div>
</div> </div>
<div class="mb-3"> <div class="col-md-6 form-group-animated">
<label for="apellido" class="form-label">Apellido</label> <label for="" class="form-label">Apellidos</label>
<input name="apellido" id="apellido" type="text" class="form-control" required> <div class="form-floating-custom">
<input name="apellido" id="apellido" type="text" class="form-control input-pulse input-gradient" placeholder="" required>
<label for="apellido" class="form-label">Apellidos</label>
</div>
</div> </div>
<div class="mb-3"> <div class="col-md-6 form-group-animated">
<label for="" class="form-label">Número de Licencia</label>
<div class="form-floating-custom">
<input name="numero_licencia" id="numero_licencia" type="text" maxlength="11" class="form-control input-pulse input-gradient" placeholder="" required>
<label for="numero_licencia" class="form-label">Número de Licencia</label> <label for="numero_licencia" class="form-label">Número de Licencia</label>
<input name="numero_licencia" id="numero_licencia" type="text" maxlength="11" class="form-control" required> </div>
</div> </div>
<div class="mb-3"> <div class="col-md-6 form-group-animated">
<label for="" class="form-label">Número de Gafete</label>
<div class="form-floating-custom">
<input name="numero_gafete" id="numero_gafete" type="text" maxlength="24" class="form-control input-pulse input-gradient" placeholder="" required>
<label for="numero_gafete" class="form-label">Número de Gafete</label> <label for="numero_gafete" class="form-label">Número de Gafete</label>
<input name="numero_gafete" id="numero_gafete" type="text" maxlength="24" class="form-control" required> </div>
</div> </div>
<div class="mb-3"> <div class="col-md-6 form-group-animated">
<label for="" class="form-label">Teléfono</label>
<div class="form-floating-custom">
<input name="telefono" id="telefono" type="tel" maxlength="11" class="form-control input-pulse input-gradient" placeholder="">
<label for="telefono" class="form-label">Teléfono</label> <label for="telefono" class="form-label">Teléfono</label>
<input name="telefono" id="telefono" type="tel" maxlength="11" class="form-control"> </div>
</div> </div>
<div class="mb-3"> <div class="col-md-6 form-group-animated">
<label for="" class="form-label">Email</label>
<div class="form-floating-custom">
<input name="email" id="email" type="email" class="form-control input-pulse input-typing" placeholder="">
<label for="email" class="form-label">Email</label> <label for="email" class="form-label">Email</label>
<input name="email" id="email" type="email" class="form-control"> </div>
</div> </div>
<div class="mb-3"> <div class="col-md-6 form-group-animated">
<label for="" class="form-label">Fecha de Ingreso</label>
<div class="form-floating-fecha">
<input name="fecha_ingreso" id="fecha_ingreso" type="text" class="form-control input-pulse input-gradient" placeholder="dd/mm/aaaa">
<label for="fecha_ingreso" class="form-label">Fecha de Ingreso</label> <label for="fecha_ingreso" class="form-label">Fecha de Ingreso</label>
<input name="fecha_ingreso" id="fecha_ingreso" type="date" class="form-control"> </div>
</div> </div>
<!-- Nuevo campo para foto --> <!-- Nuevo campo para foto -->
<div class="mb-3"> <div class="col-md-6 form-group-animated">
<label for="foto" class="form-label">Foto del Chofer</label> <label for="foto" class="form-label">Foto del Chofer (Opcional)</label>
<input name="foto" id="foto" type="file" class="form-control" accept="image/*"> <div class="form-floating-custom">
<input name="foto" id="foto" type="file" class="form-control no-animation no-border-style" accept="image/*">
</div>
</div> </div>
<div class="text-end mt-4 form-group-animated">
<button type="submit" class="btn btn-success mt-auto w-auto btn-animated">Guardar</button> <button type="submit" class="btn btn-success mt-auto w-auto btn-animated">Guardar</button>
<a href="/IMPORTADORES/choferes/lista" class="btn btn-secondary ms-2 mt-auto w-auto btn-animated">Cancelar</a> <a href="/IMPORTADORES/choferes/lista" class="btn btn-secondary ms-2 mt-auto w-auto btn-animated">Cancelar</a>
</div>
</div>
</form> </form>
</div> </div>
</div> </div>
@@ -233,6 +377,160 @@
Swal.fire({ icon: 'error', title: 'Error de validación', text: 'No fue posible validar el número de gafete. Intenta de nuevo.', confirmButtonColor: '#dc3545' }); Swal.fire({ icon: 'error', title: 'Error de validación', text: 'No fue posible validar el número de gafete. Intenta de nuevo.', confirmButtonColor: '#dc3545' });
}); });
}); });
// Script para manejar las animaciones de validación
document.addEventListener('DOMContentLoaded', function() {
const inputs = document.querySelectorAll('input.form-control, select.form-select');
inputs.forEach(input => {
// Validación en tiempo real
input.addEventListener('input', function() {
if (this.checkValidity()) {
this.classList.remove('shake');
this.classList.add('valid');
} else {
this.classList.remove('valid');
}
});
// Efecto shake en campos inválidos
input.addEventListener('invalid', function() {
this.classList.add('shake');
setTimeout(() => {
this.classList.remove('shake');
}, 500);
});
});
// Validación del formulario
document.getElementById('formAltaChoferes').addEventListener('submit', function(e) {
e.preventDefault();
let isValid = true;
const form = this;
inputs.forEach(input => {
if (!input.checkValidity()) {
input.classList.add('shake');
isValid = false;
}
});
// Si todo es válido, enviar el formulario
if (isValid) {
// Mostrar indicador de carga
const submitBtn = form.querySelector('button[type="submit"]');
const originalText = submitBtn.textContent;
submitBtn.disabled = true;
submitBtn.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Guardando...';
// Aquí puedes enviar el formulario real
form.submit();
} else {
// Mostrar mensaje de error
showNotification('Por favor, complete todos los campos obligatorios correctamente.', 'error');
}
});
});
// Manejo específico para selects
document.addEventListener('DOMContentLoaded', function() {
const selects = document.querySelectorAll('.form-select');
selects.forEach(select => {
// Manejar cambios en el select
select.addEventListener('change', function() {
updateSelectState(this);
});
// Estado inicial
updateSelectState(select);
});
function updateSelectState(select) {
// Actualizar el atributo value para que el CSS pueda detectarlo
select.setAttribute('value', select.value);
// Agregar/quitar clase valid basado en si hay valor seleccionado
if (select.value && select.value !== '') {
select.classList.add('valid');
select.classList.remove('invalid');
} else {
select.classList.remove('valid');
// Solo agregar invalid si el campo es required y se ha intentado enviar
if (select.hasAttribute('required') && select.closest('form')?.classList.contains('was-validated')) {
select.classList.add('invalid');
}
}
}
});
// Validación específica para campos de texto
document.addEventListener('DOMContentLoaded', function() {
// Validación del número de licencia (solo números y letras)
const licenciaInput = document.getElementById('numero_licencia');
if (licenciaInput) {
licenciaInput.addEventListener('input', function() {
this.value = this.value.replace(/[^A-Za-z0-9]/g, '');
});
}
// Validación del teléfono (solo números)
const telefonoInput = document.getElementById('telefono');
if (telefonoInput) {
telefonoInput.addEventListener('input', function() {
this.value = this.value.replace(/[^0-9]/g, '');
});
}
// Validación del email en tiempo real
const emailInput = document.getElementById('email');
if (emailInput) {
emailInput.addEventListener('input', function() {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (this.value && !emailRegex.test(this.value)) {
this.setCustomValidity('Por favor, ingrese un email válido');
} else {
this.setCustomValidity('');
}
});
}
});
// Función para mostrar notificaciones
function showNotification(message, type = 'info') {
// Crear el elemento de notificación
const notification = document.createElement('div');
notification.className = `alert alert-${type === 'error' ? 'danger' : type} alert-dismissible fade show position-fixed`;
notification.style.cssText = ` top: 20px; right: 20px; z-index: 9999; min-width: 300px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);`;
notification.innerHTML = `${message} <button type="button" class="btn-close" data-bs-dismiss="alert"></button>`;
document.body.appendChild(notification);
// Auto-remover después de 5 segundos
setTimeout(() => {
if (notification.parentNode) {
notification.remove();
}
}, 5000);
}
// Inicializar Flatpickr para la fecha
flatpickr("#fecha_ingreso", {
dateFormat: "d/m/Y",
locale: "es",
maxDate: "today",
onChange: function(selectedDates, dateStr, instance) {
// Validar que la fecha no sea futura
const today = new Date();
today.setHours(0, 0, 0, 0);
if (selectedDates[0] > today) {
showNotification('La fecha de ingreso no puede ser futura.', 'error');
instance.clear();
}
}
});
</script> </script>
</body> </body>

View File

@@ -97,10 +97,10 @@ if ($tipoUsuario === 'agente_aduanal') {
</div><br><br> </div><br><br>
<div class="col-md-4 d-flex align-items-end"> <div class="col-md-4 d-flex align-items-end">
<button type="submit" class="btn btn-success mt-auto w-auto btn-animated"> <button type="submit" class="btn btn-success W-100 btn-animated">
<i class="fas fa-plus"></i> Registrar Estado <i class="fas fa-plus"></i> Registrar Estado
</button> </button>
<a href="/IMPORTADORES/locaciones/lista" class="btn btn-secondary ms-2 mt-auto w-auto btn-animated">Cancelar</a> <a href="/IMPORTADORES/locaciones/lista" class="btn btn-secondary ms-2 W-100 btn-animated">Cancelar</a>
</div> </div>
</form> </form>
@@ -140,10 +140,10 @@ if ($tipoUsuario === 'agente_aduanal') {
</div><br> </div><br>
<div class="col-md-4 d-flex align-items-end"> <div class="col-md-4 d-flex align-items-end">
<button type="submit" class="btn btn-success w-auto"> <button type="submit" class="btn btn-success W-100 btn-animated">
<i class="fas fa-plus"></i> Registrar Ciudad <i class="fas fa-plus"></i> Registrar Ciudad
</button> </button>
<a href="/IMPORTADORES/locaciones/lista" class="btn btn-secondary ms-2 mt-auto w-auto btn-animated">Cancelar</a> <a href="/IMPORTADORES/locaciones/lista" class="btn btn-secondary ms-2 W-100 btn-animated">Cancelar</a>
</div> </div>
</form> </form>
</div> </div>

View File

@@ -247,8 +247,27 @@ $dos_factores_estado = obtenerEstadoDosFactores();
body: formData, body: formData,
credentials: 'same-origin' credentials: 'same-origin'
}) })
.then(response => response.json()) .then(response => {
.then(data => { // Primero verificar si la respuesta es exitosa
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// Obtener el texto de la respuesta
return response.text();
})
.then(text => {
// Intentar parsear como JSON
let data;
try {
data = JSON.parse(text);
} catch (e) {
// Si no es JSON válido, mostrar el error HTML recibido
console.error('Respuesta no válida del servidor:', text);
throw new Error('El servidor devolvió una respuesta no válida. Revisa la consola para más detalles.');
}
// Procesar la respuesta JSON
if (data.success) { if (data.success) {
// Éxito: mostrar mensaje y redirigir // Éxito: mostrar mensaje y redirigir
mostrarExito(data.message); mostrarExito(data.message);

View File

@@ -12,6 +12,8 @@ $dos_factores_estado = obtenerEstadoDosFactores();
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/2.1.2/sweetalert.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/2.1.2/sweetalert.min.js"></script>
<!-- SweetAlert2 -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<!-- Font Awesome --> <!-- Font Awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<!-- Animate.css para animaciones adicionales --> <!-- Animate.css para animaciones adicionales -->
@@ -33,6 +35,7 @@ $dos_factores_estado = obtenerEstadoDosFactores();
.sidebar .nav-link:hover, .sidebar .nav-link:hover,
.sidebar .nav-link.active { background-color: #e9ecef; color: #212529; } .sidebar .nav-link.active { background-color: #e9ecef; color: #212529; }
} }
.hide { display: none !important; }
.card { border-radius: 12px; } .card { border-radius: 12px; }
.btn i { font-family: "Font Awesome 6 Free", sans-serif; margin-right: 0.5rem; } .btn i { font-family: "Font Awesome 6 Free", sans-serif; margin-right: 0.5rem; }
.btn { font-family: 'Segoe UI', sans-serif; } .btn { font-family: 'Segoe UI', sans-serif; }
@@ -75,6 +78,68 @@ $dos_factores_estado = obtenerEstadoDosFactores();
.btn-animated::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; .btn-animated::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); transition: left 0.5s; } background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); transition: left 0.5s; }
.btn-animated:hover::before { left: 100%; } .btn-animated:hover::before { left: 100%; }
/* ========== ANIMACIONES PARA INPUTS ========== */
/* 1. Animación al hacer focus */
.form-control { transition: all 0.3s ease; border: 2px solid #dee2e6; position: relative; }
.form-control:focus { border-color: #0d6efd; box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.25), 0 0 20px rgba(13, 110, 253, 0.3); transform: translateY(-2px); }
/* 2. Animación al escribir */
.form-control:not(:placeholder-shown) { border-color: #198754; background-color: #f8fff9; }
/* 3. Efecto de shake en validación */
.form-control.shake { animation: shake 0.5s ease-in-out; }
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-5px); }
75% { transform: translateX(5px); }
}
/* 4. Floating labels con animación */
.form-floating-custom { position: relative; margin-bottom: 1.5rem; }
.form-floating-custom .form-control { padding: 1rem 0.75rem 0.5rem 0.75rem; height: auto; }
.form-floating-custom .form-label { position: absolute; top: 0.75rem; left: 0.75rem; transition: all 0.3s ease; pointer-events: none; color: #6c757d; z-index: 2; }
.form-floating-custom .form-control:focus ~ .form-label,
.form-floating-custom .form-control:not(:placeholder-shown) ~ .form-label { top: 0.25rem; font-size: 0.75rem; color: #0d6efd; font-weight: 600; }
/* 5. Efecto de pulso en hover */
.input-pulse:hover { animation: inputPulse 0.6s ease-in-out; }
@keyframes inputPulse {
0% { transform: scale(1); }
50% { transform: scale(1.02); }
100% { transform: scale(1); }
}
/* 6. Gradiente animado en el borde */
.input-gradient { position: relative; overflow: hidden; }
.input-gradient::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%;
background: linear-gradient(90deg, transparent, rgba(13, 110, 253, 0.3), transparent); transition: left 0.5s; pointer-events: none; z-index: 1; }
.input-gradient:focus::before { left: 100%; }
/* 7. Efecto de brillo en validación exitosa */
.form-control.valid { border-color: #198754; background: linear-gradient(45deg, #fff, #f8fff9); animation: successGlow 1s ease-in-out; }
@keyframes successGlow {
0% { box-shadow: 0 0 5px rgba(25, 135, 84, 0.5); }
50% { box-shadow: 0 0 20px rgba(25, 135, 84, 0.8); }
100% { box-shadow: 0 0 5px rgba(25, 135, 84, 0.5); }
}
/* 8. Typing effect simulation */
.input-typing { position: relative; }
.input-typing::after { content: '|'; position: absolute; right: 10px; top: 50%; transform: translateY(-50%); opacity: 0; animation: blink 1s infinite; color: #0d6efd; }
.input-typing:focus::after { opacity: 1; }
@keyframes blink {
0%, 50% { opacity: 1; }
51%, 100% { opacity: 0; }
}
/* 9. Efecto de ondas */
.input-ripple { position: relative; overflow: hidden; }
.input-ripple::before { content: ''; position: absolute; top: 50%; left: 50%; width: 0; height: 0; background: rgba(13, 110, 253, 0.2);
border-radius: 50%; transform: translate(-50%, -50%); transition: width 0.3s, height 0.3s; pointer-events: none; }
.input-ripple:focus::before { width: 300px; height: 300px; }
/* 10. Slide-up animation para los campos */
.form-group-animated { opacity: 0; transform: translateY(20px); animation: slideUp 0.6s ease-out forwards; }
.form-group-animated:nth-child(1) { animation-delay: 0.1s; }
.form-group-animated:nth-child(2) { animation-delay: 0.2s; }
.form-group-animated:nth-child(3) { animation-delay: 0.3s; }
.form-group-animated:nth-child(4) { animation-delay: 0.4s; }
.form-group-animated:nth-child(5) { animation-delay: 0.5s; }
.form-group-animated:nth-child(6) { animation-delay: 0.6s; }
.form-group-animated:nth-child(7) { animation-delay: 0.7s; }
.form-group-animated:nth-child(8) { animation-delay: 0.8s; }
@keyframes slideUp { to { opacity: 1; transform: translateY(0); } }
</style> </style>
</head> </head>
<body> <body>
@@ -128,11 +193,14 @@ $dos_factores_estado = obtenerEstadoDosFactores();
<p><code><?= htmlspecialchars($correos['correo_extra']) ?></code></p> <p><code><?= htmlspecialchars($correos['correo_extra']) ?></code></p>
<!-- Formulario para eliminar --> <!-- Formulario para eliminar -->
<form method="POST" action="/IMPORTADORES/seguridad/eliminarCorreoExtra" id="form-eliminar-extra" class="mt-2 hide"></form> <form method="POST" action="/IMPORTADORES/seguridad/eliminarCorreoExtra" id="form-eliminar-extra" class="mt-2 hide"></form>
<form method="POST" action="/IMPORTADORES/seguridad/modificarCorreoExtra"> <form method="POST" action="/IMPORTADORES/seguridad/modificarCorreoExtra" id="formCorreoExtra">
<div class="mb-3"> <div class="mb-3 form-group-animated">
<input type="email" name="email-extra" class="form-control" value="" placeholder="Actualizar correo adicional" required> <div class="form-floating-custom">
<input type="email" name="email-extra" id="email_extra" class="form-control input-pulse input-typing" placeholder=" " required>
<label for="email_extra" class="form-label">Correo adicional *</label>
</div> </div>
<div class="d-flex gap-2"> </div>
<div class="d-flex gap-2 form-group-animated">
<button type="submit" class="btn btn-success btn-sm mt-2 w-40 btn-animated"> <button type="submit" class="btn btn-success btn-sm mt-2 w-40 btn-animated">
<i class="fas fa-edit"></i>Actualizar <i class="fas fa-edit"></i>Actualizar
</button> </button>
@@ -142,11 +210,16 @@ $dos_factores_estado = obtenerEstadoDosFactores();
</div> </div>
</form> </form>
<?php else: ?> <?php else: ?>
<form method="POST" action="/IMPORTADORES/seguridad/correoExtra"> <form method="POST" action="/IMPORTADORES/seguridad/correoExtra" id="formCorreoExtra">
<div class="mb-3"> <div class="mb-3 form-group-animated">
<input type="email" name="email-extra" class="form-control" placeholder="Correo adicional" required> <div class="form-floating-custom">
<input type="email" name="email-extra" id="email_extra" class="form-control input-pulse input-typing" placeholder=" " required>
<label for="email_extra" class="form-label">Correo adicional *</label>
</div> </div>
</div>
<div class="mb-3 form-group-animated">
<button type="submit" class="btn btn-primary btn-sm mt-2 w-40 btn-animated"><i class="fas fa-envelope"></i>Registrar</button> <button type="submit" class="btn btn-primary btn-sm mt-2 w-40 btn-animated"><i class="fas fa-envelope"></i>Registrar</button>
</div>
</form> </form>
<?php endif; ?> <?php endif; ?>
</div> </div>
@@ -163,23 +236,33 @@ $dos_factores_estado = obtenerEstadoDosFactores();
<p><code><?= htmlspecialchars($correos['correo_respaldo']) ?></code></p> <p><code><?= htmlspecialchars($correos['correo_respaldo']) ?></code></p>
<!-- Formulario para eliminar --> <!-- Formulario para eliminar -->
<form method="POST" action="/IMPORTADORES/seguridad/eliminarCorreoRespaldo" id="form-eliminar-respaldo" class="mt-2 hide"></form> <form method="POST" action="/IMPORTADORES/seguridad/eliminarCorreoRespaldo" id="form-eliminar-respaldo" class="mt-2 hide"></form>
<form method="POST" action="/IMPORTADORES/seguridad/modificarCorreoRspaldo"> <form method="POST" action="/IMPORTADORES/seguridad/modificarCorreoRespaldo" id="formCorreoRespaldo">
<div class="mb-3"> <div class="mb-3 form-group-animated">
<input type="email" name="email-respaldo" class="form-control" value="" placeholder="Actualizar correo de respaldo" required> <div class="form-floating-custom">
<input type="email" name="email-respaldo" id="email_respaldo" class="form-control input-pulse input-typing" value="" placeholder=" " required>
<label for="email_respaldo" class="form-label">Correo de respaldo *</label>
</div> </div>
</div>
<div class="d-flex gap-2 form-group-animated">
<button type="submit" class="btn btn-success btn-sm mt-2 w-40 btn-animated"> <button type="submit" class="btn btn-success btn-sm mt-2 w-40 btn-animated">
<i class="fas fa-edit"></i>Actualizar <i class="fas fa-edit"></i>Actualizar
</button> </button>
<button type="button" class="btn btn-danger btn-sm mt-2 w-40 btn-animated" onclick="confirmarEliminacion('respaldo')"> <button type="button" class="btn btn-danger btn-sm mt-2 w-40 btn-animated" onclick="confirmarEliminacion('respaldo')">
<i class="fas fa-trash"></i> Eliminar correo <i class="fas fa-trash"></i> Eliminar correo
</button> </button>
</div>
</form> </form>
<?php else: ?> <?php else: ?>
<form method="POST" action="/IMPORTADORES/seguridad/correoRespaldo"> <form method="POST" action="/IMPORTADORES/seguridad/correoRespaldo" id="formCorreoRespaldo">
<div class="mb-3"> <div class="mb-3 form-group-animated">
<input type="email" name="email-respaldo" class="form-control" placeholder="Correo de respaldo" required> <div class="form-floating-custom">
<input type="email" name="email-respaldo" id="email_respaldo" class="form-control input-pulse input-typing" placeholder=" " required>
<label for="email_respaldo" class="form-label">Correo de respaldo *</label>
</div> </div>
</div>
<div class="mb-3 form-group-animated">
<button type="submit" class="btn btn-primary btn-sm mt-2 w-40 btn-animated"><i class="fas fa-envelope"></i>Registrar</button> <button type="submit" class="btn btn-primary btn-sm mt-2 w-40 btn-animated"><i class="fas fa-envelope"></i>Registrar</button>
</div>
</form> </form>
<?php endif; ?> <?php endif; ?>
</div> </div>
@@ -216,12 +299,12 @@ $dos_factores_estado = obtenerEstadoDosFactores();
</div> </div>
</div> </div>
<div class="modal-footer justify-content-center"> <div class="modal-footer justify-content-center">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"> <button type="button" class="btn btn-secondary btn-sm mt-2 w-40 btn-animated" data-bs-dismiss="modal">
<i class="fas fa-times me-1"></i> <i class="fas fa-times me-1"></i>
Cancelar Cancelar
</button> </button>
<form method="POST" action="/IMPORTADORES/reset/enviarCodigoInterno" style="display: inline;"> <form method="POST" action="/IMPORTADORES/reset/enviarCodigoInterno" style="display: inline;">
<button type="submit" class="btn btn-primary"> <button type="submit" class="btn btn-primary btn-sm mt-2 w-40 btn-animated">
<i class="fas fa-check me-1"></i> <i class="fas fa-check me-1"></i>
Sí, estoy seguro Sí, estoy seguro
</button> </button>
@@ -236,45 +319,158 @@ $dos_factores_estado = obtenerEstadoDosFactores();
const label = document.querySelector('label[for="dos_factores"]'); const label = document.querySelector('label[for="dos_factores"]');
chk.addEventListener('change', () => { label.textContent = chk.checked ? 'Activo' : 'Inactivo'; }); chk.addEventListener('change', () => { label.textContent = chk.checked ? 'Activo' : 'Inactivo'; });
// Función para confirmar eliminación con SweetAlert
// Función para confirmar eliminación con SweetAlert2
function confirmarEliminacion(tipo) { function confirmarEliminacion(tipo) {
const mensajes = { const mensajes = {
'extra': { titulo: '¿Eliminar correo adicional?', texto: 'No podrás recibir notificaciones en este correo.', confirmado: 'Correo adicional eliminado', form: 'form-eliminar-extra' }, 'extra': {
'respaldo': { titulo: '¿Eliminar correo de respaldo?', texto: 'No podrás recuperar tu cuenta con este correo.', confirmado: 'Correo de respaldo eliminado', form: 'form-eliminar-respaldo' } titulo: '¿Eliminar correo adicional?',
texto: 'No podrás recibir notificaciones en este correo.',
confirmado: 'Correo adicional eliminado',
form: 'form-eliminar-extra'
},
'respaldo': {
titulo: '¿Eliminar correo de respaldo?',
texto: 'No podrás recuperar tu cuenta con este correo.',
confirmado: 'Correo de respaldo eliminado',
form: 'form-eliminar-respaldo'
}
}; };
const config = mensajes[tipo]; const config = mensajes[tipo];
swal({ title: config.titulo, text: config.texto, icon: "warning", buttons: {
cancel: { text: "Cancelar", visible: true, className: "btn-secondary" }, Swal.fire({
confirm: { text: "Sí, eliminar", className: "btn-danger" } title: config.titulo,
}, dangerMode: true, text: config.texto,
}) icon: 'warning',
.then((eliminar) => { showCancelButton: true,
if (eliminar) { confirmButtonColor: '#dc3545',
// Mostrar mensaje de éxito y enviar formulario cancelButtonColor: '#6c757d',
swal({ title: "¡Eliminado!", text: config.confirmado, icon: "success", timer: 1500, buttons: false }); confirmButtonText: 'Sí, eliminar',
// Enviar el formulario después de un pequeño delay cancelButtonText: 'Cancelar',
setTimeout(() => { document.getElementById(config.form).submit(); }, 1500); reverseButtons: true
}).then((result) => {
if (result.isConfirmed) {
// Mostrar mensaje de éxito
Swal.fire({
title: '¡Eliminado!',
text: config.confirmado,
icon: 'success',
timer: 1500,
showConfirmButton: false
}).then(() => {
// Enviar el formulario después del mensaje
document.getElementById(config.form).submit();
});
} }
}); });
} }
</script>
<script> // Versión simplificada sin el mensaje de confirmación extra
function confirmarEliminacionSimple(tipo) {
const mensajes = {
'extra': {
titulo: '¿Eliminar correo adicional?',
texto: 'No podrás recibir notificaciones en este correo.',
form: 'form-eliminar-extra'
},
'respaldo': {
titulo: '¿Eliminar correo de respaldo?',
texto: 'No podrás recuperar tu cuenta con este correo.',
form: 'form-eliminar-respaldo'
}
};
const config = mensajes[tipo];
Swal.fire({
title: config.titulo,
text: config.texto,
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#dc3545',
cancelButtonColor: '#6c757d',
confirmButtonText: 'Sí, eliminar',
cancelButtonText: 'Cancelar',
reverseButtons: true
}).then((result) => {
if (result.isConfirmed) {
// Enviar el formulario directamente
document.getElementById(config.form).submit();
}
});
}
// Limpiar y consolidar los event listeners
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
const form = document.querySelector('#modalConfirmarCambio form'); // Event listener único para correo extra
const submitBtn = form.querySelector('button[type="submit"]'); const formCorreoExtra = document.getElementById('formCorreoExtra');
const modal = document.getElementById('modalConfirmarCambio'); if (formCorreoExtra) {
formCorreoExtra.addEventListener('submit', function(e) {
e.preventDefault();
// Agregar efecto de carga al botón de confirmación const correo_extra = document.getElementById('email_extra').value.trim();
form.addEventListener('submit', function() { const correoRegex = /^[a-zA-Z0-9._+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i> Enviando...';
submitBtn.disabled = true; if (!correoRegex.test(correo_extra)) {
Swal.fire({
icon: 'error',
title: 'Correo inválido',
text: 'No es una dirección de correo válida.',
confirmButtonColor: '#dc3545'
});
document.getElementById('email_extra').focus();
return;
}
// Si la validación pasa, enviar el formulario
this.submit();
});
}
// Event listener único para correo de respaldo
const formCorreoRespaldo = document.getElementById('formCorreoRespaldo');
if (formCorreoRespaldo) {
formCorreoRespaldo.addEventListener('submit', function(e) {
e.preventDefault();
const correo_respaldo = document.getElementById('email_respaldo').value.trim();
const correoRegex = /^[a-zA-Z0-9._+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
if (!correoRegex.test(correo_respaldo)) {
Swal.fire({
icon: 'error',
title: 'Correo inválido',
text: 'No es una dirección de correo válida.',
confirmButtonColor: '#dc3545'
});
document.getElementById('email_respaldo').focus();
return;
}
// Si la validación pasa, enviar el formulario
this.submit();
});
}
// Animaciones de validación
const inputs = document.querySelectorAll('.form-control');
inputs.forEach(input => {
input.addEventListener('input', function() {
if (this.checkValidity()) {
this.classList.remove('shake');
this.classList.add('valid');
} else {
this.classList.remove('valid');
}
}); });
// Resetear el botón cuando se cierra el modal input.addEventListener('invalid', function() {
modal.addEventListener('hidden.bs.modal', function() { this.classList.add('shake');
submitBtn.innerHTML = '<i class="fas fa-check me-1"></i> Sí, estoy seguro'; setTimeout(() => {
submitBtn.disabled = false; this.classList.remove('shake');
}, 500);
});
}); });
}); });
</script> </script>

View File

@@ -171,6 +171,10 @@
.select-status::after { content: ''; position: absolute; right: 2.5rem; top: 50%; transform: translateY(-50%); .select-status::after { content: ''; position: absolute; right: 2.5rem; top: 50%; transform: translateY(-50%);
width: 8px; height: 8px; border-radius: 50%; background-color: #dc3545; opacity: 0; transition: opacity 0.3s ease; } .select-status.valid::after { background-color: #198754; opacity: 1; } width: 8px; height: 8px; border-radius: 50%; background-color: #dc3545; opacity: 0; transition: opacity 0.3s ease; } .select-status.valid::after { background-color: #198754; opacity: 1; }
.select-status:invalid::after { background-color: #dc3545; opacity: 1; } .select-status:invalid::after { background-color: #dc3545; opacity: 1; }
/* Quitar todo tipo de animación y borde para el campo foto */
.no-animation,
.no-border-style { transition: none !important; border: 1px solid #ccc !important; box-shadow: none !important; background: #fff !important; }
.no-animation:focus { transform: none !important; }
</style> </style>
</head> </head>
<body> <body>
@@ -203,7 +207,7 @@
<div class="col-md-6 form-group-animated"> <div class="col-md-6 form-group-animated">
<label class="form-label">Foto (opcional)</label> <label class="form-label">Foto (opcional)</label>
<div class="form-floating-custom"> <div class="form-floating-custom">
<input type="file" name="foto" id="foto" class="form-control" accept="image/*"> <input type="file" name="foto" id="foto" class="form-control no-animation no-border-style" accept="image/*">
</div> </div>
</div> </div>