From 1bd50e6bfc836b976426b819c1bef244814139db Mon Sep 17 00:00:00 2001 From: dominik24c Date: Sat, 11 Jun 2022 12:53:55 +0200 Subject: [PATCH] update Group models and init coordinator group routes --- backend/app/coordinator/routes/groups.py | 131 ++++++++++++++++++ backend/app/coordinator/routes/students.py | 44 +++--- backend/app/factory.py | 4 +- backend/app/project_supervisor/models.py | 2 +- backend/app/students/models.py | 10 +- .../{45be50e56689_.py => 151d3b6306ec_.py} | 19 ++- backend/migrations/versions/84d4066483b8_.py | 34 ----- backend/migrations/versions/985c8a17dd66_.py | 28 ---- 8 files changed, 172 insertions(+), 100 deletions(-) create mode 100644 backend/app/coordinator/routes/groups.py rename backend/migrations/versions/{45be50e56689_.py => 151d3b6306ec_.py} (64%) delete mode 100644 backend/migrations/versions/84d4066483b8_.py delete mode 100644 backend/migrations/versions/985c8a17dd66_.py diff --git a/backend/app/coordinator/routes/groups.py b/backend/app/coordinator/routes/groups.py new file mode 100644 index 0000000..c35ebb4 --- /dev/null +++ b/backend/app/coordinator/routes/groups.py @@ -0,0 +1,131 @@ +from flask import abort +from apiflask import APIBlueprint +from flask_sqlalchemy import get_debug_queries + +from ...dependencies import db, ma + +bp = APIBlueprint("groups", __name__, url_prefix="/groups") + + +@bp.route("/", methods=["GET"]) +def list_groups(): + """ + groups = (QUERY: get all groups(includes supervisor project) and filter by name) + + # paginate groups + + return groups + """ + + +@bp.route("/", methods=["POST"]) +def create_group() -> dict: + """ + Create group: + body: + { + name:"system pri", + project_supervisor: id + students:[index1, index2] + } + + 1. if (QUERY: check if all students exist in database): + abort() + + project_supervisor = (QUERY: get project_supervisor by id) + 2. if project_supervisor is None: + abort() + + 3. if (QUERY: check if project_supervisor can have new group -> (limit_group - count(groups.id)) > 0): + abort() + + 4. If no errors, you can create a group + + return message + """ + + +@bp.route("//", methods=["GET"]) +def detail_group(id: int): + """ + group = (QUERY: get group by id) + if (group is none): + abort() + return group + """ + + +@bp.route("//", methods=["DELETE"]) +def delete_group(id: int): + """ + group = (QUERY: get group by id) + if (group is none): + abort() + delete group + return message + """ + + +@bp.route("//name", methods=["PUT"]) +def edit_group_name(id: int): + """ + body: + { + name: "name_group" + } + + group = (QUERY: get group by id) + if (group is none): + abort() + update group + return message + """ + + +@bp.route("//project_supervisor", methods=["PUT"]) +def edit_group_project_supervisor(id: int): + """ + body: + { + project_supervisor_id: 23 + } + + group = (QUERY: get group by id) + if (group is none): + abort() + + project_supervisor = (QUERY: get project_supervisor by id) + if project_supervisor is None: + abort() + + if (QUERY: check if project_supervisor can be assigned to new group -> (limit_group - count(groups.id)) > 0 ): + abort() + + update group + + return message + """ + + +@bp.route("//students", methods=["PUT"]) +def edit_group_student(id: int): + """ + body: + { + index: 344331 + } + + group = (QUERY: get group by id) + if (group is none): + abort() + + student = (QUERY: get student by index) + if student is None: + abort() + + if (QUERY: check if the student's have a group in database): + abort() + + update group + return message + """ diff --git a/backend/app/coordinator/routes/students.py b/backend/app/coordinator/routes/students.py index 7a5b582..b640f78 100644 --- a/backend/app/coordinator/routes/students.py +++ b/backend/app/coordinator/routes/students.py @@ -3,7 +3,6 @@ from itertools import islice from flask import abort from apiflask import APIBlueprint -from marshmallow import ValidationError from sqlalchemy.exc import IntegrityError from flask_sqlalchemy import get_debug_queries @@ -30,7 +29,7 @@ def list_students(query: dict) -> dict: per_page = query.get('per_page') 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) + fullname, mode, order_by_first_name, order_by_last_name) response = paginate_models(page, student_query, per_page) if (message := response.get('message')) is not None: @@ -66,20 +65,18 @@ def delete_student(index: int) -> dict: @bp.input(StudentEditSchema) @bp.output(MessageSchema) def edit_student(index: int, data: dict) -> dict: - try: - if not data: - abort(400, 'You have passed empty data!') + if not data: + abort(400, 'You have passed empty data!') - student_query = Student.query.filter_by(index=index) - student = student_query.first() + student_query = Student.query.filter_by(index=index) + student = student_query.first() - if student is None: - abort(404, 'Not found student!') + if student is None: + abort(404, 'Not found student!') + + student_query.update(data) + db.session.commit() - student_query.update(data) - db.session.commit() - except ValidationError as e: - abort(422, e.messages) return {"message": "Student was updated!"} @@ -87,18 +84,16 @@ def edit_student(index: int, data: dict) -> dict: @bp.input(StudentCreateSchema) @bp.output(MessageSchema) def create_student(data: dict) -> dict: - try: - index = data['index'] - student = Student.query.filter_by(index=index).first() - if student is not None: - abort(400, "Student has already exists!") + index = data['index'] + student = Student.query.filter_by(index=index).first() + if student is not None: + abort(400, "Student has already exists!") + + dummy_email = f'student{randint(1, 300_000)}@gmail.com' + student = Student(**data, email=dummy_email) + db.session.add(student) + db.session.commit() - dummy_email = f'student{randint(1, 300_000)}@gmail.com' - student = Student(**data, email=dummy_email) - db.session.add(student) - db.session.commit() - except ValidationError as e: - abort(422, e.messages) return {"message": "Student was created!"} @@ -122,7 +117,6 @@ def upload_students(file: dict) -> dict: except InvalidNameOrTypeHeaderException: abort(400, "Invalid format of csv file!") except IntegrityError as e: - # print(e) # in the future create sql query checks index and add only these students, which didn't exist in db abort(400, "These students have already exist!") else: diff --git a/backend/app/factory.py b/backend/app/factory.py index b4c2eee..68c4068 100644 --- a/backend/app/factory.py +++ b/backend/app/factory.py @@ -26,6 +26,8 @@ class GroupFactory(alchemy.SQLAlchemyModelFactory): 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') @@ -38,7 +40,5 @@ class StudentFactory(alchemy.SQLAlchemyModelFactory): last_name = Faker('last_name') email = Faker('email') index = Sequence(lambda n: 400_000 + n) - first_term = FuzzyInteger(1, 5) - second_term = FuzzyInteger(1, 5) # group = RelatedFactory(GroupFactory) mode = FuzzyChoice([True, False]) diff --git a/backend/app/project_supervisor/models.py b/backend/app/project_supervisor/models.py index 84e2e90..ce913c0 100644 --- a/backend/app/project_supervisor/models.py +++ b/backend/app/project_supervisor/models.py @@ -6,5 +6,5 @@ class ProjectSupervisor(Base, Person): __tablename__ = "project_supervisors" limit_group = db.Column(db.Integer, default=1, nullable=False) - count_groups = db.Column(db.Integer, default=1) + count_groups = db.Column(db.Integer, default=1, nullable=False) mode = db.Column(db.Boolean, default=True, nullable=False) # True - stationary, False - non-stationary diff --git a/backend/app/students/models.py b/backend/app/students/models.py index 5dfbc1d..91b5795 100644 --- a/backend/app/students/models.py +++ b/backend/app/students/models.py @@ -12,23 +12,23 @@ class Group(Base): name = db.Column(db.String(60), nullable=False) project_supervisor_id = db.Column(db.Integer, db.ForeignKey('project_supervisors.id')) project_supervisor = db.relationship('ProjectSupervisor', backref='groups', lazy=True) + points_for_first_term = db.Column(db.Integer, default=0, nullable=False) + points_for_second_term = db.Column(db.Integer, default=0, nullable=False) class Student(Person): __tablename__ = "students" index = db.Column(db.Integer, primary_key=True) - first_term = db.Column(db.Integer, default=0, nullable=False) - second_term = db.Column(db.Integer, default=0, nullable=False) group_id = db.Column(db.Integer, db.ForeignKey('groups.id')) group = db.relationship('Group', backref='students', lazy=True) mode = db.Column(db.Boolean, default=True, nullable=False) # True - stationary, False - non-stationary @classmethod def search_by_fullname_and_mode_and_order_by_first_name_or_last_name(cls, fullname: str = None, - mode: bool = None, - order_by_first_name: str = None, - order_by_last_name: str = None) -> BaseQuery: + mode: bool = None, + order_by_first_name: str = None, + order_by_last_name: str = None) -> BaseQuery: student_query = cls.query if mode is None: diff --git a/backend/migrations/versions/45be50e56689_.py b/backend/migrations/versions/151d3b6306ec_.py similarity index 64% rename from backend/migrations/versions/45be50e56689_.py rename to backend/migrations/versions/151d3b6306ec_.py index 0dad58f..f918b66 100644 --- a/backend/migrations/versions/45be50e56689_.py +++ b/backend/migrations/versions/151d3b6306ec_.py @@ -1,8 +1,8 @@ """empty message -Revision ID: 45be50e56689 +Revision ID: 151d3b6306ec Revises: -Create Date: 2022-05-17 19:36:35.976642 +Create Date: 2022-06-11 07:57:52.389681 """ from alembic import op @@ -10,7 +10,7 @@ import sqlalchemy as sa # revision identifiers, used by Alembic. -revision = '45be50e56689' +revision = '151d3b6306ec' down_revision = None branch_labels = None depends_on = None @@ -24,14 +24,19 @@ def upgrade(): sa.Column('last_name', sa.String(length=255), nullable=False), sa.Column('email', sa.String(length=120), nullable=True), sa.Column('limit_group', sa.Integer(), nullable=False), + sa.Column('count_groups', sa.Integer(), nullable=False), sa.Column('mode', sa.Boolean(), nullable=False), 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('groups', sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('name', sa.String(length=60), nullable=False), sa.Column('project_supervisor_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.PrimaryKeyConstraint('id') ) @@ -40,20 +45,24 @@ def upgrade(): sa.Column('last_name', sa.String(length=255), nullable=False), sa.Column('email', sa.String(length=120), nullable=True), sa.Column('index', sa.Integer(), nullable=False), - sa.Column('first_term', sa.Integer(), nullable=False), - sa.Column('second_term', sa.Integer(), nullable=False), sa.Column('group_id', sa.Integer(), nullable=True), sa.Column('mode', sa.Boolean(), nullable=False), 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) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### + 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('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 ### diff --git a/backend/migrations/versions/84d4066483b8_.py b/backend/migrations/versions/84d4066483b8_.py deleted file mode 100644 index b8acbb5..0000000 --- a/backend/migrations/versions/84d4066483b8_.py +++ /dev/null @@ -1,34 +0,0 @@ -"""empty message - -Revision ID: 84d4066483b8 -Revises: 45be50e56689 -Create Date: 2022-05-19 17:14:00.684001 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = '84d4066483b8' -down_revision = '45be50e56689' -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - 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_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) - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - 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_project_supervisors_last_name'), table_name='project_supervisors') - op.drop_index(op.f('ix_project_supervisors_first_name'), table_name='project_supervisors') - # ### end Alembic commands ### diff --git a/backend/migrations/versions/985c8a17dd66_.py b/backend/migrations/versions/985c8a17dd66_.py deleted file mode 100644 index bd1cf1e..0000000 --- a/backend/migrations/versions/985c8a17dd66_.py +++ /dev/null @@ -1,28 +0,0 @@ -"""empty message - -Revision ID: 985c8a17dd66 -Revises: 84d4066483b8 -Create Date: 2022-06-07 16:44:52.514825 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = '985c8a17dd66' -down_revision = '84d4066483b8' -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.add_column('project_supervisors', sa.Column('count_groups', sa.Integer(), nullable=True)) - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('project_supervisors', 'count_groups') - # ### end Alembic commands ###