feat: endpoint POST /reportes - buzón de incidencias

This commit is contained in:
2026-05-23 02:05:32 -06:00
parent 0c68e41963
commit d9d8597625
2 changed files with 88 additions and 6 deletions

View File

@@ -2,6 +2,7 @@ const express = require('express');
const cors = require('cors'); const cors = require('cors');
const authRoutes = require('./routes/auth.routes'); const authRoutes = require('./routes/auth.routes');
const rutaRoutes = require('./routes/ruta.routes'); const rutaRoutes = require('./routes/ruta.routes');
const reportesRoutes = require('./routes/reportes.routes');
const app = express(); const app = express();
@@ -10,7 +11,8 @@ app.use(express.json());
// ── Rutas ──────────────────────────────────────────────────────── // ── Rutas ────────────────────────────────────────────────────────
app.use('/auth', authRoutes); app.use('/auth', authRoutes);
app.use('/mi-ruta', rutaRoutes); // GET /mi-ruta/eta GET /mi-ruta/estado app.use('/mi-ruta', rutaRoutes);
app.use('/reportes', reportesRoutes);
// ── Health check ───────────────────────────────────────────────── // ── Health check ─────────────────────────────────────────────────
app.get('/health', (_req, res) => res.json({ status: 'ok' })); app.get('/health', (_req, res) => res.json({ status: 'ok' }));

View File

@@ -0,0 +1,80 @@
/**
* ================================================================
* REPORTES - Buzón de incidencias del ciudadano
*
* POST /reportes → crea un reporte asociado al usuario y su ruta
* ================================================================
*/
const express = require('express');
const pool = require('../config/db');
const { verificarToken } = require('../middleware/auth.middleware');
const router = express.Router();
router.use(verificarToken);
// Tipos de reporte válidos
const TIPOS_VALIDOS = ['no_paso', 'queja', 'calificacion', 'sugerencia'];
// ================================================================
// POST /reportes
// ================================================================
router.post('/', async (req, res) => {
const { userId, domicilioId, routeId } = req.user;
const { tipo, descripcion, calificacion } = req.body;
// ── Validaciones ───────────────────────────────────────────────
if (!tipo || !TIPOS_VALIDOS.includes(tipo)) {
return res.status(400).json({
error: `Tipo inválido. Valores permitidos: ${TIPOS_VALIDOS.join(', ')}`,
});
}
if (tipo === 'calificacion') {
if (!calificacion || calificacion < 1 || calificacion > 5) {
return res.status(400).json({
error: 'Para calificación debes enviar un valor entre 1 y 5',
});
}
}
try {
// Obtener ruta_id a partir del routeId del JWT
let rutaId = null;
if (routeId) {
const { rows } = await pool.query(
'SELECT id FROM rutas WHERE route_id = $1',
[routeId]
);
rutaId = rows[0]?.id || null;
}
const { rows: [reporte] } = await pool.query(
`INSERT INTO reportes
(user_id, domicilio_id, ruta_id, tipo, descripcion, calificacion)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING id, tipo, descripcion, calificacion, estado, creado_at`,
[userId, domicilioId || null, rutaId, tipo,
descripcion || null, calificacion || null]
);
return res.status(201).json({
message: 'Reporte enviado correctamente. Gracias por tu retroalimentación.',
reporte: {
id: reporte.id,
tipo: reporte.tipo,
descripcion: reporte.descripcion,
calificacion:reporte.calificacion,
estado: reporte.estado,
creado_at: reporte.creado_at,
},
});
} catch (err) {
console.error('❌ Error en POST /reportes:', err.message);
return res.status(500).json({ error: 'Error interno del servidor' });
}
});
module.exports = router;