diff --git a/backend/app/coordinator/routes/students.py b/backend/app/coordinator/routes/students.py index 4eaae4c..1932aae 100644 --- a/backend/app/coordinator/routes/students.py +++ b/backend/app/coordinator/routes/students.py @@ -87,10 +87,9 @@ def create_student(data: dict) -> dict: yg_id = data['year_group_id'] del data['year_group_id'] - student = Student.query.filter_by(index=index).join(Student.year_groups).first() + 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) @@ -102,6 +101,7 @@ def create_student(data: dict) -> dict: 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) diff --git a/backend/app/students/routes/year_group.py b/backend/app/students/routes/year_group.py index fc18477..420fe77 100644 --- a/backend/app/students/routes/year_group.py +++ b/backend/app/students/routes/year_group.py @@ -1,7 +1,7 @@ from apiflask import APIBlueprint from flask import abort -from ...students.models import YearGroup +from ...students.models import YearGroup, YearGroupStudents from ...dependencies import db from ...base.utils import paginate_models from ..schemas import YearGroupQueryStudentSchema, YearGroupStudentPaginationSchema @@ -22,8 +22,8 @@ def list_of_year_groups(query: dict) -> dict: page = query.get('page') per_page = query.get('per_page') - year_group_query = YearGroup.query.join(YearGroup.students). \ - filter(Student.index == st.index).order_by(db.desc(YearGroup.created_at)) + 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 { diff --git a/backend/app/utils.py b/backend/app/utils.py index 20e427e..a7de7c2 100644 --- a/backend/app/utils.py +++ b/backend/app/utils.py @@ -23,7 +23,6 @@ def import_models() -> None: models_module = "models" for dirname in directories: try: - importlib.import_module(f"app.app.{dirname}.{models_module}") + importlib.import_module(f"app.{dirname}.{models_module}") except ModuleNotFoundError: - print(models_module, dirname) warnings.warn(f"Not found module {models_module}.py in package {dirname}") diff --git a/backend/main.py b/backend/main.py index ecf4729..4d597d1 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1,5 +1,5 @@ from dotenv import load_dotenv -from .app import create_app +from app import create_app load_dotenv() app = create_app() diff --git a/backend/tests/conftest.py b/backend/tests/conftest.py index e916fe7..a784b82 100644 --- a/backend/tests/conftest.py +++ b/backend/tests/conftest.py @@ -6,8 +6,8 @@ from flask import Flask from flask.testing import FlaskClient from flask.ctx import AppContext -from ..app import create_app -from ..app.dependencies import db +from app import create_app +from app.dependencies import db @pytest.fixture() diff --git a/backend/tests/factory.py b/backend/tests/factory.py index 14a17de..e1bd2be 100644 --- a/backend/tests/factory.py +++ b/backend/tests/factory.py @@ -2,9 +2,9 @@ from factory import alchemy, Sequence from factory.faker import Faker from factory.fuzzy import FuzzyInteger -from ..app.dependencies import db -from ..app.students.models import Student, Group, YearGroupStudents -from ..app.project_supervisor.models import ProjectSupervisor, YearGroupProjectSupervisors +from app.dependencies import db +from app.students.models import Student, Group, YearGroupStudents +from app.project_supervisor.models import ProjectSupervisor, YearGroupProjectSupervisors class ProjectSupervisorFactory(alchemy.SQLAlchemyModelFactory): diff --git a/backend/tests/fake_data.py b/backend/tests/fake_data.py index 863ef8d..1b1e083 100644 --- a/backend/tests/fake_data.py +++ b/backend/tests/fake_data.py @@ -2,10 +2,10 @@ from typing import List from .factory import ProjectSupervisorFactory, YearGroupProjectSupervisorsFactory, \ StudentFactory, YearGroupStudentsFactory, GroupFactory -from ..app.dependencies import db -from ..app.project_supervisor.models import YearGroup, ProjectSupervisor -from ..app.students.models import Group, Student, YearGroupStudents -from ..app.base.mode import ModeGroups +from app.dependencies import db +from app.project_supervisor.models import YearGroup, ProjectSupervisor +from app.students.models import Group, Student, YearGroupStudents +from app.base.mode import ModeGroups def create_year_group(data: dict = None) -> YearGroup: @@ -51,12 +51,13 @@ def create_students(yg: YearGroup, amount: int) -> List[StudentFactory]: return students -def create_student(data: dict, year_group_id: int) -> Student: +def create_student(data: dict, year_group_id: int = None) -> Student: st = Student(**data) db.session.add(st) db.session.commit() - db.session.add(YearGroupStudents(year_group_id=year_group_id, student_index=st.index)) - db.session.commit() + if year_group_id is not None: + db.session.add(YearGroupStudents(year_group_id=year_group_id, student_index=st.index)) + db.session.commit() return st diff --git a/backend/tests/functional_tests/coordinator/test_groups.py b/backend/tests/functional_tests/coordinator/test_groups.py index 498ad52..08a1bc4 100644 --- a/backend/tests/functional_tests/coordinator/test_groups.py +++ b/backend/tests/functional_tests/coordinator/test_groups.py @@ -4,9 +4,9 @@ from flask import current_app from ...utils import _test_case_client, _test_case_client_without_response, assert_model_changes, _test_case_group from ...fake_data import create_year_group, create_groups, create_group, create_students, create_project_supervisors -from ....app.dependencies import db -from ....app.students.models import Group -from ....app.project_supervisor.models import YearGroupProjectSupervisors +from app.dependencies import db +from app.students.models import Group +from app.project_supervisor.models import YearGroupProjectSupervisors valid_data = { 'name': 'System Pri' diff --git a/backend/tests/functional_tests/coordinator/test_project_supervisors.py b/backend/tests/functional_tests/coordinator/test_project_supervisors.py index 1de480c..c67f098 100644 --- a/backend/tests/functional_tests/coordinator/test_project_supervisors.py +++ b/backend/tests/functional_tests/coordinator/test_project_supervisors.py @@ -1,7 +1,7 @@ from ...utils import _test_case_client, _test_case_client_without_response, assert_model_changes from ...fake_data import create_project_supervisors, create_year_group, create_dummy_group, create_dummy_ps -from ....app.dependencies import db -from ....app.project_supervisor.models import YearGroupProjectSupervisors +from app.dependencies import db +from app.project_supervisor.models import YearGroupProjectSupervisors valid_data = { 'first_name': 'John', diff --git a/backend/tests/functional_tests/coordinator/test_students.py b/backend/tests/functional_tests/coordinator/test_students.py index d887d5b..99303c4 100644 --- a/backend/tests/functional_tests/coordinator/test_students.py +++ b/backend/tests/functional_tests/coordinator/test_students.py @@ -17,7 +17,9 @@ new_data = { } data_to_create_student = { - **new_data, + 'first_name': 'Albert', + 'last_name': 'Marcus', + 'pesel': '93030312896', 'index': 123_456 } diff --git a/backend/tests/functional_tests/coordinator/test_year_group.py b/backend/tests/functional_tests/coordinator/test_year_group.py index b35df5c..f7f1566 100644 --- a/backend/tests/functional_tests/coordinator/test_year_group.py +++ b/backend/tests/functional_tests/coordinator/test_year_group.py @@ -1,6 +1,6 @@ from ...fake_data import create_year_group from ...utils import _test_case_client_without_response, _test_case_client, assert_model_changes -from ....app.base.mode import ModeGroups +from app.base.mode import ModeGroups valid_data = { 'mode': ModeGroups.STATIONARY.value, diff --git a/backend/__init__.py b/backend/tests/functional_tests/students/test_registrations.py similarity index 100% rename from backend/__init__.py rename to backend/tests/functional_tests/students/test_registrations.py diff --git a/backend/tests/functional_tests/students/test_year_group.py b/backend/tests/functional_tests/students/test_year_group.py new file mode 100644 index 0000000..674c68d --- /dev/null +++ b/backend/tests/functional_tests/students/test_year_group.py @@ -0,0 +1,50 @@ +from ...utils import _test_case_client, _test_case_client_without_response, assert_model_changes +from ...fake_data import create_year_group, create_students, create_student +from app.base.mode import ModeGroups +from app.dependencies import db +from app.students.models import YearGroupStudents + +valid_data = { + 'first_name': 'Dominic', + 'last_name': 'Mozart', + 'index': 123_345 +} + +year_group_data = [ + { + 'name': '2022/2023', + 'mode': ModeGroups.STATIONARY.value + }, + { + 'name': '2021/2022', + 'mode': ModeGroups.STATIONARY.value + }, + { + 'name': '2023/2024', + 'mode': ModeGroups.NON_STATIONARY.value + }, + { + 'name': '1997/1998', + 'mode': ModeGroups.NON_STATIONARY.value + }, +] + + +def test_list_year_group_for_specific_student(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + year_groups = [create_year_group(data) for data in year_group_data] + student = create_student(valid_data) + for yg in year_groups[:-1]: + db.session.add(YearGroupStudents(year_group_id=yg.id, student_index=student.index)) + db.session.commit() + + url = f'/api/students/year-group/?per_page=10&index={student.index}' + data = _test_case_client_without_response(client, url, None, 200, method='get') + assert data.get('max_pages') == 1 + assert len(data.get('year_groups')) == len(year_groups) - 1 + + +def test_list_year_group_if_student_doesnt_exist(test_app_with_context) -> None: + with test_app_with_context.test_client() as client: + _test_case_client(client, '/api/students/year-group/?per_page=10&index=23', None, 'Not found student!', 404, + method='get', key='error') diff --git a/backend/tests/unit_tests/test_utils.py b/backend/tests/unit_tests/test_utils.py index 0c6b275..62996a2 100644 --- a/backend/tests/unit_tests/test_utils.py +++ b/backend/tests/unit_tests/test_utils.py @@ -4,11 +4,11 @@ import pandas as pd import pytest from flask import current_app -from ...app.dependencies import db -from ...app.base.utils import is_allowed_extensions, order_by_column_name, paginate_models -from ...app.coordinator.utils import check_columns, parse_csv, generate_range_dates, generate_csv -from ...app.coordinator.exceptions import InvalidNameOrTypeHeaderException -from ...app.students.models import Student, Group +from app.dependencies import db +from app.base.utils import is_allowed_extensions, order_by_column_name, paginate_models +from app.coordinator.utils import check_columns, parse_csv, generate_range_dates, generate_csv +from app.coordinator.exceptions import InvalidNameOrTypeHeaderException +from app.students.models import Student, Group def test_is_allowed_extensions(test_app) -> None: diff --git a/backend/tests/unit_tests/test_validators.py b/backend/tests/unit_tests/test_validators.py index 16ab710..a3c8aa2 100644 --- a/backend/tests/unit_tests/test_validators.py +++ b/backend/tests/unit_tests/test_validators.py @@ -3,7 +3,7 @@ import datetime import pytest from marshmallow import ValidationError -from ...app.coordinator.validators import validate_index, validate_datetime_greater_than_now +from app.coordinator.validators import validate_index, validate_datetime_greater_than_now def test_validate_index() -> None: diff --git a/backend/tests/utils.py b/backend/tests/utils.py index 878547a..9d536e6 100644 --- a/backend/tests/utils.py +++ b/backend/tests/utils.py @@ -2,8 +2,8 @@ from typing import Union from flask.testing import FlaskClient -from ..app.dependencies import db -from ..app.students.models import Group +from app.dependencies import db +from app.students.models import Group def assert_model_changes(model: db.Model, expected_data: dict) -> None: