feat: add guest management with profiles and stay history

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-15 01:41:24 +00:00
parent baf52dc478
commit 785b1f0925
7 changed files with 771 additions and 0 deletions

View File

@@ -37,6 +37,7 @@ const incomehrxRoutes = require('./routes/incomehrx.routes');
const roomsRoutes = require('./routes/rooms.routes');
const dashboardRoutes = require('./routes/dashboard.routes');
const reservationsRoutes = require('./routes/reservations.routes');
const guestsRoutes = require('./routes/guests.routes');
//Prefijo - Auth routes are public (no middleware)
app.use('/api/auth', authRoutes);
@@ -60,5 +61,6 @@ app.use('/api/restaurantpl', authMiddleware, restaurantRoutes);
app.use('/api/rooms', authMiddleware, roomsRoutes);
app.use('/api/dashboard', authMiddleware, dashboardRoutes);
app.use('/api/reservations', authMiddleware, reservationsRoutes);
app.use('/api/guests', authMiddleware, guestsRoutes);
module.exports = app;

View File

@@ -0,0 +1,108 @@
const pool = require('../db/connection');
const getGuests = async (req, res) => {
try {
const { search, limit = 50, offset = 0 } = req.query;
let query = `
SELECT g.*,
r.room_id, rm.name_room,
r.check_in as current_check_in
FROM guests g
LEFT JOIN reservations r ON r.guest_id = g.id AND r.status = 'checked_in'
LEFT JOIN rooms rm ON rm.id_room = r.room_id
`;
const params = [];
let paramIndex = 1;
if (search) {
query += ` WHERE g.first_name ILIKE $${paramIndex} OR g.last_name ILIKE $${paramIndex} OR g.email ILIKE $${paramIndex} OR g.phone ILIKE $${paramIndex}`;
params.push(`%${search}%`);
paramIndex++;
}
query += ` ORDER BY g.created_at DESC LIMIT $${paramIndex++} OFFSET $${paramIndex++}`;
params.push(parseInt(limit), parseInt(offset));
const result = await pool.query(query, params);
const countQuery = search
? await pool.query('SELECT COUNT(*) FROM guests WHERE first_name ILIKE $1 OR last_name ILIKE $1 OR email ILIKE $1 OR phone ILIKE $1', [`%${search}%`])
: await pool.query('SELECT COUNT(*) FROM guests');
res.json({ guests: result.rows, total: parseInt(countQuery.rows[0].count) });
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Error al obtener huespedes' });
}
};
const getGuestById = async (req, res) => {
try {
const { id } = req.params;
const guest = await pool.query(`
SELECT g.*, r.room_id, rm.name_room, r.check_in as current_check_in, r.check_out as current_check_out
FROM guests g
LEFT JOIN reservations r ON r.guest_id = g.id AND r.status = 'checked_in'
LEFT JOIN rooms rm ON rm.id_room = r.room_id
WHERE g.id = $1
`, [id]);
if (guest.rows.length === 0) return res.status(404).json({ message: 'Huesped no encontrado' });
res.json({ guest: guest.rows[0] });
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Error al obtener huesped' });
}
};
const createGuest = async (req, res) => {
try {
const { first_name, last_name, email, phone, id_type, id_number, nationality, address, notes } = req.body;
const result = await pool.query(
`INSERT INTO guests (first_name, last_name, email, phone, id_type, id_number, nationality, address, notes)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING *`,
[first_name, last_name, email, phone, id_type, id_number, nationality, address, notes]
);
res.status(201).json({ guest: result.rows[0], message: 'Huesped creado correctamente' });
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Error al crear huesped' });
}
};
const updateGuest = async (req, res) => {
try {
const { id } = req.params;
const { first_name, last_name, email, phone, id_type, id_number, nationality, address, notes } = req.body;
const result = await pool.query(
`UPDATE guests SET first_name = COALESCE($1, first_name), last_name = COALESCE($2, last_name),
email = COALESCE($3, email), phone = COALESCE($4, phone), id_type = COALESCE($5, id_type),
id_number = COALESCE($6, id_number), nationality = COALESCE($7, nationality),
address = COALESCE($8, address), notes = COALESCE($9, notes), updated_at = NOW()
WHERE id = $10 RETURNING *`,
[first_name, last_name, email, phone, id_type, id_number, nationality, address, notes, id]
);
if (result.rows.length === 0) return res.status(404).json({ message: 'Huesped no encontrado' });
res.json({ guest: result.rows[0] });
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Error al actualizar huesped' });
}
};
const getGuestStays = async (req, res) => {
try {
const { id } = req.params;
const result = await pool.query(`
SELECT gs.*, rm.name_room, rm.bed_type
FROM guest_stays gs
LEFT JOIN rooms rm ON rm.id_room = gs.room_id
WHERE gs.guest_id = $1
ORDER BY gs.check_in DESC
`, [id]);
res.json({ stays: result.rows });
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Error al obtener estadias' });
}
};
module.exports = { getGuests, getGuestById, createGuest, updateGuest, getGuestStays };

View File

@@ -0,0 +1,11 @@
const express = require('express');
const router = express.Router();
const ctrl = require('../controllers/guests.controller');
router.get('/', ctrl.getGuests);
router.get('/:id', ctrl.getGuestById);
router.get('/:id/stays', ctrl.getGuestStays);
router.post('/', ctrl.createGuest);
router.put('/:id', ctrl.updateGuest);
module.exports = router;