fix group, students, project_supervisor endpoints for coordinator, fix importing csv students endpoint and add copy project supervisors from last year group, refactor code

This commit is contained in:
dominik24c 2023-01-14 01:37:31 +01:00
parent 48be4c6345
commit 038f9da93d
29 changed files with 198 additions and 529 deletions

View File

@ -7,11 +7,10 @@ from flask_cors import CORS
from .config import config
from .dependencies import db, ma
from .commands.startapp import startapp
from .commands.init_db import init_db
from .commands.clear_db import clear_db
from .utils import import_models
from .api import api_bp
from .errors import request_entity_too_large, register_error_handlers
from .errors import register_error_handlers
def create_app(config_name: str = '') -> APIFlask:
@ -37,11 +36,9 @@ def create_app(config_name: str = '') -> APIFlask:
# register commands
app.cli.add_command(startapp)
app.cli.add_command(init_db)
app.cli.add_command(clear_db)
# register errors
register_error_handlers(app)
# app.register_error_handler(413, request_entity_too_large)
return app

View File

@ -12,4 +12,4 @@ class Person(db.Model):
first_name = db.Column(db.String(255), index=True, nullable=False)
last_name = db.Column(db.String(255), index=True, nullable=False)
email = db.Column(db.String(120), unique=True)
email = db.Column(db.String(120), index=True, nullable=False)

View File

@ -0,0 +1,5 @@
from marshmallow import fields, Schema
class MessageSchema(Schema):
message = fields.Str()

View File

@ -1,37 +0,0 @@
from flask.cli import with_appcontext
from click import command
from ..dependencies import db
# from ..factory import ProjectSupervisorFactory, GroupFactory, StudentFactory
@command('init_db')
@with_appcontext
def init_db() -> None:
"""Fill database with some data"""
db.drop_all()
db.create_all()
#
# num_of_supervisors = 5
#
# projects_supervisors = [ProjectSupervisorFactory() for _ in range(num_of_supervisors)]
# db.session.add_all(projects_supervisors)
# db.session.commit()
#
# groups = [GroupFactory(project_supervisor=projects_supervisors[i]) for i in range(num_of_supervisors)]
# db.session.add_all(groups)
# db.session.commit()
#
# num_of_students = num_of_supervisors * 3
# students = [StudentFactory(group=groups[i % num_of_supervisors]) for i in range(num_of_students)]
#
# max_count = 10
# max_length = len(students)
# start_count = 0
#
# while True:
# if start_count > max_length:
# break
# db.session.add_all(students[start_count:max_count])
# db.session.commit()
# start_count += max_count

View File

@ -1,5 +0,0 @@
# from ..base.models import Base
#
#
# class Coordinator(Base):
# __tablename__ = 'coordinators'

View File

@ -5,12 +5,13 @@ from flask import abort, current_app
from sqlalchemy import or_, and_
from flask_sqlalchemy import get_debug_queries
from ..schemas import MessageSchema, TermOfDefenceSchema, TermOfDefenceListSchema, \
TemporaryAvailabilityListSchema, AssignedGroupToTermOfDefenceListSchema, GroupIdSchema
from ...examination_schedule.models import TermOfDefence, TemporaryAvailability, committee
from ..schemas import TermOfDefenceSchema, TemporaryAvailabilityListSchema, AssignedGroupToTermOfDefenceListSchema, \
GroupIdSchema
from ...examination_schedule.models import TermOfDefence, TemporaryAvailability
from ...students.models import YearGroup
from ...project_supervisor.models import ProjectSupervisor
from ...dependencies import db
from ...base.schemas import MessageSchema
from ..utils import generate_range_dates
from ..query.enrollments import get_term_of_defence_by_id_and_examination_schedule_id, set_new_group_to_term_of_defence, \
get_examination_schedule_by_id
@ -18,68 +19,6 @@ from ..query.enrollments import get_term_of_defence_by_id_and_examination_schedu
bp = APIBlueprint("enrollments", __name__, url_prefix="/enrollments")
@bp.post('/<int:examination_schedule_id>/generate')
@bp.output(MessageSchema)
def generate_term_of_defence_for_this_examination_schedule(examination_schedule_id: int) -> dict:
ex = get_examination_schedule_by_id(examination_schedule_id)
limit = current_app.config.get('LIMIT_MEMBERS_PER_COMMITTEE', 3)
term_of_defences = TermOfDefence.query. \
filter(TermOfDefence.examination_schedule_id == examination_schedule_id).first()
if term_of_defences is not None:
abort(400,
"First you have to delete all term of defences for this examination schedule to generate them again!")
temporary_availabilities = TemporaryAvailability.query. \
filter(TemporaryAvailability.examination_schedule_id == examination_schedule_id). \
join(TemporaryAvailability.project_supervisor). \
all()
if len(temporary_availabilities) == 0:
abort(404, "Not found temporary availabilities for project supervisors")
dates = generate_range_dates(ex.start_date, ex.end_date, ex.duration_time)
term_of_defences = []
for d in dates:
e = d + datetime.timedelta(minutes=ex.duration_time)
t = list(filter(lambda ta: ta.start_date <= d and ta.end_date >= e, temporary_availabilities))
if len(t) >= limit:
projects_supervisors = [t[i].project_supervisor for i in range(limit)]
term_of_defence = TermOfDefence(start_date=d, end_date=e, examination_schedule_id=examination_schedule_id)
term_of_defence.members_of_committee = projects_supervisors
term_of_defences.append(term_of_defence)
db.session.add_all(term_of_defences)
db.session.commit()
return {"message": "Term of defences was generated!"}
@bp.post('/<int:examination_schedule_id>/clear-term-of-defences/')
@bp.output(MessageSchema)
def clear_generated_term_of_defences(examination_schedule_id: int) -> dict:
get_examination_schedule_by_id(examination_schedule_id)
# count_defences = db.func.count(ProjectSupervisor.id)
# td = db.session.query(TermOfDefence, count_defences). \
# join(ProjectSupervisor, isouter=True). \
# filter(TermOfDefence.examination_schedule_id == examination_schedule_id). \
# group_by(TermOfDefence.id).having(count_defences > 0).first()
# print(td)
# if td is not None:
# abort(400, "First you remove group assigned to term of defence to clear term of defences!")
td = TermOfDefence.query. \
filter(TermOfDefence.examination_schedule_id == examination_schedule_id).all()
while True:
for t in td[0:10]:
db.session.delete(t)
db.session.commit()
if len(td) == 0:
break
td[0:10] = []
# print(len(get_debug_queries()))
return {"message": "Term of defences was deleted!"}
@bp.post('/<int:examination_schedule_id>/add')
@bp.input(TermOfDefenceSchema)
@bp.output(MessageSchema)

