From 350d9d2a321f88c4dceaa6b07ff823661082adf7 Mon Sep 17 00:00:00 2001 From: dominik24c Date: Thu, 27 Oct 2022 15:59:02 +0200 Subject: [PATCH] add the functionality for project supervisors to assign and remove to selected exam --- backend/app/config.py | 1 + backend/app/project_supervisor/query.py | 33 ++++++++++ .../app/project_supervisor/routes/__init__.py | 4 ++ .../project_supervisor/routes/enrollments.py | 66 +++++++++++++++++++ backend/app/project_supervisor/schemas.py | 16 +++++ 5 files changed, 120 insertions(+) create mode 100644 backend/app/project_supervisor/query.py create mode 100644 backend/app/project_supervisor/routes/enrollments.py diff --git a/backend/app/config.py b/backend/app/config.py index a4ffad5..7c3bc65 100644 --- a/backend/app/config.py +++ b/backend/app/config.py @@ -18,6 +18,7 @@ class Config: SQLALCHEMY_TRACK_MODIFICATIONS = False SQLALCHEMY_DATABASE_URI = f'sqlite:///{BASE_DIR / "db.sqlite"}' LIMIT_STUDENTS_PER_GROUP = 5 + LIMIT_PERSONS_PER_COMMITTEE = 4 DESCRIPTION = 'System PRI' OPENAPI_VERSION = '3.0.2' diff --git a/backend/app/project_supervisor/query.py b/backend/app/project_supervisor/query.py new file mode 100644 index 0000000..620a2d4 --- /dev/null +++ b/backend/app/project_supervisor/query.py @@ -0,0 +1,33 @@ +import datetime + +from flask import abort + +from ..dependencies import db +from ..examination_schedule.models import Enrollment, ExaminationSchedule, Committee + + +def get_enrollment_by_enrollment_and_examination_schedule_ids(examination_schedule_id: int, + enrollment_id: int) -> Enrollment: + enrollment = db.session.query(Enrollment). \ + join(ExaminationSchedule, isouter=True).join(Committee, isouter=True). \ + filter(ExaminationSchedule.id == examination_schedule_id). \ + filter(Enrollment.id == enrollment_id). \ + first() + + if enrollment is None: + abort(404, "Examination schedule doesn't exist!") + + return enrollment + + +def check_the_project_supervisor_is_in_committee(enrollment_id: int, project_supervisor_id) -> bool: + return db.session.query( + Committee.query.join(Committee.members).filter(Committee.enrollment_id == enrollment_id).filter( + Committee.members.any(id=project_supervisor_id)).exists()).scalar() + + +def check_the_enrollments_has_just_started(start_date: datetime.datetime, action: str) -> None: + now = datetime.datetime.utcnow() + + if start_date is not None and start_date.timestamp() < now.timestamp(): + abort(403, f"Forbidden! Enrollment has just started! You cannot {action} from the exam committees!") diff --git a/backend/app/project_supervisor/routes/__init__.py b/backend/app/project_supervisor/routes/__init__.py index 689fb83..aa01a5a 100644 --- a/backend/app/project_supervisor/routes/__init__.py +++ b/backend/app/project_supervisor/routes/__init__.py @@ -1,3 +1,7 @@ from flask import Blueprint +from .enrollments import bp as enrollments_bp + bp = Blueprint("project_supervisor", __name__, url_prefix="/project_supervisor") + +bp.register_blueprint(enrollments_bp) diff --git a/backend/app/project_supervisor/routes/enrollments.py b/backend/app/project_supervisor/routes/enrollments.py new file mode 100644 index 0000000..a054fa1 --- /dev/null +++ b/backend/app/project_supervisor/routes/enrollments.py @@ -0,0 +1,66 @@ +import datetime + +from apiflask import APIBlueprint +from flask import abort, current_app + +from ..schemas import MessageSchema, CommitteeCreateSchema, TemporaryProjectSupervisorSchema +from ...examination_schedule.models import Enrollment, Committee, ExaminationSchedule +from ...dependencies import db +from ..models import ProjectSupervisor +from ..query import get_enrollment_by_enrollment_and_examination_schedule_ids, \ + check_the_project_supervisor_is_in_committee, check_the_enrollments_has_just_started + +bp = APIBlueprint("enrollments", __name__, url_prefix="/") + + +@bp.post('//enrollments//') +@bp.input(CommitteeCreateSchema) +@bp.output(MessageSchema) +def assign_yourself_to_committee(examination_schedule_id: int, enrollment_id: int, data: dict) -> dict: + # this code will be removed + project_supervisor = db.session.query(ProjectSupervisor).filter( + ProjectSupervisor.id == data['project_supervisor_id']).first() + if project_supervisor is None: + abort(404, "ProjectSupervisor doesn't exist!") + ################ + + limit_of_committtee = current_app.config['LIMIT_PERSONS_PER_COMMITTEE'] + + enrollment = get_enrollment_by_enrollment_and_examination_schedule_ids(examination_schedule_id, enrollment_id) + check_the_enrollments_has_just_started(enrollment.examination_schedule.start_date, "assign") + + size_of_committee = db.session.query(Committee).join(Committee.members). \ + filter(Committee.enrollment_id == enrollment.id).count() + + if size_of_committee >= limit_of_committtee: + abort(400, "The committee is full!") + + if check_the_project_supervisor_is_in_committee(enrollment.id, project_supervisor.id): + abort(400, "You have already in this committee!") + + enrollment.committee.members.append(project_supervisor) + db.session.add(enrollment) + db.session.commit() + + return {"message": "You have just assigned yourself to committee!"} + + +@bp.delete('//enrollments//') +@bp.input(TemporaryProjectSupervisorSchema) +@bp.output(MessageSchema) +def delete_yourself_from_committee(examination_schedule_id: int, enrollment_id: int, data: dict) -> dict: + # this code will be removed + project_supervisor = db.session.query(ProjectSupervisor).filter(ProjectSupervisor.id == data['id']).first() + if project_supervisor is None: + abort(404, "ProjectSupervisor doesn't exist!") + ################ + + enrollment = get_enrollment_by_enrollment_and_examination_schedule_ids(examination_schedule_id, enrollment_id) + check_the_enrollments_has_just_started(enrollment.examination_schedule.start_date, "delete") + + if not check_the_project_supervisor_is_in_committee(enrollment.id, project_supervisor.id): + abort(400, "You are not assigned to this committee!") + + enrollment.committee.members.remove(project_supervisor) + db.session.commit() + return {"message": "You have just removed from committee!"} diff --git a/backend/app/project_supervisor/schemas.py b/backend/app/project_supervisor/schemas.py index e69de29..f040c11 100644 --- a/backend/app/project_supervisor/schemas.py +++ b/backend/app/project_supervisor/schemas.py @@ -0,0 +1,16 @@ +from marshmallow import fields, validate, Schema + + +# MessageSchema, CommitteeCreateSchema + +class MessageSchema(Schema): + message = fields.Str() + + +class CommitteeCreateSchema(Schema): + project_supervisor_id = fields.Integer(required=True) # temporary field it will be removed in the future + + +# temporary class it will be removed in the future +class TemporaryProjectSupervisorSchema(Schema): + id = fields.Integer(required=True)