Entrada 7

Fecha: 23/03/2025

Inicio: [18:45] | Fin: [21:40] | Total: [3 horas]

 Presentes: Matías Benavides Sandoval 

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
¿QUÉ HICIMOS HOY?
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Sesión enfocada en completar el backend y ordenar la estructura del proyecto.

1. Creamos src/controllers/empleadoController.ts con las dos funciones principales:
   - getEmpleados: invoca sp_GetEmpleados y retorna el dataset al frontend como JSON
   - insertEmpleado: invoca sp_InsertEmpleado y retorna éxito o error de duplicado según el código

2. Creamos src/routes/empleados.ts que conecta las rutas HTTP con las funciones del controller:
   - GET  /api/empleados → getEmpleados
   - POST /api/empleados → insertEmpleado

3. Actualizamos src/index.ts para:
   - Servir la carpeta public/ con express.static (esto hace que el browser pueda cargar el HTML, CSS y JS del frontend)
   - Conectar el router de empleados en /api/empleados

4. Reorganizamos la estructura de archivos del proyecto para que sea más clara y ordenada:
   - CSS movido a public/css/
   - SPs renombrados con sus nombres correctos
   - Eliminado el archivo tsconfig duplicado vacío

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
PROBLEMAS ENCONTRADOS Y CÓMO SE RESOLVIERON
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Problema 1:
  Descripción: El SP se llamaba de forma incorrecta desde index.ts.
  Código incorrecto:
    .execute('SPordenar')
  Código correcto:
    .execute('sp_GetEmpleados')
  Causa: El nombre del SP en el código no coincidía
  con el nombre real en la BD.

Problema 2:
  Descripción: El connection.ts tenía la IP de
  Hamachi en lugar de localhost.
  Causa: Se quedó la IP del compañero de cuando él lo probó en su máquina.
  Solución: 
Cambiar server a 'localhost' en la máquina del servidor (Matias) y mantener '25.0.119.25' solo en la del compañero.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
DUDAS Y DIVERGENCIAS DE CRITERIO
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Discutimos si el controller debería validar los campos de entrada además del frontend. Decidimos
hacer una validación mínima en el controller (verificar que nombre y salario no sean undefined) y dejar la validación completa al frontend y al SP, que es donde el enunciado la pide explícitamente.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
AVANCE DEL CÓDIGO
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
--------------------------Empleados.ts (rutas) -----------------------------------

import { Router } from 'express';
import { getEmpleados, insertEmpleado } from '../controllers/empleadoController';

const router = Router();

// GET  /api/empleados → llama a getEmpleados
router.get('/', getEmpleados);

// POST /api/empleados → llama a insertEmpleado
router.post('/', insertEmpleado);

export default router;

------------------------EmpleadosController.ts ----------------------------------
import { Request, Response } from 'express';
import { getPool, sql } from '../db/connection';

// ═══════════════════════════════════════════════
// GET /api/empleados
// Invoca sp_GetEmpleados y retorna el listado
// ═══════════════════════════════════════════════
export async function getEmpleados(
    req: Request,
    res: Response
): Promise<void> {
    try {
    const pool = await getPool();

    const result = await pool
        .request()
        .execute('sp_GetEmpleados');

    res.json({
        success: true,
        data: result.recordset
    });

    } catch (error) {
    console.error('Error en getEmpleados:', error);
    res.status(500).json({
        success: false,
        message: 'Error al obtener empleados'
    });
    }
}

// ═══════════════════════════════════════════════
// POST /api/empleados
// Invoca sp_InsertEmpleado con nombre y salario
// Retorna success o mensaje de duplicado
// ═══════════════════════════════════════════════
export async function insertEmpleado(
    req: Request,
    res: Response
): Promise<void> {
    const { nombre, salario } = req.body;

  // Validación mínima en capa lógica
    if (!nombre || salario === undefined) {
    res.status(400).json({
        success: false,
        message: 'Nombre y salario son requeridos'
    });
    return;
    }

    try {
    const pool = await getPool();

    const result = await pool
        .request()
        .input('Nombre',  sql.VarChar(128), nombre)
        .input('Salario', sql.Money,        salario)
        .output('Resultado', sql.Int)
        .execute('sp_InsertEmpleado');

    const codigo: number = result.output.Resultado;

    if (codigo === 0) {
        res.json({
        success: true,
        message: 'Inserción exitosa'
        });
    } else {
        res.status(409).json({
        success: false,
        message: 'Nombre de Empleado ya existe.'
        });
    }

    } catch (error) {
    console.error('Error en insertEmpleado:', error);
    res.status(500).json({
        success: false,
        message: 'Error interno del servidor'
    });
    }
}

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
MORALEJAS / BUENAS PRÁCTICAS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- El nombre del SP en el código debe coincidir exactamente con el nombre en la BD, incluyendo mayúsculas y guiones bajos. Un error de tipeo aquí da un error de runtime difícil de detectar.
- Mantener el connection.ts con localhost en el servidor y la IP de Hamachi en el cliente evita confusiones al hacer commits.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
PRÓXIMA SESIÓN: ¿QUÉ SIGUE?
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- Sebastián corrige index.js para que el fetch
  apunte a /api/empleados correctamente.
- Probar el flujo completo: lista → insertar →
  regresar con tabla actualizada.
- Revisar la rúbrica para verificar que todos
  los requisitos están cubiertos.
- Hacer commit final con todos los cambios.


Comentarios

Entradas más populares de este blog

Entrada 4