Entrada 9 (Controller)

 # Bitácora de Sesión

 Fecha: 23/04/2026

 Inicio: [20:30] | Fin: [22:00] || Total: [1 hora y 30 minutos]

 Presentes: Matías Benavides Sandoval

 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

¿QUÉ HICIMOS HOY?

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

- Se validó el GET /api/empleados desde el backend 

- Se validó el POST /api/empleados.

- Se reorganizó la arquitectura para que el route de empleados quede delgado y delegue al controller, igual que en el proyecto anterior.

- Se corrigió la compilación para que el backend salga en dist y no en public/js.

 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

PROBLEMAS ENCONTRADOS Y CÓMO SE RESOLVIERON

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

- El backend se estaba compilando dentro de public/js junto con el frontend.

    - Solución: cambiar outDir del backend a dist en tsconfig.json.

- Quedaron restos de JS compilado del backend dentro de public/js.

    - Solución: eliminar esos archivos y volver a compilar frontend y backend por separado.

 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

DUDAS Y DIVERGENCIAS DE CRITERIO

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

- Se confirmó que la estructura correcta es route delgado + controller con lógica.

 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

AVANCE DEL CÓDIGO

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

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()
            .output('outResultCode', sql.Int)
            .execute('sp_GetEmpleados');

        const resultCode: number = result.output.outResultCode;

        if (resultCode === 0) {
            res.json({
                success: true,
                data: result.recordset
            });
        } else {
            res.status(500).json({
                success: false,
                message: 'Error al obtener empleados'
            });
        }

    } 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('inNombre', sql.VarChar(128), nombre)
            .input('inSalario', sql.Money, salario)
            .output('outResultCode', sql.Int)
            .execute('sp_InsertEmpleado');

        const resultCode: number = result.output.outResultCode;

        if (resultCode === 0) {
            res.json({
                success: true,
                message: 'Inserción exitosa'
            });
        } else if (resultCode === 50001) {
            res.status(409).json({
                success: false,
                message: 'Nombre de Empleado ya existe.'
            });
        } else {
            res.status(500).json({
                success: false,
                message: 'Error interno del servidor'
            });
        }

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

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

MORALEJAS / BUENAS PRÁCTICAS

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

- Separar backend y frontend evita que se mezcle código generado donde no corresponde.

- Antes de avanzar de capa, conviene probar cada endpoint con datos reales.

 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

PRÓXIMA SESIÓN: ¿QUÉ SIGUE?

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

- Empezar con la pantalla de empleados en frontend, primero la lista y el filtro.

 

Comentarios

Entradas más populares de este blog

Entrada 16 (Controlador de movimientos)

Entrada 20 (Lógica de insertarMovimientos, conectarla y probarla)

Entrada 21 (Análisis de resultados)