View File

@ -9,9 +9,10 @@ from ...dependencies import db
from ...examination_schedule.models import ExaminationSchedule, TermOfDefence
from ...students.models import Group, YearGroup
from ...project_supervisor.models import ProjectSupervisor
from ..schemas import ExaminationScheduleSchema, ExaminationScheduleUpdateSchema, MessageSchema, \
from ..schemas import ExaminationScheduleSchema, ExaminationScheduleUpdateSchema, \
ExaminationSchedulesQuerySchema, ExaminationSchedulesPaginationSchema
from ..utils import generate_examination_schedule_pdf_file
from ...base.schemas import MessageSchema
bp = APIBlueprint("examination_schedule", __name__, url_prefix="/examination_schedule")

View File

@ -1,13 +1,13 @@
from flask import abort, current_app
from flask import abort
from apiflask import APIBlueprint
from flask_sqlalchemy import get_debug_queries
from ...students.models import Group, Student, YearGroup, ProjectGradeSheet
from ...project_supervisor.models import ProjectSupervisor, YearGroupProjectSupervisors
from ..schemas import GroupEditSchema, GroupsPaginationSchema, GroupCreateSchema, MessageSchema, GroupQuerySchema, \
DetailGroupSchema
from ...project_supervisor.models import ProjectSupervisor
from ..schemas import GroupEditSchema, GroupsPaginationSchema, GroupCreateSchema, GroupQuerySchema, DetailGroupSchema
from ...dependencies import db
from ...base.utils import paginate_models
from ...base.schemas import MessageSchema
from ..utils import attach_points_for_first_and_second_term_to_group_models
bp = APIBlueprint("groups", __name__, url_prefix="/groups")
@ -38,7 +38,7 @@ def list_groups(year_group_id: int, query: dict) -> dict:
@bp.output(MessageSchema, status_code=201)
def create_group(year_group_id: int, data: dict) -> dict:
name = data['name']
students_indexes = data['students']
students_ids = data['students']
project_supervisor_id = data['project_supervisor_id']
yg = YearGroup.query.filter(YearGroup.id == year_group_id).first()
@ -47,33 +47,21 @@ def create_group(year_group_id: int, data: dict) -> dict:
project_supervisor = ProjectSupervisor.query.filter_by(id=project_supervisor_id).first()
limit_student_per_group = current_app.config.get('LIMIT_STUDENTS_PER_GROUP')
if project_supervisor is None:
abort(404, f"Not found project supervisor!")
elif limit_student_per_group is not None and limit_student_per_group < len(students_indexes):
abort(400, f"Too much students you want add to group, "
f"The group can have only {limit_student_per_group} students")
limit = db.session.query(db.func.count(ProjectSupervisor.id)). \
join(Group).filter(ProjectSupervisor.id == project_supervisor_id).group_by(ProjectSupervisor.id).scalar()
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")
group = Group(name=name, project_supervisor_id=project_supervisor_id, year_group_id=year_group_id)
students_without_groups = db.session.query(Student, Group). \
join(Group, Student.groups). \
filter(Group.year_group_id == year_group_id). \
filter(db.or_(*[Student.index == idx for idx in students_indexes])).all()
filter(db.or_(*[Student.id == st_id for st_id in students_ids])).all()
if len(students_without_groups) > 0:
abort(400, "One or more students have already belonged to group!")
students = db.session.query(Student).filter(Student.index.in_(students_indexes)).all()
if len(students) != len(students_indexes):
students = db.session.query(Student).filter(Student.id.in_(students_ids)).all()
if len(students) != len(students_ids):
abort(404, "Not found students!")
db.session.add(group)
@ -81,9 +69,6 @@ def create_group(year_group_id: int, data: dict) -> dict:
for student in students:
group.students.append(student)
db.session.commit()
pgs = ProjectGradeSheet(group_id=group.id)
db.session.add(pgs)
db.session.commit()
@ -91,19 +76,19 @@ def create_group(year_group_id: int, data: dict) -> dict:
return {"message": "Group was created!"}
@bp.get("/<int:id>/detail/")
@bp.get("/<int:group_id>/detail/")
@bp.output(DetailGroupSchema)
def detail_group(id: int) -> Group:
group = Group.query.filter_by(id=id).first()
def detail_group(group_id: int) -> Group:
group = Group.query.filter_by(id=group_id).first()
if group is None:
abort(404, f"Not found group!")
return group
@bp.delete("/<int:id>/")
@bp.delete("/<int:group_id>/")
@bp.output(MessageSchema, status_code=202)
def delete_group(id: int) -> dict:
group = Group.query.filter_by(id=id).first()
def delete_group(group_id: int) -> dict:
group = Group.query.filter_by(id=group_id).first()
if group is None:
abort(404, f"Not found group!")
@ -113,26 +98,26 @@ def delete_group(id: int) -> dict:
return {"message": "Group was deleted!"}
@bp.put("/<int:id>/")
@bp.put("/<int:group_id>/")
@bp.input(GroupEditSchema)
@bp.output(MessageSchema)
def edit_group(id: int, data: dict) -> dict:
def edit_group(group_id: int, data: dict) -> dict:
if not data:
abort(400, 'You have passed empty data!')
group_query = Group.query.filter_by(id=id)
group_query = Group.query.filter_by(id=group_id)
group = group_query.first()
if group is None:
abort(404, f"Not found group!")
students_indexes = data.get('students')
students_ids = data.get('students')
name = data.get('name')
project_supervisor_id = data.get('project_supervisor_id')
if students_indexes is not None:
students = db.session.query(Student).filter(Student.index.in_(students_indexes)).all()
if len(students_indexes) != len(students):
if students_ids is not None:
students = db.session.query(Student).filter(Student.id.in_(students_ids)).all()
if len(students_ids) != len(students):
abort(404, 'Not found students!')
group.students = students

