import threading from datetime import datetime, timedelta from sqlalchemy import DateTime, cast, func from flask import current_app from bot.reminders import add_reservation_reminder, remove_reservation_reminder, update_reservation_reminder from app import db from app.models import Reservation from .lock import Lock from .free_workplaces import FreeWorkplacesController from ..exceptions import ReservationExpiredError, NoFreeWorkplaceError, UserNotConfirmedError, UserBlockedError class ReservationController(): workplaces_lock = Lock.workplaces_lock @classmethod def create(cls, user): with cls.workplaces_lock: FreeWorkplacesController.check_free_workplaces() if not user.is_confirmed: raise UserNotConfirmedError if user.is_blocked: raise UserBlockedError reservation = Reservation() reservation.user = user reservation.time_start = datetime.now() reservation.time_end = datetime.now() + current_app.config.get('RESERVATION_DURATION', timedelta(hours=1)) db.session.add(reservation) db.session.commit() add_reservation_reminder(reservation) return reservation @classmethod def extend(cls, reservation): with cls.workplaces_lock: user = reservation.user if not user.is_confirmed: raise UserNotConfirmedError if user.is_blocked: raise UserBlockedError reservation.time_end = datetime.now() + current_app.config.get('RESERVATION_DURATION', timedelta(hours=1)) db.session.commit() update_reservation_reminder(reservation) @staticmethod def get(reservation_id): return Reservation.query.get(reservation_id) @classmethod def has_active_reservation(cls, user): return cls.get_active_reservation(user) is not None @staticmethod def get_active_reservation(user): now = datetime.now() return Reservation.query \ .filter(cast(Reservation.time_start,DateTime) <= now) \ .filter(cast(Reservation.time_end,DateTime) > now) \ .filter(Reservation.user_id == user._id) \ .first() @staticmethod def get_all_active_reservations(): now = datetime.now() return Reservation.query \ .filter(cast(Reservation.time_start,DateTime) <= now) \ .filter(cast(Reservation.time_end,DateTime) > now) \ .all() @classmethod def cancel(cls, reservation): with cls.workplaces_lock: reservation.time_end = datetime.now() db.session.commit() remove_reservation_reminder(reservation)