inicio
This commit is contained in:
2025-05-05 11:03:01 -06:00
commit c73e3f2327
185 changed files with 17573 additions and 0 deletions

257
app/controllers/agentes.php Normal file
View File

@@ -0,0 +1,257 @@
<?php
session_start();
require_once __DIR__ . '/../../vendor/autoload.php';
require_once __DIR__ . '/../helpers/session.php';
require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../helpers/crypto.php';
require_once __DIR__ . '/../helpers/bitacoras.php';
require_once __DIR__ . '/../helpers/env.php';
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
loadEnv();
function dashboard() {
if (!isset($_SESSION['usuario_id']) || $_SESSION['tipo_usuario'] !== 'agente_aduanal') {
header("Location: /IMPORTADORES/login");
exit;
}
// Aquí puedes conectar a la BD si vas a mostrar métricas
// Ejemplo:
// $conn = getConnection();
// $sql = "SELECT COUNT(*) FROM solicitudes_importadores WHERE request_status = 'pending'";
// ...
include __DIR__ . '/../../views/agentes/dashboard.php';
}
function importadores_activos() {
if (!($_SESSION['usuario_id'] ?? false) || $_SESSION['tipo_usuario'] !== 'agente_aduanal') {
header('Location: /IMPORTADORES/login');
exit;
}
$conn = getConnection();
$sql = "SELECT id_importador, nombre_empresa, email, telefono, creado_en
FROM importadores
WHERE estatus = 'aprobado'
ORDER BY creado_en DESC";
$stmt = sqlsrv_query($conn, $sql);
$importadores = [];
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$importadores[] = $row;
}
include __DIR__ . '/../../views/agentes/importadores_activos.php';
}
function solicitudes_pendientes() {
if (!($_SESSION['usuario_id'] ?? false) || $_SESSION['tipo_usuario'] !== 'agente_aduanal') {
header('Location: /IMPORTADORES/login');
exit;
}
$conn = getConnection();
$sql = "SELECT request_id, company_name, rfc, email, phone, request_date,opinion_file
FROM solicitudes_importadores
WHERE request_status = 'pending'
ORDER BY request_date DESC";
$stmt = sqlsrv_query($conn, $sql);
$solicitudes = [];
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$solicitudes[] = $row;
}
include __DIR__ . '/../../views/agentes/solicitudes_pendientes.php';
}
function aprobar_solicitud()
{
$conn = getConnection();
$id = $_GET['id'] ?? null;
if (!$id || !is_numeric($id)) {
die("❌ ID inválido.");
}
// Obtener la solicitud
$sql = "SELECT * FROM solicitudes_importadores WHERE request_id = ?";
$stmt = sqlsrv_query($conn, $sql, [$id]);
$solicitud = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
if (!$solicitud) {
die("❌ Solicitud no encontrada.");
}
// Validar que no haya sido aprobada ya
if ($solicitud['request_status'] === 'approved') {
die("⚠️ Esta solicitud ya fue aprobada.");
}
// Preparar datos
$nombre = decrypt($solicitud['company_name']);
$email = $solicitud['email'];
$tipo = 'importador';
// Generar contraseña aleatoria
$password_plain = bin2hex(random_bytes(5));
$password_hash = password_hash($password_plain, PASSWORD_DEFAULT);
// Encriptar datos sensibles
$nombre_encrypt = encrypt($nombre);
$email_encrypt = encrypt($email);
// Insertar en usuarios_sistema
$sqlInsert = "INSERT INTO usuarios_sistema (nombre, email, password_hash, tipo_usuario, activo, creado_en)
VALUES (?, ?, ?, ?, 1, GETDATE())";
$stmtInsert = sqlsrv_query($conn, $sqlInsert, [
$nombre_encrypt, $email_encrypt, $password_hash, $tipo
]);
if (!$stmtInsert) {
die("❌ Error al crear usuario: " . print_r(sqlsrv_errors(), true));
}
// Actualizar solicitud
$sqlUpdate = "UPDATE solicitudes_importadores
SET request_status = 'approved', approval_date = GETDATE(), approved_by = ?
WHERE request_id = ?";
$stmtUpdate = sqlsrv_query($conn, $sqlUpdate, [$_SESSION['usuario_id'] ?? null, $id]);
if (!$stmtUpdate) {
die("❌ Error al actualizar solicitud: " . print_r(sqlsrv_errors(), true));
}
// Enviar correo al importador
$mail = new PHPMailer(true);
try {
$mail->isSMTP();
$mail->Host = 'secure.emailsrvr.com';
$mail->SMTPAuth = true;
$mail->Username = 'noreply@aduanasoft.com.mx';
$mail->Password = $_ENV['SMTP_PASS'];
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
$mail->setFrom('noreply@aduanasoft.com.mx', 'SIIH | AduanaSoft');
$mail->addAddress($email);
$mail->CharSet = 'UTF-8';
$mail->isHTML(true);
$mail->Subject = 'Tu acceso a la plataforma SIIH ha sido autorizado';
$mail->Body = "
<div style='font-family: Segoe UI, sans-serif; background-color: #f4f6f9; padding: 40px;'>
<div style='max-width: 600px; margin: auto; background: #fff; border: 1px solid #ddd; border-radius: 10px; overflow: hidden;'>
<div style='background: linear-gradient(to right, #003366, #0055A5); padding: 20px; text-align: center;'>
<h2 style='color: white;'>¡Bienvenido a SIIH!</h2>
</div>
<div style='padding: 30px; color: #333; font-size: 16px;'>
<p>Tu registro como importador ha sido aprobado. Aquí tienes tus credenciales de acceso:</p>
<p><strong>Correo:</strong> $email</p>
<p><strong>Contraseña:</strong> $password_plain</p>
<p>📌 Te recomendamos cambiar tu contraseña una vez que ingreses al sistema.</p>
<p><a href='http://siih.aduanasoft.com/IMPORTADORES/login' class='btn btn-primary'>Ir al sistema</a></p>
</div>
<div style='background: #e9ecef; text-align: center; padding: 15px; font-size: 13px; color: #666;'>
&copy; " . date('Y') . " SIIH · Desarrollado por AduanaSoft
</div>
</div>
</div>";
$mail->send();
} catch (Exception $e) {
error_log("Error al enviar correo: {$mail->ErrorInfo}");
}
header("Location: /IMPORTADORES/AGENTES/solicitudes_pendientes");
exit;
}
function activos() {
if (!($_SESSION['usuario_id'] ?? false)) {
die("⚠️ No autorizado.");
}
require_once __DIR__ . '/../helpers/crypto.php';
$conn = getConnection();
$sql = "SELECT id_usuario, nombre, email, tipo_usuario, creado_en, activo
FROM usuarios_sistema
WHERE tipo_usuario = 'importador'
ORDER BY creado_en DESC";
$stmt = sqlsrv_query($conn, $sql);
$importadores = [];
if ($stmt) {
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$row['nombre'] = decrypt($row['nombre']);
$row['email'] = decrypt($row['email']);
$importadores[] = $row;
}
}
include __DIR__ . '/../../views/agentes/importadores_activos.php';
}
function toggle_estado() {
if (!($_SESSION['usuario_id'] ?? false) || $_SESSION['tipo_usuario'] !== 'agente_aduanal') {
die("⚠️ No autorizado.");
}
$id = $_GET['id'] ?? null;
if (!$id || !is_numeric($id)) {
die("❌ ID inválido.");
}
$conn = getConnection();
$sql = "SELECT activo FROM usuarios_sistema WHERE id_usuario = ?";
$stmt = sqlsrv_query($conn, $sql, [$id]);
if (!$stmt || !($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC))) {
die("❌ Usuario no encontrado.");
}
$nuevoEstado = $row['activo'] == 1 ? 0 : 1;
$update = "UPDATE usuarios_sistema SET activo = ? WHERE id_usuario = ?";
$result = sqlsrv_query($conn, $update, [$nuevoEstado, $id]);
if (!$result) {
die("❌ Error al actualizar: " . print_r(sqlsrv_errors(), true));
}
// Guardar en bitácora
require_once __DIR__ . '/../helpers/bitacoras.php';
registrar_bitacora_usuario($_SESSION['usuario_id'], 'toggle_estado', "Modificó estado del usuario $id a $nuevoEstado");
header("Location: /IMPORTADORES/agentes/activos");
exit;
}

View File

@@ -0,0 +1,43 @@
<?php
require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../helpers/crypto.php';
session_start();
function login()
{
if (!isset($_SESSION['usuario_id'])) {
die("⚠️ No autorizado.");
}
$conn = getConnection();
$sql = "SELECT id, id_usuario, email, ip, fecha, exito, detalle FROM bitacora_login ORDER BY fecha DESC";
$stmt = sqlsrv_query($conn, $sql);
$logins = [];
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$logins[] = $row;
}
include __DIR__ . '/../../views/bitacoras/bitacora_login.php';
}
function usuarios()
{
if (!isset($_SESSION['usuario_id'])) {
die("⚠️ No autorizado.");
}
$conn = getConnection();
$sql = "SELECT id_bitacora, usuario_id, accion, descripcion, fecha FROM bitacora_usuarios ORDER BY fecha DESC";
$stmt = sqlsrv_query($conn, $sql);
$cambios = [];
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$cambios[] = $row;
}
include __DIR__ . '/../../views/bitacoras/bitacora_usuarios.php';
}

