update enrollments endpoints for coordinator, project supervisors and students
This commit is contained in:
parent
eea98dd225
commit
856372e5ab
@ -23,8 +23,6 @@ class Config:
|
||||
DESCRIPTION = 'System PRI'
|
||||
OPENAPI_VERSION = '3.0.2'
|
||||
|
||||
PROJECT_PRESENTATION_TIME = 30 # in minutes
|
||||
|
||||
|
||||
class ProductionConfig(Config):
|
||||
DB_SERVER = "0.0.0.0"
|
||||
|
@ -1,7 +1,7 @@
|
||||
from flask import Blueprint
|
||||
|
||||
from .examination_schedule import bp as examination_schedule_bp
|
||||
# from .enrollments import bp as enrollments_bp
|
||||
from .enrollments import bp as enrollments_bp
|
||||
from .groups import bp as groups_bp
|
||||
from .project_supervisor import bp as project_supervisor_bp
|
||||
from .students import bp as students_bp
|
||||
@ -15,5 +15,5 @@ bp.register_blueprint(project_supervisor_bp)
|
||||
bp.register_blueprint(groups_bp)
|
||||
bp.register_blueprint(year_group_bp)
|
||||
bp.register_blueprint(examination_schedule_bp)
|
||||
# bp.register_blueprint(enrollments_bp)
|
||||
bp.register_blueprint(enrollments_bp)
|
||||
# bp.register_blueprint(workloads_bp)
|
||||
|
@ -1,69 +1,174 @@
|
||||
import datetime
|
||||
|
||||
from apiflask import APIBlueprint
|
||||
from flask import abort, current_app
|
||||
from flask import abort
|
||||
from sqlalchemy import or_, and_
|
||||
|
||||
from ..schemas import MessageSchema, EnrollmentCreateSchema
|
||||
from ...examination_schedule.models import ExaminationSchedule
|
||||
from ..schemas import MessageSchema, TermOfDefenceSchema, TermOfDefenceListSchema, \
|
||||
TemporaryAvailabilityListSchema
|
||||
from ...examination_schedule.models import ExaminationSchedule, TermOfDefence, TemporaryAvailability
|
||||
from ...students.models import YearGroup
|
||||
from ...project_supervisor.models import ProjectSupervisor
|
||||
from ...dependencies import db
|
||||
|
||||
bp = APIBlueprint("enrollments", __name__, url_prefix="/enrollments")
|
||||
|
||||
|
||||
@bp.post('/<int:examination_schedule_id>/')
|
||||
@bp.input(EnrollmentCreateSchema, location='json')
|
||||
@bp.output(MessageSchema)
|
||||
def create_enrollments(examination_schedule_id: int, data: dict) -> dict:
|
||||
prt = current_app.config["PROJECT_PRESENTATION_TIME"]
|
||||
@bp.post('/<int:examination_schedule_id>/generate')
|
||||
def generate_term_of_defence_for_this_examination_schedule(examination_schedule_id: int) -> dict:
|
||||
pass
|
||||
|
||||
examination_schedule = db.session.query(ExaminationSchedule).filter(
|
||||
ExaminationSchedule.id == examination_schedule_id).first()
|
||||
if examination_schedule is None:
|
||||
abort(404, "Examination schedule doesn't exist!")
|
||||
|
||||
@bp.post('/<int:examination_schedule_id>/add')
|
||||
@bp.input(TermOfDefenceSchema)
|
||||
@bp.output(MessageSchema)
|
||||
def create_term_of_defence(examination_schedule_id: int, data: dict) -> dict:
|
||||
if not data:
|
||||
abort(400, "You have passed empty data!")
|
||||
|
||||
ex = ExaminationSchedule.query.filter(ExaminationSchedule.id == examination_schedule_id).first()
|
||||
if ex is None:
|
||||
abort(404, "Not found 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']
|
||||
if start_date > end_date:
|
||||
abort(400, "Invalid dates! End date must be greater than start date!")
|
||||
if start_date.date() != end_date.date():
|
||||
abort(400, "Invalid dates! Only hours can be different!")
|
||||
|
||||
enrollment = Enrollment.query.filter(Enrollment.start_date >= start_date,
|
||||
Enrollment.start_date < end_date).first()
|
||||
if enrollment is not None:
|
||||
abort(400, "You have just created enrollments for this range date!")
|
||||
if not (ex.start_date.timestamp() < start_date.timestamp() and ex.end_date.timestamp() > end_date.timestamp()):
|
||||
abort(400, "Invalid date range!")
|
||||
|
||||
enrollment = Enrollment.query.filter(Enrollment.end_date > start_date, Enrollment.end_date <= end_date).first()
|
||||
if enrollment is not None:
|
||||
abort(400, "You have just created enrollments for this range date! `1")
|
||||
if end_date <= start_date:
|
||||
abort(400, "End date must be greater than start date!")
|
||||
|
||||
delta = end_date - start_date
|
||||
delta_in_minutes = delta.total_seconds() / 60
|
||||
if delta_in_minutes % prt != 0:
|
||||
abort(400, "Invalid format dates!")
|
||||
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!")
|
||||
|
||||
amount = int(delta_in_minutes // prt)
|
||||
enrollments = []
|
||||
for i in range(amount):
|
||||
sd = start_date + datetime.timedelta(minutes=i * prt)
|
||||
ed = start_date + datetime.timedelta(minutes=(i + 1) * prt)
|
||||
enrollment = Enrollment(start_date=sd, end_date=ed, examination_schedule_id=examination_schedule_id)
|
||||
enrollments.append(enrollment)
|
||||
db.session.add_all(enrollments)
|
||||
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()
|
||||
|
||||
committees = [Committee(enrollment_id=e.id) for e in enrollments]
|
||||
db.session.add_all(committees)
|
||||
for p in project_supervisors:
|
||||
td.members_of_committee.append(p)
|
||||
db.session.commit()
|
||||
return {"message": "Enrollments was created!"}
|
||||
return {"message": "Term of defence was created!"}
|
||||
|
||||
|
||||
@bp.delete('/<int:enrollment_id>/')
|
||||
@bp.put('/<int:examination_schedule_id>/update/<int:term_of_defence_id>/')
|
||||
@bp.input(TermOfDefenceSchema)
|
||||
@bp.output(MessageSchema)
|
||||
def delete_enrollment(enrollment_id: int) -> dict:
|
||||
enrollment = db.session.query(Enrollment).filter(Enrollment.id == enrollment_id).first()
|
||||
if enrollment is None:
|
||||
abort(404, "Enrollment doesn't exist!")
|
||||
db.session.delete(enrollment)
|
||||
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!")
|
||||
|
||||
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']
|
||||
|
||||
if not (ex.start_date.timestamp() < start_date.timestamp() and ex.end_date.timestamp() > end_date.timestamp()):
|
||||
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,
|
||||
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 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 = []
|
||||
db.session.commit()
|
||||
return {"message": "Enrollment was deleted!"}
|
||||
for p in project_supervisors:
|
||||
td.members_of_committee.append(p)
|
||||
db.session.commit()
|
||||
|
||||
return {"message": "Term of defence was updated!"}
|
||||
|
||||
|
||||
@bp.delete('/<int:examination_schedule_id>/delete/<int:term_of_defence_id>/')
|
||||
@bp.output(MessageSchema)
|
||||
def delete_term_of_defence(examination_schedule_id: int, term_of_defence_id: int) -> dict:
|
||||
td = TermOfDefence.query.filter(TermOfDefence.id == term_of_defence_id,
|
||||
ExaminationSchedule.id == examination_schedule_id).first()
|
||||
if td is None:
|
||||
abort(404, "Not found term of defence!")
|
||||
|
||||
db.session.delete(td)
|
||||
db.session.commit()
|
||||
|
||||
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:
|
||||
ex = ExaminationSchedule.query.filter(ExaminationSchedule.id == examination_schedule_id).first()
|
||||
if ex is None:
|
||||
abort(400, "Examination Schedule didn't exist")
|
||||
|
||||
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:
|
||||
ex = ExaminationSchedule.query.filter(ExaminationSchedule.id == examination_schedule_id).first()
|
||||
if ex is None:
|
||||
abort(400, "Examination Schedule didn't exist")
|
||||
|
||||
td = TemporaryAvailability.query. \
|
||||
filter(TemporaryAvailability.examination_schedule_id == examination_schedule_id). \
|
||||
join(TemporaryAvailability.project_supervisor). \
|
||||
all()
|
||||
return {"temporary_availabilities": td}
|
||||
|
@ -4,6 +4,7 @@ from apiflask import APIBlueprint
|
||||
from flask import abort, Response, make_response
|
||||
|
||||
from ...base.utils import paginate_models
|
||||
from ...base.mode import ModeGroups
|
||||
from ...dependencies import db
|
||||
from ...examination_schedule.models import ExaminationSchedule
|
||||
from ...students.models import Group, YearGroup
|
||||
@ -37,7 +38,16 @@ def create_examination_schedule(year_group_id: int, data: dict) -> dict:
|
||||
if data['start_date'] > data['end_date']:
|
||||
abort(400, "Invalid data! End date must be greater than start date!")
|
||||
|
||||
examination_schedule = ExaminationSchedule(**data, year_group_id=year_group_id)
|
||||
duration_time = None
|
||||
if yg.mode == ModeGroups.NON_STATIONARY.value:
|
||||
duration_time = 20
|
||||
elif yg.mode in [ModeGroups.STATIONARY.value, ModeGroups.ENGLISH_SPEAKING_STATIONARY.value]:
|
||||
duration_time = 30
|
||||
|
||||
if duration_time is None:
|
||||
abort(400, "Invalid mode of year group!")
|
||||
|
||||
examination_schedule = ExaminationSchedule(**data, year_group_id=year_group_id, duration_time=duration_time)
|
||||
db.session.add(examination_schedule)
|
||||
db.session.commit()
|
||||
return {"message": "Examination schedule was created!"}
|
||||
|
@ -3,7 +3,7 @@ from flask import abort
|
||||
from flask_sqlalchemy import get_debug_queries
|
||||
|
||||
from ...dependencies import db
|
||||
from ...examination_schedule.models import ExaminationSchedule, Enrollment, Committee
|
||||
from ...examination_schedule.models import ExaminationSchedule
|
||||
from ...project_supervisor.models import ProjectSupervisor
|
||||
from ..schemas import WorkloadSchema
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
from flask import abort
|
||||
from apiflask import APIBlueprint
|
||||
from flask_sqlalchemy import get_debug_queries
|
||||
|
||||
from ...students.models import YearGroup
|
||||
from ..schemas import YearGroupSchema, MessageSchema, YearGroupPaginationSchema, YearGroupQuerySchema
|
||||
|
@ -1,4 +1,4 @@
|
||||
from .enrollments import EnrollmentCreateSchema
|
||||
from .enrollments import TermOfDefenceSchema, TermOfDefenceListSchema, TemporaryAvailabilityListSchema
|
||||
from .examination_schedule import ExaminationScheduleSchema, ExaminationScheduleUpdateSchema, \
|
||||
ExaminationSchedulesPaginationSchema, ExaminationSchedulesQuerySchema, WorkloadSchema
|
||||
from .groups import GroupQuerySchema, GroupsPaginationSchema, GroupCreateSchema, GroupEditSchema
|
||||
|
@ -1,8 +1,41 @@
|
||||
from marshmallow import Schema, fields
|
||||
from marshmallow import Schema, fields, validate
|
||||
|
||||
from ..validators import validate_datetime_greater_than_now
|
||||
|
||||
|
||||
class EnrollmentCreateSchema(Schema):
|
||||
class TermOfDefenceSchema(Schema):
|
||||
start_date = fields.DateTime(validate=validate_datetime_greater_than_now, required=True)
|
||||
end_date = fields.DateTime(validate=validate_datetime_greater_than_now, required=True)
|
||||
project_supervisors = fields.List(fields.Integer(required=True), validate=validate.Length(3, 3))
|
||||
|
||||
|
||||
class ProjectSupervisorForTermOfDefenceSchema(Schema):
|
||||
id = fields.Str()
|
||||
first_name = fields.Str()
|
||||
last_name = fields.Str()
|
||||
|
||||
|
||||
class TermOfDefenceItemSchema(Schema):
|
||||
start_date = fields.DateTime()
|
||||
end_date = fields.DateTime()
|
||||
members_of_committee = fields.List(fields.Nested(ProjectSupervisorForTermOfDefenceSchema))
|
||||
|
||||
|
||||
class TermOfDefenceListSchema(Schema):
|
||||
term_of_defences = fields.List(fields.Nested(TermOfDefenceItemSchema))
|
||||
|
||||
|
||||
class ProjectSupervisorForTemporaryAvailabilitySchema(Schema):
|
||||
id = fields.Str()
|
||||
first_name = fields.Str()
|
||||
last_name = fields.Str()
|
||||
|
||||
|
||||
class TemporaryAvailabilityItemSchema(Schema):
|
||||
start_date = fields.DateTime()
|
||||
end_date = fields.DateTime()
|
||||
project_supervisor = fields.Nested(ProjectSupervisorForTemporaryAvailabilitySchema)
|
||||
|
||||
|
||||
class TemporaryAvailabilityListSchema(Schema):
|
||||
temporary_availabilities = fields.List(fields.Nested(TemporaryAvailabilityItemSchema))
|
||||
|
@ -6,7 +6,7 @@ class ExaminationSchedule(Base):
|
||||
__tablename__ = 'examination_schedules'
|
||||
|
||||
title = db.Column(db.String(100), unique=True, nullable=False)
|
||||
duration_time = db.Column(db.Integer) # in minutes
|
||||
duration_time = db.Column(db.Integer) # in minutes
|
||||
start_date_for_enrollment_students = db.Column(db.DateTime)
|
||||
end_date_for_enrollment_students = db.Column(db.DateTime)
|
||||
start_date = db.Column(db.DateTime, nullable=False)
|
||||
|
@ -1,39 +0,0 @@
|
||||
import datetime
|
||||
|
||||
from apiflask import APIBlueprint
|
||||
from flask import abort
|
||||
|
||||
from ..schemas import EnrollmentPaginationSchema, EnrollmentQuerySchema, ExaminationScheduleProjectSupervisorViewSchema
|
||||
from ..utils import check_examination_schedule_is_exist, get_list_of_enrollments_response
|
||||
|
||||
bp = APIBlueprint("enrollments", __name__, url_prefix="/enrollments")
|
||||
|
||||
|
||||
# list of the exam registration for students
|
||||
@bp.get('/<int:examination_schedule_id>/student-view')
|
||||
@bp.input(EnrollmentQuerySchema, location='query')
|
||||
@bp.output(EnrollmentPaginationSchema)
|
||||
def list_enrollments_for_students(examination_schedule_id: int, query: dict) -> dict:
|
||||
page = query.get('page')
|
||||
per_page = query.get('per_page')
|
||||
|
||||
examination_schedule = check_examination_schedule_is_exist(examination_schedule_id)
|
||||
|
||||
now = datetime.datetime.utcnow()
|
||||
if examination_schedule.start_date is None or examination_schedule.end_date is None:
|
||||
abort(403, "Forbidden! The examination schedule is not available yet")
|
||||
|
||||
if examination_schedule.start_date.timestamp() > now.timestamp():
|
||||
abort(403, "Forbidden! Enrollments haven't just started!")
|
||||
|
||||
if examination_schedule.end_date.timestamp() < now.timestamp():
|
||||
abort(400, "The exam registration has just finished!")
|
||||
|
||||
return get_list_of_enrollments_response(examination_schedule_id, page, per_page)
|
||||
|
||||
|
||||
@bp.get('/<int:examination_schedule_id>/coordinator-view/')
|
||||
@bp.output(ExaminationScheduleProjectSupervisorViewSchema)
|
||||
def list_enrollments_for_coordinator(examination_schedule_id: int) -> dict:
|
||||
return check_examination_schedule_is_exist(examination_schedule_id)
|
||||
|
@ -1,18 +0,0 @@
|
||||
import datetime
|
||||
|
||||
from apiflask import APIBlueprint
|
||||
|
||||
from ...dependencies import db
|
||||
from ..models import ExaminationSchedule
|
||||
|
||||
bp = APIBlueprint("list_of_examination_schedule", __name__, url_prefix="/")
|
||||
|
||||
|
||||
@bp.get('/students-view/')
|
||||
def list_examination_schedule_for_students() -> dict:
|
||||
# in the future filter after the mode of examination schedule if we will have authorization module
|
||||
now = datetime.datetime.utcnow()
|
||||
examination_schedules = db.session.query(ExaminationSchedule).\
|
||||
filter(ExaminationSchedule.start_date_for_enrollment_students < now).\
|
||||
filter(ExaminationSchedule.end_date_for_enrollment_students > now).all()
|
||||
return {'examination_schedules': examination_schedules}
|
@ -1,39 +0,0 @@
|
||||
from marshmallow import fields, validate, Schema
|
||||
|
||||
|
||||
class ProjectSupervisorSchema(Schema):
|
||||
first_name = fields.Str()
|
||||
last_name = fields.Str()
|
||||
|
||||
|
||||
class CommitteeSchema(Schema):
|
||||
members = fields.List(fields.Nested(ProjectSupervisorSchema))
|
||||
|
||||
|
||||
class GroupSchema(Schema):
|
||||
name = fields.Str()
|
||||
|
||||
|
||||
class EnrollmentSchema(Schema):
|
||||
id = fields.Integer()
|
||||
start_date = fields.DateTime()
|
||||
end_date = fields.DateTime()
|
||||
committee = fields.Nested(CommitteeSchema)
|
||||
group = fields.Nested(GroupSchema)
|
||||
|
||||
|
||||
class EnrollmentPaginationSchema(Schema):
|
||||
enrollments = fields.List(fields.Nested(EnrollmentSchema))
|
||||
max_pages = fields.Integer()
|
||||
|
||||
|
||||
class ExaminationScheduleProjectSupervisorViewSchema(Schema):
|
||||
id = fields.Integer()
|
||||
start_date = fields.DateTime()
|
||||
end_date = fields.DateTime()
|
||||
|
||||
|
||||
class EnrollmentQuerySchema(Schema):
|
||||
page = fields.Integer()
|
||||
per_page = fields.Integer()
|
||||
|
@ -1,27 +0,0 @@
|
||||
from flask import abort
|
||||
|
||||
from ..dependencies import db
|
||||
from .models import ExaminationSchedule
|
||||
from ..students.models import Group
|
||||
from ..base.utils import paginate_models
|
||||
|
||||
|
||||
def check_examination_schedule_is_exist(examination_schedule_id: int) -> ExaminationSchedule:
|
||||
examination_schedule = db.session.query(ExaminationSchedule).filter(
|
||||
ExaminationSchedule.id == examination_schedule_id).first()
|
||||
|
||||
if examination_schedule is None:
|
||||
abort(404, "Examination Schedule doesn't exist!")
|
||||
|
||||
return examination_schedule
|
||||
|
||||
|
||||
def get_list_of_enrollments_response(examination_schedule_id: int, page: int = None, per_page: int = None) -> dict:
|
||||
enrollments_query = db.session.query(Enrollment). \
|
||||
join(Group, isouter=True).join(Committee, isouter=True). \
|
||||
join(ExaminationSchedule, isouter=True). \
|
||||
filter(ExaminationSchedule.id == examination_schedule_id)
|
||||
|
||||
data = paginate_models(page, enrollments_query, per_page)
|
||||
|
||||
return {"enrollments": data["items"], "max_pages": data["max_pages"]}
|
@ -1,27 +0,0 @@
|
||||
import datetime
|
||||
|
||||
from flask import abort
|
||||
|
||||
from ..dependencies import db
|
||||
from ..examination_schedule.models import ExaminationSchedule
|
||||
|
||||
|
||||
def get_enrollment_by_enrollment_and_examination_schedule_ids(examination_schedule_id: int,
|
||||
enrollment_id: int) -> None:
|
||||
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_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!")
|
@ -4,7 +4,7 @@ from apiflask import APIBlueprint
|
||||
from flask import abort
|
||||
|
||||
from ..schemas import MessageSchema, TimeAvailabilityCreateSchema, TemporaryProjectSupervisorSchema, \
|
||||
ListOfFreeTimesSchema
|
||||
ListOfFreeTimesSchema, ListOfTermOfDefenceSchema
|
||||
from ...dependencies import db
|
||||
from ..models import ProjectSupervisor
|
||||
from ...examination_schedule.models import ExaminationSchedule, TemporaryAvailability, TermOfDefence
|
||||
@ -32,7 +32,9 @@ 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!")
|
||||
|
||||
if not (es.start_date >= sd and es.end_date <= ed):
|
||||
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!")
|
||||
|
||||
now = datetime.utcnow()
|
||||
@ -47,18 +49,18 @@ def set_your_free_time_to_examination_schedule(examination_schedule_id: int, dat
|
||||
# implement logic
|
||||
pass
|
||||
|
||||
ta = TemporaryAvailability(**data, examination_schedule_id=examination_schedule_id,
|
||||
project_supervisor_id=project_supervisor.id)
|
||||
ta = TemporaryAvailability(**data, examination_schedule_id=examination_schedule_id)
|
||||
db.session.add(ta)
|
||||
db.session.commit()
|
||||
|
||||
return {"message": "You have just assigned your free time!"}
|
||||
|
||||
|
||||
@bp.delete('/<int:examination_schedule_id>/enrollments/<int:id>/')
|
||||
@bp.delete('/<int:examination_schedule_id>/enrollments/<int:temporary_availability_id>/')
|
||||
@bp.input(TemporaryProjectSupervisorSchema)
|
||||
@bp.output(MessageSchema)
|
||||
def delete_your_free_time_from_examination_schedule(examination_schedule_id: int, id: int, data: dict) -> dict:
|
||||
def delete_your_free_time_from_examination_schedule(examination_schedule_id: int, temporary_availability_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:
|
||||
@ -66,7 +68,7 @@ def delete_your_free_time_from_examination_schedule(examination_schedule_id: int
|
||||
################
|
||||
ta = TemporaryAvailability.query.filter(TemporaryAvailability.examination_schedule_id == examination_schedule_id,
|
||||
TemporaryAvailability.project_supervisor_id == project_supervisor.id,
|
||||
TemporaryAvailability.id == id).first()
|
||||
TemporaryAvailability.id == temporary_availability_id).first()
|
||||
|
||||
if ta is None:
|
||||
abort(404, "Your free time doesn't exist!")
|
||||
@ -76,7 +78,7 @@ def delete_your_free_time_from_examination_schedule(examination_schedule_id: int
|
||||
return {"message": "You have just removed your free time!"}
|
||||
|
||||
|
||||
@bp.get('/<int:examination_schedule_id>/')
|
||||
@bp.get('/<int:examination_schedule_id>/temporary-availabilities/')
|
||||
@bp.input(TemporaryProjectSupervisorSchema, location='query')
|
||||
@bp.output(ListOfFreeTimesSchema)
|
||||
def list_enrollments_for_project_supervisor(examination_schedule_id: int, data: dict) -> dict:
|
||||
@ -92,19 +94,21 @@ def list_enrollments_for_project_supervisor(examination_schedule_id: int, data:
|
||||
abort(404, "Examination schedule doesn't exist!")
|
||||
|
||||
now = datetime.utcnow()
|
||||
if es.start_date_for_enrollment_students.timestamp() < now.timestamp():
|
||||
start_date = es.start_date_for_enrollment_students
|
||||
if start_date is not None and start_date.timestamp() < now.timestamp():
|
||||
abort(403, "Forbidden! Enrollment has just started! You cannot assign to the exam committees!")
|
||||
|
||||
# list of your term of defences first enrollment
|
||||
ta = TemporaryAvailability.query.filter(TemporaryAvailability.examination_schedule_id == examination_schedule_id,
|
||||
TemporaryAvailability.project_supervisor_id == project_supervisor.id).all()
|
||||
return ta
|
||||
return {"free_times": ta}
|
||||
|
||||
|
||||
@bp.get('/<int:examination_schedule_id>/term-of-defences/')
|
||||
@bp.input(TemporaryProjectSupervisorSchema, location='query')
|
||||
@bp.output(ListOfFreeTimesSchema)
|
||||
def list_created_enrollment_by_coordinator_for_project_supervisor(examination_schedule_id: int, data: dict) -> dict:
|
||||
@bp.output(ListOfTermOfDefenceSchema)
|
||||
def list_created_term_of_defences_by_coordinator_for_project_supervisor(examination_schedule_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:
|
||||
@ -118,5 +122,5 @@ def list_created_enrollment_by_coordinator_for_project_supervisor(examination_sc
|
||||
# list of your free times first enrollment
|
||||
td = TermOfDefence.query.join(TermOfDefence.members_of_committee). \
|
||||
filter(TermOfDefence.examination_schedule_id == examination_schedule_id). \
|
||||
filter_by(project_supervisor_id=project_supervisor.id).all()
|
||||
return td
|
||||
filter_by(id=project_supervisor.id).all()
|
||||
return {"term_of_defences": td}
|
||||
|
@ -15,6 +15,10 @@ class ListOfFreeTimesSchema(Schema):
|
||||
free_times = fields.List(fields.Nested(FreeTimeSchema))
|
||||
|
||||
|
||||
class ListOfTermOfDefenceSchema(Schema):
|
||||
term_of_defences = fields.List(fields.Nested(FreeTimeSchema))
|
||||
|
||||
|
||||
class TimeAvailabilityCreateSchema(Schema):
|
||||
start_date = fields.DateTime(required=True)
|
||||
end_date = fields.DateTime(required=True)
|
||||
|
@ -1,10 +0,0 @@
|
||||
import datetime
|
||||
|
||||
from flask import abort
|
||||
from ..examination_schedule.models import ExaminationSchedule
|
||||
|
||||
|
||||
def check_the_enrollments_has_just_started(es: ExaminationSchedule) -> None:
|
||||
now = datetime.datetime.utcnow()
|
||||
if es.start_date is None or es.end_date is None or not (es.start_date < now < es.end_date):
|
||||
abort(403, "Forbidden! Enrollment hasn't started yet.")
|
@ -2,8 +2,10 @@ from flask import Blueprint
|
||||
|
||||
from .enrollments import bp as enrollments_bp
|
||||
from .registrations import bp as registrations_bp
|
||||
from .year_group import bp as year_group_bp
|
||||
|
||||
bp = Blueprint("students", __name__, url_prefix="/students")
|
||||
|
||||
bp.register_blueprint(registrations_bp)
|
||||
bp.register_blueprint(enrollments_bp)
|
||||
bp.register_blueprint(registrations_bp)
|
||||
bp.register_blueprint(year_group_bp)
|
||||
|
@ -3,7 +3,8 @@ import datetime
|
||||
from apiflask import APIBlueprint
|
||||
from flask import abort
|
||||
|
||||
from ..schemas import MessageSchema, TemporaryStudentSchema, ExaminationScheduleListSchema
|
||||
from ..schemas import MessageSchema, TemporaryStudentSchema, ExaminationScheduleListSchema, \
|
||||
TermOfDefenceStudentListSchema
|
||||
from ...dependencies import db
|
||||
from ..models import Student, Group, TermOfDefence
|
||||
from ...examination_schedule.models import ExaminationSchedule
|
||||
@ -12,33 +13,39 @@ from ...project_supervisor.models import ProjectSupervisor
|
||||
bp = APIBlueprint("enrollments", __name__, url_prefix="/")
|
||||
|
||||
|
||||
@bp.post('/<int:examination_schedule_id>/enrollments/<int:enrollment_id>/')
|
||||
@bp.post('/<int:examination_schedule_id>/enrollments/<int:term_of_defence_id>/')
|
||||
@bp.input(TemporaryStudentSchema)
|
||||
@bp.output(MessageSchema)
|
||||
def assign_your_group_to_term_of_defence(examination_schedule_id: int, data: dict) -> dict:
|
||||
def assign_your_group_to_term_of_defence(examination_schedule_id: int, term_of_defence_id: int, data: dict) -> dict:
|
||||
# this code will be removed
|
||||
student = Student.query.filter(Student.index == data['student_index']).first()
|
||||
if student is None:
|
||||
abort(404, "Student doesn't exist!")
|
||||
################
|
||||
term_of_defence = TermOfDefence.query.filter(TermOfDefence.id == term_of_defence_id,
|
||||
TermOfDefence.examination_schedule_id == examination_schedule_id).first()
|
||||
|
||||
if term_of_defence is None:
|
||||
abort(400, "Term of defence not found!")
|
||||
|
||||
st = Student.query.join(Group).join(ProjectSupervisor).filter(Student.index == student.index).first()
|
||||
if st is None or st.group.project_supervisor is None:
|
||||
if st is None or st.groups.project_supervisor is None:
|
||||
abort(400, "You don't have a group or your group doesn't have an assigned project supervisor!")
|
||||
|
||||
defence = TermOfDefence.query.filter(TermOfDefence.group_id == st.group.id,
|
||||
defence = TermOfDefence.query.filter(TermOfDefence.group_id == st.groups.id,
|
||||
TermOfDefence.examination_schedule_id == examination_schedule_id).first()
|
||||
if defence is not None:
|
||||
abort(400, "Your group has already assigned to any exam date!")
|
||||
|
||||
g = Group.query.filter(id=st.group_id).first()
|
||||
g = Group.query.filter(Group.id == st.group_id).first()
|
||||
td = TermOfDefence.query.join(TermOfDefence.members_of_committee). \
|
||||
filter_by(project_supervisor_id=g.project_supervisor_id).first()
|
||||
filter_by(id=g.project_supervisor_id).first()
|
||||
|
||||
if td is None:
|
||||
abort(400, "Your project supervisor is not in committee!")
|
||||
|
||||
defence.group_id = st.group.id
|
||||
db.session.add(defence)
|
||||
term_of_defence.group_id = st.groups.id
|
||||
db.session.add(term_of_defence)
|
||||
db.session.commit()
|
||||
return {"message": "You have just assigned the group for this exam date!"}
|
||||
|
||||
@ -59,7 +66,7 @@ def delete_your_group_from_term_of_defence(examination_schedule_id: int, term_of
|
||||
if term_of_defence is None:
|
||||
abort(404, "Term of defence doesn't exist!")
|
||||
|
||||
if student.group.id != term_of_defence.group_id:
|
||||
if student.groups.id != term_of_defence.group_id:
|
||||
abort(400, "You are not assigned to this group!")
|
||||
|
||||
term_of_defence.group_id = None
|
||||
@ -70,9 +77,9 @@ def delete_your_group_from_term_of_defence(examination_schedule_id: int, term_of
|
||||
|
||||
|
||||
@bp.get('/examination-schedule/year-group/<int:year_group_id>/')
|
||||
@bp.input(TemporaryStudentSchema)
|
||||
@bp.input(TemporaryStudentSchema, location='query')
|
||||
@bp.output(ExaminationScheduleListSchema)
|
||||
def list_examination_schedule_for_students(year_group_id: int, data: dict) -> dict:
|
||||
def list_examination_schedule(year_group_id: int, data: dict) -> dict:
|
||||
# this code will be removed
|
||||
student = Student.query.filter(Student.index == data['student_index']).first()
|
||||
if student is None:
|
||||
@ -88,10 +95,10 @@ def list_examination_schedule_for_students(year_group_id: int, data: dict) -> di
|
||||
return {'examination_schedules': examination_schedules}
|
||||
|
||||
|
||||
@bp.get('/enrollments/')
|
||||
@bp.input(TemporaryStudentSchema)
|
||||
@bp.output(ExaminationScheduleListSchema)
|
||||
def list_term_of_defences_for_students(data: dict) -> dict:
|
||||
@bp.get('/examination-schedule/<int:examination_schedule_id>/enrollments/')
|
||||
@bp.input(TemporaryStudentSchema, location='query')
|
||||
@bp.output(TermOfDefenceStudentListSchema)
|
||||
def list_term_of_defences(examination_schedule_id: int, data: dict) -> dict:
|
||||
# this code will be removed
|
||||
student = Student.query.filter(Student.index == data['student_index']).first()
|
||||
if student is None:
|
||||
@ -99,9 +106,9 @@ def list_term_of_defences_for_students(data: dict) -> dict:
|
||||
################
|
||||
# in the future filter after the mode of examination schedule if we will have authorization module
|
||||
now = datetime.datetime.utcnow()
|
||||
term_of_defences = TermOfDefence.query.join(ExaminationSchedule, isouter=True). \
|
||||
term_of_defences = TermOfDefence.query.filter(TermOfDefence.examination_schedule_id == examination_schedule_id). \
|
||||
join(ExaminationSchedule, isouter=True). \
|
||||
filter(ExaminationSchedule.start_date_for_enrollment_students < now). \
|
||||
filter(ExaminationSchedule.end_date_for_enrollment_students > now). \
|
||||
filter(TermOfDefence.group_id == student.group_id). \
|
||||
all()
|
||||
return {'examination_schedules': term_of_defences}
|
||||
filter(ExaminationSchedule.end_date_for_enrollment_students > now).all()
|
||||
|
||||
return {'term_of_defences': term_of_defences}
|
||||
|
32
backend/app/students/routes/year_group.py
Normal file
32
backend/app/students/routes/year_group.py
Normal file
@ -0,0 +1,32 @@
|
||||
from apiflask import APIBlueprint
|
||||
from flask import abort
|
||||
|
||||
from ...students.models import YearGroup
|
||||
from ...dependencies import db
|
||||
from ...base.utils import paginate_models
|
||||
from ..schemas import YearGroupQueryStudentSchema, YearGroupStudentPaginationSchema
|
||||
from ..models import Student
|
||||
|
||||
bp = APIBlueprint("year_group", __name__, url_prefix="/year-group")
|
||||
|
||||
|
||||
@bp.get('/')
|
||||
@bp.input(YearGroupQueryStudentSchema, location='query')
|
||||
@bp.output(YearGroupStudentPaginationSchema)
|
||||
def list_of_year_groups(query: dict) -> dict:
|
||||
index = query.get('index')
|
||||
st = Student.query.filter(Student.index == index).first()
|
||||
if st is None:
|
||||
abort(404, "Not found student!")
|
||||
####################################
|
||||
page = query.get('page')
|
||||
per_page = query.get('per_page')
|
||||
|
||||
year_group_query = YearGroup.query.join(YearGroup.students). \
|
||||
filter(Student.index == st.index).order_by(db.desc(YearGroup.created_at))
|
||||
data = paginate_models(page, year_group_query, per_page)
|
||||
|
||||
return {
|
||||
"year_groups": data['items'],
|
||||
"max_pages": data['max_pages']
|
||||
}
|
@ -35,3 +35,30 @@ class ExaminationScheduleSchema(Schema):
|
||||
|
||||
class ExaminationScheduleListSchema(Schema):
|
||||
examination_schedules = fields.List(fields.Nested(ExaminationScheduleSchema))
|
||||
|
||||
|
||||
class TermOfDefenceStudentItemSchema(Schema):
|
||||
id = fields.Integer()
|
||||
start_date = fields.DateTime()
|
||||
end_date = fields.DateTime()
|
||||
|
||||
|
||||
class TermOfDefenceStudentListSchema(Schema):
|
||||
term_of_defences = fields.List(fields.Nested(TermOfDefenceStudentItemSchema))
|
||||
|
||||
|
||||
class YearGroupStudentSchema(Schema):
|
||||
id = fields.Integer()
|
||||
name = fields.Str()
|
||||
mode = fields.Str()
|
||||
|
||||
|
||||
class YearGroupStudentPaginationSchema(Schema):
|
||||
year_groups = fields.List(fields.Nested(YearGroupStudentSchema))
|
||||
max_pages = fields.Integer()
|
||||
|
||||
|
||||
class YearGroupQueryStudentSchema(Schema):
|
||||
index = fields.Integer(required=True) # it will be removed
|
||||
page = fields.Integer()
|
||||
per_page = fields.Integer()
|
||||
|
Loading…
Reference in New Issue
Block a user