2022-10-26 15:11:50 +02:00
|
|
|
import datetime
|
|
|
|
|
|
|
|
from apiflask import APIBlueprint
|
2022-11-17 18:39:45 +01:00
|
|
|
from flask import abort, current_app
|
2022-11-16 20:42:40 +01:00
|
|
|
from sqlalchemy import or_, and_
|
2022-11-19 20:43:05 +01:00
|
|
|
from flask_sqlalchemy import get_debug_queries
|
2022-10-26 15:11:50 +02:00
|
|
|
|
2022-11-16 20:42:40 +01:00
|
|
|
from ..schemas import MessageSchema, TermOfDefenceSchema, TermOfDefenceListSchema, \
|
2022-11-19 20:43:05 +01:00
|
|
|
TemporaryAvailabilityListSchema, AssignedGroupToTermOfDefenceListSchema, GroupIdSchema
|
2022-11-23 23:45:51 +01:00
|
|
|
from ...examination_schedule.models import TermOfDefence, TemporaryAvailability, committee
|
2022-11-16 20:42:40 +01:00
|
|
|
from ...students.models import YearGroup
|
|
|
|
from ...project_supervisor.models import ProjectSupervisor
|
2022-10-26 15:11:50 +02:00
|
|
|
from ...dependencies import db
|
2022-11-17 18:39:45 +01:00
|
|
|
from ..utils import generate_range_dates
|
2022-11-19 20:43:05 +01:00
|
|
|
from ..query.enrollments import get_term_of_defence_by_id_and_examination_schedule_id, set_new_group_to_term_of_defence, \
|
|
|
|
get_examination_schedule_by_id
|
2022-10-26 15:11:50 +02:00
|
|
|
|
|
|
|
bp = APIBlueprint("enrollments", __name__, url_prefix="/enrollments")
|
|
|
|
|
|
|
|
|
2022-11-16 20:42:40 +01:00
|
|
|
@bp.post('/<int:examination_schedule_id>/generate')
|
2022-11-17 18:39:45 +01:00
|
|
|
@bp.output(MessageSchema)
|
2022-11-16 20:42:40 +01:00
|
|
|
def generate_term_of_defence_for_this_examination_schedule(examination_schedule_id: int) -> dict:
|
2022-11-19 20:43:05 +01:00
|
|
|
ex = get_examination_schedule_by_id(examination_schedule_id)
|
2022-11-17 18:39:45 +01:00
|
|
|
limit = current_app.config.get('LIMIT_MEMBERS_PER_COMMITTEE', 3)
|
|
|
|
|
2022-11-23 23:45:51 +01:00
|
|
|
term_of_defences = TermOfDefence.query. \
|
|
|
|
filter(TermOfDefence.examination_schedule_id == examination_schedule_id).first()
|
|
|
|
if term_of_defences is not None:
|
|
|
|
abort(400,
|
|
|
|
"First you have to delete all term of defences for this examination schedule to generate them again!")
|
|
|
|
|
|
|
|
temporary_availabilities = TemporaryAvailability.query. \
|
|
|
|
filter(TemporaryAvailability.examination_schedule_id == examination_schedule_id). \
|
|
|
|
join(TemporaryAvailability.project_supervisor). \
|
|
|
|
all()
|
|
|
|
if len(temporary_availabilities) == 0:
|
|
|
|
abort(404, "Not found temporary availabilities for project supervisors")
|
|
|
|
|
|
|
|
dates = generate_range_dates(ex.start_date, ex.end_date, ex.duration_time)
|
2022-11-24 23:01:35 +01:00
|
|
|
|
|
|
|
term_of_defences = []
|
2022-11-17 18:39:45 +01:00
|
|
|
for d in dates:
|
|
|
|
e = d + datetime.timedelta(minutes=ex.duration_time)
|
2022-11-23 23:45:51 +01:00
|
|
|
t = list(filter(lambda ta: ta.start_date <= d and ta.end_date >= e, temporary_availabilities))
|
|
|
|
if len(t) >= limit:
|
|
|
|
projects_supervisors = [t[i].project_supervisor for i in range(limit)]
|
|
|
|
term_of_defence = TermOfDefence(start_date=d, end_date=e, examination_schedule_id=examination_schedule_id)
|
|
|
|
term_of_defence.members_of_committee = projects_supervisors
|
2022-11-24 23:01:35 +01:00
|
|
|
term_of_defences.append(term_of_defence)
|
|
|
|
db.session.add_all(term_of_defences)
|
|
|
|
db.session.commit()
|
2022-11-17 18:39:45 +01:00
|
|
|
return {"message": "Term of defences was generated!"}
|
2022-11-16 20:42:40 +01:00
|
|
|
|
|
|
|
|
2022-11-23 23:45:51 +01:00
|
|
|
@bp.post('/<int:examination_schedule_id>/clear-term-of-defences/')
|
|
|
|
@bp.output(MessageSchema)
|
|
|
|
def clear_generated_term_of_defences(examination_schedule_id: int) -> dict:
|
|
|
|
get_examination_schedule_by_id(examination_schedule_id)
|
|
|
|
|
|
|
|
# count_defences = db.func.count(ProjectSupervisor.id)
|
|
|
|
# td = db.session.query(TermOfDefence, count_defences). \
|
|
|
|
# join(ProjectSupervisor, isouter=True). \
|
|
|
|
# filter(TermOfDefence.examination_schedule_id == examination_schedule_id). \
|
|
|
|
# group_by(TermOfDefence.id).having(count_defences > 0).first()
|
|
|
|
# print(td)
|
|
|
|
# if td is not None:
|
|
|
|
# abort(400, "First you remove group assigned to term of defence to clear term of defences!")
|
|
|
|
|
|
|
|
td = TermOfDefence.query. \
|
|
|
|
filter(TermOfDefence.examination_schedule_id == examination_schedule_id).all()
|
|
|
|
while True:
|
|
|
|
for t in td[0:10]:
|
|
|
|
db.session.delete(t)
|
|
|
|
db.session.commit()
|
|
|
|
if len(td) == 0:
|
|
|
|
break
|
|
|
|
td[0:10] = []
|
2022-11-24 23:01:35 +01:00
|
|
|
# print(len(get_debug_queries()))
|
2022-11-23 23:45:51 +01:00
|
|
|
return {"message": "Term of defences was deleted!"}
|
|
|
|
|
|
|
|
|
2022-11-16 20:42:40 +01:00
|
|
|
@bp.post('/<int:examination_schedule_id>/add')
|
|
|
|
@bp.input(TermOfDefenceSchema)
|
2022-10-26 15:11:50 +02:00
|
|
|
@bp.output(MessageSchema)
|
2022-11-16 20:42:40 +01:00
|
|
|
def create_term_of_defence(examination_schedule_id: int, data: dict) -> dict:
|
|
|
|
if not data:
|
|
|
|
abort(400, "You have passed empty data!")
|
|
|
|
|
2022-11-19 20:43:05 +01:00
|
|
|
ex = get_examination_schedule_by_id(examination_schedule_id)
|
2022-10-26 15:11:50 +02:00
|
|
|
|
2022-11-16 20:42:40 +01:00
|
|
|
yg_id = ex.year_group_id
|
|
|
|
project_supervisors_ids = data.pop('project_supervisors')
|
|
|
|
project_supervisors = ProjectSupervisor.query.filter(
|
|
|
|
or_(*[ProjectSupervisor.id == i for i in project_supervisors_ids])).filter(YearGroup.id == yg_id).all()
|
|
|
|
|
|
|
|
if len(project_supervisors) != len(project_supervisors_ids):
|
|
|
|
abort(404, "Project Supervisors didn't exist!")
|
2022-10-26 15:11:50 +02:00
|
|
|
|
|
|
|
start_date = data['start_date']
|
|
|
|
end_date = data['end_date']
|
2022-11-16 20:42:40 +01:00
|
|
|
|
2022-11-17 10:21:36 +01:00
|
|
|
if not (ex.start_date.timestamp() <= start_date.timestamp() and ex.end_date.timestamp() >= end_date.timestamp()):
|
2022-11-16 20:42:40 +01:00
|
|
|
abort(400, "Invalid date range!")
|
|
|
|
|
|
|
|
if end_date <= start_date:
|
|
|
|
abort(400, "End date must be greater than start date!")
|
|
|
|
|
|
|
|
delta_time = end_date - start_date
|
|
|
|
delta_time_in_minutes = delta_time.total_seconds() / 60
|
|
|
|
if delta_time_in_minutes != ex.duration_time:
|
|
|
|
abort(400, "Invalid duration time!")
|
|
|
|
|
|
|
|
td = TermOfDefence.query.filter(TermOfDefence.examination_schedule_id == examination_schedule_id). \
|
|
|
|
filter(
|
|
|
|
or_(and_(TermOfDefence.start_date >= start_date,
|
|
|
|
TermOfDefence.start_date < end_date,
|
|
|
|
TermOfDefence.end_date >= end_date),
|
|
|
|
and_(TermOfDefence.start_date <= start_date,
|
|
|
|
TermOfDefence.end_date > start_date,
|
|
|
|
TermOfDefence.end_date <= end_date))).first()
|
|
|
|
|
|
|
|
if td is not None:
|
|
|
|
abort(400, "This term of defence is taken! You choose other date!")
|
|
|
|
|
|
|
|
td = TermOfDefence(**data, examination_schedule_id=examination_schedule_id)
|
|
|
|
db.session.add(td)
|
|
|
|
db.session.commit()
|
|
|
|
for p in project_supervisors:
|
|
|
|
td.members_of_committee.append(p)
|
2022-10-26 15:11:50 +02:00
|
|
|
db.session.commit()
|
2022-11-16 20:42:40 +01:00
|
|
|
return {"message": "Term of defence was created!"}
|
|
|
|
|
|
|
|
|
|
|
|
@bp.put('/<int:examination_schedule_id>/update/<int:term_of_defence_id>/')
|
|
|
|
@bp.input(TermOfDefenceSchema)
|
|
|
|
@bp.output(MessageSchema)
|
|
|
|
def update_term_of_defence(examination_schedule_id: int, term_of_defence_id: int, data: dict) -> dict:
|
|
|
|
if not data:
|
|
|
|
abort(400, "You have passed empty data!")
|
2022-10-26 15:11:50 +02:00
|
|
|
|
2022-11-16 20:42:40 +01:00
|
|
|
td_query = TermOfDefence.query.filter(TermOfDefence.id == term_of_defence_id,
|
|
|
|
TermOfDefence.examination_schedule_id == examination_schedule_id)
|
|
|
|
td = td_query.first()
|
|
|
|
if td is None:
|
|
|
|
abort(404, "Not found term of defence!")
|
|
|
|
|
|
|
|
ex = td.examination_schedule
|
|
|
|
yg_id = ex.year_group_id
|
|
|
|
project_supervisors_ids = data.pop('project_supervisors')
|
|
|
|
project_supervisors = ProjectSupervisor.query.filter(
|
|
|
|
or_(*[ProjectSupervisor.id == i for i in project_supervisors_ids])).filter(YearGroup.id == yg_id).all()
|
|
|
|
|
|
|
|
if len(project_supervisors) != len(project_supervisors_ids):
|
|
|
|
abort(404, "Project Supervisors didn't exist!")
|
|
|
|
|
|
|
|
start_date = data['start_date']
|
|
|
|
end_date = data['end_date']
|
2022-11-17 10:21:36 +01:00
|
|
|
if not (ex.start_date.timestamp() <= start_date.timestamp() and ex.end_date.timestamp() >= end_date.timestamp()):
|
2022-11-16 20:42:40 +01:00
|
|
|
abort(400, "Invalid date range!")
|
|
|
|
|
|
|
|
if end_date <= start_date:
|
|
|
|
abort(400, "End date must be greater than start date!")
|
|
|
|
|
|
|
|
delta_time = end_date - start_date
|
|
|
|
delta_time_in_minutes = delta_time.total_seconds() / 60
|
|
|
|
if delta_time_in_minutes != ex.duration_time:
|
|
|
|
abort(400, "Invalid duration time!")
|
|
|
|
|
|
|
|
term_of_defence = TermOfDefence.query.filter(TermOfDefence.id != term_of_defence_id,
|
2022-11-17 10:21:36 +01:00
|
|
|
TermOfDefence.examination_schedule_id == examination_schedule_id). \
|
2022-11-16 20:42:40 +01:00
|
|
|
filter(
|
|
|
|
or_(and_(TermOfDefence.start_date >= start_date,
|
|
|
|
TermOfDefence.start_date < end_date,
|
|
|
|
TermOfDefence.end_date >= end_date),
|
|
|
|
and_(TermOfDefence.start_date <= start_date,
|
|
|
|
TermOfDefence.end_date > start_date,
|
|
|
|
TermOfDefence.end_date <= end_date))).first()
|
|
|
|
|
|
|
|
if term_of_defence is not None:
|
|
|
|
abort(400, "This term of defence is taken! You choose other date!")
|
|
|
|
|
|
|
|
td_query.update(data)
|
|
|
|
td.members_of_committee = []
|
2022-10-26 15:11:50 +02:00
|
|
|
db.session.commit()
|
2022-11-16 20:42:40 +01:00
|
|
|
for p in project_supervisors:
|
|
|
|
td.members_of_committee.append(p)
|
|
|
|
db.session.commit()
|
|
|
|
|
|
|
|
return {"message": "Term of defence was updated!"}
|
2022-10-26 15:11:50 +02:00
|
|
|
|
|
|
|
|
2022-11-16 20:42:40 +01:00
|
|
|
@bp.delete('/<int:examination_schedule_id>/delete/<int:term_of_defence_id>/')
|
2022-10-26 15:11:50 +02:00
|
|
|
@bp.output(MessageSchema)
|
2022-11-16 20:42:40 +01:00
|
|
|
def delete_term_of_defence(examination_schedule_id: int, term_of_defence_id: int) -> dict:
|
2022-11-19 20:43:05 +01:00
|
|
|
td = get_term_of_defence_by_id_and_examination_schedule_id(examination_schedule_id, term_of_defence_id)
|
2022-11-16 20:42:40 +01:00
|
|
|
db.session.delete(td)
|
2022-10-26 15:11:50 +02:00
|
|
|
db.session.commit()
|
2022-11-16 20:42:40 +01:00
|
|
|
return {"message": "Term of defence was deleted!"}
|
|
|
|
|
|
|
|
|
|
|
|
@bp.get('/<int:examination_schedule_id>/term-of-defences/')
|
|
|
|
@bp.output(TermOfDefenceListSchema)
|
|
|
|
def list_of_term_of_defences(examination_schedule_id: int) -> dict:
|
2022-11-19 20:43:05 +01:00
|
|
|
get_examination_schedule_by_id(examination_schedule_id)
|
2022-11-16 20:42:40 +01:00
|
|
|
|
|
|
|
td = TermOfDefence.query. \
|
|
|
|
filter(TermOfDefence.examination_schedule_id == examination_schedule_id). \
|
|
|
|
join(TermOfDefence.members_of_committee, isouter=True). \
|
|
|
|
all()
|
|
|
|
return {"term_of_defences": td}
|
|
|
|
|
|
|
|
|
|
|
|
@bp.get('/<int:examination_schedule_id>/temporary-availabilities/')
|
|
|
|
@bp.output(TemporaryAvailabilityListSchema)
|
|
|
|
def list_of_temporary_availability(examination_schedule_id: int) -> dict:
|
2022-11-19 20:43:05 +01:00
|
|
|
get_examination_schedule_by_id(examination_schedule_id)
|
2022-11-16 20:42:40 +01:00
|
|
|
|
|
|
|
td = TemporaryAvailability.query. \
|
|
|
|
filter(TemporaryAvailability.examination_schedule_id == examination_schedule_id). \
|
|
|
|
join(TemporaryAvailability.project_supervisor). \
|
|
|
|
all()
|
|
|
|
return {"temporary_availabilities": td}
|
2022-11-19 20:43:05 +01:00
|
|
|
|
|
|
|
|
|
|
|
@bp.get('/<int:examination_schedule_id>/assigned-group-to-term-of-defences/')
|
|
|
|
@bp.output(AssignedGroupToTermOfDefenceListSchema)
|
|
|
|
def list_of_assigned_group_to_term_of_defences(examination_schedule_id: int) -> dict:
|
|
|
|
get_examination_schedule_by_id(examination_schedule_id)
|
|
|
|
|
|
|
|
td = TermOfDefence.query. \
|
|
|
|
join(TermOfDefence.members_of_committee, isouter=True). \
|
|
|
|
join(TermOfDefence.group). \
|
|
|
|
filter(TermOfDefence.examination_schedule_id == examination_schedule_id). \
|
|
|
|
filter(TermOfDefence.group_id.isnot(None)). \
|
|
|
|
all()
|
|
|
|
return {"term_of_defences": td}
|
|
|
|
|
|
|
|
|
|
|
|
@bp.post('/<int:examination_schedule_id>/term-of-defence/<int:term_of_defence_id>/group/')
|
|
|
|
@bp.input(GroupIdSchema)
|
|
|
|
@bp.output(MessageSchema)
|
|
|
|
def add_group_to_term_of_defence(examination_schedule_id: int, term_of_defence_id: int, data: dict) -> dict:
|
|
|
|
set_new_group_to_term_of_defence(examination_schedule_id, term_of_defence_id, data.get("group_id"))
|
|
|
|
db.session.commit()
|
|
|
|
return {"message": "Group was added to term of defences!"}
|
|
|
|
|
|
|
|
|
|
|
|
@bp.delete('/<int:examination_schedule_id>/term-of-defence/<int:term_of_defence_id>/group/')
|
|
|
|
@bp.output(MessageSchema)
|
|
|
|
def delete_group_to_term_of_defence(examination_schedule_id: int, term_of_defence_id: int) -> dict:
|
|
|
|
td = get_term_of_defence_by_id_and_examination_schedule_id(examination_schedule_id, term_of_defence_id)
|
|
|
|
td.group_id = None
|
|
|
|
db.session.commit()
|
|
|
|
return {"message": "Group was deleted from term of defences!"}
|
|
|
|
|
|
|
|
|
|
|
|
@bp.put('/<int:examination_schedule_id>/term-of-defence/<int:term_of_defence_id>/group/')
|
|
|
|
@bp.input(GroupIdSchema)
|
|
|
|
@bp.output(MessageSchema)
|
|
|
|
def update_group_for_term_of_defence(examination_schedule_id: int, term_of_defence_id: int, data: dict) -> dict:
|
|
|
|
set_new_group_to_term_of_defence(examination_schedule_id, term_of_defence_id, data.get("group_id"))
|
|
|
|
db.session.commit()
|
|
|
|
return {"message": "Group for term of defence was updated!"}
|