View File

@ -2,41 +2,21 @@ from flask import abort
from apiflask import APIBlueprint
from flask_sqlalchemy import get_debug_queries
from ...project_supervisor.models import ProjectSupervisor, YearGroupProjectSupervisors
from ...project_supervisor.models import ProjectSupervisor
from ...students.models import Group, YearGroup
from ..schemas import ProjectSupervisorSchema, ProjectSupervisorEditSchema, ProjectSupervisorsPaginationSchema, \
ProjectSupervisorCreateSchema, MessageSchema, ProjectSupervisorQuerySchema, ProjectSupervisorYearGroupSchema
ProjectSupervisorCreateSchema, MessageWithIdSchema, ProjectSupervisorQuerySchema
from ...base.schemas import MessageSchema
from ...dependencies import db
from ...base.utils import paginate_models
bp = APIBlueprint("project_supervisor", __name__, url_prefix="/project_supervisor")
@bp.get("/")
@bp.input(ProjectSupervisorQuerySchema, location='query')
@bp.output(ProjectSupervisorsPaginationSchema)
def list_project_supervisors(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(
None, 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.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:
def list_project_supervisors(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')
@ -54,44 +34,44 @@ def list_project_supervisors_by_year_group(year_group_id: int, query: dict) -> d
}
@bp.post("/")
@bp.post("/<int:year_group_id>/")
@bp.input(ProjectSupervisorCreateSchema)
@bp.output(MessageSchema, status_code=201)
def create_project_supervisor(data: dict) -> dict:
first_name = data['first_name']
last_name = data['last_name']
project_supervisor = ProjectSupervisor.query.filter_by(first_name=first_name).filter_by(last_name=last_name).first()
@bp.output(MessageWithIdSchema, status_code=201)
def create_project_supervisor(year_group_id: int, data: dict) -> dict:
year_group = YearGroup.query.filter(YearGroup.id == year_group_id).first()
if year_group is None:
abort(404, "Not found year group!")
email = data['email']
project_supervisor = ProjectSupervisor.query.filter(ProjectSupervisor.email == email).first()
if project_supervisor is not None:
abort(400, "Project Supervisor has already exists!")
project_supervisor = ProjectSupervisor(**data)
project_supervisor = ProjectSupervisor(**data, year_group_id=year_group_id)
db.session.add(project_supervisor)
db.session.commit()
return {"message": "Project Supervisor was created!", "id": project_supervisor.id}
@bp.get("/<int:id>/detail/")
@bp.get("/<int:project_supervisor_id>/detail/")
@bp.output(ProjectSupervisorSchema)
def detail_project_supervisor(id: int) -> ProjectSupervisor:
project_supervisor = ProjectSupervisor.query.filter_by(id=id).first()
def detail_project_supervisor(project_supervisor_id: int) -> ProjectSupervisor:
project_supervisor = ProjectSupervisor.query.filter_by(id=project_supervisor_id).first()
if project_supervisor is None:
abort(404, 'Not found project supervisor!')
return project_supervisor
@bp.delete("/<int:id>/")
@bp.delete("/<int:project_supervisor_id>/")
@bp.output(MessageSchema)
def delete_project_supervisor(id: int) -> dict:
project_supervisor = ProjectSupervisor.query.filter_by(id=id).first()
def delete_project_supervisor(project_supervisor_id: int) -> dict:
project_supervisor = ProjectSupervisor.query.filter_by(id=project_supervisor_id).first()
if project_supervisor is None:
abort(404, "Not found project supervisor!")
count_groups = db.session.query(db.func.count(ProjectSupervisor.id)).join(Group). \
filter(ProjectSupervisor.id == id).group_by(ProjectSupervisor.id).scalar()
if count_groups is not None and count_groups > 0:
count_groups = len(Group.query.filter(Group.project_supervisor_id == project_supervisor.id).all())
if count_groups > 0:
abort(400, "Project Supervisor has at least one group!")
db.session.delete(project_supervisor)
@ -99,14 +79,14 @@ def delete_project_supervisor(id: int) -> dict:
return {"message": "Project Supervisor was deleted!"}
@bp.put("/<int:id>/")
@bp.put("/<int:project_supervisor_id>/")
@bp.input(ProjectSupervisorEditSchema)
@bp.output(MessageSchema)
def edit_project_supervisor(id: int, data: dict) -> dict:
def edit_project_supervisor(project_supervisor_id: int, data: dict) -> dict:
if not data:
abort(400, 'You have passed empty data!')
project_supervisor_query = ProjectSupervisor.query.filter_by(id=id)
project_supervisor_query = ProjectSupervisor.query.filter_by(id=project_supervisor_id)
project_supervisor = project_supervisor_query.first()
if project_supervisor is None:
@ -117,65 +97,27 @@ def edit_project_supervisor(id: int, data: dict) -> dict:
return {"message": "Project Supervisor was updated!"}
@bp.post("/<int:id>/year-group/<int:year_group_id>/")
@bp.input(ProjectSupervisorYearGroupSchema)
@bp.post("/copy-project-supervisors-from-last-year-group/<int:year_group_id>/")
@bp.output(MessageSchema, status_code=201)
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(404, f"Not found project supervisor!")
def copy_project_supervisors_from_last_year_group(year_group_id: int) -> dict:
year_group = YearGroup.query.filter(YearGroup.id == year_group_id).first()
if year_group is None:
abort(404, "Not found year group!")
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!")
last_year_group = YearGroup.query.filter(YearGroup.mode == year_group.mode). \
filter(YearGroup.id != year_group_id).filter(YearGroup.created_at < year_group.created_at). \
order_by(db.desc(YearGroup.created_at)).first()
if last_year_group is None:
abort(400, "The latest year group doesn't exist!")
ygps = YearGroupProjectSupervisors(year_group_id=year_group_id, project_supervisor_id=id,
limit_group=limit_group)
db.session.add(ygps)
project_supervisors = ProjectSupervisor.query.filter(ProjectSupervisor.year_group_id == last_year_group.id).all()
current_project_supervisors_email_in_new_year_group = [ps.email for ps in ProjectSupervisor.query.filter(
ProjectSupervisor.year_group_id == year_group_id).all()]
for ps in project_supervisors:
if ps.email not in current_project_supervisors_email_in_new_year_group:
new_ps = ProjectSupervisor(first_name=ps.first_name, last_name=ps.last_name, email=ps.email,
limit_group=ps.limit_group, year_group_id=year_group_id)
db.session.add(new_ps)
db.session.commit()
return {"message": "Project Supervisor was added to year group!"}
@bp.delete("/<int:id>/year-group/<int:year_group_id>/")
@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).first()
if project_supervisor is None:
abort(404, f"Not found project supervisor!")
year_group = YearGroup.query.filter(YearGroup.id == year_group_id).first()
if year_group is None:
abort(404, "Not found year group!")
db.session.delete(project_supervisor)
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).first()
if project_supervisor is None:
abort(404, f"Not found project supervisor!")
year_group = YearGroup.query.filter(YearGroup.id == year_group_id).first()
if year_group is None:
abort(404, "Not found year group!")
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!"}
return {"message": "Project Supervisors was added!"}

