fix layout
This commit is contained in:
+14
-5
@@ -5,18 +5,27 @@ class Classroom(db.Model):
|
|||||||
__tablename__ = 'classrooms'
|
__tablename__ = 'classrooms'
|
||||||
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
# campus_id = db.Column(db.Integer, db.ForeignKey('campuses.id'), nullable=False)
|
campus_id = db.Column(db.Integer, nullable=True) # Maps to campus_id in DB
|
||||||
building = db.Column(db.String(100), nullable=False)
|
building = db.Column(db.String(100), nullable=False)
|
||||||
code = db.Column(db.String(50), nullable=False) # Changed from room_number
|
code = db.Column('room_number', db.String(50), nullable=False) # Maps to room_number column in DB
|
||||||
name = db.Column(db.String(100), nullable=False)
|
|
||||||
floor = db.Column(db.Integer, nullable=False)
|
floor = db.Column(db.Integer, nullable=False)
|
||||||
capacity = db.Column(db.Integer, nullable=False)
|
capacity = db.Column(db.Integer, nullable=False)
|
||||||
description = db.Column(db.Text)
|
description = db.Column(db.Text)
|
||||||
campus_location = db.Column(db.String(100))
|
is_active = db.Column('active', db.Boolean, default=True, nullable=False) # Maps to active column in DB
|
||||||
is_active = db.Column(db.Boolean, default=True, nullable=False)
|
|
||||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||||
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||||
|
|
||||||
|
# Virtual properties for compatibility
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
"""Generate name from building and code"""
|
||||||
|
return f"{self.building}-{self.code}"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def campus_location(self):
|
||||||
|
"""Placeholder for campus location - can be expanded when campus model is implemented"""
|
||||||
|
return None
|
||||||
|
|
||||||
# Virtual field for compatibility - combines building and code
|
# Virtual field for compatibility - combines building and code
|
||||||
@property
|
@property
|
||||||
def room_number(self):
|
def room_number(self):
|
||||||
|
|||||||
@@ -334,11 +334,11 @@ class ReservationOptimizer:
|
|||||||
'commission_id': gene.commission_id,
|
'commission_id': gene.commission_id,
|
||||||
'classroom_id': gene.classroom_id,
|
'classroom_id': gene.classroom_id,
|
||||||
'user_id': admin_user_id,
|
'user_id': admin_user_id,
|
||||||
'start_time': gene.start_time,
|
'start_time': gene.start_time.isoformat() if gene.start_time else None,
|
||||||
'end_time': gene.end_time,
|
'end_time': gene.end_time.isoformat() if gene.end_time else None,
|
||||||
'purpose': gene.purpose,
|
'purpose': gene.purpose,
|
||||||
'expected_attendees': gene.expected_attendees,
|
'expected_attendees': gene.expected_attendees,
|
||||||
'status': ReservationStatus.PENDING
|
'status': ReservationStatus.PENDING.value # Convert enum to string
|
||||||
}
|
}
|
||||||
optimized_reservations.append(reservation_data)
|
optimized_reservations.append(reservation_data)
|
||||||
|
|
||||||
|
|||||||
@@ -15,18 +15,27 @@ class Reservation(db.Model):
|
|||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
classroom_id = db.Column(db.Integer, db.ForeignKey('classrooms.id'), nullable=False)
|
classroom_id = db.Column(db.Integer, db.ForeignKey('classrooms.id'), nullable=False)
|
||||||
commission_id = db.Column(db.Integer, db.ForeignKey('commissions.id'), nullable=False)
|
commission_id = db.Column(db.Integer, db.ForeignKey('commissions.id'), nullable=False)
|
||||||
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
|
user_id = db.Column('teacher_id', db.Integer, db.ForeignKey('users.id'), nullable=False) # Maps to teacher_id in DB
|
||||||
|
|
||||||
start_time = db.Column(db.DateTime, nullable=False)
|
start_time = db.Column(db.DateTime, nullable=False)
|
||||||
end_time = db.Column(db.DateTime, nullable=False)
|
end_time = db.Column(db.DateTime, nullable=False)
|
||||||
purpose = db.Column(db.String(500), nullable=False)
|
purpose = db.Column(db.String(500), nullable=False)
|
||||||
status = db.Column(db.Enum(ReservationStatus), default=ReservationStatus.PENDING, nullable=False)
|
status = db.Column(db.String(20), default='PENDING', nullable=False) # DB uses VARCHAR not ENUM
|
||||||
expected_attendees = db.Column(db.Integer, nullable=False)
|
expected_attendees = db.Column(db.Integer, nullable=False)
|
||||||
notes = db.Column(db.Text)
|
notes = db.Column(db.Text)
|
||||||
|
|
||||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||||
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||||
|
|
||||||
|
# Virtual property to convert status string to enum
|
||||||
|
@property
|
||||||
|
def status_enum(self):
|
||||||
|
"""Get status as enum"""
|
||||||
|
try:
|
||||||
|
return ReservationStatus(self.status)
|
||||||
|
except (ValueError, AttributeError):
|
||||||
|
return ReservationStatus.PENDING
|
||||||
|
|
||||||
# Relationships
|
# Relationships
|
||||||
classroom = db.relationship('Classroom', backref=db.backref('reservation_list', lazy=True, cascade='all, delete-orphan'))
|
classroom = db.relationship('Classroom', backref=db.backref('reservation_list', lazy=True, cascade='all, delete-orphan'))
|
||||||
commission = db.relationship('Commission', backref=db.backref('reservation_list', lazy=True, cascade='all, delete-orphan'))
|
commission = db.relationship('Commission', backref=db.backref('reservation_list', lazy=True, cascade='all, delete-orphan'))
|
||||||
@@ -42,7 +51,7 @@ class Reservation(db.Model):
|
|||||||
'start_time': self.start_time.isoformat() if self.start_time else None,
|
'start_time': self.start_time.isoformat() if self.start_time else None,
|
||||||
'end_time': self.end_time.isoformat() if self.end_time else None,
|
'end_time': self.end_time.isoformat() if self.end_time else None,
|
||||||
'purpose': self.purpose,
|
'purpose': self.purpose,
|
||||||
'status': self.status.value if self.status else None,
|
'status': self.status, # Already a string in DB
|
||||||
'expected_attendees': self.expected_attendees,
|
'expected_attendees': self.expected_attendees,
|
||||||
'notes': self.notes,
|
'notes': self.notes,
|
||||||
'created_at': self.created_at.isoformat() if self.created_at else None,
|
'created_at': self.created_at.isoformat() if self.created_at else None,
|
||||||
@@ -54,7 +63,7 @@ class Reservation(db.Model):
|
|||||||
|
|
||||||
def is_confirmed(self):
|
def is_confirmed(self):
|
||||||
"""Check if reservation is confirmed"""
|
"""Check if reservation is confirmed"""
|
||||||
return self.status == ReservationStatus.CONFIRMED
|
return self.status == ReservationStatus.CONFIRMED.value
|
||||||
|
|
||||||
def can_be_cancelled(self):
|
def can_be_cancelled(self):
|
||||||
"""Check if reservation can be cancelled (24 hours before start)"""
|
"""Check if reservation can be cancelled (24 hours before start)"""
|
||||||
@@ -65,9 +74,9 @@ class Reservation(db.Model):
|
|||||||
"""Check if this reservation conflicts with another"""
|
"""Check if this reservation conflicts with another"""
|
||||||
if self.classroom_id != other_reservation.classroom_id:
|
if self.classroom_id != other_reservation.classroom_id:
|
||||||
return False
|
return False
|
||||||
if self.status != ReservationStatus.CONFIRMED:
|
if self.status != ReservationStatus.CONFIRMED.value:
|
||||||
return False
|
return False
|
||||||
if other_reservation.status != ReservationStatus.CONFIRMED:
|
if other_reservation.status != ReservationStatus.CONFIRMED.value:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Check time overlap
|
# Check time overlap
|
||||||
@@ -79,7 +88,7 @@ class Reservation(db.Model):
|
|||||||
"""Find conflicting reservations for a specific classroom and time slot"""
|
"""Find conflicting reservations for a specific classroom and time slot"""
|
||||||
query = Reservation.query.filter(
|
query = Reservation.query.filter(
|
||||||
Reservation.classroom_id == classroom_id,
|
Reservation.classroom_id == classroom_id,
|
||||||
Reservation.status == ReservationStatus.CONFIRMED,
|
Reservation.status == ReservationStatus.CONFIRMED.value,
|
||||||
Reservation.start_time < end_time,
|
Reservation.start_time < end_time,
|
||||||
Reservation.end_time > start_time
|
Reservation.end_time > start_time
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class Subject(db.Model):
|
|||||||
department = db.Column(db.String(100), nullable=False)
|
department = db.Column(db.String(100), nullable=False)
|
||||||
credits = db.Column(db.Integer, nullable=False)
|
credits = db.Column(db.Integer, nullable=False)
|
||||||
# duration_in_minutes = db.Column(db.Integer, nullable=False)
|
# duration_in_minutes = db.Column(db.Integer, nullable=False)
|
||||||
is_active = db.Column(db.Boolean, default=True, nullable=False)
|
is_active = db.Column('active', db.Boolean, default=True, nullable=False) # Maps to active column in DB
|
||||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||||
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ def add_classroom():
|
|||||||
# campus_id=form.campus_id.data,
|
# campus_id=form.campus_id.data,
|
||||||
building=form.building.data,
|
building=form.building.data,
|
||||||
code=form.room_number.data,
|
code=form.room_number.data,
|
||||||
name=f"{form.building.data}-{form.room_number.data}",
|
|
||||||
floor=form.floor.data,
|
floor=form.floor.data,
|
||||||
capacity=form.capacity.data,
|
capacity=form.capacity.data,
|
||||||
description=form.description.data,
|
description=form.description.data,
|
||||||
@@ -106,7 +105,7 @@ def view_classroom(id):
|
|||||||
upcoming_reservations = Reservation.query.filter(
|
upcoming_reservations = Reservation.query.filter(
|
||||||
Reservation.classroom_id == id,
|
Reservation.classroom_id == id,
|
||||||
Reservation.start_time > datetime.utcnow(),
|
Reservation.start_time > datetime.utcnow(),
|
||||||
Reservation.status == ReservationStatus.CONFIRMED
|
Reservation.status == ReservationStatus.CONFIRMED.value
|
||||||
).order_by(Reservation.start_time).limit(10).all()
|
).order_by(Reservation.start_time).limit(10).all()
|
||||||
|
|
||||||
return render_template('classrooms/view.html',
|
return render_template('classrooms/view.html',
|
||||||
@@ -146,7 +145,6 @@ def edit_classroom(id):
|
|||||||
# classroom.campus_id = form.campus_id.data
|
# classroom.campus_id = form.campus_id.data
|
||||||
classroom.building = form.building.data
|
classroom.building = form.building.data
|
||||||
classroom.code = form.room_number.data
|
classroom.code = form.room_number.data
|
||||||
classroom.name = f"{form.building.data}-{form.room_number.data}"
|
|
||||||
classroom.floor = form.floor.data
|
classroom.floor = form.floor.data
|
||||||
classroom.capacity = form.capacity.data
|
classroom.capacity = form.capacity.data
|
||||||
classroom.description = form.description.data
|
classroom.description = form.description.data
|
||||||
@@ -210,7 +208,7 @@ def get_available_classrooms():
|
|||||||
# Check if classroom has conflicting reservations
|
# Check if classroom has conflicting reservations
|
||||||
conflicts = Reservation.query.filter(
|
conflicts = Reservation.query.filter(
|
||||||
Reservation.classroom_id == classroom.id,
|
Reservation.classroom_id == classroom.id,
|
||||||
Reservation.status == ReservationStatus.CONFIRMED,
|
Reservation.status == ReservationStatus.CONFIRMED.value,
|
||||||
Reservation.start_time < end_dt,
|
Reservation.start_time < end_dt,
|
||||||
Reservation.end_time > start_dt
|
Reservation.end_time > start_dt
|
||||||
).all()
|
).all()
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ def get_algorithm_status():
|
|||||||
|
|
||||||
total_classrooms = Classroom.query.filter_by(is_active=True).count()
|
total_classrooms = Classroom.query.filter_by(is_active=True).count()
|
||||||
total_commissions = Commission.query.filter_by(active=True).count()
|
total_commissions = Commission.query.filter_by(active=True).count()
|
||||||
total_reservations = Reservation.query.filter_by(status=ReservationStatus.CONFIRMED).count()
|
total_reservations = Reservation.query.filter_by(status=ReservationStatus.CONFIRMED.value).count()
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'success': True,
|
'success': True,
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ def today_schedule():
|
|||||||
).filter(
|
).filter(
|
||||||
Reservation.start_time >= today_start,
|
Reservation.start_time >= today_start,
|
||||||
Reservation.start_time <= today_end,
|
Reservation.start_time <= today_end,
|
||||||
Reservation.status.in_([ReservationStatus.CONFIRMED, ReservationStatus.PENDING])
|
Reservation.status.in_([ReservationStatus.CONFIRMED.value, ReservationStatus.PENDING.value])
|
||||||
).order_by(Reservation.start_time).all()
|
).order_by(Reservation.start_time).all()
|
||||||
|
|
||||||
# Create time blocks for timeline view
|
# Create time blocks for timeline view
|
||||||
@@ -49,7 +49,7 @@ def today_schedule():
|
|||||||
|
|
||||||
# Calculate stats
|
# Calculate stats
|
||||||
total_reservations = len(reservations)
|
total_reservations = len(reservations)
|
||||||
confirmed = len([r for r in reservations if r.status == ReservationStatus.CONFIRMED])
|
confirmed = len([r for r in reservations if r.status == ReservationStatus.CONFIRMED.value])
|
||||||
pending = len([r for r in reservations if r.status == ReservationStatus.PENDING])
|
pending = len([r for r in reservations if r.status == ReservationStatus.PENDING])
|
||||||
|
|
||||||
# Get total classrooms and calculate occupied ones
|
# Get total classrooms and calculate occupied ones
|
||||||
@@ -158,7 +158,7 @@ def add_reservation():
|
|||||||
from app.models.reservation import ReservationStatus
|
from app.models.reservation import ReservationStatus
|
||||||
existing_reservation = Reservation.query.filter_by(
|
existing_reservation = Reservation.query.filter_by(
|
||||||
classroom_id=form.classroom_id.data,
|
classroom_id=form.classroom_id.data,
|
||||||
status=ReservationStatus.CONFIRMED
|
status=ReservationStatus.CONFIRMED.value
|
||||||
).filter(
|
).filter(
|
||||||
Reservation.start_time < form.end_time.data,
|
Reservation.start_time < form.end_time.data,
|
||||||
Reservation.end_time > form.start_time.data
|
Reservation.end_time > form.start_time.data
|
||||||
@@ -177,7 +177,7 @@ def add_reservation():
|
|||||||
end_time=form.end_time.data,
|
end_time=form.end_time.data,
|
||||||
purpose=form.purpose.data,
|
purpose=form.purpose.data,
|
||||||
notes=form.notes.data,
|
notes=form.notes.data,
|
||||||
status=ReservationStatus.PENDING,
|
status=ReservationStatus.PENDING.value,
|
||||||
expected_attendees=form.expected_attendees.data
|
expected_attendees=form.expected_attendees.data
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -209,11 +209,11 @@ def confirm_reservation(id):
|
|||||||
reservation = Reservation.query.get_or_404(id)
|
reservation = Reservation.query.get_or_404(id)
|
||||||
|
|
||||||
# Validación de seguridad: Solo confirmar si está pendiente
|
# Validación de seguridad: Solo confirmar si está pendiente
|
||||||
if reservation.status != ReservationStatus.PENDING:
|
if reservation.status != ReservationStatus.PENDING.value:
|
||||||
flash('Only pending reservations can be confirmed.', 'warning')
|
flash('Only pending reservations can be confirmed.', 'warning')
|
||||||
return redirect(url_for('schedule.today_schedule'))
|
return redirect(url_for('schedule.today_schedule'))
|
||||||
|
|
||||||
reservation.status = ReservationStatus.CONFIRMED
|
reservation.status = ReservationStatus.CONFIRMED.value
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
flash(
|
flash(
|
||||||
@@ -343,7 +343,7 @@ def calendar_data():
|
|||||||
).filter(
|
).filter(
|
||||||
Reservation.start_time >= start_date,
|
Reservation.start_time >= start_date,
|
||||||
Reservation.start_time <= end_date,
|
Reservation.start_time <= end_date,
|
||||||
Reservation.status.in_([ReservationStatus.CONFIRMED, ReservationStatus.PENDING])
|
Reservation.status.in_([ReservationStatus.CONFIRMED.value, ReservationStatus.PENDING.value])
|
||||||
).order_by(Reservation.start_time).all()
|
).order_by(Reservation.start_time).all()
|
||||||
|
|
||||||
events = []
|
events = []
|
||||||
@@ -384,7 +384,7 @@ def api_today_events():
|
|||||||
).filter(
|
).filter(
|
||||||
Reservation.start_time >= today_start,
|
Reservation.start_time >= today_start,
|
||||||
Reservation.start_time <= today_end,
|
Reservation.start_time <= today_end,
|
||||||
Reservation.status == ReservationStatus.CONFIRMED
|
Reservation.status == ReservationStatus.CONFIRMED.value
|
||||||
).order_by(Reservation.start_time).all()
|
).order_by(Reservation.start_time).all()
|
||||||
|
|
||||||
events = []
|
events = []
|
||||||
|
|||||||
Reference in New Issue
Block a user