add year group and change logic of endpoints v2
This commit is contained in:
parent
82807b7c2e
commit
eea98dd225
@ -13,4 +13,3 @@ COPY requirements.txt .
|
|||||||
RUN pip install -r requirements.txt
|
RUN pip install -r requirements.txt
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
|
7
backend/app/base/mode.py
Normal file
7
backend/app/base/mode.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class ModeGroups(str, Enum):
|
||||||
|
STATIONARY = 's'
|
||||||
|
NON_STATIONARY = 'n'
|
||||||
|
ENGLISH_SPEAKING_STATIONARY = 'e'
|
@ -2,7 +2,7 @@ from flask.cli import with_appcontext
|
|||||||
from click import command
|
from click import command
|
||||||
|
|
||||||
from ..dependencies import db
|
from ..dependencies import db
|
||||||
from ..factory import ProjectSupervisorFactory, GroupFactory, StudentFactory
|
# from ..factory import ProjectSupervisorFactory, GroupFactory, StudentFactory
|
||||||
|
|
||||||
|
|
||||||
@command('init_db')
|
@command('init_db')
|
||||||
@ -11,27 +11,27 @@ def init_db() -> None:
|
|||||||
"""Fill database with some data"""
|
"""Fill database with some data"""
|
||||||
db.drop_all()
|
db.drop_all()
|
||||||
db.create_all()
|
db.create_all()
|
||||||
|
#
|
||||||
num_of_supervisors = 5
|
# num_of_supervisors = 5
|
||||||
|
#
|
||||||
projects_supervisors = [ProjectSupervisorFactory() for _ in range(num_of_supervisors)]
|
# projects_supervisors = [ProjectSupervisorFactory() for _ in range(num_of_supervisors)]
|
||||||
db.session.add_all(projects_supervisors)
|
# db.session.add_all(projects_supervisors)
|
||||||
db.session.commit()
|
# db.session.commit()
|
||||||
|
#
|
||||||
groups = [GroupFactory(project_supervisor=projects_supervisors[i]) for i in range(num_of_supervisors)]
|
# groups = [GroupFactory(project_supervisor=projects_supervisors[i]) for i in range(num_of_supervisors)]
|
||||||
db.session.add_all(groups)
|
# db.session.add_all(groups)
|
||||||
db.session.commit()
|
# db.session.commit()
|
||||||
|
#
|
||||||
num_of_students = num_of_supervisors * 3
|
# num_of_students = num_of_supervisors * 3
|
||||||
students = [StudentFactory(group=groups[i % num_of_supervisors]) for i in range(num_of_students)]
|
# students = [StudentFactory(group=groups[i % num_of_supervisors]) for i in range(num_of_students)]
|
||||||
|
#
|
||||||
max_count = 10
|
# max_count = 10
|
||||||
max_length = len(students)
|
# max_length = len(students)
|
||||||
start_count = 0
|
# start_count = 0
|
||||||
|
#
|
||||||
while True:
|
# while True:
|
||||||
if start_count > max_length:
|
# if start_count > max_length:
|
||||||
break
|
# break
|
||||||
db.session.add_all(students[start_count:max_count])
|
# db.session.add_all(students[start_count:max_count])
|
||||||
db.session.commit()
|
# db.session.commit()
|
||||||
start_count += max_count
|
# start_count += max_count
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
from flask import Blueprint
|
from flask import Blueprint
|
||||||
|
|
||||||
from .examination_schedule import bp as examination_schedule_bp
|
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 .groups import bp as groups_bp
|
||||||
from .project_supervisor import bp as project_supervisor_bp
|
from .project_supervisor import bp as project_supervisor_bp
|
||||||
from .students import bp as students_bp
|
from .students import bp as students_bp
|
||||||
from .workloads import bp as workloads_bp
|
from .year_group import bp as year_group_bp
|
||||||
|
# from .workloads import bp as workloads_bp
|
||||||
|
|
||||||
bp = Blueprint("coordinator", __name__, url_prefix="/coordinator")
|
bp = Blueprint("coordinator", __name__, url_prefix="/coordinator")
|
||||||
|
|
||||||
bp.register_blueprint(students_bp)
|
bp.register_blueprint(students_bp)
|
||||||
bp.register_blueprint(project_supervisor_bp)
|
bp.register_blueprint(project_supervisor_bp)
|
||||||
bp.register_blueprint(groups_bp)
|
bp.register_blueprint(groups_bp)
|
||||||
|
bp.register_blueprint(year_group_bp)
|
||||||
bp.register_blueprint(examination_schedule_bp)
|
bp.register_blueprint(examination_schedule_bp)
|
||||||
bp.register_blueprint(enrollments_bp)
|
# bp.register_blueprint(enrollments_bp)
|
||||||
bp.register_blueprint(workloads_bp)
|
# bp.register_blueprint(workloads_bp)
|
||||||
|
@ -4,7 +4,7 @@ from apiflask import APIBlueprint
|
|||||||
from flask import abort, current_app
|
from flask import abort, current_app
|
||||||
|
|
||||||
from ..schemas import MessageSchema, EnrollmentCreateSchema
|
from ..schemas import MessageSchema, EnrollmentCreateSchema
|
||||||
from ...examination_schedule.models import Enrollment, Committee, ExaminationSchedule
|
from ...examination_schedule.models import ExaminationSchedule
|
||||||
from ...dependencies import db
|
from ...dependencies import db
|
||||||
|
|
||||||
bp = APIBlueprint("enrollments", __name__, url_prefix="/enrollments")
|
bp = APIBlueprint("enrollments", __name__, url_prefix="/enrollments")
|
||||||
|
@ -5,8 +5,8 @@ from flask import abort, Response, make_response
|
|||||||
|
|
||||||
from ...base.utils import paginate_models
|
from ...base.utils import paginate_models
|
||||||
from ...dependencies import db
|
from ...dependencies import db
|
||||||
from ...examination_schedule.models import ExaminationSchedule, Enrollment
|
from ...examination_schedule.models import ExaminationSchedule
|
||||||
from ...students.models import Group
|
from ...students.models import Group, YearGroup
|
||||||
from ...project_supervisor.models import ProjectSupervisor
|
from ...project_supervisor.models import ProjectSupervisor
|
||||||
from ..schemas import ExaminationScheduleSchema, ExaminationScheduleUpdateSchema, MessageSchema, \
|
from ..schemas import ExaminationScheduleSchema, ExaminationScheduleUpdateSchema, MessageSchema, \
|
||||||
ExaminationSchedulesQuerySchema, ExaminationSchedulesPaginationSchema
|
ExaminationSchedulesQuerySchema, ExaminationSchedulesPaginationSchema
|
||||||
@ -15,21 +15,29 @@ from ..utils import generate_examination_schedule_pdf_file
|
|||||||
bp = APIBlueprint("examination_schedule", __name__, url_prefix="/examination_schedule")
|
bp = APIBlueprint("examination_schedule", __name__, url_prefix="/examination_schedule")
|
||||||
|
|
||||||
|
|
||||||
@bp.get('/')
|
@bp.get('/<int:year_group_id>/')
|
||||||
@bp.input(ExaminationSchedulesQuerySchema, location='query')
|
@bp.input(ExaminationSchedulesQuerySchema, location='query')
|
||||||
@bp.output(ExaminationSchedulesPaginationSchema)
|
@bp.output(ExaminationSchedulesPaginationSchema)
|
||||||
def list_examination_schedule(query: dict) -> dict:
|
def list_examination_schedule(year_group_id: int, query: dict) -> dict:
|
||||||
page = query.get('page')
|
page = query.get('page')
|
||||||
per_page = query.get('per_page')
|
per_page = query.get('per_page')
|
||||||
data = paginate_models(page, ExaminationSchedule.query, per_page)
|
es_query = ExaminationSchedule.query.filter(ExaminationSchedule.year_group_id == year_group_id)
|
||||||
|
data = paginate_models(page, es_query, per_page)
|
||||||
return {'examination_schedules': data['items'], 'max_pages': data['max_pages']}
|
return {'examination_schedules': data['items'], 'max_pages': data['max_pages']}
|
||||||
|
|
||||||
|
|
||||||
@bp.post('/')
|
@bp.post('/<int:year_group_id>/')
|
||||||
@bp.input(ExaminationScheduleSchema)
|
@bp.input(ExaminationScheduleSchema)
|
||||||
@bp.output(MessageSchema)
|
@bp.output(MessageSchema)
|
||||||
def create_examination_schedule(data: dict) -> dict:
|
def create_examination_schedule(year_group_id: int, data: dict) -> dict:
|
||||||
examination_schedule = ExaminationSchedule(**data)
|
yg = YearGroup.query.filter(YearGroup.id == year_group_id).first()
|
||||||
|
if yg is None:
|
||||||
|
abort(404, "Year group doesn't exist!")
|
||||||
|
|
||||||
|
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)
|
||||||
db.session.add(examination_schedule)
|
db.session.add(examination_schedule)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return {"message": "Examination schedule was created!"}
|
return {"message": "Examination schedule was created!"}
|
||||||
@ -70,7 +78,7 @@ def set_date_of_examination_schedule(id: int, data: dict) -> dict:
|
|||||||
if examination_schedule is None:
|
if examination_schedule is None:
|
||||||
abort(404, "Examination schedule doesn't exist!")
|
abort(404, "Examination schedule doesn't exist!")
|
||||||
|
|
||||||
if data['start_date'] > data['end_date']:
|
if data['start_date_for_enrollment_students'] > data['end_date_for_enrollment_students']:
|
||||||
abort(400, "Invalid data! End date must be greater than start date!")
|
abort(400, "Invalid data! End date must be greater than start date!")
|
||||||
|
|
||||||
examination_schedule_query.update(data)
|
examination_schedule_query.update(data)
|
||||||
@ -91,7 +99,7 @@ def download_examination_schedule(examination_schedule_id: int) -> Response:
|
|||||||
nested_enrollments = []
|
nested_enrollments = []
|
||||||
for d in distinct_dates:
|
for d in distinct_dates:
|
||||||
date_tmp = datetime.datetime.strptime(d[0], "%Y-%m-%d").date()
|
date_tmp = datetime.datetime.strptime(d[0], "%Y-%m-%d").date()
|
||||||
enrollment = db.session.query(Enrollment).join(ExaminationSchedule, isouter=True).\
|
enrollment = db.session.query(Enrollment).join(ExaminationSchedule, isouter=True). \
|
||||||
join(Group, isouter=True).join(ProjectSupervisor, isouter=True). \
|
join(Group, isouter=True).join(ProjectSupervisor, isouter=True). \
|
||||||
filter(ExaminationSchedule.id == examination_schedule_id).filter(
|
filter(ExaminationSchedule.id == examination_schedule_id).filter(
|
||||||
db.func.Date(Enrollment.start_date) == date_tmp).all()
|
db.func.Date(Enrollment.start_date) == date_tmp).all()
|
||||||
|
@ -2,8 +2,8 @@ from flask import abort, current_app
|
|||||||
from apiflask import APIBlueprint
|
from apiflask import APIBlueprint
|
||||||
from flask_sqlalchemy import get_debug_queries
|
from flask_sqlalchemy import get_debug_queries
|
||||||
|
|
||||||
from ...students.models import Group, Student
|
from ...students.models import Group, Student, YearGroup
|
||||||
from ...project_supervisor.models import ProjectSupervisor
|
from ...project_supervisor.models import ProjectSupervisor, YearGroupProjectSupervisors
|
||||||
from ..schemas import GroupSchema, GroupEditSchema, GroupsPaginationSchema, \
|
from ..schemas import GroupSchema, GroupEditSchema, GroupsPaginationSchema, \
|
||||||
GroupCreateSchema, MessageSchema, GroupQuerySchema
|
GroupCreateSchema, MessageSchema, GroupQuerySchema
|
||||||
from ...dependencies import db
|
from ...dependencies import db
|
||||||
@ -12,15 +12,15 @@ from ...base.utils import paginate_models
|
|||||||
bp = APIBlueprint("groups", __name__, url_prefix="/groups")
|
bp = APIBlueprint("groups", __name__, url_prefix="/groups")
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/", methods=["GET"])
|
@bp.get("/<int:year_group_id>/")
|
||||||
@bp.input(GroupQuerySchema, location='query')
|
@bp.input(GroupQuerySchema, location='query')
|
||||||
@bp.output(GroupsPaginationSchema)
|
@bp.output(GroupsPaginationSchema)
|
||||||
def list_groups(query: dict) -> dict:
|
def list_groups(year_group_id: int, query: dict) -> dict:
|
||||||
search_name = query.get('name')
|
search_name = query.get('name')
|
||||||
page = query.get('page')
|
page = query.get('page')
|
||||||
per_page = query.get('per_page')
|
per_page = query.get('per_page')
|
||||||
|
|
||||||
groups_query = Group.search_by_name(search_name)
|
groups_query = Group.search_by_name(year_group_id, search_name)
|
||||||
|
|
||||||
data = paginate_models(page, groups_query, per_page)
|
data = paginate_models(page, groups_query, per_page)
|
||||||
|
|
||||||
@ -30,14 +30,18 @@ def list_groups(query: dict) -> dict:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/", methods=["POST"])
|
@bp.post("/<int:year_group_id>/")
|
||||||
@bp.input(GroupCreateSchema)
|
@bp.input(GroupCreateSchema)
|
||||||
@bp.output(MessageSchema)
|
@bp.output(MessageSchema)
|
||||||
def create_group(data: dict) -> dict:
|
def create_group(year_group_id: int, data: dict) -> dict:
|
||||||
name = data['name']
|
name = data['name']
|
||||||
students_indexes = data['students']
|
students_indexes = data['students']
|
||||||
project_supervisor_id = data['project_supervisor_id']
|
project_supervisor_id = data['project_supervisor_id']
|
||||||
|
|
||||||
|
yg = YearGroup.query.filter(YearGroup.id == year_group_id).first()
|
||||||
|
if yg is None:
|
||||||
|
abort(404, "YearGroup doesn't exist!")
|
||||||
|
|
||||||
project_supervisor = ProjectSupervisor.query.filter_by(id=project_supervisor_id).first()
|
project_supervisor = ProjectSupervisor.query.filter_by(id=project_supervisor_id).first()
|
||||||
|
|
||||||
limit_student_per_group = current_app.config.get('LIMIT_STUDENTS_PER_GROUP')
|
limit_student_per_group = current_app.config.get('LIMIT_STUDENTS_PER_GROUP')
|
||||||
@ -47,13 +51,16 @@ def create_group(data: dict) -> dict:
|
|||||||
abort(400, f"Too much students you want add to group, "
|
abort(400, f"Too much students you want add to group, "
|
||||||
f"The group can have only {limit_student_per_group} students")
|
f"The group can have only {limit_student_per_group} students")
|
||||||
|
|
||||||
limit = db.session.query(ProjectSupervisor.limit_group - db.func.count(ProjectSupervisor.id)).join(Group).filter(
|
limit = db.session.query(db.func.count(ProjectSupervisor.id)). \
|
||||||
ProjectSupervisor.id == project_supervisor_id).group_by(ProjectSupervisor.id).scalar()
|
join(Group).filter(ProjectSupervisor.id == project_supervisor_id).group_by(ProjectSupervisor.id).scalar()
|
||||||
|
|
||||||
if limit is not None and limit <= 0:
|
ygps = YearGroupProjectSupervisors.query. \
|
||||||
|
filter(YearGroupProjectSupervisors.year_group_id == year_group_id,
|
||||||
|
YearGroupProjectSupervisors.project_supervisor_id == project_supervisor_id).first()
|
||||||
|
if limit is not None and ygps is not None and limit >= ygps.limit_group:
|
||||||
abort(400, "Can't create new group, project supervisor achieved a limit of groups")
|
abort(400, "Can't create new group, project supervisor achieved a limit of groups")
|
||||||
|
|
||||||
group = Group(name=name, project_supervisor_id=project_supervisor_id)
|
group = Group(name=name, project_supervisor_id=project_supervisor_id, year_group_id=year_group_id)
|
||||||
|
|
||||||
students_without_groups = db.session.query(Student).join(Group, isouter=True) \
|
students_without_groups = db.session.query(Student).join(Group, isouter=True) \
|
||||||
.filter(Group.id.is_(None)).filter(Student.index.in_(students_indexes)).count()
|
.filter(Group.id.is_(None)).filter(Student.index.in_(students_indexes)).count()
|
||||||
@ -65,7 +72,6 @@ def create_group(data: dict) -> dict:
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
students = db.session.query(Student).filter(Student.index.in_(students_indexes)).all()
|
students = db.session.query(Student).filter(Student.index.in_(students_indexes)).all()
|
||||||
project_supervisor.count_groups += 1
|
|
||||||
for student in students:
|
for student in students:
|
||||||
student.group_id = group.id
|
student.group_id = group.id
|
||||||
|
|
||||||
@ -74,7 +80,7 @@ def create_group(data: dict) -> dict:
|
|||||||
return {"message": "Group was created!"}
|
return {"message": "Group was created!"}
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/<int:id>/", methods=["GET"])
|
@bp.get("/<int:id>/")
|
||||||
@bp.output(GroupSchema)
|
@bp.output(GroupSchema)
|
||||||
def detail_group(id: int) -> Group:
|
def detail_group(id: int) -> Group:
|
||||||
group = Group.query.filter_by(id=id).first()
|
group = Group.query.filter_by(id=id).first()
|
||||||
@ -83,16 +89,13 @@ def detail_group(id: int) -> Group:
|
|||||||
return group
|
return group
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/<int:id>/", methods=["DELETE"])
|
@bp.delete("/<int:id>/")
|
||||||
@bp.output(MessageSchema, status_code=202)
|
@bp.output(MessageSchema, status_code=202)
|
||||||
def delete_group(id: int) -> dict:
|
def delete_group(id: int) -> dict:
|
||||||
group = Group.query.filter_by(id=id).first()
|
group = Group.query.filter_by(id=id).first()
|
||||||
if group is None:
|
if group is None:
|
||||||
abort(400, f"Group with id {id} doesn't exist!")
|
abort(400, f"Group with id {id} doesn't exist!")
|
||||||
|
|
||||||
project_supervisor = ProjectSupervisor.query.filter_by(id=group.project_supervisor_id).first()
|
|
||||||
project_supervisor.count_groups -= 1
|
|
||||||
|
|
||||||
students = db.session.query(Student).filter_by(group_id=id).all()
|
students = db.session.query(Student).filter_by(group_id=id).all()
|
||||||
for student in students:
|
for student in students:
|
||||||
student.group_id = None
|
student.group_id = None
|
||||||
@ -102,7 +105,7 @@ def delete_group(id: int) -> dict:
|
|||||||
return {"message": "Group was deleted!"}
|
return {"message": "Group was deleted!"}
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/<int:id>", methods=["PUT"])
|
@bp.put("/<int:id>/")
|
||||||
@bp.input(GroupEditSchema)
|
@bp.input(GroupEditSchema)
|
||||||
@bp.output(MessageSchema)
|
@bp.output(MessageSchema)
|
||||||
def edit_group(id: int, data: dict) -> dict:
|
def edit_group(id: int, data: dict) -> dict:
|
||||||
|
@ -2,29 +2,28 @@ from flask import abort
|
|||||||
from apiflask import APIBlueprint
|
from apiflask import APIBlueprint
|
||||||
from flask_sqlalchemy import get_debug_queries
|
from flask_sqlalchemy import get_debug_queries
|
||||||
|
|
||||||
from ...project_supervisor.models import ProjectSupervisor
|
from ...project_supervisor.models import ProjectSupervisor, YearGroupProjectSupervisors
|
||||||
from ...students.models import Group
|
from ...students.models import Group, YearGroup
|
||||||
from ..schemas import ProjectSupervisorSchema, ProjectSupervisorEditSchema, ProjectSupervisorsPaginationSchema, \
|
from ..schemas import ProjectSupervisorSchema, ProjectSupervisorEditSchema, ProjectSupervisorsPaginationSchema, \
|
||||||
ProjectSupervisorCreateSchema, MessageSchema, ProjectSupervisorQuerySchema
|
ProjectSupervisorCreateSchema, MessageSchema, ProjectSupervisorQuerySchema, ProjectSupervisorYearGroupSchema
|
||||||
from ...dependencies import db
|
from ...dependencies import db
|
||||||
from ...base.utils import paginate_models
|
from ...base.utils import paginate_models
|
||||||
|
|
||||||
bp = APIBlueprint("project_supervisor", __name__, url_prefix="/project_supervisor")
|
bp = APIBlueprint("project_supervisor", __name__, url_prefix="/project_supervisor")
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/", methods=["GET"])
|
@bp.get("/")
|
||||||
@bp.input(ProjectSupervisorQuerySchema, location='query')
|
@bp.input(ProjectSupervisorQuerySchema, location='query')
|
||||||
@bp.output(ProjectSupervisorsPaginationSchema)
|
@bp.output(ProjectSupervisorsPaginationSchema)
|
||||||
def list_project_supervisors(query: dict) -> dict:
|
def list_project_supervisors(query: dict) -> dict:
|
||||||
fullname = query.get('fullname')
|
fullname = query.get('fullname')
|
||||||
order_by_first_name = query.get('order_by_first_name')
|
order_by_first_name = query.get('order_by_first_name')
|
||||||
order_by_last_name = query.get('order_by_last_name')
|
order_by_last_name = query.get('order_by_last_name')
|
||||||
mode = query.get('mode')
|
|
||||||
page = query.get('page')
|
page = query.get('page')
|
||||||
per_page = query.get('per_page')
|
per_page = query.get('per_page')
|
||||||
|
|
||||||
project_supervisor_query = ProjectSupervisor.search_by_fullname_and_mode_and_order_by_first_name_or_last_name(
|
project_supervisor_query = ProjectSupervisor.search_by_fullname_and_mode_and_order_by_first_name_or_last_name(
|
||||||
fullname, mode, order_by_first_name, order_by_last_name)
|
None, fullname, order_by_first_name, order_by_last_name)
|
||||||
|
|
||||||
data = paginate_models(page, project_supervisor_query, per_page)
|
data = paginate_models(page, project_supervisor_query, per_page)
|
||||||
# print(get_debug_queries()[0])
|
# print(get_debug_queries()[0])
|
||||||
@ -34,7 +33,28 @@ def list_project_supervisors(query: dict) -> dict:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/", methods=["POST"])
|
@bp.get("/<int:year_group_id>/")
|
||||||
|
@bp.input(ProjectSupervisorQuerySchema, location='query')
|
||||||
|
@bp.output(ProjectSupervisorsPaginationSchema)
|
||||||
|
def list_project_supervisors_by_year_group(year_group_id: int, query: dict) -> dict:
|
||||||
|
fullname = query.get('fullname')
|
||||||
|
order_by_first_name = query.get('order_by_first_name')
|
||||||
|
order_by_last_name = query.get('order_by_last_name')
|
||||||
|
page = query.get('page')
|
||||||
|
per_page = query.get('per_page')
|
||||||
|
|
||||||
|
project_supervisor_query = ProjectSupervisor.search_by_fullname_and_mode_and_order_by_first_name_or_last_name(
|
||||||
|
year_group_id, fullname, order_by_first_name, order_by_last_name)
|
||||||
|
|
||||||
|
data = paginate_models(page, project_supervisor_query, per_page)
|
||||||
|
# print(get_debug_queries()[0])
|
||||||
|
return {
|
||||||
|
"project_supervisors": data['items'],
|
||||||
|
"max_pages": data['max_pages']
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@bp.post("/")
|
||||||
@bp.input(ProjectSupervisorCreateSchema)
|
@bp.input(ProjectSupervisorCreateSchema)
|
||||||
@bp.output(MessageSchema)
|
@bp.output(MessageSchema)
|
||||||
def create_project_supervisor(data: dict) -> dict:
|
def create_project_supervisor(data: dict) -> dict:
|
||||||
@ -52,7 +72,7 @@ def create_project_supervisor(data: dict) -> dict:
|
|||||||
return {"message": "Project Supervisor was created!"}
|
return {"message": "Project Supervisor was created!"}
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/<int:id>/", methods=["GET"])
|
@bp.get("/<int:id>/")
|
||||||
@bp.output(ProjectSupervisorSchema)
|
@bp.output(ProjectSupervisorSchema)
|
||||||
def detail_project_supervisor(id: int) -> ProjectSupervisor:
|
def detail_project_supervisor(id: int) -> ProjectSupervisor:
|
||||||
project_supervisor = ProjectSupervisor.query.filter_by(id=id).first()
|
project_supervisor = ProjectSupervisor.query.filter_by(id=id).first()
|
||||||
@ -61,25 +81,25 @@ def detail_project_supervisor(id: int) -> ProjectSupervisor:
|
|||||||
return project_supervisor
|
return project_supervisor
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/<int:id>/", methods=["DELETE"])
|
@bp.delete("/<int:id>/")
|
||||||
@bp.output(MessageSchema, status_code=202)
|
@bp.output(MessageSchema, status_code=202)
|
||||||
def delete_project_supervisor(id: int) -> dict:
|
def delete_project_supervisor(id: int) -> dict:
|
||||||
project_supervisor = ProjectSupervisor.query.filter_by(id=id).first()
|
project_supervisor = ProjectSupervisor.query.filter_by(id=id).first()
|
||||||
if project_supervisor is None:
|
if project_supervisor is None:
|
||||||
abort(400, f"Project Supervisor with id {id} doesn't exist!")
|
abort(400, f"Project Supervisor with id {id} doesn't exist!")
|
||||||
|
|
||||||
count_groups = db.session.query(db.func.count(ProjectSupervisor.id)).join(Group).\
|
count_groups = db.session.query(db.func.count(ProjectSupervisor.id)).join(Group). \
|
||||||
filter(ProjectSupervisor.id == id).group_by(ProjectSupervisor.id)
|
filter(ProjectSupervisor.id == id).group_by(ProjectSupervisor.id)
|
||||||
|
|
||||||
if count_groups is not None:
|
if count_groups is not None:
|
||||||
abort(400, f"Project Supervisor with id {id} has gropus!")
|
abort(400, f"Project Supervisor with id {id} has groups!")
|
||||||
|
|
||||||
db.session.delete(project_supervisor)
|
db.session.delete(project_supervisor)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return {"message": "Project Supervisor was deleted!"}
|
return {"message": "Project Supervisor was deleted!"}
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/<int:id>", methods=["PUT"])
|
@bp.put("/<int:id>/")
|
||||||
@bp.input(ProjectSupervisorEditSchema)
|
@bp.input(ProjectSupervisorEditSchema)
|
||||||
@bp.output(MessageSchema)
|
@bp.output(MessageSchema)
|
||||||
def edit_project_supervisor(id: int, data: dict) -> dict:
|
def edit_project_supervisor(id: int, data: dict) -> dict:
|
||||||
@ -95,3 +115,65 @@ def edit_project_supervisor(id: int, data: dict) -> dict:
|
|||||||
project_supervisor_query.update(data)
|
project_supervisor_query.update(data)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return {"message": "Project Supervisor was updated!"}
|
return {"message": "Project Supervisor was updated!"}
|
||||||
|
|
||||||
|
|
||||||
|
@bp.post("/<int:id>/year-group/<int:year_group_id>")
|
||||||
|
@bp.input(ProjectSupervisorYearGroupSchema)
|
||||||
|
@bp.output(MessageSchema)
|
||||||
|
def add_project_supervisor_to_year_group(id: int, year_group_id: int, data: dict) -> dict:
|
||||||
|
if not data:
|
||||||
|
abort(400, 'You have passed empty data!')
|
||||||
|
|
||||||
|
limit_group = data.get('limit_group')
|
||||||
|
|
||||||
|
project_supervisor = ProjectSupervisor.query.filter(ProjectSupervisor.id == id).first()
|
||||||
|
if project_supervisor is None:
|
||||||
|
abort(400, f"Project Supervisor with id {id} doesn't exist!")
|
||||||
|
|
||||||
|
year_group = YearGroup.query.filter(YearGroup.id == year_group_id).first()
|
||||||
|
if year_group is None:
|
||||||
|
abort(400, "Year group doesn't exist!")
|
||||||
|
|
||||||
|
ygps = YearGroupProjectSupervisors.query.filter(YearGroupProjectSupervisors.project_supervisor_id == id). \
|
||||||
|
filter(YearGroupProjectSupervisors.year_group_id == year_group_id).first()
|
||||||
|
if ygps is not None:
|
||||||
|
abort(400, "Project supervisor is assigned to this year group!")
|
||||||
|
|
||||||
|
ygps = YearGroupProjectSupervisors(year_group_id=year_group_id, project_supervisor_id=id,
|
||||||
|
limit_group=limit_group)
|
||||||
|
db.session.add(ygps)
|
||||||
|
db.session.commit()
|
||||||
|
return {"message": "Project Supervisor was added to year group!"}
|
||||||
|
|
||||||
|
|
||||||
|
@bp.delete("/<int:id>/year-group/<int:year_group_id>")
|
||||||
|
@bp.input(ProjectSupervisorYearGroupSchema)
|
||||||
|
@bp.output(MessageSchema)
|
||||||
|
def delete_project_supervisor_to_year_group(id: int, year_group_id: int) -> dict:
|
||||||
|
project_supervisor = ProjectSupervisor.query.filter(ProjectSupervisor.id == id). \
|
||||||
|
filter(YearGroup.id == year_group_id).first()
|
||||||
|
if project_supervisor is None:
|
||||||
|
abort(400, "Project Supervisor doesn't exist!")
|
||||||
|
|
||||||
|
ygps = YearGroupProjectSupervisors.query.filter(YearGroupProjectSupervisors.project_supervisor_id == id). \
|
||||||
|
filter(YearGroupProjectSupervisors.year_group_id == year_group_id).first()
|
||||||
|
db.session.delete(project_supervisor)
|
||||||
|
db.session.delete(ygps)
|
||||||
|
db.session.commit()
|
||||||
|
return {"message": "Project Supervisor was removed from this year group!"}
|
||||||
|
|
||||||
|
|
||||||
|
@bp.put("/<int:id>/year-group/<int:year_group_id>")
|
||||||
|
@bp.input(ProjectSupervisorYearGroupSchema)
|
||||||
|
@bp.output(MessageSchema)
|
||||||
|
def update_limit_of_group_for_project_supervisor(id: int, year_group_id: int, data: dict) -> dict:
|
||||||
|
project_supervisor = ProjectSupervisor.query.filter(ProjectSupervisor.id == id). \
|
||||||
|
filter(YearGroup.id == year_group_id).first()
|
||||||
|
if project_supervisor is None:
|
||||||
|
abort(400, "Project Supervisor doesn't exist!")
|
||||||
|
|
||||||
|
ygps = YearGroupProjectSupervisors.query.filter(YearGroupProjectSupervisors.project_supervisor_id == id). \
|
||||||
|
filter(YearGroupProjectSupervisors.year_group_id == year_group_id)
|
||||||
|
ygps.update(data)
|
||||||
|
db.session.commit()
|
||||||
|
return {"message": "Limit of group was changed!"}
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
from random import randint
|
from random import randint
|
||||||
from itertools import islice
|
from itertools import islice
|
||||||
from typing import List
|
|
||||||
|
|
||||||
from flask import Response, abort
|
from flask import Response, abort
|
||||||
from apiflask import APIBlueprint
|
from apiflask import APIBlueprint
|
||||||
from sqlalchemy.exc import IntegrityError
|
from sqlalchemy.exc import IntegrityError
|
||||||
from flask_sqlalchemy import get_debug_queries
|
from flask_sqlalchemy import get_debug_queries
|
||||||
|
|
||||||
from ...students.models import Student, Group
|
from ...students.models import Student, Group, YearGroup, YearGroupStudents
|
||||||
from ...project_supervisor.models import ProjectSupervisor
|
from ...project_supervisor.models import ProjectSupervisor
|
||||||
from ..schemas import StudentSchema, StudentEditSchema, StudentsPaginationSchema, \
|
from ..schemas import StudentSchema, StudentEditSchema, StudentsPaginationSchema, \
|
||||||
StudentCreateSchema, MessageSchema, FileSchema, StudentQuerySchema, StudentListFileDownloaderSchema
|
StudentCreateSchema, MessageSchema, FileSchema, StudentQuerySchema, StudentListFileDownloaderSchema
|
||||||
@ -19,19 +18,19 @@ from ...base.utils import paginate_models, is_allowed_extensions
|
|||||||
bp = APIBlueprint("students", __name__, url_prefix="/students")
|
bp = APIBlueprint("students", __name__, url_prefix="/students")
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/", methods=["GET"])
|
@bp.get("/<int:year_group_id>/")
|
||||||
@bp.input(StudentQuerySchema, location='query')
|
@bp.input(StudentQuerySchema, location='query')
|
||||||
@bp.output(StudentsPaginationSchema)
|
@bp.output(StudentsPaginationSchema)
|
||||||
def list_students(query: dict) -> dict:
|
def list_students(year_group_id: int, query: dict) -> dict:
|
||||||
|
# add filter by year group
|
||||||
fullname = query.get('fullname')
|
fullname = query.get('fullname')
|
||||||
order_by_first_name = query.get('order_by_first_name')
|
order_by_first_name = query.get('order_by_first_name')
|
||||||
order_by_last_name = query.get('order_by_last_name')
|
order_by_last_name = query.get('order_by_last_name')
|
||||||
mode = query.get('mode')
|
|
||||||
page = query.get('page')
|
page = query.get('page')
|
||||||
per_page = query.get('per_page')
|
per_page = query.get('per_page')
|
||||||
|
|
||||||
student_query = Student.search_by_fullname_and_mode_and_order_by_first_name_or_last_name(
|
student_query = Student.search_by_fullname_and_mode_and_order_by_first_name_or_last_name(
|
||||||
fullname, mode, order_by_first_name, order_by_last_name)
|
year_group_id, fullname, order_by_first_name, order_by_last_name)
|
||||||
|
|
||||||
data = paginate_models(page, student_query, per_page)
|
data = paginate_models(page, student_query, per_page)
|
||||||
# print(get_debug_queries()[0])
|
# print(get_debug_queries()[0])
|
||||||
@ -41,7 +40,7 @@ def list_students(query: dict) -> dict:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/<int:index>/", methods=["GET"])
|
@bp.get("/<int:index>/")
|
||||||
@bp.output(StudentSchema)
|
@bp.output(StudentSchema)
|
||||||
def detail_student(index: int) -> Student:
|
def detail_student(index: int) -> Student:
|
||||||
student = Student.query.filter_by(index=index).first()
|
student = Student.query.filter_by(index=index).first()
|
||||||
@ -50,7 +49,7 @@ def detail_student(index: int) -> Student:
|
|||||||
return student
|
return student
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/<int:index>/", methods=["DELETE"])
|
@bp.delete("/<int:index>/")
|
||||||
@bp.output(MessageSchema, status_code=202)
|
@bp.output(MessageSchema, status_code=202)
|
||||||
def delete_student(index: int) -> dict:
|
def delete_student(index: int) -> dict:
|
||||||
student = Student.query.filter_by(index=index).first()
|
student = Student.query.filter_by(index=index).first()
|
||||||
@ -61,7 +60,7 @@ def delete_student(index: int) -> dict:
|
|||||||
return {"message": "Student was deleted!"}
|
return {"message": "Student was deleted!"}
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/<int:index>/", methods=["PUT"])
|
@bp.put("/<int:index>/")
|
||||||
@bp.input(StudentEditSchema)
|
@bp.input(StudentEditSchema)
|
||||||
@bp.output(MessageSchema)
|
@bp.output(MessageSchema)
|
||||||
def edit_student(index: int, data: dict) -> dict:
|
def edit_student(index: int, data: dict) -> dict:
|
||||||
@ -80,11 +79,13 @@ def edit_student(index: int, data: dict) -> dict:
|
|||||||
return {"message": "Student was updated!"}
|
return {"message": "Student was updated!"}
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/", methods=["POST"])
|
@bp.post("/")
|
||||||
@bp.input(StudentCreateSchema)
|
@bp.input(StudentCreateSchema)
|
||||||
@bp.output(MessageSchema)
|
@bp.output(MessageSchema)
|
||||||
def create_student(data: dict) -> dict:
|
def create_student(data: dict) -> dict:
|
||||||
index = data['index']
|
index = data['index']
|
||||||
|
yg_id = data['year_group_id']
|
||||||
|
del data['year_group_id']
|
||||||
student = Student.query.filter_by(index=index).first()
|
student = Student.query.filter_by(index=index).first()
|
||||||
if student is not None:
|
if student is not None:
|
||||||
abort(400, "Student has already exists!")
|
abort(400, "Student has already exists!")
|
||||||
@ -92,12 +93,20 @@ def create_student(data: dict) -> dict:
|
|||||||
dummy_email = f'student{randint(1, 300_000)}@gmail.com'
|
dummy_email = f'student{randint(1, 300_000)}@gmail.com'
|
||||||
student = Student(**data, email=dummy_email)
|
student = Student(**data, email=dummy_email)
|
||||||
db.session.add(student)
|
db.session.add(student)
|
||||||
|
|
||||||
|
# add student to the chosen year group
|
||||||
|
year_group = YearGroup.query.filter(YearGroup.id == yg_id).first()
|
||||||
|
if year_group is None:
|
||||||
|
abort(400, "Year group doesn't exist!")
|
||||||
|
ygs = YearGroupStudents(student_index=student.index, year_group_id=year_group.id)
|
||||||
|
db.session.add(ygs)
|
||||||
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
return {"message": "Student was created!"}
|
return {"message": "Student was created!"}
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/upload/", methods=["POST"])
|
@bp.post("/upload/")
|
||||||
@bp.input(FileSchema, location='form_and_files')
|
@bp.input(FileSchema, location='form_and_files')
|
||||||
@bp.output(MessageSchema)
|
@bp.output(MessageSchema)
|
||||||
def upload_students(file: dict) -> dict:
|
def upload_students(file: dict) -> dict:
|
||||||
@ -125,7 +134,7 @@ def upload_students(file: dict) -> dict:
|
|||||||
return {"message": "Students was created by uploading csv file!"}
|
return {"message": "Students was created by uploading csv file!"}
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/download/", methods=["POST"])
|
@bp.post("/download/")
|
||||||
@bp.input(StudentListFileDownloaderSchema, location='query')
|
@bp.input(StudentListFileDownloaderSchema, location='query')
|
||||||
def download_students(query: dict) -> Response:
|
def download_students(query: dict) -> Response:
|
||||||
mode = query.get('mode')
|
mode = query.get('mode')
|
||||||
|
72
backend/app/coordinator/routes/year_group.py
Normal file
72
backend/app/coordinator/routes/year_group.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
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
|
||||||
|
from ...dependencies import db
|
||||||
|
from ...base.utils import paginate_models
|
||||||
|
|
||||||
|
bp = APIBlueprint("year_group", __name__, url_prefix="/year-group")
|
||||||
|
|
||||||
|
|
||||||
|
@bp.post('/')
|
||||||
|
@bp.input(YearGroupSchema)
|
||||||
|
@bp.output(MessageSchema, status_code=200)
|
||||||
|
def create_year_group(data: dict) -> dict:
|
||||||
|
name = data['name']
|
||||||
|
year_group = YearGroup.query.filter(YearGroup.name == name).first()
|
||||||
|
if year_group is not None:
|
||||||
|
abort(400, "Year group has already exists!")
|
||||||
|
|
||||||
|
yg = YearGroup(**data)
|
||||||
|
db.session.add(yg)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return {"message": "Year group was created!"}
|
||||||
|
|
||||||
|
|
||||||
|
@bp.get('/')
|
||||||
|
@bp.input(YearGroupQuerySchema, location='query')
|
||||||
|
@bp.output(YearGroupPaginationSchema)
|
||||||
|
def list_of_year_groups(query: dict) -> dict:
|
||||||
|
page = query.get('page')
|
||||||
|
per_page = query.get('per_page')
|
||||||
|
|
||||||
|
year_group_query = YearGroup.query.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']
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@bp.put('/<int:id>/')
|
||||||
|
@bp.input(YearGroupSchema)
|
||||||
|
@bp.output(MessageSchema)
|
||||||
|
def update_year_of_group(id: int, data: dict) -> dict:
|
||||||
|
if not data:
|
||||||
|
abort(400, 'You have passed empty data!')
|
||||||
|
|
||||||
|
year_group_query = YearGroup.query.filter(YearGroup.id == id)
|
||||||
|
year_group = year_group_query.first()
|
||||||
|
|
||||||
|
if year_group is None:
|
||||||
|
abort(404, 'Not found year group!')
|
||||||
|
|
||||||
|
year_group_query.update(data)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return {"message": "Year group was updated!"}
|
||||||
|
|
||||||
|
|
||||||
|
@bp.delete('/<int:id>/')
|
||||||
|
@bp.output(MessageSchema, status_code=202)
|
||||||
|
def delete_year_of_group(id: int) -> dict:
|
||||||
|
year_group = YearGroup.query.filter_by(id=id).first()
|
||||||
|
if year_group is None:
|
||||||
|
abort(404, f"Year group doesn't exist!")
|
||||||
|
db.session.delete(year_group)
|
||||||
|
db.session.commit()
|
||||||
|
return {"message": "Year group was deleted!"}
|
@ -3,7 +3,8 @@ from .examination_schedule import ExaminationScheduleSchema, ExaminationSchedule
|
|||||||
ExaminationSchedulesPaginationSchema, ExaminationSchedulesQuerySchema, WorkloadSchema
|
ExaminationSchedulesPaginationSchema, ExaminationSchedulesQuerySchema, WorkloadSchema
|
||||||
from .groups import GroupQuerySchema, GroupsPaginationSchema, GroupCreateSchema, GroupEditSchema
|
from .groups import GroupQuerySchema, GroupsPaginationSchema, GroupCreateSchema, GroupEditSchema
|
||||||
from .project_supervisor import ProjectSupervisorQuerySchema, ProjectSupervisorsPaginationSchema, \
|
from .project_supervisor import ProjectSupervisorQuerySchema, ProjectSupervisorsPaginationSchema, \
|
||||||
ProjectSupervisorCreateSchema, ProjectSupervisorEditSchema
|
ProjectSupervisorCreateSchema, ProjectSupervisorEditSchema, ProjectSupervisorYearGroupSchema
|
||||||
from .students import ProjectSupervisorSchema, GroupSchema, StudentSchema, StudentsPaginationSchema, \
|
from .students import ProjectSupervisorSchema, GroupSchema, StudentSchema, StudentsPaginationSchema, \
|
||||||
StudentListFileDownloaderSchema, StudentCreateSchema, StudentEditSchema, MessageSchema, FileSchema, \
|
StudentListFileDownloaderSchema, StudentCreateSchema, StudentEditSchema, MessageSchema, FileSchema, \
|
||||||
StudentQuerySchema
|
StudentQuerySchema
|
||||||
|
from .year_group import YearGroupSchema, YearGroupPaginationSchema, YearGroupQuerySchema
|
||||||
|
@ -5,20 +5,22 @@ from ..validators import validate_datetime_greater_than_now
|
|||||||
|
|
||||||
class ExaminationScheduleSchema(Schema):
|
class ExaminationScheduleSchema(Schema):
|
||||||
title = fields.Str(validate=validate.Length(min=1, max=100), required=True)
|
title = fields.Str(validate=validate.Length(min=1, max=100), required=True)
|
||||||
mode = fields.Boolean(required=True)
|
start_date = fields.DateTime(validate=validate_datetime_greater_than_now, required=True)
|
||||||
|
end_date = fields.DateTime(validate=validate_datetime_greater_than_now, required=True)
|
||||||
|
|
||||||
|
|
||||||
class ExaminationScheduleUpdateSchema(Schema):
|
class ExaminationScheduleUpdateSchema(Schema):
|
||||||
start_date = fields.DateTime(validate=validate_datetime_greater_than_now, required=True)
|
start_date_for_enrollment_students = fields.DateTime(validate=validate_datetime_greater_than_now, required=True)
|
||||||
end_date = fields.DateTime(validate=validate_datetime_greater_than_now, required=True)
|
end_date_for_enrollment_students = fields.DateTime(validate=validate_datetime_greater_than_now, required=True)
|
||||||
|
|
||||||
|
|
||||||
class ExaminationScheduleListItemSchema(Schema):
|
class ExaminationScheduleListItemSchema(Schema):
|
||||||
id = fields.Integer(required=True)
|
id = fields.Integer()
|
||||||
title = fields.Str(validate=validate.Length(min=1, max=100), required=True)
|
title = fields.Str()
|
||||||
mode = fields.Boolean(required=True)
|
start_date = fields.DateTime()
|
||||||
start_date = fields.DateTime(validate=validate_datetime_greater_than_now, required=True)
|
end_date = fields.DateTime()
|
||||||
end_date = fields.DateTime(validate=validate_datetime_greater_than_now, required=True)
|
start_date_for_enrollment_students = fields.DateTime()
|
||||||
|
end_date_for_enrollment_students = fields.DateTime()
|
||||||
|
|
||||||
|
|
||||||
class ExaminationSchedulesPaginationSchema(Schema):
|
class ExaminationSchedulesPaginationSchema(Schema):
|
||||||
@ -32,7 +34,7 @@ class ExaminationSchedulesQuerySchema(Schema):
|
|||||||
|
|
||||||
|
|
||||||
class ProjectSupervisorStatisticsSchema(Schema):
|
class ProjectSupervisorStatisticsSchema(Schema):
|
||||||
full_name = fields.Str()
|
fullname = fields.Str()
|
||||||
assigned_to_committee = fields.Integer()
|
assigned_to_committee = fields.Integer()
|
||||||
groups_assigned_to_his_committee = fields.Integer()
|
groups_assigned_to_his_committee = fields.Integer()
|
||||||
|
|
||||||
|
@ -1,36 +1,32 @@
|
|||||||
from marshmallow import fields, validate
|
from marshmallow import fields, validate, Schema
|
||||||
|
|
||||||
from ...dependencies import ma
|
|
||||||
from ..validators import validate_index
|
|
||||||
from .students import ProjectSupervisorSchema
|
from .students import ProjectSupervisorSchema
|
||||||
|
|
||||||
|
|
||||||
class ProjectSupervisorQuerySchema(ma.Schema):
|
class ProjectSupervisorQuerySchema(Schema):
|
||||||
fullname = fields.Str()
|
fullname = fields.Str()
|
||||||
order_by_first_name = fields.Str()
|
order_by_first_name = fields.Str()
|
||||||
order_by_last_name = fields.Str()
|
order_by_last_name = fields.Str()
|
||||||
page = fields.Integer()
|
page = fields.Integer()
|
||||||
per_page = fields.Integer()
|
per_page = fields.Integer()
|
||||||
mode = fields.Integer()
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectSupervisorsPaginationSchema(ma.Schema):
|
class ProjectSupervisorsPaginationSchema(Schema):
|
||||||
project_supervisors = fields.List(fields.Nested(ProjectSupervisorSchema))
|
project_supervisors = fields.List(fields.Nested(ProjectSupervisorSchema))
|
||||||
max_pages = fields.Integer()
|
max_pages = fields.Integer()
|
||||||
|
|
||||||
|
|
||||||
class ProjectSupervisorCreateSchema(ma.Schema):
|
class ProjectSupervisorCreateSchema(Schema):
|
||||||
first_name = fields.Str(validate=validate.Length(min=1, max=255), required=True)
|
first_name = fields.Str(validate=validate.Length(min=1, max=255), required=True)
|
||||||
last_name = fields.Str(validate=validate.Length(min=1, max=255), required=True)
|
last_name = fields.Str(validate=validate.Length(min=1, max=255), required=True)
|
||||||
email = fields.Str(validate=validate.Length(min=1, max=255), required=True)
|
email = fields.Str(validate=validate.Length(min=1, max=255), required=True)
|
||||||
limit_group = fields.Integer()
|
|
||||||
mode = fields.Integer(required=True)
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectSupervisorEditSchema(ma.Schema):
|
class ProjectSupervisorEditSchema(Schema):
|
||||||
first_name = fields.Str(validate=validate.Length(min=1, max=255), required=True)
|
first_name = fields.Str(validate=validate.Length(min=1, max=255), required=True)
|
||||||
last_name = fields.Str(validate=validate.Length(min=1, max=255), required=True)
|
last_name = fields.Str(validate=validate.Length(min=1, max=255), required=True)
|
||||||
email = fields.Str(validate=validate.Length(min=0, max=11), required=True)
|
email = fields.Str(validate=validate.Length(min=0, max=11), required=True)
|
||||||
limit_group = fields.Integer(validate=validate_index)
|
|
||||||
count_groups = fields.Integer(validate=validate_index)
|
|
||||||
mode = fields.Integer(required=True)
|
class ProjectSupervisorYearGroupSchema(Schema):
|
||||||
|
limit_group = fields.Integer(required=True)
|
||||||
|
@ -40,7 +40,7 @@ class StudentCreateSchema(ma.Schema):
|
|||||||
last_name = fields.Str(validate=validate.Length(min=1, max=255), required=True)
|
last_name = fields.Str(validate=validate.Length(min=1, max=255), required=True)
|
||||||
pesel = fields.Str(validate=validate.Length(min=0, max=11), required=True)
|
pesel = fields.Str(validate=validate.Length(min=0, max=11), required=True)
|
||||||
index = fields.Integer(validate=validate_index, required=True)
|
index = fields.Integer(validate=validate_index, required=True)
|
||||||
mode = fields.Boolean(required=True)
|
year_group_id = fields.Integer()
|
||||||
|
|
||||||
|
|
||||||
class StudentEditSchema(ma.Schema):
|
class StudentEditSchema(ma.Schema):
|
||||||
@ -48,7 +48,6 @@ class StudentEditSchema(ma.Schema):
|
|||||||
last_name = fields.Str(validate=validate.Length(min=1, max=255))
|
last_name = fields.Str(validate=validate.Length(min=1, max=255))
|
||||||
pesel = fields.Str(validate=validate.Length(min=0, max=11))
|
pesel = fields.Str(validate=validate.Length(min=0, max=11))
|
||||||
index = fields.Integer(validate=validate_index)
|
index = fields.Integer(validate=validate_index)
|
||||||
mode = fields.Boolean()
|
|
||||||
|
|
||||||
|
|
||||||
class MessageSchema(ma.Schema):
|
class MessageSchema(ma.Schema):
|
||||||
@ -65,4 +64,3 @@ class StudentQuerySchema(ma.Schema):
|
|||||||
order_by_last_name = fields.Str()
|
order_by_last_name = fields.Str()
|
||||||
page = fields.Integer()
|
page = fields.Integer()
|
||||||
per_page = fields.Integer()
|
per_page = fields.Integer()
|
||||||
mode = fields.Boolean()
|
|
||||||
|
30
backend/app/coordinator/schemas/year_group.py
Normal file
30
backend/app/coordinator/schemas/year_group.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
from marshmallow import Schema, fields, validate, ValidationError
|
||||||
|
|
||||||
|
from ...base.mode import ModeGroups
|
||||||
|
|
||||||
|
|
||||||
|
def validate_mode(value: str) -> str:
|
||||||
|
if value not in [m.value for m in ModeGroups]:
|
||||||
|
raise ValidationError("Invalid mode!")
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
class YearGroupSchema(Schema):
|
||||||
|
name = fields.Str(validate=validate.Regexp('^\d{4}/\d{4}$'), required=True)
|
||||||
|
mode = fields.Str(validate=validate_mode, required=True)
|
||||||
|
|
||||||
|
|
||||||
|
class YearGroupItemSchema(Schema):
|
||||||
|
id = fields.Integer()
|
||||||
|
name = fields.Str()
|
||||||
|
mode = fields.Str()
|
||||||
|
|
||||||
|
|
||||||
|
class YearGroupPaginationSchema(Schema):
|
||||||
|
year_groups = fields.List(fields.Nested(YearGroupItemSchema))
|
||||||
|
max_pages = fields.Integer()
|
||||||
|
|
||||||
|
|
||||||
|
class YearGroupQuerySchema(Schema):
|
||||||
|
page = fields.Integer()
|
||||||
|
per_page = fields.Integer()
|
@ -13,7 +13,7 @@ from reportlab.platypus import SimpleDocTemplate, Paragraph, PageBreak, Table
|
|||||||
|
|
||||||
from .exceptions import InvalidNameOrTypeHeaderException
|
from .exceptions import InvalidNameOrTypeHeaderException
|
||||||
from ..students.models import Student
|
from ..students.models import Student
|
||||||
from ..examination_schedule.models import Enrollment
|
# from ..examination_schedule.models import Enrollment
|
||||||
|
|
||||||
|
|
||||||
def check_columns(df: pd.DataFrame) -> bool:
|
def check_columns(df: pd.DataFrame) -> bool:
|
||||||
@ -66,7 +66,7 @@ def generate_csv(students: List[Student]) -> str:
|
|||||||
return df.to_csv(index=False)
|
return df.to_csv(index=False)
|
||||||
|
|
||||||
|
|
||||||
def generate_examination_schedule_pdf_file(title: str, nested_enrollments: List[List[Enrollment]]) -> bytes:
|
def generate_examination_schedule_pdf_file(title: str, nested_enrollments: List[List[object]]) -> bytes:
|
||||||
pagesize = (297 * mm, 210 * mm)
|
pagesize = (297 * mm, 210 * mm)
|
||||||
headers = ["lp.", "Godzina", "Nazwa projektu", "Opiekun", "Zespol", "Komisja"]
|
headers = ["lp.", "Godzina", "Nazwa projektu", "Opiekun", "Zespol", "Komisja"]
|
||||||
pdf_buffer = BytesIO()
|
pdf_buffer = BytesIO()
|
||||||
|
@ -6,33 +6,40 @@ class ExaminationSchedule(Base):
|
|||||||
__tablename__ = 'examination_schedules'
|
__tablename__ = 'examination_schedules'
|
||||||
|
|
||||||
title = db.Column(db.String(100), unique=True, nullable=False)
|
title = db.Column(db.String(100), unique=True, nullable=False)
|
||||||
mode = db.Column(db.Boolean, default=True, nullable=False) # True - stationary, False - non-stationary
|
duration_time = db.Column(db.Integer) # in minutes
|
||||||
start_date = db.Column(db.DateTime)
|
start_date_for_enrollment_students = db.Column(db.DateTime)
|
||||||
end_date = db.Column(db.DateTime)
|
end_date_for_enrollment_students = db.Column(db.DateTime)
|
||||||
|
start_date = db.Column(db.DateTime, nullable=False)
|
||||||
|
end_date = db.Column(db.DateTime, nullable=False)
|
||||||
|
year_group_id = db.Column(db.Integer, db.ForeignKey('year_groups.id'), nullable=False)
|
||||||
|
year_group = db.relationship('YearGroup', backref='examination_schedules')
|
||||||
|
|
||||||
|
|
||||||
class Enrollment(Base):
|
committee = db.Table(
|
||||||
__tablename__ = 'enrollments'
|
"committees",
|
||||||
|
db.Column("term_of_defence_id", db.ForeignKey("term_of_defences.id")),
|
||||||
|
db.Column("project_supervisor_id", db.ForeignKey("project_supervisors.id")),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TermOfDefence(Base):
|
||||||
|
__tablename__ = 'term_of_defences'
|
||||||
|
|
||||||
start_date = db.Column(db.DateTime, nullable=False)
|
start_date = db.Column(db.DateTime, nullable=False)
|
||||||
end_date = db.Column(db.DateTime, nullable=False)
|
end_date = db.Column(db.DateTime, nullable=False)
|
||||||
examination_schedule_id = db.Column(db.Integer, db.ForeignKey('examination_schedules.id'))
|
examination_schedule_id = db.Column(db.Integer, db.ForeignKey('examination_schedules.id'))
|
||||||
examination_schedule = db.relationship('ExaminationSchedule', backref='enrollments')
|
examination_schedule = db.relationship('ExaminationSchedule', backref='term_of_defences')
|
||||||
committee = db.relationship("Committee", uselist=False, backref=db.backref('enrollment', passive_deletes=True))
|
|
||||||
group_id = db.Column(db.Integer, db.ForeignKey('groups.id'))
|
group_id = db.Column(db.Integer, db.ForeignKey('groups.id'))
|
||||||
group = db.relationship("Group", uselist=False, backref='enrollment')
|
group = db.relationship("Group", uselist=False, backref='term_of_defence')
|
||||||
|
members_of_committee = db.relationship("ProjectSupervisor", secondary=committee)
|
||||||
|
|
||||||
|
|
||||||
class Committee(Base):
|
class TemporaryAvailability(Base):
|
||||||
__tablename__ = 'committees'
|
__tablename__ = 'temporary_availabilities'
|
||||||
|
|
||||||
enrollment_id = db.Column(db.Integer, db.ForeignKey('enrollments.id', ondelete='CASCADE'))
|
start_date = db.Column(db.DateTime, nullable=False)
|
||||||
members = db.relationship('ProjectSupervisor', secondary='committees_projects_supervisors', backref='committees')
|
end_date = db.Column(db.DateTime, nullable=False)
|
||||||
|
examination_schedule_id = db.Column(db.Integer, db.ForeignKey('examination_schedules.id'), nullable=False)
|
||||||
|
examination_schedule = db.relationship("ExaminationSchedule", backref='temporary_availabilities')
|
||||||
class CommitteeProjectSupervisor(Base):
|
project_supervisor_id = db.Column(db.Integer, db.ForeignKey('project_supervisors.id'), nullable=False)
|
||||||
__tablename__ = 'committees_projects_supervisors'
|
project_supervisor = db.relationship("ProjectSupervisor", backref='temporary_availabilities')
|
||||||
|
|
||||||
chairman = db.Column(db.Boolean, default=False, nullable=False)
|
|
||||||
committee_id = db.Column(db.Integer, db.ForeignKey('committees.id'))
|
|
||||||
member_id = db.Column(db.Integer, db.ForeignKey('project_supervisors.id'))
|
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
from flask import Blueprint
|
from flask import Blueprint
|
||||||
|
|
||||||
from .enrollments import bp as enrollments_bp
|
|
||||||
from .examination_schedule import bp as examination_schedule_bp
|
|
||||||
|
|
||||||
bp = Blueprint("examination_schedule", __name__, url_prefix="/examination_schedule")
|
bp = Blueprint("examination_schedule", __name__, url_prefix="/examination_schedule")
|
||||||
|
|
||||||
bp.register_blueprint(enrollments_bp)
|
|
||||||
bp.register_blueprint(examination_schedule_bp)
|
|
||||||
|
@ -3,7 +3,7 @@ import datetime
|
|||||||
from apiflask import APIBlueprint
|
from apiflask import APIBlueprint
|
||||||
from flask import abort
|
from flask import abort
|
||||||
|
|
||||||
from ..schemas import EnrollmentPaginationSchema, EnrollmentQuerySchema
|
from ..schemas import EnrollmentPaginationSchema, EnrollmentQuerySchema, ExaminationScheduleProjectSupervisorViewSchema
|
||||||
from ..utils import check_examination_schedule_is_exist, get_list_of_enrollments_response
|
from ..utils import check_examination_schedule_is_exist, get_list_of_enrollments_response
|
||||||
|
|
||||||
bp = APIBlueprint("enrollments", __name__, url_prefix="/enrollments")
|
bp = APIBlueprint("enrollments", __name__, url_prefix="/enrollments")
|
||||||
@ -33,29 +33,7 @@ def list_enrollments_for_students(examination_schedule_id: int, query: dict) ->
|
|||||||
|
|
||||||
|
|
||||||
@bp.get('/<int:examination_schedule_id>/coordinator-view/')
|
@bp.get('/<int:examination_schedule_id>/coordinator-view/')
|
||||||
@bp.input(EnrollmentQuerySchema, location='query')
|
@bp.output(ExaminationScheduleProjectSupervisorViewSchema)
|
||||||
@bp.output(EnrollmentPaginationSchema)
|
def list_enrollments_for_coordinator(examination_schedule_id: int) -> dict:
|
||||||
def list_enrollments_for_coordinator(examination_schedule_id: int, query: dict) -> dict:
|
return check_examination_schedule_is_exist(examination_schedule_id)
|
||||||
page = query.get('page')
|
|
||||||
per_page = query.get('per_page')
|
|
||||||
|
|
||||||
check_examination_schedule_is_exist(examination_schedule_id)
|
|
||||||
|
|
||||||
return get_list_of_enrollments_response(examination_schedule_id, page, per_page)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.get('/<int:examination_schedule_id>/project-supervisor-view/')
|
|
||||||
@bp.input(EnrollmentQuerySchema, location='query')
|
|
||||||
@bp.output(EnrollmentPaginationSchema)
|
|
||||||
def list_enrollments_for_project_supervisor(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.timestamp() < now.timestamp():
|
|
||||||
abort(403, "Forbidden! Enrollment has just started! You cannot assign to the exam committees!")
|
|
||||||
|
|
||||||
return get_list_of_enrollments_response(examination_schedule_id, page, per_page)
|
|
||||||
|
@ -1,32 +1,18 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from apiflask import APIBlueprint
|
from apiflask import APIBlueprint
|
||||||
from flask import abort
|
|
||||||
|
|
||||||
from ...dependencies import db
|
from ...dependencies import db
|
||||||
from ..models import ExaminationSchedule
|
from ..models import ExaminationSchedule
|
||||||
from ..schemas import ExaminationScheduleListSchema
|
|
||||||
|
|
||||||
bp = APIBlueprint("list_of_examination_schedule", __name__, url_prefix="/")
|
bp = APIBlueprint("list_of_examination_schedule", __name__, url_prefix="/")
|
||||||
|
|
||||||
|
|
||||||
@bp.get('/project-supervisor-view/')
|
|
||||||
@bp.output(ExaminationScheduleListSchema)
|
|
||||||
def list_examination_schedule_for_project_supervisors() -> dict:
|
|
||||||
now = datetime.datetime.utcnow()
|
|
||||||
examination_schedules = db.session.query(ExaminationSchedule). \
|
|
||||||
filter(ExaminationSchedule.start_date > now). \
|
|
||||||
all()
|
|
||||||
return {'examination_schedules': examination_schedules}
|
|
||||||
|
|
||||||
|
|
||||||
@bp.get('/students-view/')
|
@bp.get('/students-view/')
|
||||||
@bp.output(ExaminationScheduleListSchema)
|
|
||||||
def list_examination_schedule_for_students() -> dict:
|
def list_examination_schedule_for_students() -> dict:
|
||||||
# in the future filter after the mode of examination schedule if we will have authorization module
|
# in the future filter after the mode of examination schedule if we will have authorization module
|
||||||
now = datetime.datetime.utcnow()
|
now = datetime.datetime.utcnow()
|
||||||
examination_schedules = db.session.query(ExaminationSchedule).\
|
examination_schedules = db.session.query(ExaminationSchedule).\
|
||||||
filter(ExaminationSchedule.start_date < now).\
|
filter(ExaminationSchedule.start_date_for_enrollment_students < now).\
|
||||||
filter(ExaminationSchedule.end_date > now).\
|
filter(ExaminationSchedule.end_date_for_enrollment_students > now).all()
|
||||||
all()
|
|
||||||
return {'examination_schedules': examination_schedules}
|
return {'examination_schedules': examination_schedules}
|
||||||
|
@ -27,15 +27,13 @@ class EnrollmentPaginationSchema(Schema):
|
|||||||
max_pages = fields.Integer()
|
max_pages = fields.Integer()
|
||||||
|
|
||||||
|
|
||||||
|
class ExaminationScheduleProjectSupervisorViewSchema(Schema):
|
||||||
|
id = fields.Integer()
|
||||||
|
start_date = fields.DateTime()
|
||||||
|
end_date = fields.DateTime()
|
||||||
|
|
||||||
|
|
||||||
class EnrollmentQuerySchema(Schema):
|
class EnrollmentQuerySchema(Schema):
|
||||||
page = fields.Integer()
|
page = fields.Integer()
|
||||||
per_page = fields.Integer()
|
per_page = fields.Integer()
|
||||||
|
|
||||||
|
|
||||||
class ExaminationScheduleSchema(Schema):
|
|
||||||
id = fields.Integer()
|
|
||||||
title = fields.Str()
|
|
||||||
|
|
||||||
|
|
||||||
class ExaminationScheduleListSchema(Schema):
|
|
||||||
examination_schedules = fields.List(fields.Nested(ExaminationScheduleSchema))
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from flask import abort
|
from flask import abort
|
||||||
|
|
||||||
from ..dependencies import db
|
from ..dependencies import db
|
||||||
from .models import Enrollment, Committee, ExaminationSchedule
|
from .models import ExaminationSchedule
|
||||||
from ..students.models import Group
|
from ..students.models import Group
|
||||||
from ..base.utils import paginate_models
|
from ..base.utils import paginate_models
|
||||||
|
|
||||||
|
@ -3,24 +3,31 @@ from flask_sqlalchemy import BaseQuery
|
|||||||
from ..dependencies import db
|
from ..dependencies import db
|
||||||
from ..base.models import Person, Base
|
from ..base.models import Person, Base
|
||||||
from ..base.utils import order_by_column_name
|
from ..base.utils import order_by_column_name
|
||||||
|
from ..students.models import YearGroup
|
||||||
|
|
||||||
|
|
||||||
|
class YearGroupProjectSupervisors(Base):
|
||||||
|
__tablename__ = 'year_group_project_supervisors'
|
||||||
|
|
||||||
|
project_supervisor_id = db.Column(db.Integer, db.ForeignKey('project_supervisors.id'), nullable=False)
|
||||||
|
year_group_id = db.Column(db.Integer, db.ForeignKey('year_groups.id'), nullable=False)
|
||||||
|
limit_group = db.Column(db.Integer, default=3, nullable=False)
|
||||||
|
|
||||||
|
|
||||||
class ProjectSupervisor(Base, Person):
|
class ProjectSupervisor(Base, Person):
|
||||||
__tablename__ = "project_supervisors"
|
__tablename__ = "project_supervisors"
|
||||||
|
|
||||||
limit_group = db.Column(db.Integer, default=3, nullable=False)
|
year_groups = db.relationship('YearGroupProjectSupervisors', lazy=True)
|
||||||
count_groups = db.Column(db.Integer, default=0, nullable=False)
|
|
||||||
mode = db.Column(db.Integer, default=0, nullable=False) # 0 - stationary, 1 - non-stationary, 2 - both
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def search_by_fullname_and_mode_and_order_by_first_name_or_last_name(cls, fullname: str = None,
|
def search_by_fullname_and_mode_and_order_by_first_name_or_last_name(cls, year_group_id: int = None,
|
||||||
mode: int = None,
|
fullname: str = None,
|
||||||
order_by_first_name: str = None,
|
order_by_first_name: str = None,
|
||||||
order_by_last_name: str = None) -> BaseQuery:
|
order_by_last_name: str = None) -> BaseQuery:
|
||||||
project_supervisors_query = cls.query
|
project_supervisors_query = cls.query
|
||||||
|
|
||||||
if mode is not None:
|
if year_group_id is not None:
|
||||||
project_supervisors_query = project_supervisors_query.filter(mode != 1 - mode)
|
project_supervisors_query = project_supervisors_query.filter(YearGroup.id == year_group_id)
|
||||||
|
|
||||||
if fullname is not None:
|
if fullname is not None:
|
||||||
project_supervisors_query = project_supervisors_query.filter(
|
project_supervisors_query = project_supervisors_query.filter(
|
||||||
|
@ -3,11 +3,11 @@ import datetime
|
|||||||
from flask import abort
|
from flask import abort
|
||||||
|
|
||||||
from ..dependencies import db
|
from ..dependencies import db
|
||||||
from ..examination_schedule.models import Enrollment, ExaminationSchedule, Committee
|
from ..examination_schedule.models import ExaminationSchedule
|
||||||
|
|
||||||
|
|
||||||
def get_enrollment_by_enrollment_and_examination_schedule_ids(examination_schedule_id: int,
|
def get_enrollment_by_enrollment_and_examination_schedule_ids(examination_schedule_id: int,
|
||||||
enrollment_id: int) -> Enrollment:
|
enrollment_id: int) -> None:
|
||||||
enrollment = db.session.query(Enrollment). \
|
enrollment = db.session.query(Enrollment). \
|
||||||
join(ExaminationSchedule, isouter=True).join(Committee, isouter=True). \
|
join(ExaminationSchedule, isouter=True).join(Committee, isouter=True). \
|
||||||
filter(ExaminationSchedule.id == examination_schedule_id). \
|
filter(ExaminationSchedule.id == examination_schedule_id). \
|
||||||
@ -20,12 +20,6 @@ def get_enrollment_by_enrollment_and_examination_schedule_ids(examination_schedu
|
|||||||
return enrollment
|
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:
|
def check_the_enrollments_has_just_started(start_date: datetime.datetime, action: str) -> None:
|
||||||
now = datetime.datetime.utcnow()
|
now = datetime.datetime.utcnow()
|
||||||
|
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
from apiflask import APIBlueprint
|
from datetime import datetime
|
||||||
from flask import abort, current_app
|
|
||||||
|
|
||||||
from ..schemas import MessageSchema, CommitteeCreateSchema, TemporaryProjectSupervisorSchema
|
from apiflask import APIBlueprint
|
||||||
from ...examination_schedule.models import Committee
|
from flask import abort
|
||||||
|
|
||||||
|
from ..schemas import MessageSchema, TimeAvailabilityCreateSchema, TemporaryProjectSupervisorSchema, \
|
||||||
|
ListOfFreeTimesSchema
|
||||||
from ...dependencies import db
|
from ...dependencies import db
|
||||||
from ..models import ProjectSupervisor
|
from ..models import ProjectSupervisor
|
||||||
from ..query import get_enrollment_by_enrollment_and_examination_schedule_ids, \
|
from ...examination_schedule.models import ExaminationSchedule, TemporaryAvailability, TermOfDefence
|
||||||
check_the_project_supervisor_is_in_committee, check_the_enrollments_has_just_started
|
|
||||||
|
|
||||||
bp = APIBlueprint("enrollments", __name__, url_prefix="/")
|
bp = APIBlueprint("enrollments", __name__, url_prefix="/")
|
||||||
|
|
||||||
|
|
||||||
@bp.post('/<int:examination_schedule_id>/enrollments/<int:enrollment_id>/')
|
@bp.post('/<int:examination_schedule_id>/enrollments/')
|
||||||
@bp.input(CommitteeCreateSchema)
|
@bp.input(TimeAvailabilityCreateSchema)
|
||||||
@bp.output(MessageSchema)
|
@bp.output(MessageSchema)
|
||||||
def assign_yourself_to_committee(examination_schedule_id: int, enrollment_id: int, data: dict) -> dict:
|
def set_your_free_time_to_examination_schedule(examination_schedule_id: int, data: dict) -> dict:
|
||||||
# this code will be removed
|
# this code will be removed
|
||||||
project_supervisor = db.session.query(ProjectSupervisor).filter(
|
project_supervisor = db.session.query(ProjectSupervisor).filter(
|
||||||
ProjectSupervisor.id == data['project_supervisor_id']).first()
|
ProjectSupervisor.id == data['project_supervisor_id']).first()
|
||||||
@ -22,43 +23,100 @@ def assign_yourself_to_committee(examination_schedule_id: int, enrollment_id: in
|
|||||||
abort(404, "ProjectSupervisor doesn't exist!")
|
abort(404, "ProjectSupervisor doesn't exist!")
|
||||||
################
|
################
|
||||||
|
|
||||||
limit_of_committtee = current_app.config['LIMIT_PERSONS_PER_COMMITTEE']
|
es = ExaminationSchedule.query.filter(ExaminationSchedule.id == examination_schedule_id).first()
|
||||||
|
if es is None:
|
||||||
|
abort(404, "Examination schedule doesn't exist!")
|
||||||
|
|
||||||
enrollment = get_enrollment_by_enrollment_and_examination_schedule_ids(examination_schedule_id, enrollment_id)
|
sd = data['start_date']
|
||||||
check_the_enrollments_has_just_started(enrollment.examination_schedule.start_date, "assign")
|
ed = data['end_date']
|
||||||
|
if sd > ed:
|
||||||
|
abort(400, "Invalid data! End date must be greater than start date!")
|
||||||
|
|
||||||
size_of_committee = db.session.query(Committee).join(Committee.members). \
|
if not (es.start_date >= sd and es.end_date <= ed):
|
||||||
filter(Committee.enrollment_id == enrollment.id).count()
|
abort(400, "Invalid date ranges!")
|
||||||
|
|
||||||
if size_of_committee >= limit_of_committtee:
|
now = datetime.utcnow()
|
||||||
abort(400, "The committee is full!")
|
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!")
|
||||||
|
|
||||||
if check_the_project_supervisor_is_in_committee(enrollment.id, project_supervisor.id):
|
ta_query = TemporaryAvailability.query.filter(
|
||||||
abort(400, "You have already in this committee!")
|
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
|
||||||
|
|
||||||
enrollment.committee.members.append(project_supervisor)
|
ta = TemporaryAvailability(**data, examination_schedule_id=examination_schedule_id,
|
||||||
db.session.add(enrollment)
|
project_supervisor_id=project_supervisor.id)
|
||||||
|
db.session.add(ta)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
return {"message": "You have just assigned yourself to committee!"}
|
return {"message": "You have just assigned your free time!"}
|
||||||
|
|
||||||
|
|
||||||
@bp.delete('/<int:examination_schedule_id>/enrollments/<int:enrollment_id>/')
|
@bp.delete('/<int:examination_schedule_id>/enrollments/<int:id>/')
|
||||||
@bp.input(TemporaryProjectSupervisorSchema)
|
@bp.input(TemporaryProjectSupervisorSchema)
|
||||||
@bp.output(MessageSchema)
|
@bp.output(MessageSchema)
|
||||||
def delete_yourself_from_committee(examination_schedule_id: int, enrollment_id: int, data: dict) -> dict:
|
def delete_your_free_time_from_examination_schedule(examination_schedule_id: int, id: int, data: dict) -> dict:
|
||||||
# this code will be removed
|
# this code will be removed
|
||||||
project_supervisor = db.session.query(ProjectSupervisor).filter(ProjectSupervisor.id == data['id']).first()
|
project_supervisor = db.session.query(ProjectSupervisor).filter(ProjectSupervisor.id == data['id']).first()
|
||||||
if project_supervisor is None:
|
if project_supervisor is None:
|
||||||
abort(404, "ProjectSupervisor doesn't exist!")
|
abort(404, "ProjectSupervisor doesn't exist!")
|
||||||
################
|
################
|
||||||
|
ta = TemporaryAvailability.query.filter(TemporaryAvailability.examination_schedule_id == examination_schedule_id,
|
||||||
|
TemporaryAvailability.project_supervisor_id == project_supervisor.id,
|
||||||
|
TemporaryAvailability.id == id).first()
|
||||||
|
|
||||||
enrollment = get_enrollment_by_enrollment_and_examination_schedule_ids(examination_schedule_id, enrollment_id)
|
if ta is None:
|
||||||
check_the_enrollments_has_just_started(enrollment.examination_schedule.start_date, "delete")
|
abort(404, "Your free time doesn't exist!")
|
||||||
|
|
||||||
if not check_the_project_supervisor_is_in_committee(enrollment.id, project_supervisor.id):
|
db.session.delete(ta)
|
||||||
abort(400, "You are not assigned to this committee!")
|
|
||||||
|
|
||||||
enrollment.committee.members.remove(project_supervisor)
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return {"message": "You have just removed from committee!"}
|
return {"message": "You have just removed your free time!"}
|
||||||
|
|
||||||
|
|
||||||
|
@bp.get('/<int:examination_schedule_id>/')
|
||||||
|
@bp.input(TemporaryProjectSupervisorSchema, location='query')
|
||||||
|
@bp.output(ListOfFreeTimesSchema)
|
||||||
|
def list_enrollments_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:
|
||||||
|
abort(404, "ProjectSupervisor doesn't exist!")
|
||||||
|
################
|
||||||
|
es = ExaminationSchedule.query.filter(ExaminationSchedule.id == examination_schedule_id,
|
||||||
|
ExaminationSchedule.year_group_id).first()
|
||||||
|
|
||||||
|
if es is None:
|
||||||
|
abort(404, "Examination schedule doesn't exist!")
|
||||||
|
|
||||||
|
now = datetime.utcnow()
|
||||||
|
if es.start_date_for_enrollment_students.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
|
||||||
|
|
||||||
|
|
||||||
|
@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:
|
||||||
|
# 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!")
|
||||||
|
################
|
||||||
|
es = ExaminationSchedule.query.filter(ExaminationSchedule.id == examination_schedule_id,
|
||||||
|
ExaminationSchedule.year_group_id).first()
|
||||||
|
if es is None:
|
||||||
|
abort(404, "Examination schedule doesn't exist!")
|
||||||
|
|
||||||
|
# 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
|
||||||
|
@ -1,13 +1,23 @@
|
|||||||
from marshmallow import fields, validate, Schema
|
from marshmallow import fields, validate, Schema
|
||||||
|
|
||||||
|
|
||||||
# MessageSchema, CommitteeCreateSchema
|
|
||||||
|
|
||||||
class MessageSchema(Schema):
|
class MessageSchema(Schema):
|
||||||
message = fields.Str()
|
message = fields.Str()
|
||||||
|
|
||||||
|
|
||||||
class CommitteeCreateSchema(Schema):
|
class FreeTimeSchema(Schema):
|
||||||
|
id = fields.Integer()
|
||||||
|
start_date = fields.DateTime(required=True)
|
||||||
|
end_date = fields.DateTime(required=True)
|
||||||
|
|
||||||
|
|
||||||
|
class ListOfFreeTimesSchema(Schema):
|
||||||
|
free_times = fields.List(fields.Nested(FreeTimeSchema))
|
||||||
|
|
||||||
|
|
||||||
|
class TimeAvailabilityCreateSchema(Schema):
|
||||||
|
start_date = fields.DateTime(required=True)
|
||||||
|
end_date = fields.DateTime(required=True)
|
||||||
project_supervisor_id = fields.Integer(required=True) # temporary field it will be removed in the future
|
project_supervisor_id = fields.Integer(required=True) # temporary field it will be removed in the future
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,9 +1,27 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from flask_sqlalchemy import BaseQuery
|
from flask_sqlalchemy import BaseQuery
|
||||||
|
|
||||||
from ..dependencies import db
|
from ..dependencies import db
|
||||||
from ..base.models import Person, Base
|
from ..base.models import Person, Base
|
||||||
from ..base.utils import order_by_column_name
|
from ..base.utils import order_by_column_name
|
||||||
from ..examination_schedule.models import Enrollment
|
from ..examination_schedule.models import TermOfDefence
|
||||||
|
|
||||||
|
|
||||||
|
class YearGroupStudents(Base):
|
||||||
|
__tablename__ = 'year_group_students'
|
||||||
|
|
||||||
|
year_group_id = db.Column(db.Integer, db.ForeignKey('year_groups.id', ondelete='CASCADE'))
|
||||||
|
student_index = db.Column(db.Integer, db.ForeignKey('students.index', ondelete='CASCADE'))
|
||||||
|
|
||||||
|
|
||||||
|
class YearGroup(Base):
|
||||||
|
__tablename__ = 'year_groups'
|
||||||
|
|
||||||
|
name = db.Column(db.String(50), unique=True, nullable=False)
|
||||||
|
mode = db.Column(db.String(1), unique=True, nullable=False)
|
||||||
|
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
|
||||||
|
students = db.relationship("YearGroupStudents")
|
||||||
|
|
||||||
|
|
||||||
class Group(Base):
|
class Group(Base):
|
||||||
@ -15,13 +33,14 @@ class Group(Base):
|
|||||||
tzaj_kod = db.Column(db.String(60), default='LAB')
|
tzaj_kod = db.Column(db.String(60), default='LAB')
|
||||||
project_supervisor_id = db.Column(db.Integer, db.ForeignKey('project_supervisors.id'))
|
project_supervisor_id = db.Column(db.Integer, db.ForeignKey('project_supervisors.id'))
|
||||||
project_supervisor = db.relationship('ProjectSupervisor', backref='groups', lazy=True)
|
project_supervisor = db.relationship('ProjectSupervisor', backref='groups', lazy=True)
|
||||||
|
year_group_id = db.Column(db.Integer, db.ForeignKey('year_groups.id'))
|
||||||
|
year_group = db.relationship('YearGroup', backref='groups', lazy=True)
|
||||||
points_for_first_term = db.Column(db.Integer, default=0, nullable=False)
|
points_for_first_term = db.Column(db.Integer, default=0, nullable=False)
|
||||||
points_for_second_term = db.Column(db.Integer, default=0, nullable=False)
|
points_for_second_term = db.Column(db.Integer, default=0, nullable=False)
|
||||||
# enrollment = db.relationship('Enrollment', uselist=False, backref='group')
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def search_by_name(cls, search_name: str = None) -> BaseQuery:
|
def search_by_name(cls, year_group_id: int, search_name: str = None) -> BaseQuery:
|
||||||
group_query = cls.query
|
group_query = cls.query.filter(Group.year_group_id == year_group_id)
|
||||||
|
|
||||||
if search_name is not None:
|
if search_name is not None:
|
||||||
group_query = group_query.filter(Group.name.like(f'{search_name}%'))
|
group_query = group_query.filter(Group.name.like(f'{search_name}%'))
|
||||||
@ -35,18 +54,14 @@ class Student(Person):
|
|||||||
pesel = db.Column(db.String(11), default='')
|
pesel = db.Column(db.String(11), default='')
|
||||||
index = db.Column(db.Integer, primary_key=True)
|
index = db.Column(db.Integer, primary_key=True)
|
||||||
group_id = db.Column(db.Integer, db.ForeignKey('groups.id'))
|
group_id = db.Column(db.Integer, db.ForeignKey('groups.id'))
|
||||||
group = db.relationship('Group', backref='students', lazy=True)
|
groups = db.relationship('Group', backref='students', lazy=True)
|
||||||
mode = db.Column(db.Boolean, default=True, nullable=False) # True - stationary, False - non-stationary
|
year_groups = db.relationship("YearGroupStudents")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def search_by_fullname_and_mode_and_order_by_first_name_or_last_name(cls, fullname: str = None,
|
def search_by_fullname_and_mode_and_order_by_first_name_or_last_name(cls, year_group_id: int, fullname: str = None,
|
||||||
mode: bool = None,
|
|
||||||
order_by_first_name: str = None,
|
order_by_first_name: str = None,
|
||||||
order_by_last_name: str = None) -> BaseQuery:
|
order_by_last_name: str = None) -> BaseQuery:
|
||||||
student_query = cls.query
|
student_query = cls.query.filter(YearGroup.id == year_group_id)
|
||||||
|
|
||||||
if mode is not None:
|
|
||||||
student_query = student_query.filter_by(mode=mode)
|
|
||||||
|
|
||||||
if fullname is not None:
|
if fullname is not None:
|
||||||
student_query = student_query.filter((Student.first_name + ' ' + Student.last_name).like(f'{fullname}%'))
|
student_query = student_query.filter((Student.first_name + ' ' + Student.last_name).like(f'{fullname}%'))
|
||||||
|
@ -3,14 +3,11 @@ import datetime
|
|||||||
from apiflask import APIBlueprint
|
from apiflask import APIBlueprint
|
||||||
from flask import abort
|
from flask import abort
|
||||||
|
|
||||||
from ..schemas import MessageSchema, TemporaryStudentSchema
|
from ..schemas import MessageSchema, TemporaryStudentSchema, ExaminationScheduleListSchema
|
||||||
from ...dependencies import db
|
from ...dependencies import db
|
||||||
from ...examination_schedule.models import Enrollment
|
from ..models import Student, Group, TermOfDefence
|
||||||
from ..models import Student, Group
|
from ...examination_schedule.models import ExaminationSchedule
|
||||||
from ...project_supervisor.models import ProjectSupervisor
|
from ...project_supervisor.models import ProjectSupervisor
|
||||||
from ...project_supervisor.query import get_enrollment_by_enrollment_and_examination_schedule_ids, \
|
|
||||||
check_the_project_supervisor_is_in_committee
|
|
||||||
from ..query import check_the_enrollments_has_just_started
|
|
||||||
|
|
||||||
bp = APIBlueprint("enrollments", __name__, url_prefix="/")
|
bp = APIBlueprint("enrollments", __name__, url_prefix="/")
|
||||||
|
|
||||||
@ -18,52 +15,93 @@ bp = APIBlueprint("enrollments", __name__, url_prefix="/")
|
|||||||
@bp.post('/<int:examination_schedule_id>/enrollments/<int:enrollment_id>/')
|
@bp.post('/<int:examination_schedule_id>/enrollments/<int:enrollment_id>/')
|
||||||
@bp.input(TemporaryStudentSchema)
|
@bp.input(TemporaryStudentSchema)
|
||||||
@bp.output(MessageSchema)
|
@bp.output(MessageSchema)
|
||||||
def assign_group_for_this_exam_date(examination_schedule_id: int, enrollment_id: int, data: dict) -> dict:
|
def assign_your_group_to_term_of_defence(examination_schedule_id: int, data: dict) -> dict:
|
||||||
# this code will be removed
|
# this code will be removed
|
||||||
student = Student.query.filter(Student.index == data['student_index']).first()
|
student = Student.query.filter(Student.index == data['student_index']).first()
|
||||||
if student is None:
|
if student is None:
|
||||||
abort(404, "Student doesn't exist!")
|
abort(404, "Student doesn't exist!")
|
||||||
################
|
################
|
||||||
st = Student.query.join(Group).join(ProjectSupervisor).filter(Student.index == student.index).first()
|
st = Student.query.join(Group).join(ProjectSupervisor).filter(Student.index == student.index).first()
|
||||||
|
|
||||||
enrollment = db.session.query(Enrollment.id).filter(Enrollment.group_id == st.group.id).first()
|
|
||||||
if enrollment is not None:
|
|
||||||
abort(400, "Your group has already assigned to any exam date!")
|
|
||||||
|
|
||||||
enrollment = get_enrollment_by_enrollment_and_examination_schedule_ids(examination_schedule_id, enrollment_id)
|
|
||||||
check_the_enrollments_has_just_started(enrollment.examination_schedule)
|
|
||||||
|
|
||||||
if st is None or st.group.project_supervisor is None:
|
if st is None or st.group.project_supervisor is None:
|
||||||
abort(400, "You don't have a group or your group doesn't have an assigned project supervisor!")
|
abort(400, "You don't have a group or your group doesn't have an assigned project supervisor!")
|
||||||
|
|
||||||
if not check_the_project_supervisor_is_in_committee(enrollment_id, st.group.project_supervisor.id):
|
defence = TermOfDefence.query.filter(TermOfDefence.group_id == st.group.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()
|
||||||
|
td = TermOfDefence.query.join(TermOfDefence.members_of_committee). \
|
||||||
|
filter_by(project_supervisor_id=g.project_supervisor_id).first()
|
||||||
|
|
||||||
|
if td is None:
|
||||||
abort(400, "Your project supervisor is not in committee!")
|
abort(400, "Your project supervisor is not in committee!")
|
||||||
|
|
||||||
enrollment.group_id = st.group.id
|
defence.group_id = st.group.id
|
||||||
db.session.add(enrollment)
|
db.session.add(defence)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return {"message": "You have just assigned the group for this exam date!"}
|
return {"message": "You have just assigned the group for this exam date!"}
|
||||||
|
|
||||||
|
|
||||||
@bp.delete('/<int:examination_schedule_id>/enrollments/<int:enrollment_id>/')
|
@bp.delete('/<int:examination_schedule_id>/enrollments/<int:term_of_defence_id>/')
|
||||||
@bp.input(TemporaryStudentSchema)
|
@bp.input(TemporaryStudentSchema)
|
||||||
@bp.output(MessageSchema)
|
@bp.output(MessageSchema)
|
||||||
def delete_group_for_this_exam_date(examination_schedule_id: int, enrollment_id: int, data: dict) -> dict:
|
def delete_your_group_from_term_of_defence(examination_schedule_id: int, term_of_defence_id: int, data: dict) -> dict:
|
||||||
# this code will be removed
|
# this code will be removed
|
||||||
student = Student.query.filter(Student.index == data['student_index']).first()
|
student = Student.query.filter(Student.index == data['student_index']).first()
|
||||||
if student is None:
|
if student is None:
|
||||||
abort(404, "Student doesn't exist!")
|
abort(404, "Student doesn't exist!")
|
||||||
################
|
################
|
||||||
|
|
||||||
enrollment = get_enrollment_by_enrollment_and_examination_schedule_ids(examination_schedule_id, enrollment_id)
|
term_of_defence = TermOfDefence.query.filter(TermOfDefence.id == term_of_defence_id). \
|
||||||
|
filter(TermOfDefence.examination_schedule_id == examination_schedule_id).first()
|
||||||
|
|
||||||
if student.group.id != enrollment.group_id:
|
if term_of_defence is None:
|
||||||
abort(400, "You are not assigned to this committee!")
|
abort(404, "Term of defence doesn't exist!")
|
||||||
|
|
||||||
check_the_enrollments_has_just_started(enrollment.examination_schedule)
|
if student.group.id != term_of_defence.group_id:
|
||||||
|
abort(400, "You are not assigned to this group!")
|
||||||
|
|
||||||
enrollment.group = None
|
term_of_defence.group_id = None
|
||||||
db.session.add(enrollment)
|
db.session.add(term_of_defence)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
return {"message": "You have just removed the group for this exam date!"}
|
return {"message": "You have just removed the group for this exam date!"}
|
||||||
|
|
||||||
|
|
||||||
|
@bp.get('/examination-schedule/year-group/<int:year_group_id>/')
|
||||||
|
@bp.input(TemporaryStudentSchema)
|
||||||
|
@bp.output(ExaminationScheduleListSchema)
|
||||||
|
def list_examination_schedule_for_students(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:
|
||||||
|
abort(404, "Student doesn't exist!")
|
||||||
|
################
|
||||||
|
|
||||||
|
# in the future filter after the mode of examination schedule if we will have authorization module
|
||||||
|
now = datetime.datetime.utcnow()
|
||||||
|
examination_schedules = ExaminationSchedule.query. \
|
||||||
|
filter(ExaminationSchedule.year_group_id == year_group_id). \
|
||||||
|
filter(ExaminationSchedule.start_date_for_enrollment_students < now). \
|
||||||
|
filter(ExaminationSchedule.end_date_for_enrollment_students > now).all()
|
||||||
|
return {'examination_schedules': examination_schedules}
|
||||||
|
|
||||||
|
|
||||||
|
@bp.get('/enrollments/')
|
||||||
|
@bp.input(TemporaryStudentSchema)
|
||||||
|
@bp.output(ExaminationScheduleListSchema)
|
||||||
|
def list_term_of_defences_for_students(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!")
|
||||||
|
################
|
||||||
|
# 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). \
|
||||||
|
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}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from apiflask import APIBlueprint
|
from apiflask import APIBlueprint
|
||||||
|
|
||||||
from ...project_supervisor.models import ProjectSupervisor
|
from ...project_supervisor.models import ProjectSupervisor, YearGroupProjectSupervisors
|
||||||
from ..models import Group
|
from ..models import Group
|
||||||
from ...dependencies import db
|
from ...dependencies import db
|
||||||
from ..schemas import ProjectSupervisorQuerySchema, ProjectSupervisorPaginationSchema
|
from ..schemas import ProjectSupervisorQuerySchema, ProjectSupervisorPaginationSchema
|
||||||
@ -9,21 +9,20 @@ from ...base.utils import paginate_models
|
|||||||
bp = APIBlueprint("registrations", __name__, url_prefix="/registrations")
|
bp = APIBlueprint("registrations", __name__, url_prefix="/registrations")
|
||||||
|
|
||||||
|
|
||||||
@bp.get('/')
|
@bp.get('/<int:year_group_id>/')
|
||||||
@bp.input(ProjectSupervisorQuerySchema, location='query')
|
@bp.input(ProjectSupervisorQuerySchema, location='query')
|
||||||
@bp.output(ProjectSupervisorPaginationSchema)
|
@bp.output(ProjectSupervisorPaginationSchema)
|
||||||
def list_available_groups(query: dict) -> dict:
|
def list_available_groups(year_group_id: int, query: dict) -> dict:
|
||||||
mode = 0 if query.get('mode') else 1
|
|
||||||
page = query.get('page')
|
page = query.get('page')
|
||||||
per_page = query.get('per_page')
|
per_page = query.get('per_page')
|
||||||
|
|
||||||
available_groups = (ProjectSupervisor.limit_group - ProjectSupervisor.count_groups)
|
available_groups = (YearGroupProjectSupervisors.limit_group - db.func.count(Group.id))
|
||||||
ps_query = db.session.query(ProjectSupervisor, available_groups).join(Group, isouter=True)
|
ps_query = db.session. \
|
||||||
|
query(ProjectSupervisor, available_groups). \
|
||||||
if mode is not None:
|
join(Group, isouter=True). \
|
||||||
ps_query = ps_query.filter(ProjectSupervisor.mode != 1-mode)
|
join(YearGroupProjectSupervisors, isouter=True). \
|
||||||
|
filter(YearGroupProjectSupervisors.year_group_id == year_group_id).\
|
||||||
ps_query = ps_query.group_by(ProjectSupervisor.id)
|
group_by(ProjectSupervisor.id)
|
||||||
|
|
||||||
data = paginate_models(page, ps_query, per_page)
|
data = paginate_models(page, ps_query, per_page)
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ class ProjectSupervisorSchema(Schema):
|
|||||||
first_name = fields.Str()
|
first_name = fields.Str()
|
||||||
last_name = fields.Str()
|
last_name = fields.Str()
|
||||||
email = fields.Str()
|
email = fields.Str()
|
||||||
mode = fields.Integer()
|
|
||||||
available_groups = fields.Integer()
|
available_groups = fields.Integer()
|
||||||
|
|
||||||
|
|
||||||
@ -17,7 +16,6 @@ class ProjectSupervisorPaginationSchema(Schema):
|
|||||||
class ProjectSupervisorQuerySchema(Schema):
|
class ProjectSupervisorQuerySchema(Schema):
|
||||||
page = fields.Integer()
|
page = fields.Integer()
|
||||||
per_page = fields.Integer()
|
per_page = fields.Integer()
|
||||||
mode = fields.Boolean()
|
|
||||||
|
|
||||||
|
|
||||||
class TemporaryStudentSchema(Schema):
|
class TemporaryStudentSchema(Schema):
|
||||||
@ -26,3 +24,14 @@ class TemporaryStudentSchema(Schema):
|
|||||||
|
|
||||||
class MessageSchema(Schema):
|
class MessageSchema(Schema):
|
||||||
message = fields.Str()
|
message = fields.Str()
|
||||||
|
|
||||||
|
|
||||||
|
class ExaminationScheduleSchema(Schema):
|
||||||
|
id = fields.Integer()
|
||||||
|
title = fields.Str()
|
||||||
|
start_date = fields.DateTime()
|
||||||
|
end_date = fields.DateTime()
|
||||||
|
|
||||||
|
|
||||||
|
class ExaminationScheduleListSchema(Schema):
|
||||||
|
examination_schedules = fields.List(fields.Nested(ExaminationScheduleSchema))
|
||||||
|
28
backend/migrations/versions/5c3c4c4e1a72_.py
Normal file
28
backend/migrations/versions/5c3c4c4e1a72_.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: 5c3c4c4e1a72
|
||||||
|
Revises: a96f91e5b556
|
||||||
|
Create Date: 2022-11-12 11:48:38.377516
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '5c3c4c4e1a72'
|
||||||
|
down_revision = 'a96f91e5b556'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('examination_schedules', sa.Column('duration_time', sa.Integer(), nullable=True))
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column('examination_schedules', 'duration_time')
|
||||||
|
# ### end Alembic commands ###
|
141
backend/migrations/versions/a96f91e5b556_.py
Normal file
141
backend/migrations/versions/a96f91e5b556_.py
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: a96f91e5b556
|
||||||
|
Revises:
|
||||||
|
Create Date: 2022-11-12 11:34:01.223667
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'a96f91e5b556'
|
||||||
|
down_revision = None
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('project_supervisors',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column('first_name', sa.String(length=255), nullable=False),
|
||||||
|
sa.Column('last_name', sa.String(length=255), nullable=False),
|
||||||
|
sa.Column('email', sa.String(length=120), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint('id'),
|
||||||
|
sa.UniqueConstraint('email')
|
||||||
|
)
|
||||||
|
op.create_index(op.f('ix_project_supervisors_first_name'), 'project_supervisors', ['first_name'], unique=False)
|
||||||
|
op.create_index(op.f('ix_project_supervisors_last_name'), 'project_supervisors', ['last_name'], unique=False)
|
||||||
|
op.create_table('year_groups',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column('name', sa.String(length=50), nullable=False),
|
||||||
|
sa.Column('mode', sa.String(length=1), nullable=False),
|
||||||
|
sa.Column('created_at', sa.DateTime(), nullable=False),
|
||||||
|
sa.PrimaryKeyConstraint('id'),
|
||||||
|
sa.UniqueConstraint('mode'),
|
||||||
|
sa.UniqueConstraint('name')
|
||||||
|
)
|
||||||
|
op.create_table('examination_schedules',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column('title', sa.String(length=100), nullable=False),
|
||||||
|
sa.Column('year_group_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('start_date_for_enrollment_students', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('end_date_for_enrollment_students', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('start_date', sa.DateTime(), nullable=False),
|
||||||
|
sa.Column('end_date', sa.DateTime(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['year_group_id'], ['year_groups.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id'),
|
||||||
|
sa.UniqueConstraint('title')
|
||||||
|
)
|
||||||
|
op.create_table('groups',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column('name', sa.String(length=60), nullable=False),
|
||||||
|
sa.Column('cdyd_kod', sa.String(length=60), nullable=True),
|
||||||
|
sa.Column('prz_kod', sa.String(length=60), nullable=True),
|
||||||
|
sa.Column('tzaj_kod', sa.String(length=60), nullable=True),
|
||||||
|
sa.Column('project_supervisor_id', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('year_group_id', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('points_for_first_term', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('points_for_second_term', sa.Integer(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['project_supervisor_id'], ['project_supervisors.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['year_group_id'], ['year_groups.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('year_group_project_supervisors',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column('project_supervisor_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('year_group_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('limit_group', sa.Integer(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['project_supervisor_id'], ['project_supervisors.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['year_group_id'], ['year_groups.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('students',
|
||||||
|
sa.Column('first_name', sa.String(length=255), nullable=False),
|
||||||
|
sa.Column('last_name', sa.String(length=255), nullable=False),
|
||||||
|
sa.Column('email', sa.String(length=120), nullable=True),
|
||||||
|
sa.Column('pesel', sa.String(length=11), nullable=True),
|
||||||
|
sa.Column('index', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('group_id', sa.Integer(), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['group_id'], ['groups.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('index'),
|
||||||
|
sa.UniqueConstraint('email')
|
||||||
|
)
|
||||||
|
op.create_index(op.f('ix_students_first_name'), 'students', ['first_name'], unique=False)
|
||||||
|
op.create_index(op.f('ix_students_last_name'), 'students', ['last_name'], unique=False)
|
||||||
|
op.create_table('temporary_availabilities',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column('start_date', sa.DateTime(), nullable=False),
|
||||||
|
sa.Column('end_date', sa.DateTime(), nullable=False),
|
||||||
|
sa.Column('examination_schedule_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('project_supervisor_id', sa.Integer(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['examination_schedule_id'], ['examination_schedules.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['project_supervisor_id'], ['project_supervisors.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('term_of_defences',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column('start_date', sa.DateTime(), nullable=False),
|
||||||
|
sa.Column('end_date', sa.DateTime(), nullable=False),
|
||||||
|
sa.Column('examination_schedule_id', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('group_id', sa.Integer(), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['examination_schedule_id'], ['examination_schedules.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['group_id'], ['groups.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('committees',
|
||||||
|
sa.Column('term_of_defence_id', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('project_supervisor_id', sa.Integer(), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['project_supervisor_id'], ['project_supervisors.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['term_of_defence_id'], ['term_of_defences.id'], )
|
||||||
|
)
|
||||||
|
op.create_table('year_group_students',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column('year_group_id', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('student_index', sa.Integer(), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['student_index'], ['students.index'], ondelete='CASCADE'),
|
||||||
|
sa.ForeignKeyConstraint(['year_group_id'], ['year_groups.id'], ondelete='CASCADE'),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_table('year_group_students')
|
||||||
|
op.drop_table('committees')
|
||||||
|
op.drop_table('term_of_defences')
|
||||||
|
op.drop_table('temporary_availabilities')
|
||||||
|
op.drop_index(op.f('ix_students_last_name'), table_name='students')
|
||||||
|
op.drop_index(op.f('ix_students_first_name'), table_name='students')
|
||||||
|
op.drop_table('students')
|
||||||
|
op.drop_table('year_group_project_supervisors')
|
||||||
|
op.drop_table('groups')
|
||||||
|
op.drop_table('examination_schedules')
|
||||||
|
op.drop_table('year_groups')
|
||||||
|
op.drop_index(op.f('ix_project_supervisors_last_name'), table_name='project_supervisors')
|
||||||
|
op.drop_index(op.f('ix_project_supervisors_first_name'), table_name='project_supervisors')
|
||||||
|
op.drop_table('project_supervisors')
|
||||||
|
# ### end Alembic commands ###
|
Loading…
Reference in New Issue
Block a user