From c574183cee2cbc93f88afcbb8bbfaa0516b165ae Mon Sep 17 00:00:00 2001 From: Alexeer Date: Fri, 30 May 2025 16:55:31 -0600 Subject: [PATCH] Requerimientos sprint 2 --- app/controllers/transportistas.php | 151 ++++++++++++++++++----------- views/registro/form.php | 1 - views/transportistas/alta.php | 94 ++++++++++++++++-- views/transportistas/lista.php | 13 +-- 4 files changed, 184 insertions(+), 75 deletions(-) diff --git a/app/controllers/transportistas.php b/app/controllers/transportistas.php index 7468ca5..f66b9d8 100644 --- a/app/controllers/transportistas.php +++ b/app/controllers/transportistas.php @@ -20,7 +20,6 @@ $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, @@ -87,18 +86,12 @@ function ciudades() { exit; } - - -function lista() { - +function lista() +{ include __DIR__ . '/../../views/transportistas/lista.php'; } - - - /** - * Descarga la plantilla CSV para carga masiva - */ + /** Descarga la plantilla CSV para carga masiva **/ function template() { $file = __DIR__ . '/../../public/downloads/transportistas_template.csv'; if (!file_exists($file)) { @@ -112,10 +105,7 @@ function template() { exit; } - -/** - * Procesa la carga masiva desde un CSV - */ +/** Procesa la carga masiva desde un CSV **/ function importar() { // 1) Verificar sesión if (!($_SESSION['usuario_id'] ?? false)) { @@ -162,23 +152,58 @@ function importar() { continue; } // mapear valores y trim - list($clave,$nombre,$rfc,$curp,$tel,$caat,$pais,$estado,$ciudad,$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 if ($clave==='' || $nombre==='' || $rfc==='' || $tel==='' || $caat==='' - || $pais==='' || $estado==='' || $ciudad==='' || $dom==='') { + || $pais_id==='' || $estado_id==='' || $ciudad_id==='' || $dom==='') { $errors[] = "Fila $rowNum: faltan datos obligatorios."; continue; } - // 5) Insertar en BD + // Convertir IDs a nombres + $pais_nombre = ''; + $estado_nombre = ''; + $ciudad_nombre = ''; + + // Consultar nombre del país + $sql = "SELECT nombre FROM dbo.paises WHERE id_pais = ?"; + $stmt = sqlsrv_query($conn, $sql, [$pais_id]); + if ($row_pais = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { + $pais_nombre = $row_pais['nombre']; + } else { + $errors[] = "Fila $rowNum: país con ID $pais_id no encontrado."; + continue; + } + + // Consultar nombre del estado + $sql = "SELECT nombre FROM dbo.estados WHERE id_estado = ?"; + $stmt = sqlsrv_query($conn, $sql, [$estado_id]); + if ($row_estado = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { + $estado_nombre = $row_estado['nombre']; + } else { + $errors[] = "Fila $rowNum: estado con ID $estado_id no encontrado."; + continue; + } + + // Consultar nombre de la ciudad + $sql = "SELECT nombre FROM dbo.ciudades WHERE id_ciudad = ?"; + $stmt = sqlsrv_query($conn, $sql, [$ciudad_id]); + if ($row_ciudad = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { + $ciudad_nombre = $row_ciudad['nombre']; + } else { + $errors[] = "Fila $rowNum: ciudad con ID $ciudad_id no encontrada."; + continue; + } + + // 5) Insertar en BD con nombres $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, + $caat, $pais_nombre, $estado_nombre, $ciudad_nombre, $dom, $usr_id ]; $stmt = sqlsrv_query($conn, $sql, $params); @@ -204,7 +229,6 @@ function bulk_upload() { include __DIR__ . '/../../views/transportistas/bulk_upload.php'; } - function ajax_lista() { // 1) Autorización if (!($_SESSION['usuario_id'] ?? false)) { @@ -222,11 +246,11 @@ function ajax_lista() { $length = intval($_GET['length'] ?? 10); $search = $_GET['search']['value'] ?? ''; - // Mapeo columnas - $cols = ['id_transportista','clave_identificador','nombre','rfc','ciudad','creado_en']; + // 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']; $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'; + $orderCol = in_array($orderColIdx, range(0,5)) ? $cols[$orderColIdx] : 't.creado_en'; // 3) Total registros sin filtro $sqlTotal = "SELECT COUNT(*) AS total FROM dbo.transportistas WHERE id_usuario = ? AND activo = 1"; @@ -234,23 +258,55 @@ function ajax_lista() { $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); $recordsTotal = (int)$row['total']; - // 4) Total registros con filtro - $where = "id_usuario = ? AND activo = 1 "; + // 4) Construir condiciones de filtro + $where = "t.id_usuario = ? AND t.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]); + // Ahora buscamos en campos de transportista Y en el nombre de la ciudad + $where .= " AND ( + t.clave_identificador LIKE ? OR + t.nombre LIKE ? OR + t.rfc LIKE ? OR + t.curp LIKE ? OR + t.telefono LIKE ? OR + t.caat LIKE ? OR + c.nombre LIKE ? OR + p.nombre LIKE ? OR + e.nombre LIKE ? + )"; + $like = "%{$search}%"; + // Agregamos el parámetro para cada campo de búsqueda + $params = array_merge($params, array_fill(0, 9, $like)); } - $sqlFiltered = "SELECT COUNT(*) AS total FROM dbo.transportistas WHERE $where"; + + // 5) Total registros filtrados (CON JOIN) + $sqlFiltered = " + SELECT COUNT(*) AS total + FROM dbo.transportistas t + LEFT JOIN dbo.ciudades c ON t.ciudad = c.id_ciudad + 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 + "; $stmtF = sqlsrv_query($conn, $sqlFiltered, $params); $rowF = sqlsrv_fetch_array($stmtF, SQLSRV_FETCH_ASSOC); $recordsFiltered = (int)$rowF['total']; - // 5) Datos de la página + // 6) Datos de la página con JOIN completo $sqlData = " - SELECT id_transportista, clave_identificador, nombre, rfc, ciudad, creado_en - FROM dbo.transportistas + SELECT t.id_transportista, + t.clave_identificador, + t.nombre, + t.rfc, + COALESCE(c.nombre, 'Ciudad no encontrada') as ciudad_nombre, + COALESCE(e.nombre, '') as estado_nombre, + COALESCE(p.nombre, '') as pais_nombre, + t.creado_en + FROM dbo.transportistas t + LEFT JOIN dbo.ciudades c ON t.ciudad = c.id_ciudad + 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 ORDER BY $orderCol $orderDir OFFSET ? ROWS FETCH NEXT ? ROWS ONLY @@ -267,14 +323,14 @@ function ajax_lista() { $r['clave_identificador'], $r['nombre'], $r['rfc'], - $r['ciudad'], + $r['ciudad_nombre'], // Ahora muestra el nombre real de la ciudad $r['creado_en'] instanceof DateTime ? $r['creado_en']->format('Y-m-d H:i') : '' ]; } - // 6) Devolver JSON + // 7) Devolver JSON header('Content-Type: application/json; charset=UTF-8'); echo json_encode([ "draw" => $draw, @@ -320,22 +376,14 @@ function editar() { // --- 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']] - ); + $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']] - ); + $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; } @@ -344,9 +392,7 @@ function editar() { include __DIR__ . '/../../views/transportistas/editar.php'; } -/** - * Procesa el POST de actualización - */ +/** Procesa el POST de actualización **/ function actualizar() { session_start(); if (!($_SESSION['usuario_id'] ?? false)) { @@ -415,9 +461,6 @@ function actualizar() { } - - - function eliminar() { session_start(); if (!($_SESSION['usuario_id'] ?? false)) { @@ -435,17 +478,15 @@ function eliminar() { // 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"; + 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 ya eliminado."); + die("❌ Transportista no encontrado o no autorizado."); } - // Soft-delete - $sqlDel = "UPDATE dbo.transportistas - SET activo = 0 - WHERE id_transportista = ?"; + // ELIMINACIÓN REAL - DELETE en lugar de UPDATE + $sqlDel = "DELETE FROM dbo.transportistas WHERE id_transportista = ?"; $stmtDel = sqlsrv_query($conn, $sqlDel, [$id]); if ($stmtDel === false) { die("❌ Error al eliminar: " . print_r(sqlsrv_errors(), true)); diff --git a/views/registro/form.php b/views/registro/form.php index 001637c..cb06e4b 100644 --- a/views/registro/form.php +++ b/views/registro/form.php @@ -123,7 +123,6 @@ $color2 = explode(',', $config['colores_primarios'] ?? '#003366,#0055A5')
-
diff --git a/views/transportistas/alta.php b/views/transportistas/alta.php index 3d14c36..ebd206c 100644 --- a/views/transportistas/alta.php +++ b/views/transportistas/alta.php @@ -4,6 +4,9 @@ + + + - - - - - -

@@ -158,7 +151,7 @@ function confirmDelete(id) { Swal.fire({ title: '¿Eliminar transportista?', - text: 'Esto sólo lo desactivará; no se podrá volver a usar.', + text: 'Esto sólo lo eliminara completamente y no se podrá volver a usar.', icon: 'warning', showCancelButton: true, confirmButtonText: 'Sí, eliminar',