View File

@ -6,14 +6,15 @@ from apiflask import APIBlueprint
from sqlalchemy import or_
from flask_sqlalchemy import get_debug_queries
from ...students.models import Student, Group, YearGroup, YearGroupStudents
from ...students.models import Student, Group, YearGroup
from ...project_supervisor.models import ProjectSupervisor
from ..schemas import StudentSchema, StudentEditSchema, StudentsPaginationSchema, YearGroupInfoQuery, \
StudentCreateSchema, MessageSchema, FileSchema, StudentQuerySchema, StudentListFileDownloaderSchema
StudentCreateSchema, FileSchema, StudentQuerySchema, StudentListFileDownloaderSchema
from ...dependencies import db
from ..utils import parse_csv, generate_csv
from ..exceptions import InvalidNameOrTypeHeaderException
from ...base.utils import paginate_models, is_allowed_extensions
from ...base.schemas import MessageSchema
bp = APIBlueprint("students", __name__, url_prefix="/students")
@ -40,19 +41,19 @@ def list_students(year_group_id: int, query: dict) -> dict:
}
@bp.get("/<int:index>/detail/")
@bp.get("/<int:student_id>/detail/")
@bp.output(StudentSchema)
def detail_student(index: int) -> Student:
student = Student.query.filter_by(index=index).first()
def detail_student(student_id: int) -> Student:
student = Student.query.filter_by(id=student_id).first()
if student is None:
abort(404, "Not found student!")
return student
@bp.delete("/<int:index>/")
@bp.delete("/<int:student_id>/")
@bp.output(MessageSchema, status_code=202)
def delete_student(index: int) -> dict:
student = Student.query.filter_by(index=index).first()
def delete_student(student_id: int) -> dict:
student = Student.query.filter_by(id=student_id).first()
if student is None:
abort(404, "Not found student!")
db.session.delete(student)
@ -60,14 +61,14 @@ def delete_student(index: int) -> dict:
return {"message": "Student was deleted!"}
@bp.put("/<int:index>/")
@bp.put("/<int:student_id>/")
@bp.input(StudentEditSchema)
@bp.output(MessageSchema)
def edit_student(index: int, data: dict) -> dict:
def edit_student(student_id: int, data: dict) -> dict:
if not data:
abort(400, 'You have passed empty data!')
student_query = Student.query.filter_by(index=index)
student_query = Student.query.filter(Student.id==student_id)
student = student_query.first()
if student is None:
@ -87,24 +88,18 @@ def create_student(data: dict) -> dict:
yg_id = data['year_group_id']
del data['year_group_id']
student = Student.query.filter(Student.index == index).first()
# if student is not None:
# abort(400, "Student has already exists!")
if student is None:
dummy_email = f'student{randint(1, 300_000)}@gmail.com'
student = Student(**data, email=dummy_email)
db.session.add(student)
student = Student.query.filter(Student.index == index, Student.year_group_id == yg_id).first()
if student is not None:
abort(400, "Student has already assigned to this year group!")
# add student to the chosen year group
year_group = YearGroup.query.filter(YearGroup.id == yg_id).first()
if year_group is None:
abort(404, "Not found year group!")
if any((year_group.id == yg.id for yg in student.year_groups)):
abort(400, "You are assigned to this year group!")
ygs = YearGroupStudents(student_index=student.index, year_group_id=year_group.id)
db.session.add(ygs)
dummy_email = f'student{randint(1, 300_000)}@gmail.com'
student = Student(**data, email=dummy_email, year_group_id=yg_id)
db.session.add(student)
db.session.commit()
return {"message": "Student was created!"}
@ -117,7 +112,7 @@ def create_student(data: dict) -> dict:
def upload_students(query: dict, file: dict) -> dict:
"""Add only Students to chosen year group if students exist in db and assigned to correct year group,
they will be omitted"""
year_group_id = query.get('id')
year_group_id = query.get('year_group_id')
yg = YearGroup.query.filter(YearGroup.id == year_group_id).first()
if yg is None:
abort(404, "Not found year group!")
@ -125,7 +120,7 @@ def upload_students(query: dict, file: dict) -> dict:
uploaded_file = file.get('file')
if uploaded_file and is_allowed_extensions(uploaded_file.filename):
try:
students = parse_csv(uploaded_file)
students = parse_csv(uploaded_file, year_group_id)
while True:
sliced_students = islice(students, 5)
list_of_students = list(sliced_students)
@ -133,25 +128,13 @@ def upload_students(query: dict, file: dict) -> dict:
if len(list_of_students) == 0:
break
students_in_db = Student.query.filter(or_(Student.index == s.index for s in list_of_students)).all()
students_in_db_and_assigned_to_year_group = Student.query.join(YearGroupStudents, isouter=True). \
filter(YearGroupStudents.year_group_id == year_group_id). \
filter(or_(Student.index == s.index for s in list_of_students)).all()
students_in_db = Student.query.filter(or_(Student.index == s.index for s in list_of_students)).\
filter(Student.year_group_id==year_group_id).all()
student_index_in_db = [s.index for s in students_in_db]
student_index_in_year_group = [s.index for s in students_in_db_and_assigned_to_year_group]
students_in_db_and_not_assigned_to_year_group = list(
filter(lambda s: s.index not in student_index_in_year_group, students_in_db))
students_not_exists_in_db = list(filter(lambda s: s.index not in student_index_in_db, list_of_students))
db.session.add_all(students_not_exists_in_db)
db.session.commit()
ygs = [YearGroupStudents(year_group_id=year_group_id, student_index=student.index) for student in
students_in_db_and_not_assigned_to_year_group + students_not_exists_in_db]
db.session.add_all(ygs)
db.session.commit()
except InvalidNameOrTypeHeaderException:
abort(400, "Invalid format of csv file!")
else:
@ -169,7 +152,7 @@ def download_students(query: dict) -> Response:
join(ProjectSupervisor).all()
if len(students_and_groups) == 0:
abort(404, "Not found students, which are assigned to group!")
abort(404, "Not found students!")
csv_file = generate_csv(students_and_groups)
response = Response(csv_file, mimetype='text/csv')

