feat: refactorizar espacios fisicos desacoplando Edificio, Piso y Aula con selectores en cascada y filtros
This commit is contained in:
+32
-19
@@ -40,8 +40,8 @@ def today_schedule():
|
||||
~Classroom.building.ilike('%Virtual%')
|
||||
)
|
||||
|
||||
if floor_filter and floor_filter.isdigit():
|
||||
query = query.filter(Classroom.floor == int(floor_filter))
|
||||
if floor_filter:
|
||||
query = query.filter(Classroom.floor == str(floor_filter).strip())
|
||||
|
||||
if shift_filter:
|
||||
query = query.filter(Reservation.shift.ilike(f'%{shift_filter}%'))
|
||||
@@ -140,9 +140,11 @@ def view_reservation(id):
|
||||
def calendar_view():
|
||||
"""Show calendar view with classroom, subject, career, shift, floor and virtual filtering"""
|
||||
from app.models.career import Career
|
||||
from app.models.building import Building
|
||||
classrooms = Classroom.query.filter_by(is_active=True).order_by(Classroom.building.asc(), Classroom.code.asc()).all()
|
||||
subjects = Subject.query.filter_by(is_active=True).order_by(Subject.name.asc()).all()
|
||||
careers = Career.query.order_by(Career.name.asc()).all()
|
||||
buildings = Building.query.filter_by(is_active=True).order_by(Building.name.asc()).all()
|
||||
|
||||
floors = db.session.query(Classroom.floor).filter(Classroom.is_active==True, Classroom.floor.isnot(None)).distinct().order_by(Classroom.floor.asc()).all()
|
||||
available_floors = [f[0] for f in floors]
|
||||
@@ -154,6 +156,7 @@ def calendar_view():
|
||||
classrooms=classrooms,
|
||||
subjects=subjects,
|
||||
careers=careers,
|
||||
buildings=buildings,
|
||||
available_floors=available_floors
|
||||
)
|
||||
|
||||
@@ -400,23 +403,23 @@ def add_reservation():
|
||||
"""Add new reservation"""
|
||||
from app.models.classroom import Classroom
|
||||
from app.models.subject import Commission
|
||||
from app.models.building import Building
|
||||
|
||||
form = ReservationForm()
|
||||
|
||||
# Get active classrooms for the dropdown
|
||||
classrooms = Classroom.query.filter_by(is_active=True).all()
|
||||
|
||||
# Get active commissions for the dropdown
|
||||
# Get active buildings and classrooms
|
||||
buildings = Building.query.filter_by(is_active=True).order_by(Building.name.asc()).all()
|
||||
classrooms = Classroom.query.filter_by(is_active=True).order_by(Classroom.building_id.asc(), Classroom.floor.asc(), Classroom.code.asc()).all()
|
||||
commissions = Commission.query.filter_by(active=True).all()
|
||||
|
||||
# Populate form choices
|
||||
form.classroom_id.choices = [(c.id, f'{c.building} - {c.code} (Cap: {c.capacity_display})') for c in classrooms]
|
||||
form.classroom_id.choices = [(c.id, f'{c.building_name} - {c.code} (Cap: {c.capacity_display})') for c in classrooms]
|
||||
form.commission_id.choices = [(c.id, f'{c.get_full_code()} - {c.subject.name if c.subject else "No Subject"} (Students: {c.max_students})') for c in commissions]
|
||||
|
||||
if request.method == 'POST':
|
||||
if form.validate_on_submit():
|
||||
try:
|
||||
# Check for existing reservations at the same time
|
||||
# Check for existing reservations at the same time
|
||||
from app.models.reservation import ReservationStatus
|
||||
existing_reservation = Reservation.query.filter_by(
|
||||
classroom_id=form.classroom_id.data,
|
||||
@@ -428,7 +431,7 @@ def add_reservation():
|
||||
|
||||
if existing_reservation:
|
||||
flash('This classroom is already booked for the selected time slot.', 'danger')
|
||||
return render_template('schedule/add.html', form=form, title='New Reservation', classroom_list=classrooms, commission_list=commissions)
|
||||
return render_template('schedule/add.html', form=form, title='New Reservation', classroom_list=classrooms, commission_list=commissions, buildings=buildings)
|
||||
|
||||
# Create new reservation
|
||||
reservation = Reservation(
|
||||
@@ -451,10 +454,9 @@ def add_reservation():
|
||||
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
current_app.logger.error(f"Error creating reservation: {str(e)}")
|
||||
flash(f'Error creating reservation: {str(e)}', 'danger')
|
||||
|
||||
return render_template('schedule/add.html', form=form, title='New Reservation', classroom_list=classrooms, commission_list=commissions)
|
||||
return render_template('schedule/add.html', form=form, title='New Reservation', classroom_list=classrooms, commission_list=commissions, buildings=buildings)
|
||||
|
||||
@schedule_bp.route('/list')
|
||||
@login_required
|
||||
@@ -498,8 +500,8 @@ def list_reservations():
|
||||
~Classroom.building.ilike('%Virtual%')
|
||||
)
|
||||
|
||||
if floor_filter and floor_filter.isdigit():
|
||||
query = query.filter(Classroom.floor == int(floor_filter))
|
||||
if floor_filter:
|
||||
query = query.filter(Classroom.floor == str(floor_filter).strip())
|
||||
|
||||
if shift_filter:
|
||||
query = query.filter(Reservation.shift.ilike(f'%{shift_filter}%'))
|
||||
@@ -666,7 +668,6 @@ def calendar_data():
|
||||
search = request.args.get('search', '').strip()
|
||||
|
||||
if start and end:
|
||||
from datetime import datetime
|
||||
# Clean up ISO timezone strings for PostgreSQL naive timestamp comparison
|
||||
start_clean = start.replace('Z', '+00:00')
|
||||
end_clean = end.replace('Z', '+00:00')
|
||||
@@ -695,6 +696,16 @@ def calendar_data():
|
||||
if career_id and career_id.isdigit():
|
||||
query = query.filter(Subject.career_id == int(career_id))
|
||||
|
||||
building = request.args.get('building', '').strip()
|
||||
if building:
|
||||
from app.models.building import Building
|
||||
query = query.filter(
|
||||
or_(
|
||||
Classroom.building.ilike(f'%{building}%'),
|
||||
Classroom.building_entity.has(Building.name.ilike(f'%{building}%'))
|
||||
)
|
||||
)
|
||||
|
||||
if shift:
|
||||
query = query.filter(Reservation.shift.ilike(f'%{shift}%'))
|
||||
|
||||
@@ -704,8 +715,8 @@ def calendar_data():
|
||||
~Classroom.building.ilike('%Virtual%')
|
||||
)
|
||||
|
||||
if floor and floor.isdigit():
|
||||
query = query.filter(Classroom.floor == int(floor))
|
||||
if floor:
|
||||
query = query.filter(Classroom.floor == str(floor).strip())
|
||||
|
||||
if search:
|
||||
query = query.filter(
|
||||
@@ -725,8 +736,9 @@ def calendar_data():
|
||||
subject_code = subject.code if subject else (reservation.commission.code if reservation.commission else '')
|
||||
subject_name = subject.name if subject else (reservation.purpose or 'Clase')
|
||||
classroom_name = reservation.classroom.code if reservation.classroom else 'Sin Aula'
|
||||
classroom_floor = reservation.classroom.floor if reservation.classroom else None
|
||||
is_virtual = bool(reservation.classroom and ('VIRTUAL' in (reservation.classroom.code or '').upper() or 'VIRTUAL' in (reservation.classroom.building or '').upper()))
|
||||
classroom_floor = reservation.classroom.floor_display if reservation.classroom else None
|
||||
classroom_building = reservation.classroom.building_name if reservation.classroom else ''
|
||||
is_virtual = bool(reservation.classroom and reservation.classroom.is_virtual)
|
||||
career_name = subject.career_obj.name if (subject and subject.career_obj) else (subject.department if subject else '')
|
||||
status_val = str(reservation.status.value if hasattr(reservation.status, 'value') else reservation.status)
|
||||
|
||||
@@ -741,9 +753,10 @@ def calendar_data():
|
||||
'subject_code': subject_code,
|
||||
'subject_name': subject_name,
|
||||
'classroom': classroom_name,
|
||||
'building': reservation.classroom.building if reservation.classroom else '',
|
||||
'building': classroom_building,
|
||||
'floor': classroom_floor,
|
||||
'is_virtual': is_virtual,
|
||||
'location_display': reservation.classroom.location_display if reservation.classroom else '',
|
||||
'career': career_name,
|
||||
'commission': reservation.commission.code if reservation.commission else '',
|
||||
'shift': reservation.shift or '',
|
||||
|
||||
Reference in New Issue
Block a user