View File

@@ -0,0 +1,304 @@
<?php
session_start();
require_once __DIR__ . '/../../config/database.php';
function lista() {
if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login');
exit;
}
$usr = $_SESSION['usuario_id'];
$conn = getConnection();
$sql = "
SELECT
c.*,
(c.nombre + ' ' + c.apellido) AS nombre_completo,
tr.nombre AS transportista
FROM dbo.choferes c
JOIN dbo.transportistas tr
ON c.transportista_id = tr.id_transportista
WHERE tr.id_usuario = ?
AND c.status = 1
ORDER BY c.created_at DESC
";
$stmt = sqlsrv_query($conn, $sql, [$usr]);
if ($stmt === false) {
die("Error en lista(): " . print_r(sqlsrv_errors(), true));
}
$choferes = [];
while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$choferes[] = $r;
}
include __DIR__ . '/../../views/choferes/lista.php';
}
function crear() {
if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login');
exit;
}
$usr = $_SESSION['usuario_id'];
$conn = getConnection();
// OJO: aquí usamos "activo" según tu esquema original
$sql = "
SELECT id_transportista, nombre
FROM dbo.transportistas
WHERE id_usuario = ? AND activo = 1
ORDER BY nombre
";
$stmt = sqlsrv_query($conn, $sql, [$usr]);
if ($stmt === false) {
die("Error en crear(): " . print_r(sqlsrv_errors(), true));
}
$transportistas = [];
while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$transportistas[] = $r;
}
include __DIR__ . '/../../views/choferes/crear.php';
}
function guardar() {
if (!($_SESSION['usuario_id'] ?? false)) {
die("⚠️ No autorizado.");
}
$transportista_id = $_POST['transportista_id'] ?? null;
$nombre = trim($_POST['nombre'] ?? '');
$apellido = trim($_POST['apellido'] ?? '');
$licencia = trim($_POST['numero_licencia'] ?? '');
$telefono = trim($_POST['telefono'] ?? '');
$email = trim($_POST['email'] ?? '');
$fecha_ingreso = $_POST['fecha_ingreso'] ?: null;
if (!$transportista_id || $nombre === '' || $apellido === '' || $licencia === '') {
die("❌ Todos los campos obligatorios deben llenarse.");
}
// Manejo de foto
$fotoUrl = null;
if (!empty($_FILES['foto']['tmp_name'])) {
$ext = strtolower(pathinfo($_FILES['foto']['name'], PATHINFO_EXTENSION));
$dest = __DIR__ . '/../../public/uploads/chofer_'.uniqid().".{$ext}";
if (!is_dir(dirname($dest))) mkdir(dirname($dest), 0755, true);
if (move_uploaded_file($_FILES['foto']['tmp_name'], $dest)) {
$fotoUrl = "/IMPORTADORES/public/uploads/" . basename($dest);
}
}
$conn = getConnection();
$sql = "
INSERT INTO dbo.choferes
(transportista_id, nombre, apellido, numero_licencia, telefono, email, fecha_ingreso, foto_url, status)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1)
";
$params = [
(int)$transportista_id,
$nombre,
$apellido,
$licencia,
$telefono,
$email,
$fecha_ingreso,
$fotoUrl
];
$stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt === false) {
die("Error en guardar(): " . print_r(sqlsrv_errors(), true));
}
header('Location: /IMPORTADORES/choferes/lista?created=ok');
exit;
}
function editar() {
if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login');
exit;
}
$id = $_GET['id'] ?? null;
if (!$id || !is_numeric($id)) {
die("❌ ID inválido.");
}
$conn = getConnection();
$sql = "
SELECT c.*, tr.nombre AS transportista
FROM dbo.choferes c
JOIN dbo.transportistas tr
ON c.transportista_id = tr.id_transportista
WHERE c.id_chofer = ?
AND tr.id_usuario = ?
AND c.status = 1
";
$stmt = sqlsrv_query($conn, $sql, [(int)$id, $_SESSION['usuario_id']]);
if ($stmt === false) {
die("Error en editar(): " . print_r(sqlsrv_errors(), true));
}
$chofer = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
if (!$chofer) {
die("❌ Chofer no encontrado o no autorizado.");
}
// ✅ Aquí convertimos fecha_ingreso a string YYYY-MM-DD
if ($chofer['fecha_ingreso'] instanceof DateTime) {
$chofer['fecha_ingreso'] = $chofer['fecha_ingreso']->format('Y-m-d');
}
// Lista de transportistas
$sql2 = "
SELECT id_transportista, nombre
FROM dbo.transportistas
WHERE id_usuario = ? AND activo = 1
ORDER BY nombre
";
$stmt2 = sqlsrv_query($conn, $sql2, [$_SESSION['usuario_id']]);
if ($stmt2 === false) {
die("Error en editar() [transportistas]: " . print_r(sqlsrv_errors(), true));
}
$transportistas = [];
while ($r = sqlsrv_fetch_array($stmt2, SQLSRV_FETCH_ASSOC)) {
$transportistas[] = $r;
}
include __DIR__ . '/../../views/choferes/editar.php';
}
/**
* Procesa la actualización de un chofer
*/
function actualizar() {
if (!($_SESSION['usuario_id'] ?? false)) {
die("⚠️ No autorizado.");
}
$id = $_POST['id_chofer'] ?? null;
$transportista_id = $_POST['transportista_id'] ?? null;
$nombre = trim($_POST['nombre'] ?? '');
$apellido = trim($_POST['apellido'] ?? '');
$licencia = trim($_POST['numero_licencia']?? '');
$telefono = trim($_POST['telefono'] ?? '');
$email = trim($_POST['email'] ?? '');
$fecha_ingreso = $_POST['fecha_ingreso'] ?: null;
$status = isset($_POST['status']) ? 1 : 0;
// Validación básica
if (
!$id || !is_numeric($id) ||
!$transportista_id || !is_numeric($transportista_id) ||
$nombre === '' || $apellido === '' || $licencia === ''
) {
die("❌ Datos inválidos o incompletos.");
}
// Manejo de foto nueva (opcional)
$fotoUrl = null;
if (!empty($_FILES['foto']['tmp_name']) && $_FILES['foto']['error'] === UPLOAD_ERR_OK) {
$ext = strtolower(pathinfo($_FILES['foto']['name'], PATHINFO_EXTENSION));
$dest = __DIR__ . '/../../public/uploads/chofer_'.uniqid().".{$ext}";
if (!is_dir(dirname($dest))) {
mkdir(dirname($dest), 0755, true);
}
if (move_uploaded_file($_FILES['foto']['tmp_name'], $dest)) {
$fotoUrl = "/IMPORTADORES/public/uploads/" . basename($dest);
} else {
error_log("Error al mover foto en actualizar(): {$dest}");
}
}
$conn = getConnection();
if ($fotoUrl) {
$sql = "
UPDATE dbo.choferes SET
transportista_id = ?,
nombre = ?,
apellido = ?,
numero_licencia = ?,
telefono = ?,
email = ?,
fecha_ingreso = ?,
foto_url = ?,
status = ?,
updated_at = GETDATE()
WHERE id_chofer = ?
";
$params = [
(int)$transportista_id,
$nombre,
$apellido,
$licencia,
$telefono,
$email,
$fecha_ingreso,
$fotoUrl,
$status,
(int)$id
];
} else {
$sql = "
UPDATE dbo.choferes SET
transportista_id = ?,
nombre = ?,
apellido = ?,
numero_licencia = ?,
telefono = ?,
email = ?,
fecha_ingreso = ?,
status = ?,
updated_at = GETDATE()
WHERE id_chofer = ?
";
$params = [
(int)$transportista_id,
$nombre,
$apellido,
$licencia,
$telefono,
$email,
$fecha_ingreso,
$status,
(int)$id
];
}
$stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt === false) {
die("❌ Error en actualizar(): " . print_r(sqlsrv_errors(), true));
}
header('Location: /IMPORTADORES/choferes/lista?updated=ok');
exit;
}
/**
* “Soft-delete” (status = 0) de un chofer
*/
function eliminar() {
if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login');
exit;
}
$id = $_GET['id'] ?? null;
if (!$id || !is_numeric($id)) {
die("❌ ID inválido.");
}
$conn = getConnection();
$sql = "
UPDATE dbo.choferes
SET status = 0,
updated_at = GETDATE()
WHERE id_chofer = ?
";
$stmt = sqlsrv_query($conn, $sql, [(int)$id]);
if ($stmt === false) {
die("❌ Error en eliminar(): " . print_r(sqlsrv_errors(), true));
}
header('Location: /IMPORTADORES/choferes/lista?deleted=ok');
exit;
}

5
app/controllers/home.php Normal file
View File

@@ -0,0 +1,5 @@
<?php
function index() {
include __DIR__ . '/../../views/home/inicio.php';
}

View File

@@ -0,0 +1,16 @@
<?php
require_once __DIR__ . '/../helpers/session.php';
require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../helpers/crypto.php';
function dashboard()
{
if (!isset($_SESSION['usuario_id']) || $_SESSION['tipo_usuario'] !== 'importador') {
header('Location: /IMPORTADORES/login');
exit;
}
$nombreImportador = $_SESSION['usuario_nombre'];
include __DIR__ . '/../../views/importadores/dashboard_importador.php';
}

