from flask import Blueprint, request, jsonify, g from pydantic import ValidationError from app.services.classroom_service import ClassroomService from app.schemas.classroom_dto import ClassroomCreateDTO, ClassroomUpdateDTO, ClassroomResponseDTO from app.utils.jwt_decorators import jwt_required, jwt_role_required api_classrooms_bp = Blueprint('api_classrooms', __name__, url_prefix='/api/v1/classrooms') classroom_service = ClassroomService() @api_classrooms_bp.route('', methods=['GET']) @jwt_required def list_classrooms(): """Lista aulas con filtros opcionales (building_id, floor, mode).""" building_id = request.args.get('building_id', type=int) floor = request.args.get('floor') mode = request.args.get('mode', '').lower() only_virtual = mode == 'virtual' only_physical = mode == 'physical' classrooms = classroom_service.list_classrooms( building_id=building_id, floor=floor, only_virtual=only_virtual, only_physical=only_physical ) result = [] for c in classrooms: result.append({ 'id': c.id, 'code': c.code, 'building': c.building_name, 'building_id': c.building_id, 'floor': c.floor, 'floor_display': c.floor_display, 'capacity': c.capacity, 'is_virtual': c.is_virtual, 'location_display': c.location_display, 'description': c.description, 'is_active': c.is_active }) return jsonify({'total': len(result), 'classrooms': result}), 200 @api_classrooms_bp.route('/', methods=['GET']) @jwt_required def get_classroom(classroom_id: int): """Obtiene el detalle de un aula por ID.""" c = classroom_service.get_classroom(classroom_id) if not c: return jsonify({'error': 'NotFound', 'message': f'Aula {classroom_id} no encontrada.'}), 404 return jsonify({ 'id': c.id, 'code': c.code, 'building': c.building_name, 'building_id': c.building_id, 'floor': c.floor, 'floor_display': c.floor_display, 'capacity': c.capacity, 'is_virtual': c.is_virtual, 'location_display': c.location_display, 'description': c.description, 'is_active': c.is_active }), 200 @api_classrooms_bp.route('', methods=['POST']) @jwt_role_required('ADMIN', 'ADMINISTRADOR', 'BEDELIA') def create_classroom(): """Crea una nueva aula validando el contrato con ClassroomCreateDTO.""" data = request.get_json(silent=True) or {} try: dto = ClassroomCreateDTO(**data) except ValidationError as e: return jsonify({'error': 'ValidationError', 'details': e.errors()}), 400 try: classroom = classroom_service.create_classroom(dto) return jsonify({ 'message': 'Aula creada exitosamente.', 'id': classroom.id, 'code': classroom.code, 'location_display': classroom.location_display }), 201 except ValueError as e: return jsonify({'error': 'ConflictOrValidation', 'message': str(e)}), 400 @api_classrooms_bp.route('/', methods=['PUT']) @jwt_role_required('ADMIN', 'ADMINISTRADOR', 'BEDELIA') def update_classroom(classroom_id: int): """Actualiza los datos de un aula.""" data = request.get_json(silent=True) or {} try: dto = ClassroomUpdateDTO(**data) except ValidationError as e: return jsonify({'error': 'ValidationError', 'details': e.errors()}), 400 try: classroom = classroom_service.update_classroom(classroom_id, dto) return jsonify({ 'message': 'Aula actualizada exitosamente.', 'id': classroom.id, 'code': classroom.code, 'capacity': classroom.capacity }), 200 except ValueError as e: return jsonify({'error': 'ConflictOrValidation', 'message': str(e)}), 400 @api_classrooms_bp.route('/', methods=['DELETE']) @jwt_role_required('ADMIN', 'ADMINISTRADOR') def delete_classroom(classroom_id: int): """Elimina o desactiva un aula.""" deleted = classroom_service.delete_classroom(classroom_id) if not deleted: return jsonify({'error': 'NotFound', 'message': f'Aula {classroom_id} no encontrada.'}), 404 return jsonify({'message': f'Aula {classroom_id} eliminada/desactivada correctamente.'}), 200