"""Routes salles - GMAO Collège""" from datetime import date, datetime, timedelta from flask import Blueprint, render_template, redirect, url_for, request, flash from flask_login import login_required from app_new.extensions import db from app_new.core.models.college import Room, Zone, Building, RoomType, RoomSchedule from app_new.core.models.equipment import Equipment rooms_bp = Blueprint('rooms', __name__, template_folder='templates') def _room_form_context(room=None): """Return all reference data used by the room form. The building list is deliberately loaded independently from the zone list. Previously the GET route only supplied ``zones`` which left the required building select empty and made every room creation impossible. """ return { 'room': room, 'buildings': Building.query.order_by(Building.name).all(), 'zones': Zone.query.join(Building).order_by(Building.name, Zone.name).all(), 'room_types': RoomType.query.order_by(RoomType.name).all(), } @rooms_bp.route('/') @login_required def index(): """Liste des salles.""" zones_filter = request.args.getlist('zone') or None room_type_id = request.args.get('room_type', type=int) query = Room.query.join(Zone).join(Building) if zones_filter: query = query.filter(Zone.id.in_(zones_filter)) if room_type_id: query = query.filter_by(room_type_id=room_type_id) rooms = query.order_by(Building.name, Zone.name, Room.name).all() zones = Zone.query.join(Building).order_by(Building.name, Zone.name).all() room_types = RoomType.query.order_by(RoomType.name).all() return render_template('equipments/rooms.html', rooms=rooms, zones=zones, room_types=room_types, selected_zones=[int(z) for z in zones_filter] if zones_filter else []) @rooms_bp.route('/') @login_required def detail(id): """Détail d'une salle.""" room = Room.query.get_or_404(id) today = date.today() week_start = today - timedelta(days=today.weekday()) courses = RoomSchedule.query.filter_by( room_id=room.id, week_start=week_start, day_of_week=today.weekday(), ).order_by(RoomSchedule.start_time).all() current_time = datetime.now().time() current_course = next( (course for course in courses if course.start_time <= current_time <= course.end_time), None, ) next_course = next( (course for course in courses if course.start_time > current_time), None, ) if current_course: room_status = { 'status': 'occupee', 'message': 'Salle actuellement occupée', 'course': current_course, 'next_occupied': None, } elif courses: room_status = { 'status': 'libre', 'message': 'Salle libre actuellement', 'course': None, 'next_occupied': next_course.start_time.strftime('%H:%M') if next_course else None, } else: room_status = { 'status': 'inconnu', 'message': "Aucun emploi du temps importé pour cette salle aujourd'hui.", 'course': None, 'next_occupied': None, } equipments = Equipment.query.filter( Equipment.room_id == room.id, Equipment.is_deleted.is_(False), ).order_by(Equipment.name, Equipment.individual_number).all() return render_template('equipments/room_detail.html', room=room, equipments=equipments, courses=courses, room_status=room_status) @rooms_bp.route('/new', methods=['GET', 'POST']) @login_required def create(): """Créer une salle.""" if request.method == 'POST': name = (request.form.get('name') or '').strip() building_id = request.form.get('building_id', type=int) zone_id = request.form.get('zone_id', type=int) building = db.session.get(Building, building_id) if building_id else None zone = db.session.get(Zone, zone_id) if zone_id else None errors = [] if not name: errors.append('Le nom de la salle est obligatoire.') if not building: errors.append('Sélectionnez un bâtiment valide.') if zone and building and zone.building_id != building.id: errors.append('La zone sélectionnée n’appartient pas au bâtiment choisi.') if errors: for error in errors: flash(error, 'danger') context = _room_form_context() context['form_data'] = request.form return render_template('equipments/room_form.html', **context), 400 room = Room( name=name, code=request.form.get('code') or None, zone_id=zone_id, building_id=building.id, room_type_id=request.form.get('room_type_id', type=int), floor=request.form.get('floor', 0, type=int) ) db.session.add(room) try: db.session.commit() except Exception: db.session.rollback() flash('Impossible d’enregistrer cette salle. Vérifiez les valeurs saisies.', 'danger') context = _room_form_context() context['form_data'] = request.form return render_template('equipments/room_form.html', **context), 400 flash(f"Salle '{room.name}' créée.", 'success') return redirect(url_for('rooms.index')) context = _room_form_context() context['form_data'] = {} context['title'] = 'Nouvelle salle' return render_template('equipments/room_form.html', **context) @rooms_bp.route('//edit', methods=['GET', 'POST']) @login_required def edit(id): """Modifier une salle.""" room = Room.query.get_or_404(id) if request.method == 'POST': name = (request.form.get('name') or '').strip() building_id = request.form.get('building_id', type=int) zone_id = request.form.get('zone_id', type=int) building = db.session.get(Building, building_id) if building_id else None zone = db.session.get(Zone, zone_id) if zone_id else None if not name or not building or (zone and zone.building_id != building.id): flash('Le nom, le bâtiment et une zone cohérente sont obligatoires.', 'danger') context = _room_form_context(room) context['form_data'] = request.form context['title'] = 'Modifier la salle' return render_template('equipments/room_form.html', **context), 400 room.name = name room.code = request.form.get('code') or None room.zone_id = zone_id room.building_id = building.id room.room_type_id = request.form.get('room_type_id', type=int) room.floor = request.form.get('floor', 0, type=int) try: db.session.commit() except Exception: db.session.rollback() flash('Impossible d’enregistrer cette salle. Vérifiez les valeurs saisies.', 'danger') context = _room_form_context(room) context['form_data'] = request.form context['title'] = 'Modifier la salle' return render_template('equipments/room_form.html', **context), 400 flash(f"Salle '{room.name}' mise à jour.", 'success') return redirect(url_for('rooms.index')) context = _room_form_context(room) context['form_data'] = {} context['title'] = 'Modifier la salle' return render_template('equipments/room_form.html', **context) @rooms_bp.route('//delete', methods=['POST']) @login_required def delete(id): """Supprimer une salle.""" room = Room.query.get_or_404(id) db.session.delete(room) db.session.commit() flash(f"Salle '{room.name}' supprimée.", 'success') return redirect(url_for('rooms.index'))