76
app/controllers/login.php Normal file
View File

@@ -0,0 +1,76 @@
<?php
require_once __DIR__ . '/../helpers/session.php';
require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../helpers/crypto.php';
require_once __DIR__ . '/../helpers/bitacoras.php';
require_once __DIR__ . '/../helpers/env.php';
loadEnv();
function index()
{
include __DIR__ . '/../../views/login/index.php';
}
function validar()
{
$conn = getConnection();
$email = trim($_POST['email'] ?? '');
$password = $_POST['password'] ?? '';
$ip = $_SERVER['REMOTE_ADDR'] ?? 'N/A';
if (empty($email) || empty($password)) {
$_SESSION['login_error'] = 'Debes ingresar ambos campos.';
header('Location: /IMPORTADORES/login');
exit;
}
$emailEncrypted = encrypt($email);
$sql = "SELECT id_usuario, nombre, email, password_hash, tipo_usuario, activo
FROM usuarios_sistema
WHERE email = ?";
$stmt = sqlsrv_query($conn, $sql, [$emailEncrypted]);
if ($stmt && $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
if (!$row['activo']) {
registrarBitacora($conn, $row['id_usuario'], $email, $ip, 0, 'Usuario inactivo');
$_SESSION['login_error'] = 'Tu usuario está inactivo.';
header('Location: /IMPORTADORES/login');
exit;
}
if (password_verify($password, $row['password_hash'])) {
$_SESSION['usuario_id'] = $row['id_usuario'];
$_SESSION['usuario_nombre'] = decrypt($row['nombre']);
$_SESSION['usuario_email'] = $email;
$_SESSION['tipo_usuario'] = $row['tipo_usuario'];
registrarBitacora($conn, $row['id_usuario'], $email, $ip, 1, 'Login exitoso');
// Redirección por rol
if ($row['tipo_usuario'] === 'importador') {
header('Location: /IMPORTADORES/importadores/dashboard');
} elseif ($row['tipo_usuario'] === 'agente_aduanal') {
header('Location: /IMPORTADORES/AGENTES/dashboard');
} else {
header('Location: /IMPORTADORES/importadores/dashboard');
}
exit;
} else {
registrarBitacora($conn, $row['id_usuario'], $email, $ip, 0, 'Contraseña incorrecta');
}
} else {
registrarBitacora($conn, null, $email, $ip, 0, 'Usuario no encontrado');
}
$_SESSION['login_error'] = 'Credenciales incorrectas.';
header('Location: /IMPORTADORES/login');
}

View File

@@ -0,0 +1,162 @@
<?php
require_once __DIR__ . '/../../vendor/autoload.php';
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require_once __DIR__ . '/../../config/database.php';
function index() {
include __DIR__ . '/../../views/registro/form.php';
}
require_once __DIR__ . '/../helpers/crypto.php';
require_once __DIR__ . '/../helpers/env.php';
loadEnv();
function enviar() {
// Validar reCAPTCHA
$captchaResponse = $_POST['g-recaptcha-response'] ?? '';
if (!$captchaResponse) {
die("❌ Debes completar el reCAPTCHA.");
}
$secretKey = $_ENV['RECAPTCHA_SECRET'];
$verifyUrl = "https://www.google.com/recaptcha/api/siteverify";
$data = [
'secret' => $secretKey,
'response' => $captchaResponse
];
$options = [
'http' => [
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data)
]
];
$context = stream_context_create($options);
$result = file_get_contents($verifyUrl, false, $context);
$response = json_decode($result);
if (!$response->success) {
die("❌ Error de verificación reCAPTCHA.");
}
$conn = getConnection();
$empresa = encrypt($_POST['company_name'] ?? '');
$rfc = encrypt($_POST['rfc'] ?? '');
$email = $_POST['email'] ?? '';
$telefono = $_POST['phone'] ?? '';
$archivo = $_FILES['opinion_file'];
// Validar archivo
if ($archivo['error'] !== 0 || pathinfo($archivo['name'], PATHINFO_EXTENSION) !== 'pdf') {
die("Archivo inválido. Solo se permiten PDFs.");
}
// Guardar archivo
$nombreArchivo = uniqid() . '_' . basename($archivo['name']);
$rutaDestino = __DIR__ . '/../../storage/opiniones/' . $nombreArchivo;
move_uploaded_file($archivo['tmp_name'], $rutaDestino);
// Insertar en la base de datos
$sql = "INSERT INTO solicitudes_importadores
(company_name, rfc, email, phone, opinion_file, request_status, request_date)
VALUES (?, ?, ?, ?, ?, 'pending', GETDATE())";
$params = [$empresa, $rfc, $email, $telefono, $nombreArchivo];
$stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt === false) {
die(print_r(sqlsrv_errors(), true));
}
$mail = new PHPMailer(true);
try {
// Configuración SMTP
$mail->isSMTP();
$mail->Host = 'secure.emailsrvr.com';
$mail->SMTPAuth = true;
$mail->Username = 'noreply@aduanasoft.com.mx';
$mail->Password = $_ENV['SMTP_PASS']; // desde el .env
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
// Correo remitente y destinatario
$mail->setFrom('noreply@aduanasoft.com.mx', 'SIIH | AduanaSoft');
$mail->addAddress($email); // destinatario principal
// Formato y contenido
$mail->CharSet = 'UTF-8';
$mail->isHTML(true);
$mail->Subject = 'Confirmación de solicitud de registro | SIIH';
$fechaRegistro = date('d/m/Y H:i');
// Consulta configuración institucional
$sqlConf = "SELECT TOP 1 * FROM configuracion_sistema";
$stmtConf = sqlsrv_query($conn, $sqlConf);
$conf = sqlsrv_fetch_array($stmtConf, SQLSRV_FETCH_ASSOC);
$nombrePlataforma = $conf['nombre_plataforma'] ?? 'Sistema Integral para Importadores de Hidrocarburos';
$siglas = $conf['siglas'] ?? 'SIIH';
$logoUrl = $conf['logo_url'] ?? 'assets/img/logo_siih.png';
$color1 = explode(',', $conf['colores_primarios'] ?? '#003366,#0055A5')[0];
$color2 = explode(',', $conf['colores_primarios'] ?? '#003366,#0055A5')[1];
$mail->Body = "
<div style='font-family: Segoe UI, sans-serif; background-color: #f4f6f9; padding: 40px;'>
<div style='max-width: 600px; margin: auto; background: #fff; border: 1px solid #ddd; border-radius: 10px; overflow: hidden;'>
<div style='background: linear-gradient(to right, #FFF, $color2); padding: 20px; text-align: center;'>
<img src='http://{$_SERVER['HTTP_HOST']}/IMPORTADORES/public/$logoUrl' alt='Logo $siglas' style='height: 140px;'>
<h2 style='color: #fff; margin-top: 10px;'>Confirmación de Registro</h2>
</div>
<div style='padding: 30px; color: #333;'>
<p style='font-size: 16px;'>¡Hola!</p>
<p style='font-size: 15px;'>Tu solicitud de registro ha sido recibida exitosamente en <strong>$nombrePlataforma</strong>.</p>
<hr style='margin: 20px 0;'>
<p><strong>📋 Empresa:</strong> " . htmlspecialchars($_POST['company_name']) . "</p>
<p><strong>📞 Teléfono:</strong> " . htmlspecialchars($telefono) . "</p>
<p><strong>🕓 Fecha de registro:</strong> $fechaRegistro</p>
<hr style='margin: 20px 0;'>
<p style='font-size: 14px;'>Un agente aduanal revisará tu información y te notificará por este medio cuando tu solicitud sea aprobada.</p>
<p style='font-size: 14px;'>Por favor, mantente atento a tu correo (y revisa también tu carpeta de spam o promociones).</p>
<p style='margin-top: 30px; font-size: 13px; color: #888;'>Este es un mensaje automático enviado por el sistema de registro de importadores.</p>
</div>
<div style='background: #f1f1f1; text-align: center; padding: 15px; font-size: 12px; color: #666;'>
&copy; " . date('Y') . " $siglas · Desarrollado por AduanaSoft
</div>
</div>
</div>
";
$mail->send();
} catch (Exception $e) {
error_log("Error al enviar correo: {$mail->ErrorInfo}");
}
include __DIR__ . '/../../views/registro/gracias.php';
}

View File

