add license
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify
|
||||
from flask_login import login_required
|
||||
from app import db
|
||||
from app.models.classroom import Classroom, ClassroomResource
|
||||
from app.models.reservation import Reservation, ReservationStatus
|
||||
from app.forms.classroom import ClassroomForm, ClassroomResourceForm
|
||||
from datetime import datetime
|
||||
|
||||
classrooms_bp = Blueprint('classrooms', __name__, url_prefix='/classrooms')
|
||||
|
||||
@classrooms_bp.route('/')
|
||||
@login_required
|
||||
def list_classrooms():
|
||||
"""List all classrooms"""
|
||||
page = request.args.get('page', 1, type=int)
|
||||
search = request.args.get('search', '')
|
||||
campus = request.args.get('campus', '')
|
||||
|
||||
query = Classroom.query.filter_by(is_active=True)
|
||||
|
||||
if search:
|
||||
query = query.filter(
|
||||
Classroom.code.contains(search) |
|
||||
Classroom.name.contains(search) |
|
||||
Classroom.building.contains(search)
|
||||
)
|
||||
|
||||
if campus:
|
||||
query = query.filter(Classroom.campus_location == campus)
|
||||
|
||||
classrooms = query.paginate(
|
||||
page=page,
|
||||
per_page=20,
|
||||
error_out=False
|
||||
)
|
||||
|
||||
return render_template('classrooms/list.html',
|
||||
classrooms=classrooms,
|
||||
search=search,
|
||||
campus=campus)
|
||||
|
||||
@classrooms_bp.route('/add', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def add_classroom():
|
||||
"""Add new classroom"""
|
||||
form = ClassroomForm()
|
||||
|
||||
if form.validate_on_submit():
|
||||
classroom = Classroom(
|
||||
code=form.code.data,
|
||||
name=form.name.data,
|
||||
building=form.building.data,
|
||||
floor=form.floor.data,
|
||||
capacity=form.capacity.data,
|
||||
description=form.description.data,
|
||||
campus_location=form.campus_location.data
|
||||
)
|
||||
|
||||
try:
|
||||
db.session.add(classroom)
|
||||
db.session.commit()
|
||||
flash(f'Classroom {classroom.code} added successfully!', 'success')
|
||||
return redirect(url_for('classrooms.list_classrooms'))
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
flash('Error adding classroom. Classroom code might already exist.', 'error')
|
||||
|
||||
return render_template('classrooms/add.html', form=form)
|
||||
|
||||
@classrooms_bp.route('/edit/<int:Id>', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def edit_classroom(Id):
|
||||
"""Edit classroom"""
|
||||
classroom = Classroom.query.get_or_404(Id)
|
||||
|
||||
if not classroom.is_active:
|
||||
flash('This classroom has been deactivated.', 'warning')
|
||||
return redirect(url_for('classrooms.list_classrooms'))
|
||||
|
||||
form = ClassroomForm(obj=classroom)
|
||||
|
||||
if form.validate_on_submit():
|
||||
try:
|
||||
classroom.code = form.code.data
|
||||
classroom.name = form.name.data
|
||||
classroom.building = form.building.data
|
||||
classroom.floor = form.floor.data
|
||||
classroom.capacity = form.capacity.data
|
||||
classroom.description = form.description.data
|
||||
classroom.campus_location = form.campus_location.data
|
||||
classroom.updated_at = datetime.utcnow()
|
||||
|
||||
db.session.commit()
|
||||
flash(f'Classroom {classroom.code} updated successfully!', 'success')
|
||||
return redirect(url_for('classrooms.view_classroom', Id=classroom.id))
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
flash('Error updating classroom.', 'error')
|
||||
|
||||
return render_template('classrooms/edit.html', form=form, classroom=classroom)
|
||||
|
||||
@classrooms_bp.route('/view/<int:Id>')
|
||||
@login_required
|
||||
def view_classroom(Id):
|
||||
"""View classroom details"""
|
||||
classroom = Classroom.query.get_or_404(Id)
|
||||
|
||||
if not classroom.is_active:
|
||||
flash('This classroom has been deactivated.', 'warning')
|
||||
return redirect(url_for('classrooms.list_classrooms'))
|
||||
|
||||
# Get classroom resources
|
||||
resources = ClassroomResource.query.filter_by(classroom_id=Id).all()
|
||||
|
||||
# Get upcoming reservations
|
||||
upcoming_reservations = Reservation.query.filter(
|
||||
Reservation.classroom_id == Id,
|
||||
Reservation.start_time >= datetime.utcnow(),
|
||||
Reservation.status.in_([ReservationStatus.CONFIRMED, ReservationStatus.PENDING])
|
||||
).order_by(Reservation.start_time).limit(10).all()
|
||||
|
||||
return render_template('classrooms/view.html',
|
||||
classroom=classroom,
|
||||
resources=resources,
|
||||
upcoming_reservations=upcoming_reservations)
|
||||
|
||||
@classrooms_bp.route('/delete/<int:Id>')
|
||||
@login_required
|
||||
def delete_classroom(Id):
|
||||
"""Delete/deactivate classroom"""
|
||||
classroom = Classroom.query.get_or_404(Id)
|
||||
|
||||
# Check for active reservations
|
||||
active_reservations = Reservation.query.filter(
|
||||
Reservation.classroom_id == Id,
|
||||
Reservation.status.in_([ReservationStatus.CONFIRMED, ReservationStatus.PENDING])
|
||||
).count()
|
||||
|
||||
if active_reservations > 0:
|
||||
flash('Cannot delete classroom with active reservations.', 'error')
|
||||
return redirect(url_for('classrooms.view_classroom', Id=Id))
|
||||
|
||||
try:
|
||||
classroom.is_active = False
|
||||
classroom.updated_at = datetime.utcnow()
|
||||
db.session.commit()
|
||||
flash(f'Classroom {classroom.code} has been deactivated.', 'success')
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
flash('Error deactivating classroom.', 'error')
|
||||
|
||||
return redirect(url_for('classrooms.list_classrooms'))
|
||||
|
||||
@classrooms_bp.route('/<int:classroom_id>/add_resource', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def add_resource(classroom_id):
|
||||
"""Add resource to classroom"""
|
||||
classroom = Classroom.query.get_or_404(classroom_id)
|
||||
form = ClassroomResourceForm()
|
||||
|
||||
if form.validate_on_submit():
|
||||
resource = ClassroomResource(
|
||||
classroom_id=classroom_id,
|
||||
resource_type=form.resource_type.data,
|
||||
brand=form.brand.data,
|
||||
model=form.model.data,
|
||||
specifications=form.specifications.data,
|
||||
quantity=form.quantity.data
|
||||
)
|
||||
|
||||
try:
|
||||
db.session.add(resource)
|
||||
db.session.commit()
|
||||
flash(f'{resource.resource_type} added to {classroom.code} successfully!', 'success')
|
||||
return redirect(url_for('classrooms.view_classroom', Id=classroom_id))
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
flash('Error adding resource.', 'error')
|
||||
|
||||
return render_template('classrooms/add_resource.html', form=form, classroom=classroom)
|
||||
|
||||
@classrooms_bp.route('/api/available')
|
||||
@login_required
|
||||
def api_available_classrooms():
|
||||
"""API endpoint to get available classrooms"""
|
||||
start_time = request.args.get('start_time')
|
||||
end_time = request.args.get('end_time')
|
||||
min_capacity = request.args.get('min_capacity', 0, type=int)
|
||||
|
||||
if not start_time or not end_time:
|
||||
return jsonify({'error': 'start_time and end_time are required'}), 400
|
||||
|
||||
try:
|
||||
start_dt = datetime.fromisoformat(start_time)
|
||||
end_dt = datetime.fromisoformat(end_time)
|
||||
except ValueError:
|
||||
return jsonify({'error': 'Invalid datetime format'}), 400
|
||||
|
||||
# Find available classrooms (without conflicts)
|
||||
conflicting_classroom_ids = [
|
||||
r.classroom_id for r in Reservation.query.filter(
|
||||
Reservation.start_time < end_dt,
|
||||
Reservation.end_time > start_dt,
|
||||
Reservation.status == ReservationStatus.CONFIRMED
|
||||
).all()
|
||||
]
|
||||
|
||||
available_classrooms = Classroom.query.filter(
|
||||
Classroom.is_active == True,
|
||||
Classroom.capacity >= min_capacity,
|
||||
~Classroom.id.in_(conflicting_classroom_ids)
|
||||
).all()
|
||||
|
||||
return jsonify([classroom.to_dict() for classroom in available_classrooms])
|
||||
Reference in New Issue
Block a user