const { Reservation, Client, Table } = require('../models/associations'); const { Op } = require('sequelize'); class ReservationController { // Get all reservations async getAllReservations(req, res) { try { const { page = 1, limit = 10, statut, date_debut, date_fin, table_id, sort_by = 'date_reservation', sort_order = 'ASC' } = req.query; const offset = (parseInt(page) - 1) * parseInt(limit); const whereClause = {}; // Status filter if (statut) { whereClause.statut = statut; } // Date range filter if (date_debut && date_fin) { whereClause.date_reservation = { [Op.between]: [new Date(date_debut), new Date(date_fin)] }; } else if (date_debut) { whereClause.date_reservation = { [Op.gte]: new Date(date_debut) }; } else if (date_fin) { whereClause.date_reservation = { [Op.lte]: new Date(date_fin) }; } // Table filter if (table_id) { whereClause.table_id = table_id; } const { count, rows } = await Reservation.findAndCountAll({ where: whereClause, include: [ { model: Client, as: 'client', attributes: ['nom', 'prenom', 'email', 'telephone'] }, { model: Table, as: 'table', attributes: ['nom', 'capacity', 'location'] } ], limit: parseInt(limit), offset: offset, order: [[sort_by, sort_order.toUpperCase()]] }); res.json({ success: true, data: { reservations: rows, pagination: { currentPage: parseInt(page), totalPages: Math.ceil(count / parseInt(limit)), totalItems: count, itemsPerPage: parseInt(limit) } } }); } catch (error) { res.status(500).json({ success: false, message: 'Erreur lors de la récupération des réservations', error: error.message }); } } // Get reservation by ID async getReservationById(req, res) { try { const { id } = req.params; const reservation = await Reservation.findByPk(id, { include: [ { model: Client, as: 'client', attributes: ['nom', 'prenom', 'email', 'telephone'] }, { model: Table, as: 'table', attributes: ['nom', 'capacity', 'location'] }, { association: 'commandes' } ] }); if (!reservation) { return res.status(404).json({ success: false, message: 'Réservation non trouvée' }); } res.json({ success: true, data: reservation }); } catch (error) { res.status(500).json({ success: false, message: 'Erreur lors de la récupération de la réservation', error: error.message }); } } // Create new reservation async createReservation(req, res) { try { const reservationData = req.body; // Check table availability const existingReservation = await Reservation.findOne({ where: { table_id: reservationData.table_id, date_reservation: { [Op.between]: [ new Date(new Date(reservationData.date_reservation).getTime() - 2 * 60 * 60 * 1000), new Date(new Date(reservationData.date_reservation).getTime() + 2 * 60 * 60 * 1000) ] }, statut: { [Op.in]: ['confirmee', 'en_attente'] } } }); if (existingReservation) { return res.status(400).json({ success: false, message: 'Table déjà réservée à cette heure' }); } // Check table capacity const table = await Table.findByPk(reservationData.table_id); if (!table) { return res.status(404).json({ success: false, message: 'Table non trouvée' }); } if (reservationData.nombre_personnes > table.capacity) { return res.status(400).json({ success: false, message: 'Nombre de personnes supérieur à la capacité de la table' }); } const reservation = await Reservation.create(reservationData); // Include related data in response const createdReservation = await Reservation.findByPk(reservation.id, { include: [ { model: Client, as: 'client', attributes: ['nom', 'prenom', 'email', 'telephone'] }, { model: Table, as: 'table', attributes: ['nom', 'capacity', 'location'] } ] }); res.status(201).json({ success: true, message: 'Réservation créée avec succès', data: createdReservation }); } catch (error) { if (error.name === 'SequelizeValidationError') { return res.status(400).json({ success: false, message: 'Données invalides', errors: error.errors.map(e => ({ field: e.path, message: e.message })) }); } res.status(500).json({ success: false, message: 'Erreur lors de la création de la réservation', error: error.message }); } } // Update reservation async updateReservation(req, res) { try { const { id } = req.params; const updateData = req.body; const reservation = await Reservation.findByPk(id); if (!reservation) { return res.status(404).json({ success: false, message: 'Réservation non trouvée' }); } await reservation.update(updateData); const updatedReservation = await Reservation.findByPk(id, { include: [ { model: Client, as: 'client', attributes: ['nom', 'prenom', 'email', 'telephone'] }, { model: Table, as: 'table', attributes: ['nom', 'capacity', 'location'] } ] }); res.json({ success: true, message: 'Réservation mise à jour avec succès', data: updatedReservation }); } catch (error) { res.status(500).json({ success: false, message: 'Erreur lors de la mise à jour de la réservation', error: error.message }); } } // Delete reservation async deleteReservation(req, res) { try { const { id } = req.params; const reservation = await Reservation.findByPk(id); if (!reservation) { return res.status(404).json({ success: false, message: 'Réservation non trouvée' }); } await reservation.destroy(); res.json({ success: true, message: 'Réservation supprimée avec succès' }); } catch (error) { res.status(500).json({ success: false, message: 'Erreur lors de la suppression de la réservation', error: error.message }); } } // Get reservations by status async getReservationsByStatus(req, res) { try { const { status } = req.params; const { page = 1, limit = 10 } = req.query; const offset = (parseInt(page) - 1) * parseInt(limit); const { count, rows } = await Reservation.findAndCountAll({ where: { statut: status }, include: [ { model: Client, as: 'client', attributes: ['nom', 'prenom', 'email', 'telephone'] }, { model: Table, as: 'table', attributes: ['nom', 'capacity', 'location'] } ], limit: parseInt(limit), offset: offset, order: [['date_reservation', 'ASC']] }); res.json({ success: true, data: { reservations: rows, pagination: { currentPage: parseInt(page), totalPages: Math.ceil(count / parseInt(limit)), totalItems: count, itemsPerPage: parseInt(limit) } } }); } catch (error) { res.status(500).json({ success: false, message: 'Erreur lors de la récupération des réservations', error: error.message }); } } // Get today's reservations async getTodayReservations(req, res) { try { const today = new Date(); const startOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate()); const endOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1); const reservations = await Reservation.findAll({ where: { date_reservation: { [Op.between]: [startOfDay, endOfDay] } }, include: [ { model: Client, as: 'client', attributes: ['nom', 'prenom', 'email', 'telephone'] }, { model: Table, as: 'table', attributes: ['nom', 'capacity', 'location'] } ], order: [['date_reservation', 'ASC']] }); res.json({ success: true, data: reservations }); } catch (error) { res.status(500).json({ success: false, message: 'Erreur lors de la récupération des réservations du jour', error: error.message }); } } // Get reservation statistics async getReservationStats(req, res) { try { const total = await Reservation.count(); const confirmees = await Reservation.count({ where: { statut: 'confirmee' } }); const en_attente = await Reservation.count({ where: { statut: 'en_attente' } }); const annulees = await Reservation.count({ where: { statut: 'annulee' } }); const terminees = await Reservation.count({ where: { statut: 'terminee' } }); const today = new Date(); const startOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate()); const endOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1); const todayCount = await Reservation.count({ where: { date_reservation: { [Op.between]: [startOfDay, endOfDay] } } }); res.json({ success: true, data: { total, confirmees, en_attente, annulees, terminees, todayCount } }); } catch (error) { res.status(500).json({ success: false, message: 'Erreur lors de la récupération des statistiques', error: error.message }); } } } module.exports = new ReservationController();