@@ -0,0 +1,297 @@
<?php
require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../helpers/env.php';
require_once __DIR__ . '/../helpers/crypto.php';
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
loadEnv();
session_start();
function index() {
header("Location: /IMPORTADORES/sistemas/login");
exit;
}
function login() {
// Si es GET, mostrar el formulario
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
include __DIR__ . '/../../views/admin/login_sistemas.php';
return;
}
// Si es POST, procesar login
$email = $_POST['email'] ?? '';
$clave = $_POST['clave'] ?? '';
if ($email === 'sistemas@aduanasoft.com.mx' && $clave === 'rootSecure2025!') {
$_SESSION['usuario_sistemas'] = true;
header("Location: /IMPORTADORES/sistemas/alta_usuarios");
} else {
echo "❌ Acceso denegado.";
}
}
function alta_usuarios() {
if (!($_SESSION['usuario_sistemas'] ?? false)) {
die("⚠️ No autorizado.");
}
$conn = getConnection();
$sql = "SELECT * FROM usuarios_sistema ORDER BY creado_en DESC";
$stmt = sqlsrv_query($conn, $sql);
$usuarios = [];
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$usuarios[] = $row;
}
include __DIR__ . '/../../views/admin/alta_usuarios.php';
}
function guardar_usuario()
{
if (!($_SESSION['usuario_sistemas'] ?? false)) {
die("⚠️ No autorizado.");
}
$conn = getConnection();
// 1. Capturar y validar datos
$nombre = trim($_POST['nombre'] ?? '');
$email = trim($_POST['email'] ?? '');
$password = $_POST['password'] ?? '';
$tipo = $_POST['tipo_usuario'] ?? '';
if (empty($nombre) || empty($email) || empty($password) || empty($tipo)) {
die("❌ Todos los campos son obligatorios.");
}
if (!in_array($tipo, ['importador', 'agente_aduanal'])) {
die("❌ Tipo de usuario inválido.");
}
// 2. Encriptar datos sensibles
$nombre_encrypted = encrypt($nombre);
$email_encrypted = encrypt($email);
$password_hash = password_hash($password, PASSWORD_DEFAULT);
// 3. Validar duplicado por email encriptado
$sqlCheck = "SELECT COUNT(*) AS total FROM usuarios_sistema WHERE email = ?";
$stmtCheck = sqlsrv_query($conn, $sqlCheck, [$email_encrypted]);
$rowCheck = sqlsrv_fetch_array($stmtCheck, SQLSRV_FETCH_ASSOC);
if ($rowCheck['total'] > 0) {
die("❌ Este correo ya está registrado.");
}
// 4. Insertar usuario
$sqlInsert = "INSERT INTO usuarios_sistema (nombre, email, password_hash, tipo_usuario, activo, creado_en)
VALUES (?, ?, ?, ?, 1, GETDATE())";
$params = [$nombre_encrypted, $email_encrypted, $password_hash, $tipo];
$stmtInsert = sqlsrv_query($conn, $sqlInsert, $params);
if ($stmtInsert === false) {
die("❌ Error al guardar: " . print_r(sqlsrv_errors(), true));
}
// 5. Redirigir
header("Location: /IMPORTADORES/sistemas/alta_usuarios");
exit;
}
function logout() {
session_start();
session_unset(); // Limpia variables de sesión
session_destroy(); // Destruye la sesión
header("Location: /IMPORTADORES/sistemas/login");
exit;
}
function toggle_estado() {
session_start();
if (!($_SESSION['usuario_sistemas'] ?? false)) {
die("⚠️ No autorizado.");
}
$conn = getConnection();
$id = $_GET['id'] ?? null;
if (!$id || !is_numeric($id)) {
die("❌ ID inválido.");
}
// Obtener el estado actual
$sqlEstado = "SELECT activo FROM usuarios_sistema WHERE id_usuario = ?";
$stmtEstado = sqlsrv_query($conn, $sqlEstado, [$id]);
if (!$stmtEstado || !($row = sqlsrv_fetch_array($stmtEstado, SQLSRV_FETCH_ASSOC))) {
die("❌ Usuario no encontrado.");
}
$nuevoEstado = $row['activo'] ? 0 : 1;
// Actualizar estado
$sqlUpdate = "UPDATE usuarios_sistema SET activo = ? WHERE id_usuario = ?";
$stmtUpdate = sqlsrv_query($conn, $sqlUpdate, [$nuevoEstado, $id]);
if (!$stmtUpdate) {
die("❌ Error al actualizar: " . print_r(sqlsrv_errors(), true));
}
header("Location: /IMPORTADORES/sistemas/alta_usuarios");
exit;
}
function reset_password() {
session_start();
if (!($_SESSION['usuario_sistemas'] ?? false)) {
die("⚠️ No autorizado.");
}
$conn = getConnection();
$id = $_GET['id'] ?? null;
if (!$id || !is_numeric($id)) {
die("❌ ID inválido.");
}
// 🔐 Generar contraseña aleatoria de 10 caracteres
$randomPassword = bin2hex(random_bytes(5)); // genera algo como 'a8c4f1b92d'
$passwordHash = password_hash($randomPassword, PASSWORD_DEFAULT);
$sqlEmail = "SELECT email FROM usuarios_sistema WHERE id_usuario = ?";
$stmtEmail = sqlsrv_query($conn, $sqlEmail, [$id]);
$row = sqlsrv_fetch_array($stmtEmail, SQLSRV_FETCH_ASSOC);
$sql = "UPDATE usuarios_sistema SET password_hash = ? WHERE id_usuario = ?";
$stmt = sqlsrv_query($conn, $sql, [$passwordHash, $id]);
if (!$stmt) {
die("❌ Error al actualizar: " . print_r(sqlsrv_errors(), true));
}
// 🔁 Redirigir pasando la contraseña como parámetro temporal (solo visible para el admin)
header("Location: /IMPORTADORES/sistemas/alta_usuarios?reset=ok&pass=" . urlencode($randomPassword) . "&email=" . urlencode(decrypt($row['email'])));
exit;
}
function enviar_password() {
$email = $_GET['email'] ?? '';
$pass = $_GET['pass'] ?? '';
if (!$email || !$pass) {
http_response_code(400);
echo "Datos incompletos.";
return;
}
require_once __DIR__ . '/../../vendor/autoload.php';
$mail = new PHPMailer(true);
try {
$mail->isSMTP();
$mail->Host = 'secure.emailsrvr.com';
$mail->SMTPAuth = true;
$mail->Username = 'noreply@aduanasoft.com.mx';
$mail->Password = $_ENV['SMTP_PASS'];
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
$mail->setFrom('noreply@aduanasoft.com.mx', 'SIIH | AduanaSoft');
$mail->addAddress($email);
$mail->isHTML(true);
$mail->Subject = 'Nueva contraseña de acceso';
$mail->CharSet = 'UTF-8';
$logoURL='http://siih.aduanasoft.com/IMPORTADORES/public/assets/img/logo_siih.png';
$mail->Body = "
<div style='font-family: Segoe UI, sans-serif; background-color: #f4f6f9; padding: 40px;'>
<div style='max-width: 600px; margin: auto; background: #fff; border: 1px solid #ddd; border-radius: 10px; overflow: hidden;'>
<div style='background: linear-gradient(to right, #003366, #0055A5); padding: 20px; text-align: center;'>
<img src='$logoURL' alt='Logo $siglas' style='height: 80px; width: 80px; margin-bottom: 10px;'>
<h2 style='color: white;'>Contraseña restablecida</h2>
</div>
<div style='padding: 30px; color: #333; font-size: 16px;'>
<p>Tu contraseña de acceso al <strong>$nombreSistema</strong> ha sido restablecida por el administrador.</p>
<p style='margin-top: 20px; font-size: 18px;'>
<strong>Nueva contraseña:</strong><br>
<span style='background-color: #f0f0f0; padding: 10px 15px; border-radius: 5px; display: inline-block; font-family: monospace;'>$pass</span>
</p>
<p style='margin-top: 20px;'>Por favor, cambia esta contraseña una vez que inicies sesión.</p>
<hr style='margin: 30px 0;'>
<p style='font-size: 14px; color: #888;'>Este es un mensaje automático generado por el sistema. Si no solicitaste esta acción, contacta al administrador.</p>
</div>
<div style='background: #e9ecef; text-align: center; padding: 15px; font-size: 13px; color: #666;'>
&copy; " . date('Y') . " $siglas · Desarrollado por AduanaSoft
</div>
</div>
</div>
";
$mail->send();
echo "Correo enviado";
} catch (Exception $e) {
http_response_code(500);
echo "Error al enviar correo: {$mail->ErrorInfo}";
}
}
function bitacora_login() {
if (!($_SESSION['usuario_sistemas'] ?? false)) {
die("⚠️ No autorizado.");
}
$conn = getConnection();
$sql = "SELECT * FROM bitacora_login ORDER BY fecha DESC";
$stmt = sqlsrv_query($conn, $sql);
$registros = [];
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$registros[] = $row;
}
include __DIR__ . '/../../views/admin/bitacora_login.php';
}
function bitacora_usuarios() {
if (!($_SESSION['usuario_sistemas'] ?? false)) {
die("⚠️ No autorizado.");
}
$conn = getConnection();
$sql = "SELECT * FROM bitacora_usuarios ORDER BY fecha DESC";
$stmt = sqlsrv_query($conn, $sql);
$registros = [];
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$registros[] = $row;
}
include __DIR__ . '/../../views/admin/bitacora_usuarios.php';
}

View File