View File

@ -2,9 +2,10 @@ from flask import abort
from apiflask import APIBlueprint
from ...students.models import YearGroup
from ..schemas import YearGroupSchema, MessageSchema, YearGroupPaginationSchema, YearGroupQuerySchema
from ..schemas import YearGroupSchema, YearGroupPaginationSchema, YearGroupQuerySchema
from ...dependencies import db
from ...base.utils import paginate_models
from ...base.schemas import MessageSchema
bp = APIBlueprint("year_group", __name__, url_prefix="/year-group")

View File

@ -4,8 +4,8 @@ from .examination_schedule import ExaminationScheduleSchema, ExaminationSchedule
ExaminationSchedulesPaginationSchema, ExaminationSchedulesQuerySchema, WorkloadSchema
from .groups import GroupQuerySchema, GroupsPaginationSchema, GroupCreateSchema, GroupEditSchema, GroupIdSchema
from .project_supervisor import ProjectSupervisorQuerySchema, ProjectSupervisorsPaginationSchema, \
ProjectSupervisorCreateSchema, ProjectSupervisorEditSchema, ProjectSupervisorYearGroupSchema
ProjectSupervisorCreateSchema, ProjectSupervisorEditSchema
from .students import ProjectSupervisorSchema, GroupSchema, StudentSchema, StudentsPaginationSchema, \
StudentListFileDownloaderSchema, StudentCreateSchema, StudentEditSchema, MessageSchema, FileSchema, \
StudentListFileDownloaderSchema, StudentCreateSchema, StudentEditSchema, MessageWithIdSchema, FileSchema, \
StudentQuerySchema, YearGroupInfoQuery, DetailGroupSchema
from .year_group import YearGroupSchema, YearGroupPaginationSchema, YearGroupQuerySchema

View File

@ -1,7 +1,7 @@
from marshmallow import Schema, fields, validate
from ..validators import validate_index
from .students import GroupSchema, StudentSchema
from .students import GroupSchema
class GroupQuerySchema(Schema):
@ -18,13 +18,13 @@ class GroupsPaginationSchema(Schema):
class GroupCreateSchema(Schema):
name = fields.Str(validate=validate.Length(min=1, max=255), required=True)
project_supervisor_id = fields.Integer(required=True)
students = fields.List(fields.Integer(validate=validate_index, required=True))
students = fields.List(fields.Integer(required=True))
class GroupEditSchema(Schema):
name = fields.Str(validate=validate.Length(min=1, max=255))
project_supervisor_id = fields.Integer()
students = fields.List(fields.Integer(validate=validate_index))
students = fields.List(fields.Integer())
class GroupIdSchema(Schema):

View File

@ -20,13 +20,11 @@ class ProjectSupervisorCreateSchema(Schema):
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)
email = fields.Str(validate=[validate.Length(min=1, max=255), validate.Email()], required=True)
limit_group = fields.Integer(required=True)
class ProjectSupervisorEditSchema(Schema):
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)
email = fields.Str(validate=[validate.Length(min=0, max=255), validate.Email()], required=True)
class ProjectSupervisorYearGroupSchema(Schema):
limit_group = fields.Integer(required=True)
first_name = fields.Str(validate=validate.Length(min=1, max=255))
last_name = fields.Str(validate=validate.Length(min=1, max=255))
email = fields.Str(validate=[validate.Length(min=0, max=255), validate.Email()])
limit_group = fields.Integer()

View File

@ -20,7 +20,7 @@ class GroupSchema(ma.SQLAlchemyAutoSchema):
class StudentSchema(ma.SQLAlchemyAutoSchema):
groups = fields.List(fields.Nested(GroupSchema))
group = fields.Nested(GroupSchema)
class Meta:
model = Student
@ -38,7 +38,6 @@ class StudentListFileDownloaderSchema(ma.Schema):
class StudentCreateSchema(ma.Schema):
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)
pesel = fields.Str(validate=validate.Length(min=0, max=11), required=True)
index = fields.Integer(validate=validate_index, required=True)
year_group_id = fields.Integer()
@ -50,7 +49,7 @@ class StudentEditSchema(ma.Schema):
index = fields.Integer(validate=validate_index)
class MessageSchema(ma.Schema):
class MessageWithIdSchema(ma.Schema):
message = fields.Str(required=True)
id = fields.Str(required=False)
@ -68,7 +67,7 @@ class StudentQuerySchema(ma.Schema):
class YearGroupInfoQuery(Schema):
id = fields.Integer(required=True)
year_group_id = fields.Integer(required=True)
class DetailGroupSchema(ma.SQLAlchemyAutoSchema):
project_supervisor = fields.Nested(ProjectSupervisorSchema)

View File

