Files
admin-edu-space/app/models/classroom.py
T
2026-03-30 17:11:13 -03:00

157 lines
6.3 KiB
Python

from app import db
from datetime import datetime
class Classroom(db.Model):
__tablename__ = 'classrooms'
id = db.Column(db.Integer, primary_key=True)
# campus_id = db.Column(db.Integer, db.ForeignKey('campuses.id'), nullable=False)
building = db.Column(db.String(100), nullable=False)
code = db.Column(db.String(50), nullable=False) # Changed from room_number
name = db.Column(db.String(100), nullable=False)
floor = db.Column(db.Integer, nullable=False)
capacity = db.Column(db.Integer, nullable=False)
description = db.Column(db.Text)
campus_location = db.Column(db.String(100))
is_active = db.Column(db.Boolean, default=True, nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Virtual field for compatibility - combines building and code
@property
def room_number(self):
return self.code
@room_number.setter
def room_number(self, value):
self.code = value
# Override code property for consistency
@property
def code_display(self):
return f"{self.building}-{self.code}"
def to_dict(self):
"""Convert classroom to dictionary"""
return {
'id': self.id,
'code': self.code_display,
'building': self.building,
'name': self.name,
'floor': self.floor,
'capacity': self.capacity,
'description': self.description,
'campus_location': self.campus_location,
'is_active': self.is_active,
'created_at': self.created_at.isoformat() if self.created_at else None,
'updated_at': self.updated_at.isoformat() if self.updated_at else None,
'resources': [resource.to_dict() for resource in self.resources] if hasattr(self, 'resources') else []
}
def get_full_location(self):
"""Get full classroom location"""
location = f"{self.building} - Floor {self.floor}"
if self.campus_location:
location += f" ({self.campus_location})"
return location
@staticmethod
def find_best_classroom(max_students, start_time, end_time, exclude_reservation_id=None):
"""Find the best suitable classroom for a commission based on capacity and availability"""
from app.models.reservation import Reservation, ReservationStatus
# Get all active classrooms with sufficient capacity
suitable_classrooms = Classroom.query.filter(
Classroom.is_active == True,
Classroom.capacity >= max_students
).order_by(Classroom.capacity.asc()).all() # Start with smallest suitable
# Check availability for each classroom
available_classrooms = []
for classroom in suitable_classrooms:
# Check for conflicts
conflicts = Reservation.find_conflicts(
classroom.id, start_time, end_time, exclude_reservation_id
)
if not conflicts:
# Calculate efficiency score (how well the capacity matches)
efficiency = classroom.capacity / max_students if max_students > 0 else float('inf')
available_classrooms.append({
'classroom': classroom,
'efficiency': efficiency,
'wasted_capacity': classroom.capacity - max_students
})
# Sort by efficiency (closest capacity match first)
available_classrooms.sort(key=lambda x: x['efficiency'])
return available_classrooms
@staticmethod
def get_availability_status(start_time, end_time, exclude_reservation_id=None):
"""Get all classrooms classified as available or occupied for a time slot"""
from app.models.reservation import Reservation, ReservationStatus
all_classrooms = Classroom.query.filter_by(is_active=True).all()
available = []
occupied = []
for classroom in all_classrooms:
conflicts = Reservation.find_conflicts(
classroom.id, start_time, end_time, exclude_reservation_id
)
classroom_info = {
'classroom': classroom,
'conflicts': conflicts
}
if conflicts:
occupied.append(classroom_info)
else:
available.append(classroom_info)
return {
'available': available,
'occupied': occupied,
'total_available': len(available),
'total_occupied': len(occupied)
}
def __repr__(self):
return f'<Classroom {self.code_display}>'
class ClassroomResource(db.Model):
__tablename__ = 'classroom_resources'
id = db.Column(db.Integer, primary_key=True)
classroom_id = db.Column(db.Integer, db.ForeignKey('classrooms.id'), nullable=False)
resource_type = db.Column(db.String(50), nullable=False) # PROJECTOR, WHITEBOARD, COMPUTER, etc.
brand = db.Column(db.String(100))
model = db.Column(db.String(100))
specifications = db.Column(db.Text)
functional = db.Column(db.Boolean, default=True)
last_maintenance_date = db.Column(db.DateTime)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Relationships
classroom = db.relationship('Classroom', backref=db.backref('resources', lazy=True, cascade='all, delete-orphan'))
def to_dict(self):
"""Convert resource to dictionary"""
return {
'id': self.id,
'classroom_id': self.classroom_id,
'resource_type': self.resource_type,
'brand': self.brand,
'model': self.model,
'specifications': self.specifications,
'functional': self.functional,
'last_maintenance_date': self.last_maintenance_date.isoformat() if self.last_maintenance_date else None,
'created_at': self.created_at.isoformat() if self.created_at else None
}
def __repr__(self):
return f'<Resource {self.resource_type} for Classroom {self.classroom_id}>'