@@ -0,0 +1,245 @@
<?php
session_start();
require_once __DIR__ . '/../../config/database.php';
/**
* Listado de solicitudes de importación (facturas) del importador logueado
*/
function lista() {
if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login');
exit;
}
$id_importador = $_SESSION['usuario_id'];
$conn = getConnection();
$sql = "
SELECT
f.*,
tr.nombre AS transportista,
(c.nombre + ' ' + c.apellido) AS chofer,
f.foto_solicitud_url
FROM dbo.solicitud_importacion_factura f
JOIN dbo.transportistas tr
ON f.transportista_id = tr.id_transportista
LEFT JOIN dbo.choferes c
ON f.chofer_id = c.id_chofer
WHERE f.id_importador = ?
AND f.status = 1
ORDER BY f.created_at DESC
";
$stmt = sqlsrv_query($conn, $sql, [$id_importador]);
if ($stmt === false) {
die("Error en lista(): " . print_r(sqlsrv_errors(), true));
}
$facturas = [];
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
if ($row['fecha_factura'] instanceof DateTime) {
$row['fecha_factura'] = $row['fecha_factura']->format('Y-m-d');
}
$facturas[] = $row;
}
include __DIR__ . '/../../views/solicitud_importacion/lista.php';
}
/**
* Formulario de nueva factura
*/
function crear() {
if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login');
exit;
}
$id_importador = $_SESSION['usuario_id'];
$conn = getConnection();
// Carga de datos para selects
$transportistas = [];
$stmtT = sqlsrv_query($conn, "SELECT id_transportista,nombre FROM dbo.transportistas WHERE id_usuario=? AND activo=1 ORDER BY nombre",[$id_importador]);
while ($r = sqlsrv_fetch_array($stmtT, SQLSRV_FETCH_ASSOC)) { $transportistas[] = $r; }
$choferes = [];
$stmtC = sqlsrv_query($conn, "SELECT c.id_chofer, c.nombre+' '+c.apellido AS nombre FROM dbo.choferes c JOIN dbo.transportistas t ON c.transportista_id=t.id_transportista WHERE t.id_usuario=? AND c.status=1 ORDER BY c.nombre",[$id_importador]);
while ($r = sqlsrv_fetch_array($stmtC, SQLSRV_FETCH_ASSOC)) { $choferes[] = $r; }
$paises = [];
$stmtP = sqlsrv_query($conn, "SELECT id_pais,nombre FROM dbo.paises ORDER BY nombre");
while ($r = sqlsrv_fetch_array($stmtP, SQLSRV_FETCH_ASSOC)) { $paises[] = $r; }
$aduanas = [];
$stmtA = sqlsrv_query($conn, "SELECT aduana_seccion,nombre FROM dbo.aduanas ORDER BY aduana_seccion");
while ($r = sqlsrv_fetch_array($stmtA, SQLSRV_FETCH_ASSOC)) { $aduanas[] = $r; }
$incoterms = [];
$stmtI = sqlsrv_query($conn, "SELECT INCOTERM,DESCESPANOL FROM dbo.gIncoterms ORDER BY INCOTERM");
while ($r = sqlsrv_fetch_array($stmtI, SQLSRV_FETCH_ASSOC)) { $incoterms[] = $r; }
include __DIR__ . '/../../views/solicitud_importacion/crear.php';
}
/**
* Procesa la creación de una nueva factura y sus partidas
*/
function guardar() {
if (!($_SESSION['usuario_id'] ?? false)) {
die("⚠️ No autorizado.");
}
$id_importador = $_SESSION['usuario_id'];
$aduana_seccion = $_POST['anexo22_apendice'] ?? null;
$num_factura = trim($_POST['numero_factura'] ?? '');
$fecha = $_POST['fecha_factura'] ?? null;
$incoterm = $_POST['incoterm'] ?? null;
$pais_proveedor = $_POST['pais_proveedor'] ?? null;
$tipo_moneda = $_POST['tipo_moneda'] ?? null;
$valor_factura = $_POST['valor_factura'] ?? null;
$vinculacion = $_POST['vinculacion'] ?? 0;
$transportista_id = $_POST['transportista_id'] ?? null;
$chofer_id = $_POST['chofer_id'] ?? null;
$status = isset($_POST['status']) ? 1 : 0;
if (empty($num_factura) || empty($fecha) || empty($transportista_id) || empty($chofer_id)) {
die("❌ Faltan campos obligatorios.");
}
// Foto solicitud
$fotoUrl=null;
if (!empty($_FILES['foto_solicitud']['tmp_name']) && $_FILES['foto_solicitud']['error']===UPLOAD_ERR_OK) {
$ext=pathinfo($_FILES['foto_solicitud']['name'],PATHINFO_EXTENSION);
$dest=__DIR__.'/../../public/uploads/solicitud_'.uniqid().".$ext";
if (!is_dir(dirname($dest))) mkdir(dirname($dest),0755,true);
if(move_uploaded_file($_FILES['foto_solicitud']['tmp_name'],$dest)) {
$fotoUrl="/IMPORTADORES/public/uploads/".basename($dest);
}
}
$conn = getConnection();
$sql = "INSERT INTO dbo.solicitud_importacion_factura
(id_importador,aduana,anexo22_apendice,numero_factura,fecha_factura,
numero_pedimento,incoterm,pais_proveedor,tipo_moneda,
valor_factura,vinculacion,transportista_id,chofer_id,foto_solicitud_url,status)
VALUES(?,?,?,?,?,NULL,?,?,?,?,?,?,?,?,?)";
$params=[
$id_importador,
$aduana_seccion,
$aduana_seccion,
$num_factura,
$fecha,
$incoterm,
$pais_proveedor,
$tipo_moneda,
$valor_factura,
$vinculacion,
(int)$transportista_id,
(int)$chofer_id,
$fotoUrl,
$status
];
$stmt=sqlsrv_query($conn,$sql,$params);
if($stmt===false) die("Error en guardar():".print_r(sqlsrv_errors(),true));
// Obtener nuevo ID
$idRow=sqlsrv_query($conn,'SELECT SCOPE_IDENTITY() AS id');
$new=sqlsrv_fetch_array($idRow,SQLSRV_FETCH_ASSOC);
$id_solicitud=(int)$new['id'];
// Partidas
if(!empty($_POST['partidas'])&&is_array($_POST['partidas'])){
$sqlP="INSERT INTO dbo.solicitud_importacion_partidas
(id_solicitud,descripcion,precio_unitario)
VALUES(?,?,?)";
foreach($_POST['partidas'] as $p){
$d=trim($p['descripcion']??'');
$u=floatval($p['precio_unitario']??0);
if($d!==''&&$u>0) sqlsrv_query($conn,$sqlP,[$id_solicitud,$d,$u]);
}
}
header('Location: /IMPORTADORES/solicitud_importacion/lista?created=ok');
exit;
}
/**
* Formulario de edición de factura
*/
function editar() {
if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login'); exit;
}
$id_solicitud = $_GET['id']??null;
if(!$id_solicitud||!is_numeric($id_solicitud)) die("❌ ID inválido.");
$id_importador=$_SESSION['usuario_id'];
$conn=getConnection();
$stmt=sqlsrv_query($conn,
"SELECT * FROM dbo.solicitud_importacion_factura WHERE id_solicitud=? AND id_importador=?",
[(int)$id_solicitud,$id_importador]
);
if($stmt===false) die(print_r(sqlsrv_errors(),true));
$factura=sqlsrv_fetch_array($stmt,SQLSRV_FETCH_ASSOC);
if(!$factura) die("❌ No autorizado.");
if($factura['fecha_factura'] instanceof DateTime)
$factura['fecha_factura']=$factura['fecha_factura']->format('Y-m-d');
// Carga selects (igual que crear)
// Transportistas
$transportistas=[]; $stmtT=sqlsrv_query($conn,"SELECT id_transportista,nombre FROM dbo.transportistas WHERE id_usuario=? AND activo=1 ORDER BY nombre",[$id_importador]);
while($r=sqlsrv_fetch_array($stmtT,SQLSRV_FETCH_ASSOC)) $transportistas[]=$r;
// Choferes
$choferes=[]; $stmtC=sqlsrv_query($conn,"SELECT c.id_chofer,c.nombre+' '+c.apellido AS nombre FROM dbo.choferes c JOIN dbo.transportistas t ON c.transportista_id=t.id_transportista WHERE t.id_usuario=? AND c.status=1 ORDER BY c.nombre",[$id_importador]);
while($r=sqlsrv_fetch_array($stmtC,SQLSRV_FETCH_ASSOC)) $choferes[]=$r;
// Paises
$paises=[]; $stmtP=sqlsrv_query($conn,"SELECT id_pais,nombre FROM dbo.paises ORDER BY nombre");
while($r=sqlsrv_fetch_array($stmtP,SQLSRV_FETCH_ASSOC)) $paises[]=$r;
// Aduanas
$aduanas=[]; $stmtA=sqlsrv_query($conn,"SELECT aduana_seccion,nombre FROM dbo.aduanas ORDER BY aduana_seccion");
while($r=sqlsrv_fetch_array($stmtA,SQLSRV_FETCH_ASSOC)) $aduanas[]=$r;
// Incoterms
$incoterms=[]; $stmtI=sqlsrv_query($conn,"SELECT INCOTERM,DESCESPANOL FROM dbo.gIncoterms ORDER BY INCOTERM");
while($r=sqlsrv_fetch_array($stmtI,SQLSRV_FETCH_ASSOC)) $incoterms[]=$r;
// Partidas existentes
$partidas=[];
$stmtPar=sqlsrv_query($conn,"SELECT id_partida,descripcion,precio_unitario 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;
include __DIR__ . '/../../views/solicitud_importacion/editar.php';
}
/**
* Procesa la actualización de una factura y sus partidas
*/
function actualizar() {
if (!($_SESSION['usuario_id'] ?? false)) die("⚠️ No autorizado.");
$id_solicitud=(int)($_POST['id_solicitud']??0);
// Validaciones similares a guardar()
// ... omito por brevedad, copia de guardar() + UPDATE ...
$conn=getConnection();
// Actualizar factura
$sqlU = "UPDATE dbo.solicitud_importacion_factura SET
aduana=?,anexo22_apendice=?,numero_factura=?,fecha_factura=?,incoterm=?,pais_proveedor=?,tipo_moneda=?,valor_factura=?,vinculacion=?,transportista_id=?,chofer_id=?,foto_solicitud_url=?,status=?,updated_at=GETDATE()
WHERE id_solicitud=? AND id_importador=?";
// Ejecutar UPDATE con parámetros
// ...
// Borrar partidas previas
sqlsrv_query($conn,"DELETE FROM dbo.solicitud_importacion_partidas WHERE id_solicitud=?",[$id_solicitud]);
// Reinsertar partidas igual que guardar()
// ...
header('Location: /IMPORTADORES/solicitud_importacion/lista?updated=ok'); exit;
}
/**
* “Soft-delete” de una factura
*/
function eliminar() {
if (!($_SESSION['usuario_id'] ?? false)) { header('Location: /IMPORTADORES/login'); exit; }
$id=(int)($_GET['id']??0);
$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']]);
header('Location: /IMPORTADORES/solicitud_importacion/lista?deleted=ok'); exit;
}

