update Group models and init coordinator group routes

This commit is contained in:
dominik24c 2022-06-11 12:53:55 +02:00
parent 850671e147
commit 1bd50e6bfc
8 changed files with 172 additions and 100 deletions

View File

@ -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("/<int:id>/", methods=["GET"])
def detail_group(id: int):
"""
group = (QUERY: get group by id)
if (group is none):
abort()
return group
"""
@bp.route("/<int:id>/", methods=["DELETE"])
def delete_group(id: int):
"""
group = (QUERY: get group by id)
if (group is none):
abort()
delete group
return message
"""
@bp.route("/<int:id>/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("/<int:id>/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("/<int:id>/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
"""

View File

@ -3,7 +3,6 @@ from itertools import islice
from flask import abort from flask import abort
from apiflask import APIBlueprint from apiflask import APIBlueprint
from marshmallow import ValidationError
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
from flask_sqlalchemy import get_debug_queries from flask_sqlalchemy import get_debug_queries
@ -30,7 +29,7 @@ def list_students(query: dict) -> dict:
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) fullname, mode, order_by_first_name, order_by_last_name)
response = paginate_models(page, student_query, per_page) response = paginate_models(page, student_query, per_page)
if (message := response.get('message')) is not None: if (message := response.get('message')) is not None:
@ -66,20 +65,18 @@ def delete_student(index: int) -> dict:
@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:
try: if not data:
if not data: abort(400, 'You have passed empty data!')
abort(400, 'You have passed empty data!')
student_query = Student.query.filter_by(index=index) student_query = Student.query.filter_by(index=index)
student = student_query.first() student = student_query.first()
if student is None: if student is None:
abort(404, 'Not found student!') 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!"} return {"message": "Student was updated!"}
@ -87,18 +84,16 @@ def edit_student(index: int, data: dict) -> dict:
@bp.input(StudentCreateSchema) @bp.input(StudentCreateSchema)
@bp.output(MessageSchema) @bp.output(MessageSchema)
def create_student(data: dict) -> dict: def create_student(data: dict) -> dict:
try: index = data['index']
index = data['index'] 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!")
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!"} return {"message": "Student was created!"}
@ -122,7 +117,6 @@ def upload_students(file: dict) -> dict:
except InvalidNameOrTypeHeaderException: except InvalidNameOrTypeHeaderException:
abort(400, "Invalid format of csv file!") abort(400, "Invalid format of csv file!")
except IntegrityError as e: 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 # 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!") abort(400, "These students have already exist!")
else: else:

View File

@ -26,6 +26,8 @@ class GroupFactory(alchemy.SQLAlchemyModelFactory):
sqlalchemy_session = db.session sqlalchemy_session = db.session
name = Sequence(lambda n: f'Group-{n}') 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') # project_supervisor = RelatedFactory(ProjectSupervisorFactory, 'project_supervisor')
@ -38,7 +40,5 @@ class StudentFactory(alchemy.SQLAlchemyModelFactory):
last_name = Faker('last_name') last_name = Faker('last_name')
email = Faker('email') email = Faker('email')
index = Sequence(lambda n: 400_000 + n) index = Sequence(lambda n: 400_000 + n)
first_term = FuzzyInteger(1, 5)
second_term = FuzzyInteger(1, 5)
# group = RelatedFactory(GroupFactory) # group = RelatedFactory(GroupFactory)
mode = FuzzyChoice([True, False]) mode = FuzzyChoice([True, False])

View File

@ -6,5 +6,5 @@ class ProjectSupervisor(Base, Person):
__tablename__ = "project_supervisors" __tablename__ = "project_supervisors"
limit_group = db.Column(db.Integer, default=1, nullable=False) 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 mode = db.Column(db.Boolean, default=True, nullable=False) # True - stationary, False - non-stationary

View File

@ -12,23 +12,23 @@ class Group(Base):
name = db.Column(db.String(60), nullable=False) name = db.Column(db.String(60), nullable=False)
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)
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): class Student(Person):
__tablename__ = "students" __tablename__ = "students"
index = db.Column(db.Integer, primary_key=True) 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_id = db.Column(db.Integer, db.ForeignKey('groups.id'))
group = db.relationship('Group', backref='students', lazy=True) group = db.relationship('Group', backref='students', lazy=True)
mode = db.Column(db.Boolean, default=True, nullable=False) # True - stationary, False - non-stationary mode = db.Column(db.Boolean, default=True, nullable=False) # True - stationary, False - non-stationary
@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, fullname: str = None,
mode: bool = 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
if mode is None: if mode is None:

View File

@ -1,8 +1,8 @@
"""empty message """empty message
Revision ID: 45be50e56689 Revision ID: 151d3b6306ec
Revises: Revises:
Create Date: 2022-05-17 19:36:35.976642 Create Date: 2022-06-11 07:57:52.389681
""" """
from alembic import op from alembic import op
@ -10,7 +10,7 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = '45be50e56689' revision = '151d3b6306ec'
down_revision = None down_revision = None
branch_labels = None branch_labels = None
depends_on = None depends_on = None
@ -24,14 +24,19 @@ def upgrade():
sa.Column('last_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('email', sa.String(length=120), nullable=True),
sa.Column('limit_group', sa.Integer(), nullable=False), sa.Column('limit_group', sa.Integer(), nullable=False),
sa.Column('count_groups', sa.Integer(), nullable=False),
sa.Column('mode', sa.Boolean(), nullable=False), sa.Column('mode', sa.Boolean(), nullable=False),
sa.PrimaryKeyConstraint('id'), sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('email') 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', op.create_table('groups',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('name', sa.String(length=60), nullable=False), sa.Column('name', sa.String(length=60), nullable=False),
sa.Column('project_supervisor_id', sa.Integer(), nullable=True), 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.ForeignKeyConstraint(['project_supervisor_id'], ['project_supervisors.id'], ),
sa.PrimaryKeyConstraint('id') sa.PrimaryKeyConstraint('id')
) )
@ -40,20 +45,24 @@ def upgrade():
sa.Column('last_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('email', sa.String(length=120), nullable=True),
sa.Column('index', sa.Integer(), nullable=False), 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('group_id', sa.Integer(), nullable=True),
sa.Column('mode', sa.Boolean(), nullable=False), sa.Column('mode', sa.Boolean(), nullable=False),
sa.ForeignKeyConstraint(['group_id'], ['groups.id'], ), sa.ForeignKeyConstraint(['group_id'], ['groups.id'], ),
sa.PrimaryKeyConstraint('index'), sa.PrimaryKeyConstraint('index'),
sa.UniqueConstraint('email') 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 ### # ### end Alembic commands ###
def downgrade(): def downgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### 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('students')
op.drop_table('groups') 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') op.drop_table('project_supervisors')
# ### end Alembic commands ### # ### end Alembic commands ###

View File

@ -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 ###

View File

@ -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 ###