@ -24,42 +24,31 @@ from ..examination_schedule.models import TermOfDefence
def check_columns(df: pd.DataFrame) -> bool:
headers = set(df.keys().values)
columns = ['NAZWISKO', 'IMIE', 'INDEKS', 'PESEL', 'EMAIL']
if len(headers - set(columns)) != 0:
return False
flag = True
col_types = ['object', 'object', 'int', 'int64', 'object']
for name, col_type in zip(columns, col_types):
if not str(df.dtypes[name]).startswith(col_type):
flag = False
break
return flag
column_names = ['NAZWISKO', 'IMIE', 'INDEKS', 'EMAIL']
column_types = ['object', 'object', 'int', 'object']
return all((column_name in headers for column_name in column_names)) and \
all((str(df.dtypes[column_name]).startswith(column_type) for column_name, column_type in
zip(column_names, column_types)))
def parse_csv(file: Union[FileStorage, TextIO]) -> Generator[Student, Any, None]:
def parse_csv(file: Union[FileStorage, TextIO], year_group_id: int) -> Generator[Student, Any, None]:
df = pd.read_csv(file)
# raise Exception(df.to_string())
if not check_columns(df):
raise InvalidNameOrTypeHeaderException
students = (Student(last_name=dict(item.items())['NAZWISKO'],
first_name=dict(item.items())['IMIE'],
index=dict(item.items())['INDEKS'],
pesel=str(int(dict(item.items())['PESEL'])) if not pd.isna(
dict(item.items())['PESEL']) else None,
email=dict(item.items())['EMAIL'])
email=dict(item.items())['EMAIL'],
year_group_id=year_group_id)
for _, item in df.iterrows())
return students
def generate_csv(students_and_groups: List[Tuple[Student, Group]]) -> str:
headers = ['PESEL', 'INDEKS', 'IMIE', 'NAZWISKO', 'EMAIL', 'CDYD_KOD', 'PRZ_KOD', 'TZAJ_KOD', 'GR_NR', 'PRG_KOD']
data = [(student.pesel, student.index, student.first_name, student.last_name, student.email,
headers = ['INDEKS', 'IMIE', 'NAZWISKO', 'EMAIL', 'CDYD_KOD', 'PRZ_KOD', 'TZAJ_KOD', 'GR_NR', 'PRG_KOD']
data = [(student.index, student.first_name, student.last_name, student.email,
group.cdyd_kod, group.prz_kod, group.tzaj_kod, group.project_supervisor_id,
None) for student, group in students_and_groups]
dataframe = defaultdict(list)

View File

@ -1,12 +1,7 @@
import json
from typing import Tuple
from apiflask import APIFlask
from werkzeug.exceptions import RequestEntityTooLarge, HTTPException
def request_entity_too_large(error: RequestEntityTooLarge) -> Tuple[dict, int]:
return {'error': 'File too large!'}, 413
from werkzeug.exceptions import HTTPException
def register_error_handlers(app: APIFlask):

View File

@ -1,44 +0,0 @@
from factory import alchemy, Sequence
from factory.faker import Faker
from factory.fuzzy import FuzzyInteger, FuzzyChoice
from .dependencies import db
from .students.models import Student, Group
from .project_supervisor.models import ProjectSupervisor
class ProjectSupervisorFactory(alchemy.SQLAlchemyModelFactory):
class Meta:
model = ProjectSupervisor
sqlalchemy_session = db.session
first_name = Faker('first_name')
last_name = Faker('last_name')
email = Faker('email')
limit_group = 4 # FuzzyInteger(3, 5)
count_groups = 4
mode = 0
class GroupFactory(alchemy.SQLAlchemyModelFactory):
class Meta:
model = Group
sqlalchemy_session = db.session
name = Sequence(lambda n: f'Group-{n}')
points_for_first_term = FuzzyInteger(1, 5)
points_for_second_term = FuzzyInteger(1, 5)
# project_supervisor = RelatedFactory(ProjectSupervisorFactory, 'project_supervisor')
class StudentFactory(alchemy.SQLAlchemyModelFactory):
class Meta:
model = Student
sqlalchemy_session = db.session
first_name = Faker('first_name')
last_name = Faker('last_name')
email = Faker('email')
index = Sequence(lambda n: 400_000 + n)
# group = RelatedFactory(GroupFactory)
mode = FuzzyChoice([True, False])

View File

@ -6,18 +6,12 @@ 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):
__tablename__ = "project_supervisors"
year_groups = db.relationship('YearGroupProjectSupervisors', lazy=True)
limit_group = db.Column(db.Integer, default=3, nullable=False)
year_group_id = db.Column(db.Integer, db.ForeignKey('year_groups.id'))
year_group = db.relationship('YearGroup', backref='project_supervisors')
@classmethod
def search_by_fullname_and_mode_and_order_by_first_name_or_last_name(cls, year_group_id: int = None,
@ -27,8 +21,8 @@ class ProjectSupervisor(Base, Person):
project_supervisors_query = cls.query
if year_group_id is not None:
project_supervisors_query = project_supervisors_query.join(YearGroupProjectSupervisors). \
filter(YearGroupProjectSupervisors.year_group_id == year_group_id)
project_supervisors_query = project_supervisors_query. \
filter(ProjectSupervisor.year_group_id == year_group_id)
if fullname is not None:
project_supervisors_query = project_supervisors_query.filter(

View File

@ -3,11 +3,12 @@ from datetime import datetime
from apiflask import APIBlueprint
from flask import abort
from sqlalchemy import and_, or_
from ..schemas import MessageSchema, TimeAvailabilityCreateSchema, TemporaryProjectSupervisorSchema, \
from ..schemas import TimeAvailabilityCreateSchema, TemporaryProjectSupervisorSchema, \
ListOfFreeTimesSchema, ListOfTermOfDefenceSchema
from ...dependencies import db
from ..models import ProjectSupervisor
from ...examination_schedule.models import ExaminationSchedule, TemporaryAvailability, TermOfDefence
from ...base.schemas import MessageSchema
bp = APIBlueprint("enrollments", __name__, url_prefix="/")

View File

@ -3,10 +3,11 @@ from flask import abort
from ...dependencies import db
from ..models import ProjectSupervisor
from ..schemas import ProjectSupervisorTermQuerySchema, MessageSchema, TemporaryProjectSupervisorSchema
from ..schemas import ProjectSupervisorTermQuerySchema, TemporaryProjectSupervisorSchema
from ...students.schemas import ProjectGradeSheetDetailFirstTermSchema, ProjectGradeSheetDetailSecondTermSchema, \
ProjectGradeSheetEditFirstTermSchema, ProjectGradeSheetEditSecondTermSchema
from ...students.models import Group, ProjectGradeSheet
from ...base.schemas import MessageSchema
bp = APIBlueprint("project_grade_sheet_for_project_supervisor", __name__, url_prefix="/project-grade-sheet")

View File

@ -1,10 +1,6 @@
from marshmallow import fields, validate, Schema
class MessageSchema(Schema):
message = fields.Str()
class FreeTimeSchema(Schema):
id = fields.Integer()
start_date = fields.DateTime(required=True)
@ -29,6 +25,7 @@ class TimeAvailabilityCreateSchema(Schema):
class TemporaryProjectSupervisorSchema(Schema):
id = fields.Integer(required=True)
class ProjectSupervisorTermQuerySchema(Schema):
id = fields.Integer(required=True)
term = fields.Integer(required=True, validate=validate.OneOf([1, 2]))

View File

@ -8,20 +8,12 @@ from ..base.utils import order_by_column_name
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), nullable=False)
mode = db.Column(db.String(1), nullable=False)
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
students = db.relationship("YearGroupStudents", lazy='joined')
__table__args = (
db.UniqueConstraint('name', 'mode', name='uc_name_mode_year_group')
@ -30,7 +22,7 @@ class YearGroup(Base):
students_groups = db.Table('students_groups',
db.Column('group_id', db.ForeignKey('groups.id'), nullable=False),
db.Column('student_index', db.ForeignKey('students.index'), nullable=False))
db.Column('student_id', db.ForeignKey('students.id'), nullable=False))
class Group(Base):
@ -41,12 +33,12 @@ class Group(Base):
prz_kod = db.Column(db.String(60), default='06-DPRILI0')
tzaj_kod = db.Column(db.String(60), default='LAB')
project_supervisor_id = db.Column(db.Integer, db.ForeignKey('project_supervisors.id'))
project_supervisor = db.relationship('ProjectSupervisor', backref='groups', lazy='joined')
project_supervisor = db.relationship('ProjectSupervisor', backref='groups')
year_group_id = db.Column(db.Integer, db.ForeignKey('year_groups.id'))
year_group = db.relationship('YearGroup', backref='groups', lazy='joined')
points_for_first_term = db.Column(db.Integer, default=0, nullable=False)
points_for_second_term = db.Column(db.Integer, default=0, nullable=False)
students = db.relationship('Student', secondary=students_groups, back_populates='groups', lazy='joined')
students = db.relationship('Student', secondary=students_groups, back_populates='groups')
@classmethod
def search_by_name(cls, year_group_id: int, search_name: str = None) -> BaseQuery:
@ -62,7 +54,7 @@ class ProjectGradeSheet(Base):
__tablename__ = 'project_grade_sheets'
group_id = db.Column(db.Integer, db.ForeignKey('groups.id'))
group = db.relationship('Group', backref='project_grade_sheet', uselist=False, lazy='joined')
group = db.relationship('Group', backref='project_grade_sheet', uselist=False)
presentation_required_content_1 = db.Column(db.Integer, default=0)
presentation_required_content_2 = db.Column(db.Integer, default=0)
@ -125,20 +117,19 @@ class ProjectGradeSheet(Base):
products_project_technology_2 = db.Column(db.Integer, default=0)
class Student(Person):
class Student(Base, Person):
__tablename__ = "students"
pesel = db.Column(db.String(11), default='')
index = db.Column(db.Integer, primary_key=True)
groups = db.relationship('Group', secondary=students_groups, back_populates='students', lazy='joined')
year_groups = db.relationship("YearGroupStudents", lazy='joined')
index = db.Column(db.Integer, nullable=False)
groups = db.relationship('Group', secondary=students_groups, back_populates='students')
year_group_id = db.Column(db.Integer, db.ForeignKey('year_groups.id'))
year_group = db.relationship('YearGroup', backref='students')
@classmethod
def search_by_fullname_and_mode_and_order_by_first_name_or_last_name(cls, year_group_id: int, fullname: str = None,
order_by_first_name: str = None,
order_by_last_name: str = None) -> BaseQuery:
student_query = cls.query.join(YearGroupStudents, isouter=True). \
filter(YearGroupStudents.year_group_id == year_group_id)
student_query = cls.query.filter(Student.year_group_id == year_group_id)
if fullname is not None:
student_query = student_query.filter((Student.first_name + ' ' + Student.last_name).like(f'{fullname}%'))

View File

@ -3,11 +3,9 @@ from flask import Blueprint
from .enrollments import bp as enrollments_bp
from .project_grade_sheet import bp as project_grade_sheet_bp
from .registrations import bp as registrations_bp
from .year_group import bp as year_group_bp
bp = Blueprint("students", __name__, url_prefix="/students")
bp.register_blueprint(enrollments_bp)
bp.register_blueprint(project_grade_sheet_bp)
bp.register_blueprint(registrations_bp)
bp.register_blueprint(year_group_bp)

View File

@ -3,12 +3,13 @@ import datetime
from apiflask import APIBlueprint
from flask import abort
from ..schemas import MessageSchema, TemporaryStudentSchema, ExaminationScheduleListSchema, \
from ..schemas import TemporaryStudentSchema, ExaminationScheduleListSchema, \
TermOfDefenceStudentListSchema
from ...dependencies import db
from ..models import Student, Group, TermOfDefence
from ...examination_schedule.models import ExaminationSchedule
from ...project_supervisor.models import ProjectSupervisor
from ...base.schemas import MessageSchema
bp = APIBlueprint("enrollments", __name__, url_prefix="/")

View File

@ -1,6 +1,6 @@
from apiflask import APIBlueprint
from ...project_supervisor.models import ProjectSupervisor, YearGroupProjectSupervisors
from ...project_supervisor.models import ProjectSupervisor
from ..models import Group
from ...dependencies import db
from ..schemas import ProjectSupervisorQuerySchema, ProjectSupervisorPaginationSchema
@ -16,12 +16,11 @@ def list_available_groups(year_group_id: int, query: dict) -> dict:
page = query.get('page')
per_page = query.get('per_page')
available_groups = (YearGroupProjectSupervisors.limit_group - db.func.count(Group.id))
available_groups = (ProjectSupervisor.limit_group - db.func.count(Group.id))
ps_query = db.session. \
query(ProjectSupervisor, available_groups). \
join(Group, isouter=True). \
join(YearGroupProjectSupervisors, isouter=True). \
filter(YearGroupProjectSupervisors.year_group_id == year_group_id).\
filter(ProjectSupervisor.year_group_id == year_group_id).\
group_by(ProjectSupervisor.id)
data = paginate_models(page, ps_query, per_page)

View File

@ -1,32 +0,0 @@
from apiflask import APIBlueprint
from flask import abort
from ...students.models import YearGroup, YearGroupStudents
from ...dependencies import db
from ...base.utils import paginate_models
from ..schemas import YearGroupQueryStudentSchema, YearGroupStudentPaginationSchema
from ..models import Student
bp = APIBlueprint("year_group", __name__, url_prefix="/year-group")
@bp.get('/')
@bp.input(YearGroupQueryStudentSchema, location='query')
@bp.output(YearGroupStudentPaginationSchema)
def list_of_year_groups(query: dict) -> dict:
index = query.get('index')
st = Student.query.filter(Student.index == index).first()
if st is None:
abort(404, "Not found student!")
####################################
page = query.get('page')
per_page = query.get('per_page')
year_group_query = db.session.query(YearGroup).join(YearGroupStudents, isouter=True). \
filter(YearGroupStudents.student_index == st.index).order_by(db.desc(YearGroup.created_at))
data = paginate_models(page, year_group_query, per_page)
return {
"year_groups": data['items'],
"max_pages": data['max_pages']
}

View File

@ -24,10 +24,6 @@ class TemporaryStudentSchema(Schema):
student_index = fields.Integer(required=True)
class MessageSchema(Schema):
message = fields.Str()
class ExaminationScheduleSchema(Schema):
id = fields.Integer()
title = fields.Str()
@ -51,39 +47,26 @@ class TermOfDefenceStudentItemSchema(Schema):
end_date = fields.DateTime()
members_of_committee = fields.List(fields.Nested(ProjectSupervisorCommitteeSchema))
class StudentDataItemSchema(Schema):
index = fields.Integer()
first_name = fields.Str()
last_name = fields.Str()
last_name = fields.Str()
class GroupDataItemSchema(Schema):
name = fields.Str()
students = fields.List(fields.Nested(StudentDataItemSchema))
students = fields.List(fields.Nested(StudentDataItemSchema))
class AssignedGroupToTermOfDefenceItemSchema(TermOfDefenceStudentItemSchema):
group = fields.Nested(GroupDataItemSchema)
class TermOfDefenceStudentListSchema(Schema):
term_of_defences = fields.List(fields.Nested(AssignedGroupToTermOfDefenceItemSchema))
class YearGroupStudentSchema(Schema):
id = fields.Integer()
name = fields.Str()
mode = fields.Str()
class YearGroupStudentPaginationSchema(Schema):
year_groups = fields.List(fields.Nested(YearGroupStudentSchema))
max_pages = fields.Integer()
class YearGroupQueryStudentSchema(Schema):
index = fields.Integer(required=True) # it will be removed
page = fields.Integer()
per_page = fields.Integer()
class StudentIndexQueryTempSchema(Schema):
index = fields.Integer(required=True) # it will be removed
term = fields.Integer(required=True, validate=validate.OneOf([1, 2]))

View File

@ -1,8 +1,8 @@
"""empty message
Revision ID: b3003ddd0564
Revision ID: 3fd120fc5e12
Revises:
Create Date: 2023-01-03 18:37:53.103562
Create Date: 2023-01-14 00:03:06.327441
"""
from alembic import op
@ -10,7 +10,7 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'b3003ddd0564'
revision = '3fd120fc5e12'
down_revision = None
branch_labels = None
depends_on = None
@ -18,27 +18,6 @@ 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('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.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('year_groups',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('name', sa.String(length=50), nullable=False),
@ -59,6 +38,32 @@ def upgrade():
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('title')
)
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=False),
sa.Column('limit_group', sa.Integer(), nullable=False),
sa.Column('year_group_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['year_group_id'], ['year_groups.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_project_supervisors_email'), 'project_supervisors', ['email'], unique=False)
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('students',
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=False),
sa.Column('index', sa.Integer(), nullable=False),
sa.Column('year_group_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['year_group_id'], ['year_groups.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_students_email'), 'students', ['email'], unique=False)
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('groups',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('name', sa.String(length=60), nullable=False),
@ -73,21 +78,14 @@ def upgrade():
sa.ForeignKeyConstraint(['year_group_id'], ['year_groups.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('year_group_project_supervisors',
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.Column('year_group_id', sa.Integer(), nullable=False),
sa.Column('limit_group', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['examination_schedule_id'], ['examination_schedules.id'], ),
sa.ForeignKeyConstraint(['project_supervisor_id'], ['project_supervisors.id'], ),
sa.ForeignKeyConstraint(['year_group_id'], ['year_groups.id'], ),
sa.PrimaryKeyConstraint('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')
)
op.create_table('project_grade_sheets',
@ -154,19 +152,9 @@ def upgrade():
)
op.create_table('students_groups',
sa.Column('group_id', sa.Integer(), nullable=False),
sa.Column('student_index', sa.Integer(), nullable=False),
sa.Column('student_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['group_id'], ['groups.id'], ),
sa.ForeignKeyConstraint(['student_index'], ['students.index'], )
)
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')
sa.ForeignKeyConstraint(['student_id'], ['students.id'], )
)
op.create_table('term_of_defences',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
@ -191,18 +179,18 @@ def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('committees')
op.drop_table('term_of_defences')
op.drop_table('temporary_availabilities')
op.drop_table('students_groups')
op.drop_table('project_grade_sheets')
op.drop_table('year_group_students')
op.drop_table('year_group_project_supervisors')
op.drop_table('temporary_availabilities')
op.drop_table('groups')
op.drop_table('examination_schedules')
op.drop_table('year_groups')
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_index(op.f('ix_students_email'), table_name='students')
op.drop_table('students')
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_index(op.f('ix_project_supervisors_email'), table_name='project_supervisors')
op.drop_table('project_supervisors')
op.drop_table('examination_schedules')
op.drop_table('year_groups')
# ### end Alembic commands ###