View File

@@ -0,0 +1,319 @@
<?php
session_start();
require_once __DIR__ . '/../../config/database.php';
/**
* Listado de transportes (sólo activos) para el importador logueado
*/
function lista() {
if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login');
exit;
}
$usr = $_SESSION['usuario_id'];
$conn = getConnection();
// Sólo mostrar transportes de los transportistas que le pertenecen al usuario
$sql = "
SELECT t.*, tr.nombre AS transportista
FROM dbo.transportes t
JOIN dbo.transportistas tr
ON t.id_transportista = tr.id_transportista
WHERE tr.id_usuario = ? AND t.status = 1
ORDER BY t.creado_en DESC
";
$stmt = sqlsrv_query($conn, $sql, [$usr]);
$transportes = [];
while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$transportes[] = $r;
}
include __DIR__ . '/../../views/transportes/lista.php';
}
/**
* Formulario de alta de transporte
*/
function crear() {
if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login');
exit;
}
$usr = $_SESSION['usuario_id'];
$conn = getConnection();
// Traer transportistas propios para el select
$sql = "
SELECT id_transportista, nombre
FROM dbo.transportistas
WHERE id_usuario = ? AND activo = 1
ORDER BY nombre
";
$stmt = sqlsrv_query($conn, $sql, [$usr]);
$transportistas = [];
while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$transportistas[] = $r;
}
include __DIR__ . '/../../views/transportes/crear.php';
}
/**
* Procesa la creación de un nuevo transporte
*/
function guardar() {
if (!($_SESSION['usuario_id'] ?? false)) {
die("⚠️ No autorizado.");
}
$vehiculo = trim($_POST['vehiculo'] ?? '');
$identFiscal= trim($_POST['identificador_fiscal'] ?? '');
$idTrans = $_POST['id_transportista'] ?? null;
if ($vehiculo === '' || $identFiscal === '' || !$idTrans) {
die("❌ Todos los campos son obligatorios.");
}
// Manejo de foto
$fotoUrl = null;
if (!empty($_FILES['foto']['tmp_name'])) {
$ext = pathinfo($_FILES['foto']['name'], PATHINFO_EXTENSION);
$dest = __DIR__ . '/../../public/uploads/transporte_'.uniqid().".{$ext}";
if (move_uploaded_file($_FILES['foto']['tmp_name'], $dest)) {
// ruta relativa
$fotoUrl = "/IMPORTADORES/public/uploads/" . basename($dest);
}
}
$conn = getConnection();
$sql = "
INSERT INTO dbo.transportes
(vehiculo, identificador_fiscal, foto_url, status, id_transportista)
VALUES (?, ?, ?, 1, ?)
";
$params = [$vehiculo, $identFiscal, $fotoUrl, $idTrans];
$stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt === false) {
die("❌ Error al guardar: ".print_r(sqlsrv_errors(),true));
}
header('Location: /IMPORTADORES/transportes/lista?created=ok');
exit;
}
/**
* Formulario de edición
*/
function editar() {
if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login');
exit;
}
$id = $_GET['id'] ?? null;
if (!$id || !is_numeric($id)) {
die("❌ ID inválido.");
}
$conn = getConnection();
// Validar pertenencia igual que en index()
$sql = "
SELECT t.*, tr.nombre AS transportista
FROM dbo.transportes t
JOIN dbo.transportistas tr
ON t.id_transportista = tr.id_transportista
WHERE t.id_transporte = ?
AND tr.id_usuario = ?
AND t.status = 1
";
$stmt = sqlsrv_query($conn, $sql, [$id, $_SESSION['usuario_id']]);
$t = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
if (!$t) die("❌ Transporte no encontrado o no autorizado.");
// Mismo select de transportistas que en crear()
$sql2 = "
SELECT id_transportista, nombre
FROM dbo.transportistas
WHERE id_usuario = ? AND activo = 1
ORDER BY nombre
";
$stmt2 = sqlsrv_query($conn, $sql2, [$_SESSION['usuario_id']]);
$transportistas = [];
while ($r=sqlsrv_fetch_array($stmt2,SQLSRV_FETCH_ASSOC)) $transportistas[]=$r;
include __DIR__ . '/../../views/transportes/editar.php';
}
/**
* Procesa la actualización
*/
function actualizar() {
if (!($_SESSION['usuario_id'] ?? false)) {
die("⚠️ No autorizado.");
}
$id = $_POST['id_transporte'] ?? null;
$vehiculo = trim($_POST['vehiculo'] ?? '');
$identFiscal = trim($_POST['identificador_fiscal'] ?? '');
$idTrans = $_POST['id_transportista'] ?? null;
if (!$id || !is_numeric($id) || $vehiculo === '' || $identFiscal === '' || !$idTrans) {
die("❌ Faltan datos.");
}
$conn = getConnection();
// —– Manejo de nueva foto —–
$fotoUrl = null;
if (isset($_FILES['foto']) && $_FILES['foto']['error'] === UPLOAD_ERR_OK) {
$ext = strtolower(pathinfo($_FILES['foto']['name'], PATHINFO_EXTENSION));
$dest = __DIR__ . '/../../public/uploads/transporte_'.uniqid().".{$ext}";
if (!is_dir(dirname($dest))) {
mkdir(dirname($dest), 0755, true);
}
if (move_uploaded_file($_FILES['foto']['tmp_name'], $dest)) {
$fotoUrl = "/IMPORTADORES/public/uploads/" . basename($dest);
} else {
error_log("Error al mover archivo en actualizar(): {$dest}");
}
}
// —– Construye el UPDATE dinámico —–
if ($fotoUrl) {
$sql = "
UPDATE dbo.transportes SET
vehiculo = ?,
identificador_fiscal = ?,
id_transportista = ?,
foto_url = ?
WHERE id_transporte = ?
";
$params = [$vehiculo, $identFiscal, $idTrans, $fotoUrl, $id];
} else {
$sql = "
UPDATE dbo.transportes SET
vehiculo = ?,
identificador_fiscal = ?,
id_transportista = ?
WHERE id_transporte = ?
";
$params = [$vehiculo, $identFiscal, $idTrans, $id];
}
$stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt === false) {
die("❌ Error al actualizar: " . print_r(sqlsrv_errors(), true));
}
header('Location: /IMPORTADORES/transportes/lista?updated=ok');
exit;
}
/**
* “Soft-delete” (status = 0)
*/
function eliminar() {
if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login');
exit;
}
$id = $_GET['id'] ?? null;
if (!$id||!is_numeric($id)) {
die("❌ ID inválido.");
}
$conn = getConnection();
$sql = "UPDATE dbo.transportes SET status = 0 WHERE id_transporte = ?";
$stmt = sqlsrv_query($conn, $sql, [$id]);
if ($stmt === false) {
die("❌ Error al eliminar: ".print_r(sqlsrv_errors(),true));
}
header('Location: /IMPORTADORES/transportes/lista?deleted=ok');
exit;
}
/**
* Formulario de importación masiva
*/
function masivo() {
if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login');
exit;
}
include __DIR__ . '/../../views/transportes/importar_masivo.php';
}
/**
* Procesa la importación masiva desde CSV
*/
function importarGuardar() {
if (!($_SESSION['usuario_id'] ?? false)) {
die("⚠️ No autorizado.");
}
// Validar subida del archivo
if (!isset($_FILES['csv']) || $_FILES['csv']['error'] !== UPLOAD_ERR_OK) {
$_SESSION['import_result'] = [
'imported' => 0,
'errors' => ["Error al subir el archivo CSV."]
];
header('Location: /IMPORTADORES/transportes/importar');
exit;
}
$tmp = $_FILES['csv']['tmp_name'];
$handle = fopen($tmp, 'r');
$headers = fgetcsv($handle, 1000, ',');
$conn = getConnection();
$usr = $_SESSION['usuario_id'];
$imported = 0;
$errors = [];
$row = 1;
while (($data = fgetcsv($handle, 1000, ',')) !== false) {
$row++;
if (count($data) < 3) {
$errors[] = "Fila $row: formato incorrecto.";
continue;
}
list($vehiculo, $identFiscal, $idTrans) = array_map('trim', $data);
// Validaciones básicas
if ($vehiculo === '' || $identFiscal === '' || !is_numeric($idTrans)) {
$errors[] = "Fila $row: datos incompletos o inválidos.";
continue;
}
// Verificar que el transportista pertenezca al usuario
$sqlCheck = "SELECT COUNT(*) AS cnt
FROM dbo.transportistas
WHERE id_transportista = ? AND id_usuario = ?";
$stmtCheck = sqlsrv_query($conn, $sqlCheck, [$idTrans, $usr]);
$rCheck = sqlsrv_fetch_array($stmtCheck, SQLSRV_FETCH_ASSOC);
if ($rCheck['cnt'] == 0) {
$errors[] = "Fila $row: transportista $idTrans no válido.";
continue;
}
// Insertar sin foto
$sql = "INSERT INTO dbo.transportes
(vehiculo, identificador_fiscal, foto_url, status, id_transportista)
VALUES (?, ?, NULL, 1, ?)";
$stmt = sqlsrv_query($conn, $sql, [$vehiculo, $identFiscal, $idTrans]);
if ($stmt === false) {
$errors[] = "Fila $row: error al insertar.";
continue;
}
$imported++;
}
fclose($handle);
// Guardar resultado en sesión y redirigir de vuelta al formulario
$_SESSION['import_result'] = [
'imported' => $imported,
'errors' => $errors
];
header('Location: /IMPORTADORES/transportes/masivo');
exit;
}

