from flask import Blueprint, render_template, jsonify, redirect, url_for, session, request, flash from flask_login import login_required, current_user from app import db from app.models.reservation import Reservation from app.models.classroom import Classroom from app.models.subject import Subject from app.models.subject import Commission from datetime import datetime, timedelta from sqlalchemy import func from flask_babel import gettext as _ main_bp = Blueprint('main', __name__) @main_bp.route('/') @login_required def dashboard(): """Main dashboard page""" # Get statistics try: total_classrooms = Classroom.query.filter_by(is_active=True).count() except: total_classrooms = 0 try: total_subjects = Subject.query.filter_by(is_active=True).count() except: total_subjects = 0 # Get today's reservations today = datetime.utcnow().date() try: today_reservations = Reservation.query.filter( func.date(Reservation.start_time) == today ).count() except: today_reservations = 0 # Get this week's reservations week_start = today - timedelta(days=today.weekday()) week_end = week_start + timedelta(days=6) try: week_reservations = Reservation.query.filter( func.date(Reservation.start_time) >= week_start, func.date(Reservation.start_time) <= week_end ).count() except: week_reservations = 0 # Get upcoming reservations (next 7 days) try: upcoming_reservations = Reservation.query.filter( Reservation.start_time >= datetime.utcnow(), Reservation.start_time <= datetime.utcnow() + timedelta(days=7) ).limit(10).all() except: upcoming_reservations = [] stats = { 'total_classrooms': total_classrooms, 'total_subjects': total_subjects, 'today_reservations': today_reservations, 'week_reservations': week_reservations } return render_template('dashboard.html', stats=stats, upcoming_reservations=upcoming_reservations) @main_bp.route('/api/dashboard-stats') @login_required def dashboard_stats_api(): """API endpoint for dashboard statistics""" # Get today's data today = datetime.utcnow().date() today_reservations = Reservation.query.filter( func.date(Reservation.start_time) == today ).count() # Get this week's data week_start = today - timedelta(days=today.weekday()) week_end = week_start + timedelta(days=6) week_reservations = Reservation.query.filter( func.date(Reservation.start_time) >= week_start, func.date(Reservation.start_time) <= week_end ).count() # Get monthly data for chart current_date = datetime.utcnow() monthly_data = [] for i in range(12): month_date = current_date - timedelta(days=30 * i) month_start = month_date.replace(day=1) month_end = (month_start + timedelta(days=32)).replace(day=1) - timedelta(days=1) monthly_reservations = Reservation.query.filter( func.date(Reservation.start_time) >= month_start.date(), func.date(Reservation.start_time) <= month_end.date() ).count() monthly_data.append({ 'month': month_start.strftime('%Y-%m'), 'reservations': monthly_reservations }) return jsonify({ 'today_reservations': today_reservations, 'week_reservations': week_reservations, 'monthly_data': list(reversed(monthly_data)) }) @main_bp.route('/genetic-optimizer') @login_required def genetic_optimizer(): """Serve the genetic algorithm optimization interface""" if not (current_user.has_permission('optimizer', 'read') or (current_user.role and current_user.role.upper() == 'ADMIN')): flash(_('No tienes permisos para acceder a la herramienta de optimización.'), 'danger') return redirect(url_for('main.dashboard')) return render_template('genetic_optimizer.html') @main_bp.route('/set_language/') def set_language(language=None): if language not in ['en', 'es']: language = 'es' session['language'] = language # Si se selecciona el idioma desde la pantalla de login, registrar la selección explícita if request.referrer and 'login' in request.referrer: session['login_lang_explicit'] = language if current_user.is_authenticated: current_user.preferred_language = language db.session.commit() return redirect(request.referrer or url_for('main.dashboard')) @main_bp.route('/api/milestone-types') def api_milestone_types(): """Retorna las tipificaciones de hitos activas en JSON para consumo de frontend/mobile""" from app.models.milestone import MilestoneType, BASE_MILESTONE_TYPES if MilestoneType.query.count() == 0: for item in BASE_MILESTONE_TYPES: mt = MilestoneType( name=item['name'], code=item['code'], color=item['color'], description=item['description'], sort_order=item['sort_order'], is_active=True ) db.session.add(mt) db.session.commit() types = MilestoneType.query.filter_by(is_active=True).order_by(MilestoneType.sort_order.asc(), MilestoneType.id.asc()).all() return jsonify([t.to_dict() for t in types])