diff --git a/backend/app/coordinator/routes/enrollments.py b/backend/app/coordinator/routes/enrollments.py index 8878e33..a069031 100644 --- a/backend/app/coordinator/routes/enrollments.py +++ b/backend/app/coordinator/routes/enrollments.py @@ -1,5 +1,4 @@ import datetime -from itertools import islice from apiflask import APIBlueprint from flask import abort, current_app @@ -8,7 +7,7 @@ from flask_sqlalchemy import get_debug_queries from ..schemas import MessageSchema, TermOfDefenceSchema, TermOfDefenceListSchema, \ TemporaryAvailabilityListSchema, AssignedGroupToTermOfDefenceListSchema, GroupIdSchema -from ...examination_schedule.models import ExaminationSchedule, TermOfDefence, TemporaryAvailability +from ...examination_schedule.models import TermOfDefence, TemporaryAvailability, committee from ...students.models import YearGroup from ...project_supervisor.models import ProjectSupervisor from ...dependencies import db @@ -23,56 +22,66 @@ bp = APIBlueprint("enrollments", __name__, url_prefix="/enrollments") @bp.output(MessageSchema) def generate_term_of_defence_for_this_examination_schedule(examination_schedule_id: int) -> dict: ex = get_examination_schedule_by_id(examination_schedule_id) - - # print(ex.start_date.date()) - # print(ex.end_date.date()) - dates = generate_range_dates(ex.start_date, ex.end_date, ex.duration_time) - # print(dates) limit = current_app.config.get('LIMIT_MEMBERS_PER_COMMITTEE', 3) - # in future optimize sql query - # project_supervisor cache in memory (flyweight) - # while True: - # sliced_dates = islice(dates, 1) - # list_of_dates = list(sliced_dates) - # - # if len(list_of_dates) == 0: - # break + 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) + print(temporary_availabilities) for d in dates: e = d + datetime.timedelta(minutes=ex.duration_time) - # print(f"{d} - {e}") - temporary_availabilities = TemporaryAvailability.query.filter( - TemporaryAvailability.examination_schedule_id == examination_schedule_id). \ - filter(TemporaryAvailability.start_date <= d, - TemporaryAvailability.end_date >= e).all() - if len(temporary_availabilities) >= limit: - # create term of defence - # check term of defence exist in this date range - td = TermOfDefence.query.filter(or_(and_(TermOfDefence.start_date <= d, TermOfDefence.end_date >= e), - and_(TermOfDefence.start_date > d, TermOfDefence.end_date >= e, - TermOfDefence.start_date < e), - and_(TermOfDefence.start_date <= d, TermOfDefence.end_date > d, - TermOfDefence.end_date < e) - )).first() - if td is None: - term_of_defence = TermOfDefence(start_date=d, end_date=e, - examination_schedule_id=examination_schedule_id) - db.session.add(term_of_defence) - db.session.commit() - project_supervisors_ids = [] - for i in range(limit): - ta = temporary_availabilities[i] - project_supervisors_ids.append(ta.project_supervisor_id) - project_supervisors = ProjectSupervisor.query.filter( - or_(*[ProjectSupervisor.id == idx for idx in project_supervisors_ids])).all() - for p in project_supervisors: - term_of_defence.members_of_committee.append(p) - db.session.commit() + t = list(filter(lambda ta: ta.start_date <= d and ta.end_date >= e, temporary_availabilities)) + if len(t) >= limit: + print(f'{d} -- {e}') + print(t) + print("IN") + 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 + db.session.add(term_of_defence) + db.session.commit() - # print(temporary_availabilities) return {"message": "Term of defences was generated!"} +@bp.post('//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] = [] + + return {"message": "Term of defences was deleted!"} + + @bp.post('//add') @bp.input(TermOfDefenceSchema) @bp.output(MessageSchema) diff --git a/backend/app/project_supervisor/routes/enrollments.py b/backend/app/project_supervisor/routes/enrollments.py index 2b3dcc1..63ef9eb 100644 --- a/backend/app/project_supervisor/routes/enrollments.py +++ b/backend/app/project_supervisor/routes/enrollments.py @@ -2,7 +2,7 @@ from datetime import datetime from apiflask import APIBlueprint from flask import abort - +from sqlalchemy import and_, or_ from ..schemas import MessageSchema, TimeAvailabilityCreateSchema, TemporaryProjectSupervisorSchema, \ ListOfFreeTimesSchema, ListOfTermOfDefenceSchema from ...dependencies import db @@ -17,8 +17,7 @@ bp = APIBlueprint("enrollments", __name__, url_prefix="/") @bp.output(MessageSchema) def set_your_free_time_to_examination_schedule(examination_schedule_id: int, data: dict) -> dict: # this code will be removed - project_supervisor = db.session.query(ProjectSupervisor).filter( - ProjectSupervisor.id == data['project_supervisor_id']).first() + project_supervisor = ProjectSupervisor.query.filter(ProjectSupervisor.id == data['project_supervisor_id']).first() if project_supervisor is None: abort(404, "ProjectSupervisor doesn't exist!") ################ @@ -32,22 +31,22 @@ def set_your_free_time_to_examination_schedule(examination_schedule_id: int, dat if sd > ed: abort(400, "Invalid data! End date must be greater than start date!") - print(es.start_date.timestamp() >= sd.timestamp()) - print(es.end_date.timestamp() <= ed.timestamp()) if not (es.start_date.timestamp() <= sd.timestamp() and es.end_date.timestamp() >= ed.timestamp()): - abort(400, "Invalid date ranges!") + abort(400, "Date range is not within the examination schedule!") now = datetime.utcnow() if es.start_date_for_enrollment_students is not None and \ es.start_date_for_enrollment_students.timestamp() < now.timestamp(): abort(403, "Enrollment has started! You cannot set your free time!") - ta_query = TemporaryAvailability.query.filter( - TemporaryAvailability.examination_schedule_id == examination_schedule_id). \ - filter(TemporaryAvailability.project_supervisor_id == project_supervisor.id) - if ta_query.first() is not None: - # implement logic - pass + ta = TemporaryAvailability.query.filter(TemporaryAvailability.examination_schedule_id == examination_schedule_id). \ + filter(TemporaryAvailability.project_supervisor_id == project_supervisor.id). \ + filter(or_(and_(TemporaryAvailability.start_date >= sd, TemporaryAvailability.start_date < ed, + TemporaryAvailability.end_date >= ed), + and_(TemporaryAvailability.start_date <= sd, TemporaryAvailability.end_date > sd, + TemporaryAvailability.end_date <= ed))).first() + if ta is not None: + abort(400, "Invalid date ranges. You set your free time in this date range! Choose another date!") ta = TemporaryAvailability(**data, examination_schedule_id=examination_schedule_id) db.session.add(ta)