View File

@@ -0,0 +1,457 @@
<?php
session_start();
function guardar() {
if (!($_SESSION['usuario_id'] ?? false)) {
die("⚠️ No autorizado.");
}
$conn = getConnection();
// Capturar campos del formulario
$clave = $_POST['clave'];
$nombre = $_POST['nombre'];
$rfc = $_POST['rfc'];
$curp = $_POST['curp'] ?? null;
$dom = $_POST['domicilio'];
$pais = $_POST['pais'];
$entidad = $_POST['entidad'];
$ciudad = $_POST['ciudad'];
$tel = $_POST['telefono'];
$caat = $_POST['caat'];
$usr_id = $_SESSION['usuario_id'];
// Validaciones básicas…
// INSERT incluyendo id_usuario
$sql = "INSERT INTO dbo.transportistas
(clave_identificador, nombre, rfc, curp, domicilio, pais,
entidad_federativa, ciudad, telefono, caat, id_usuario)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$params = [
$clave, $nombre, $rfc, $curp, $dom,
$pais, $entidad, $ciudad, $tel, $caat,
$usr_id
];
$stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt === false) {
die("❌ Error al guardar transportista: " . print_r(sqlsrv_errors(), true));
}
// Redirigir de vuelta a la lista o mostrar mensaje…
header("Location: /IMPORTADORES/transportistas/lista?success=1");
exit;
}
require_once __DIR__ . '/../../config/database.php';
function alta() {
$conn = getConnection();
// 1) Cargar países
$sql = "SELECT id_pais, nombre FROM paises ORDER BY nombre";
$stmt = sqlsrv_query($conn, $sql);
$paises = [];
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$paises[] = $row;
}
include __DIR__ . '/../../views/transportistas/alta.php';
}
// AJAX: devuelve los estados de un país dado
function estados() {
header('Content-Type: application/json; charset=utf-8');
$pais = $_GET['pais'] ?? '';
$conn = getConnection();
$sql = "SELECT id_estado, nombre FROM estados WHERE pais_id = ? ORDER BY nombre";
$stmt = sqlsrv_query($conn, $sql, [$pais]);
$out = [];
while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$out[] = $r;
}
echo json_encode($out);
exit;
}
// AJAX: devuelve las ciudades de un estado dado
function ciudades() {
header('Content-Type: application/json; charset=utf-8');
$estado = $_GET['estado'] ?? '';
$conn = getConnection();
$sql = "SELECT id_ciudad, nombre FROM ciudades WHERE estado_id = ? ORDER BY nombre";
$stmt = sqlsrv_query($conn, $sql, [$estado]);
$out = [];
while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$out[] = $r;
}
echo json_encode($out);
exit;
}
function lista() {
include __DIR__ . '/../../views/transportistas/lista.php';
}
/**
* Descarga la plantilla CSV para carga masiva
*/
function template() {
$file = __DIR__ . '/../../public/downloads/transportistas_template.csv';
if (!file_exists($file)) {
http_response_code(404);
echo "❌ Plantilla no encontrada.";
exit;
}
header('Content-Type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename="transportistas_template.csv"');
readfile($file);
exit;
}
/**
* Procesa la carga masiva desde un CSV
*/
function importar() {
// 1) Verificar sesión
if (!($_SESSION['usuario_id'] ?? false)) {
die("⚠️ No autorizado.");
}
$usr_id = $_SESSION['usuario_id'];
// 2) Validar archivo subido
if (!isset($_FILES['archivo_csv']) || $_FILES['archivo_csv']['error'] !== UPLOAD_ERR_OK) {
die("❌ Debes subir un archivo CSV válido.");
}
$ext = pathinfo($_FILES['archivo_csv']['name'], PATHINFO_EXTENSION);
if (strtolower($ext) !== 'csv') {
die("❌ Solo se permiten archivos .csv");
}
// 3) Abrir y leer CSV
$fh = fopen($_FILES['archivo_csv']['tmp_name'], 'r');
if (!$fh) {
die("❌ No se pudo abrir el archivo.");
}
// 4) Encabezados esperados
$header = fgetcsv($fh, 1000, ',');
$expected = [
'clave_identificador','nombre','rfc','curp',
'telefono','caat','pais_id','estado_id',
'ciudad_id','domicilio'
];
if ($header === false || array_map('trim', $header) !== $expected) {
fclose($fh);
die("❌ Encabezado de CSV inválido. Debe contener: " . implode(',', $expected));
}
$conn = getConnection();
$errors = [];
$rowNum = 1;
while (($row = fgetcsv($fh, 2000, ',')) !== false) {
$rowNum++;
// asegurarse de tener todas las columnas
if (count($row) < count($expected)) {
$errors[] = "Fila $rowNum: faltan columnas.";
continue;
}
// mapear valores y trim
list($clave,$nombre,$rfc,$curp,$tel,$caat,$pais,$estado,$ciudad,$dom) = array_map('trim', $row);
// validar obligatorios
if ($clave==='' || $nombre==='' || $rfc==='' || $tel==='' || $caat===''
|| $pais==='' || $estado==='' || $ciudad==='' || $dom==='') {
$errors[] = "Fila $rowNum: faltan datos obligatorios.";
continue;
}
// 5) Insertar en BD
$sql = "INSERT INTO dbo.transportistas
(clave_identificador, nombre, rfc, curp, telefono, caat,
pais, entidad_federativa, ciudad, domicilio, id_usuario)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$params = [
$clave, $nombre, $rfc, $curp, $tel,
$caat, $pais, $estado, $ciudad, $dom,
$usr_id
];
$stmt = sqlsrv_query($conn, $sql, $params);
if ($stmt === false) {
$errors[] = "Fila $rowNum: error al guardar → " . print_r(sqlsrv_errors(), true);
}
}
fclose($fh);
// 6) Redirigir con resultado
if (count($errors) > 0) {
$_SESSION['import_errors'] = $errors;
header('Location: /IMPORTADORES/transportistas/bulk_upload?status=error');
} else {
$_SESSION['import_success'] = true;
header('Location: /IMPORTADORES/transportistas/bulk_upload?status=ok');
}
exit;
}
function bulk_upload() {
include __DIR__ . '/../../views/transportistas/bulk_upload.php';
}
function ajax_lista() {
// 1) Autorización
if (!($_SESSION['usuario_id'] ?? false)) {
http_response_code(403);
echo json_encode([]);
exit;
}
$usr = $_SESSION['usuario_id'];
$conn = getConnection();
// 2) Parámetros de DataTables
$draw = intval($_GET['draw'] ?? 0);
$start = intval($_GET['start'] ?? 0);
$length = intval($_GET['length'] ?? 10);
$search = $_GET['search']['value'] ?? '';
// Mapeo columnas
$cols = ['id_transportista','clave_identificador','nombre','rfc','ciudad','creado_en'];
$orderColIdx = intval($_GET['order'][0]['column'] ?? 5);
$orderDir = strtoupper($_GET['order'][0]['dir'] ?? 'ASC') === 'DESC' ? 'DESC' : 'ASC';
$orderCol = in_array($orderColIdx, range(0,5)) ? $cols[$orderColIdx] : 'creado_en';
// 3) Total registros sin filtro
$sqlTotal = "SELECT COUNT(*) AS total FROM dbo.transportistas WHERE id_usuario = ? AND activo = 1";
$stmt = sqlsrv_query($conn, $sqlTotal, [$usr]);
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
$recordsTotal = (int)$row['total'];
// 4) Total registros con filtro
$where = "id_usuario = ? AND activo = 1 ";
$params = [$usr];
if ($search !== '') {
$where .= " AND (clave_identificador LIKE ? OR nombre LIKE ? OR rfc LIKE ? OR ciudad LIKE ?)";
$like = "%{$search}%";
$params = array_merge($params, [$like, $like, $like, $like]);
}
$sqlFiltered = "SELECT COUNT(*) AS total FROM dbo.transportistas WHERE $where";
$stmtF = sqlsrv_query($conn, $sqlFiltered, $params);
$rowF = sqlsrv_fetch_array($stmtF, SQLSRV_FETCH_ASSOC);
$recordsFiltered = (int)$rowF['total'];
// 5) Datos de la página
$sqlData = "
SELECT id_transportista, clave_identificador, nombre, rfc, ciudad, creado_en
FROM dbo.transportistas
WHERE $where
ORDER BY $orderCol $orderDir
OFFSET ? ROWS FETCH NEXT ? ROWS ONLY
";
// agregar offset/limit al final
$params[] = $start;
$params[] = $length;
$stmtD = sqlsrv_query($conn, $sqlData, $params);
$data = [];
while ($r = sqlsrv_fetch_array($stmtD, SQLSRV_FETCH_ASSOC)) {
$data[] = [
$r['id_transportista'],
$r['clave_identificador'],
$r['nombre'],
$r['rfc'],
$r['ciudad'],
$r['creado_en'] instanceof DateTime
? $r['creado_en']->format('Y-m-d H:i')
: ''
];
}
// 6) Devolver JSON
header('Content-Type: application/json; charset=UTF-8');
echo json_encode([
"draw" => $draw,
"recordsTotal" => $recordsTotal,
"recordsFiltered" => $recordsFiltered,
"data" => $data
]);
exit;
}
function editar() {
// 1) Verificar sesión
if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login');
exit;
}
$usr = $_SESSION['usuario_id'];
// 2) Obtener el ID y validarlo
$id = $_GET['id'] ?? null;
if (!$id || !is_numeric($id)) {
die("❌ ID de transportista inválido.");
}
$conn = getConnection();
// 3) Consultar el transportista (pertenece al usuario)
$sql = "SELECT * FROM dbo.transportistas
WHERE id_transportista = ? AND id_usuario = ?";
$stmt = sqlsrv_query($conn, $sql, [$id, $usr]);
$t = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
if (!$t) {
die("❌ Transportista no encontrado o no autorizado.");
}
// 4) Cargar listas de países, estados y ciudades
// --- Países ---
$paises = [];
$rs = sqlsrv_query($conn, "SELECT id_pais, nombre FROM dbo.paises ORDER BY nombre");
while ($r = sqlsrv_fetch_array($rs, SQLSRV_FETCH_ASSOC)) {
$paises[] = $r;
}
// --- Estados para el país actual ---
$estados = [];
$rs = sqlsrv_query(
$conn,
"SELECT id_estado, nombre FROM dbo.estados WHERE pais_id = ? ORDER BY nombre",
[$t['pais']]
);
while ($r = sqlsrv_fetch_array($rs, SQLSRV_FETCH_ASSOC)) {
$estados[] = $r;
}
// --- Ciudades para el estado actual ---
$ciudades = [];
$rs = sqlsrv_query(
$conn,
"SELECT id_ciudad, nombre FROM dbo.ciudades WHERE estado_id = ? ORDER BY nombre",
[$t['entidad_federativa']]
);
while ($r = sqlsrv_fetch_array($rs, SQLSRV_FETCH_ASSOC)) {
$ciudades[] = $r;
}
// 5) Renderizar la vista
include __DIR__ . '/../../views/transportistas/editar.php';
}
/**
* Procesa el POST de actualización
*/
function actualizar() {
session_start();
if (!($_SESSION['usuario_id'] ?? false)) {
die("⚠️ No autorizado.");
}
$usr = $_SESSION['usuario_id'];
// 1) Capturar y validar datos
$id = $_POST['id_transportista'] ?? null;
$clave = trim($_POST['clave'] ?? '');
$nombre= trim($_POST['nombre'] ?? '');
$rfc = trim($_POST['rfc'] ?? '');
$curp = trim($_POST['curp'] ?? '');
$tel = trim($_POST['telefono'] ?? '');
$caat = trim($_POST['caat'] ?? '');
$pais = $_POST['pais'] ?? '';
$estado= $_POST['entidad'] ?? '';
$ciudad= $_POST['ciudad'] ?? '';
$dom = trim($_POST['domicilio'] ?? '');
if (!$id || !is_numeric($id)
|| $clave===''||$nombre===''||$rfc===''||$tel===''||$caat===''
|| $pais===''||$estado===''||$ciudad===''||$dom===''
) {
die("❌ Faltan datos obligatorios.");
}
$conn = getConnection();
// 2) Verificar que exista y pertenezca al usuario
$sqlChk = "SELECT COUNT(*) AS cnt
FROM dbo.transportistas
WHERE id_transportista = ? AND id_usuario = ?";
$stmtChk = sqlsrv_query($conn, $sqlChk, [$id, $usr]);
$rowChk = sqlsrv_fetch_array($stmtChk, SQLSRV_FETCH_ASSOC);
if ($rowChk['cnt'] == 0) {
die("❌ Transportista no encontrado o no autorizado.");
}
// 3) Ejecutar UPDATE
$sqlUpd = "UPDATE dbo.transportistas SET
clave_identificador = ?,
nombre = ?,
rfc = ?,
curp = ?,
telefono = ?,
caat = ?,
pais = ?,
entidad_federativa = ?,
ciudad = ?,
domicilio = ?
WHERE id_transportista = ?";
$params = [
$clave, $nombre, $rfc, $curp, $tel,
$caat, $pais, $estado, $ciudad, $dom,
$id
];
$stmtUpd = sqlsrv_query($conn, $sqlUpd, $params);
if ($stmtUpd === false) {
die("❌ Error al actualizar: " . print_r(sqlsrv_errors(), true));
}
// 4) Redirigir con éxito
header("Location: /IMPORTADORES/transportistas/lista?edit=ok");
exit;
}
function eliminar() {
session_start();
if (!($_SESSION['usuario_id'] ?? false)) {
header('Location: /IMPORTADORES/login');
exit;
}
$usr = $_SESSION['usuario_id'];
$id = $_GET['id'] ?? null;
if (!$id || !is_numeric($id)) {
die("❌ ID inválido.");
}
$conn = getConnection();
// Verificar que el transportista exista y pertenezca al usuario
$sqlChk = "SELECT COUNT(*) AS cnt
FROM dbo.transportistas
WHERE id_transportista = ? AND id_usuario = ? AND activo = 1";
$stmtChk = sqlsrv_query($conn, $sqlChk, [$id, $usr]);
$rowChk = sqlsrv_fetch_array($stmtChk, SQLSRV_FETCH_ASSOC);
if ($rowChk['cnt'] == 0) {
die("❌ Transportista no encontrado o ya eliminado.");
}
// Soft-delete
$sqlDel = "UPDATE dbo.transportistas
SET activo = 0
WHERE id_transportista = ?";
$stmtDel = sqlsrv_query($conn, $sqlDel, [$id]);
if ($stmtDel === false) {
die("❌ Error al eliminar: " . print_r(sqlsrv_errors(), true));
}
// Redirigir con parámetro para SweetAlert
header("Location: /IMPORTADORES/transportistas/lista?deleted=ok");
exit;
}

20
app/helpers/bitacoras.php Normal file
View File

@@ -0,0 +1,20 @@
<?php
function registrarBitacora($conn, $idUsuario, $email, $ip, $exito, $detalle) {
$sql = "INSERT INTO bitacora_login (id_usuario, email, ip, exito, detalle)
VALUES (?, ?, ?, ?, ?)";
$params = [$idUsuario, $email, $ip, $exito, $detalle];
sqlsrv_query($conn, $sql, $params);
}
function registrar_bitacora_usuario($usuarioId, $accion, $descripcion) {
$conn = getConnection();
$sql = "INSERT INTO bitacora_usuarios (usuario_id, accion, descripcion)
VALUES (?, ?, ?)";
$params = [$usuarioId, $accion, $descripcion];
sqlsrv_query($conn, $sql, $params);
}

12
app/helpers/crypto.php Normal file
View File

@@ -0,0 +1,12 @@
<?php
function encrypt($data) {
$key = $_ENV['ENCRYPTION_KEY'];
$iv = $_ENV['ENCRYPTION_IV'];
return base64_encode(openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv));
}
function decrypt($data) {
$key = $_ENV['ENCRYPTION_KEY'];
$iv = $_ENV['ENCRYPTION_IV'];
return openssl_decrypt(base64_decode($data), 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
}

11
app/helpers/env.php Normal file
View File

@@ -0,0 +1,11 @@
<?php
function loadEnv($path = __DIR__ . '/../../.env') {
if (!file_exists($path)) return;
$lines = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($lines as $line) {
if (str_starts_with(trim($line), '#')) continue;
list($name, $value) = explode('=', $line, 2);
$_ENV[trim($name)] = trim($value);
}
}

4
app/helpers/session.php Normal file
View File

@@ -0,0 +1,4 @@
<?php
if (session_status() === PHP_SESSION_NONE) {
session_start();
}