diff --git a/app/blueprints/skills_category_blueprint.py b/app/blueprints/skills_category_blueprint.py index 7705b2f..3f0112e 100644 --- a/app/blueprints/skills_category_blueprint.py +++ b/app/blueprints/skills_category_blueprint.py @@ -5,13 +5,13 @@ Security, Auth, ) -from app.controllers.skills_category_controller import SkillsCategoryController +from app.controllers.skill_category_controller import SkillCategoryController url_prefix = "{}/skills_categories".format(BaseBlueprint.base_url_prefix) skills_category_blueprint = Blueprint( "skills_category", __name__, url_prefix=url_prefix ) -skills_category_controller = SkillsCategoryController(request) +skills_category_controller = SkillCategoryController(request) @skills_category_blueprint.route("/", methods=["GET"]) diff --git a/app/blueprints/user_employment_blueprint.py b/app/blueprints/user_employment_blueprint.py index f0964f8..95df5df 100644 --- a/app/blueprints/user_employment_blueprint.py +++ b/app/blueprints/user_employment_blueprint.py @@ -39,6 +39,7 @@ def get_user_employment(user_employment_id): "start_date|required:date", "end_date|required:date", "is_current|required", + "skills|optional:list_int", ] ) @Auth.has_permission(["create_user_employment_history"]) diff --git a/app/controllers/skills_category_controller.py b/app/controllers/skill_category_controller.py similarity index 78% rename from app/controllers/skills_category_controller.py rename to app/controllers/skill_category_controller.py index fa45506..ee87fe2 100644 --- a/app/controllers/skills_category_controller.py +++ b/app/controllers/skill_category_controller.py @@ -1,16 +1,16 @@ from app.controllers.base_controller import BaseController -from app.repositories.skills_category_repo import SkillsCategoryRepo +from app.repositories.skill_category_repo import SkillCategoryRepo from app.utils.redisset import RedisSet -class SkillsCategoryController(BaseController): +class SkillCategoryController(BaseController): def __init__(self, request): BaseController.__init__(self, request) - self.skills_category_repo = SkillsCategoryRepo() + self.skill_category_repo = SkillCategoryRepo() self.redis_set = RedisSet() def list_skills_categories(self): - skills_categories = self.skills_category_repo.filter_by(is_deleted=False) + skills_categories = self.skill_category_repo.filter_by(is_deleted=False) skills_category_list = [ skills_category.serialize() for skills_category in skills_categories.items @@ -24,7 +24,7 @@ def list_skills_categories(self): ) def get_skills_category(self, skills_category_id): - skills_category = self.skills_category_repo.get(skills_category_id) + skills_category = self.skill_category_repo.get(skills_category_id) if skills_category: return self.handle_response( "OK", payload={"skills_category": skills_category.serialize()} @@ -35,11 +35,11 @@ def get_skills_category(self, skills_category_id): def create_skills_category(self): name, help_ = self.request_params("name", "help") - skills_category1 = self.skills_category_repo.find_first(name=name) + skills_category1 = self.skill_category_repo.find_first(name=name) if not skills_category1: try: - skills_category = self.skills_category_repo.new_skills_category( + skills_category = self.skill_category_repo.new_skill_category( name=name, help_=help_ ) return self.handle_response( @@ -58,11 +58,11 @@ def create_skills_category(self): def update_skills_category(self, skills_category_id): name, help_ = self.request_params("name", "help") - skills_category = self.skills_category_repo.get(skills_category_id) + skills_category = self.skill_category_repo.get(skills_category_id) if skills_category: updates = {} if name: - skills_category1 = self.skills_category_repo.find_first(name=name) + skills_category1 = self.skill_category_repo.find_first(name=name) if skills_category1: return self.handle_response( "Skills Category with this name already exists", status_code=400 @@ -71,7 +71,7 @@ def update_skills_category(self, skills_category_id): if help_: updates["help"] = help_ - self.skills_category_repo.update(skills_category, **updates) + self.skill_category_repo.update(skills_category, **updates) return self.handle_response( "OK", payload={"skills_category": skills_category.serialize()} ) @@ -80,11 +80,11 @@ def update_skills_category(self, skills_category_id): ) def delete_skills_category(self, skills_category_id): - skills_category = self.skills_category_repo.get(skills_category_id) + skills_category = self.skill_category_repo.get(skills_category_id) if skills_category: updates = {} updates["is_deleted"] = True - self.skills_category_repo.update(skills_category, **updates) + self.skill_category_repo.update(skills_category, **updates) return self.handle_response( "skills category deleted", payload={"status": "success"} ) diff --git a/app/controllers/user_employment_controller.py b/app/controllers/user_employment_controller.py index 8f54e98..f00cbcf 100644 --- a/app/controllers/user_employment_controller.py +++ b/app/controllers/user_employment_controller.py @@ -1,8 +1,12 @@ import datetime from app.controllers.base_controller import BaseController -from app.repositories import UserRepo -from app.repositories.user_employment_repo import UserEmploymentRepo +from app.repositories import ( + UserRepo, + SkillRepo, + UserEmploymentRepo, + UserEmploymentSkillRepo, +) class UserEmploymentController(BaseController): @@ -10,14 +14,31 @@ def __init__(self, request): BaseController.__init__(self, request) self.user_repo = UserRepo() self.user_employment_repo = UserEmploymentRepo() + self.user_employment_skill_repo = UserEmploymentSkillRepo() + self.skill_repo = SkillRepo() + + def _get_employment_skills(self, employment_id): + skills_list = [] + skills = self.user_employment_skill_repo.get_unpaginated( + user_employment_id=employment_id + ) + for skill in skills: + skill_data = self.skill_repo.find_first(id=skill) + skill_dict = skill_data.serialize() + skill_dict["name"] = skill_data.name + skills_list.append(skill_dict) + return skills_list def list_user_employment_history(self, user_id): user_employments = self.user_employment_repo.get_unpaginated(user_id=user_id) - user_employment_list = [ - user_employment.serialize() for user_employment in user_employments - ] - + user_employment_list = [] + for user_employment in user_employments: + user_employment_dict = user_employment.serialize() + user_employment_dict["skills"] = self._get_employment_skills( + user_employment.id + ) + user_employment_list.append(user_employment_dict) return self.handle_response( "OK", payload={ @@ -27,9 +48,14 @@ def list_user_employment_history(self, user_id): def get_user_employment(self, user_employment_id): user_employment = self.user_employment_repo.get(user_employment_id) + if user_employment: + user_employment_dict = user_employment.serialize() + user_employment_dict["skills"] = self._get_employment_skills( + user_employment.id + ) return self.handle_response( - "OK", payload={"user_employment": user_employment.serialize()} + "OK", payload={"user_employment": user_employment_dict} ) return self.handle_response( "Invalid User Employment or Missing user_employment_id", status_code=400 @@ -43,6 +69,7 @@ def create_user_employment(self): start_date, end_date, is_current, + skills, ) = self.request_params( "user_id", "institution_name", @@ -50,6 +77,7 @@ def create_user_employment(self): "start_date", "end_date", "is_current", + "skills", ) try: @@ -69,14 +97,35 @@ def create_user_employment(self): end_date=end_date, is_current=is_current, ) + skills_dict = self._process_skills(user_employment.id, skills) + + user_employment_serialized = user_employment.serialize() + user_employment_serialized["skills"] = skills_dict return self.handle_response( "OK", - payload={"user_employment": user_employment.serialize()}, + payload={"user_employment": user_employment_serialized}, status_code=201, ) except Exception as e: return self.handle_response("Error processing: " + str(e), status_code=400) + def _process_skills(self, user_employment_id, skills): + skills_dict = [] + + if skills is not None: + + for skill in skills: + user_employment_skills = ( + self.user_employment_skill_repo.new_user_employment_skill( + user_employment_id=user_employment_id, skill_id=skill + ) + ) + skill_data = self.skill_repo.find_first(id=skill) + user_employment_skill_dict = user_employment_skills.serialize() + user_employment_skill_dict["name"] = skill_data.name + skills_dict.append(user_employment_skill_dict) + return skills_dict + def update_user_employment(self, update_id): ( user_id, @@ -86,6 +135,7 @@ def update_user_employment(self, update_id): start_date, end_date, is_current, + skills, ) = self.request_params( "user_id", "user_employment_id", @@ -94,6 +144,7 @@ def update_user_employment(self, update_id): "start_date", "end_date", "is_current", + "skills", ) if update_id != user_employment_id: return self.handle_response( @@ -116,9 +167,14 @@ def update_user_employment(self, update_id): } self.user_employment_repo.update(user_employment, **updates) + skills_dict = self._process_skills(user_employment.id, skills) + user_employment_serialized = user_employment.serialize() + user_employment_serialized["skills"] = skills_dict return self.handle_response( - "OK", payload={"user_employment": user_employment.serialize()} + "OK", + payload={"user_employment": user_employment_serialized}, ) + return self.handle_response( "Invalid or incorrect user_employment_id provided", status_code=400 ) diff --git a/app/models/__init__.py b/app/models/__init__.py index 0906690..4845b51 100755 --- a/app/models/__init__.py +++ b/app/models/__init__.py @@ -7,10 +7,10 @@ from .user_role import UserRole from .user import User from .skill import Skill -from .skills_category import SkillsCategory +from .skill_category import SkillCategory from .user_education import UserEducation from .user_employment import UserEmployment -from .user_employment_skills import UserEmploymentSkill +from .user_employment_skill import UserEmploymentSkill from .user_project import UserProject from .user_skills import UserSkills from .location import Location @@ -21,7 +21,7 @@ "UserRole", "Activity", "User", - "SkillsCategory", + "SkillCategory", "Skill", "UserSkills", "UserProject", @@ -44,7 +44,7 @@ UserRole, User, Skill, - SkillsCategory, + SkillCategory, Location, ] tables_logged_after_every_update = [ @@ -58,7 +58,7 @@ UserRole, User, Skill, - SkillsCategory, + SkillCategory, Location, ] tables_logged_after_every_delete = [ @@ -72,7 +72,7 @@ UserRole, User, Skill, - SkillsCategory, + SkillCategory, Location, ] generate_id_tables = (User,) diff --git a/app/models/skill.py b/app/models/skill.py index 3e109f6..7e3f640 100644 --- a/app/models/skill.py +++ b/app/models/skill.py @@ -7,7 +7,7 @@ class Skill(BaseModel): __tablename__ = "skills" name = db.Column(db.String(100), nullable=False) - skills_category_id = db.Column(db.Integer(), db.ForeignKey("skill_categories.id")) - skills_category = db.relationship("SkillsCategory", lazy=False) + skill_category_id = db.Column(db.Integer(), db.ForeignKey("skill_categories.id")) + skill_category = db.relationship("SkillCategory", lazy=False) is_active = db.Column(db.Boolean, default=True, nullable=True) is_deleted = db.Column(db.Boolean, default=False, nullable=True) diff --git a/app/models/skills_category.py b/app/models/skill_category.py similarity index 74% rename from app/models/skills_category.py rename to app/models/skill_category.py index 96f6da1..57b8f92 100644 --- a/app/models/skills_category.py +++ b/app/models/skill_category.py @@ -1,7 +1,7 @@ from .base_model import BaseModel, db -class SkillsCategory(BaseModel): +class SkillCategory(BaseModel): __tablename__ = "skill_categories" @@ -9,3 +9,4 @@ class SkillsCategory(BaseModel): help = db.Column(db.Text(), nullable=True) is_active = db.Column(db.Boolean, default=True, nullable=True) is_deleted = db.Column(db.Boolean, default=False, nullable=True) + skills = db.relationship("Skill", backref="skill_categories", lazy=True) diff --git a/app/models/user.py b/app/models/user.py index ab7fb54..e2c531d 100644 --- a/app/models/user.py +++ b/app/models/user.py @@ -18,6 +18,6 @@ class User(BaseModel): image_url = db.Column(db.String, nullable=True) gender = db.Column(db.Enum(Gender), nullable=True) date_of_birth = db.Column(db.Date(), nullable=False) - user_role = db.relationship("UserRole", lazy=True) + user_role = db.relationship("UserRole", backref="user_roles", lazy=True) is_active = db.Column(db.Boolean, default=True, nullable=True) is_deleted = db.Column(db.Boolean, default=True, nullable=True) diff --git a/app/models/user_employment.py b/app/models/user_employment.py index 5df1b28..b541040 100644 --- a/app/models/user_employment.py +++ b/app/models/user_employment.py @@ -12,3 +12,6 @@ class UserEmployment(BaseModel): user_id = db.Column(db.Integer(), db.ForeignKey("users.id")) user = db.relationship("User", lazy=False) is_current = db.Column(db.Boolean, default=False, nullable=True) + skills = db.relationship( + "UserEmploymentSkill", backref="user_employment_skills", lazy=True + ) diff --git a/app/models/user_employment_skills.py b/app/models/user_employment_skill.py similarity index 63% rename from app/models/user_employment_skills.py rename to app/models/user_employment_skill.py index 81bf107..b084f26 100644 --- a/app/models/user_employment_skills.py +++ b/app/models/user_employment_skill.py @@ -6,7 +6,7 @@ class UserEmploymentSkill(BaseModel): __tablename__ = "user_employment_skills" - user_employement_id = db.Column(db.Integer(), db.ForeignKey("user_employments.id")) - user_employement = db.relationship("UserEmployment", lazy=False) + user_employment_id = db.Column(db.Integer(), db.ForeignKey("user_employments.id")) + user_employment = db.relationship("UserEmployment", lazy=False) skill_id = db.Column(db.Integer(), db.ForeignKey("skills.id")) skill = db.relationship("Skill", lazy=False) diff --git a/app/repositories/__init__.py b/app/repositories/__init__.py index 496d5a8..734158d 100755 --- a/app/repositories/__init__.py +++ b/app/repositories/__init__.py @@ -4,4 +4,7 @@ from .user_repo import UserRepo from .user_role_repo import UserRoleRepo from .permission_repo import PermissionRepo -from .skills_category_repo import SkillsCategoryRepo +from .skill_category_repo import SkillCategoryRepo +from .skill_repo import SkillRepo +from .user_employment_repo import UserEmploymentRepo +from .user_employment_skill_repo import UserEmploymentSkillRepo diff --git a/app/repositories/skill_category_repo.py b/app/repositories/skill_category_repo.py new file mode 100644 index 0000000..5d823db --- /dev/null +++ b/app/repositories/skill_category_repo.py @@ -0,0 +1,15 @@ +from app.repositories.base_repo import BaseRepo +from app.models.skill_category import SkillCategory + + +class SkillCategoryRepo(BaseRepo): + def __init__(self): + BaseRepo.__init__(self, SkillCategory) + + def new_skill_category(self, name, help_=None, is_active=True, is_deleted=False): + skills_category = SkillCategory( + name=name, help=help_, is_active=is_active, is_deleted=is_deleted + ) + + skills_category.save() + return skills_category diff --git a/app/repositories/skill_repo.py b/app/repositories/skill_repo.py new file mode 100644 index 0000000..c158368 --- /dev/null +++ b/app/repositories/skill_repo.py @@ -0,0 +1,18 @@ +from app.repositories.base_repo import BaseRepo +from app.models.skill import Skill + + +class SkillRepo(BaseRepo): + def __init__(self): + BaseRepo.__init__(self, Skill) + + def new_skill(self, name, skill_category_id, is_active=True, is_deleted=False): + new_skill = Skill( + name=name, + skill_category_id=skill_category_id, + is_active=is_active, + is_deleted=is_deleted, + ) + + new_skill.save() + return new_skill diff --git a/app/repositories/skills_category_repo.py b/app/repositories/skills_category_repo.py deleted file mode 100644 index c3098db..0000000 --- a/app/repositories/skills_category_repo.py +++ /dev/null @@ -1,15 +0,0 @@ -from app.repositories.base_repo import BaseRepo -from app.models.skills_category import SkillsCategory - - -class SkillsCategoryRepo(BaseRepo): - def __init__(self): - BaseRepo.__init__(self, SkillsCategory) - - def new_skills_category(self, name, help_=None, is_active=True, is_deleted=False): - skills_category = SkillsCategory( - name=name, help=help_, is_active=is_active, is_deleted=is_deleted - ) - - skills_category.save() - return skills_category diff --git a/app/repositories/user_employment_skill_repo.py b/app/repositories/user_employment_skill_repo.py new file mode 100644 index 0000000..286b296 --- /dev/null +++ b/app/repositories/user_employment_skill_repo.py @@ -0,0 +1,15 @@ +from app.repositories.base_repo import BaseRepo +from app.models.user_employment_skill import UserEmploymentSkill + + +class UserEmploymentSkillRepo(BaseRepo): + def __init__(self): + BaseRepo.__init__(self, UserEmploymentSkill) + + def new_user_employment_skill(self, user_employment_id, skill_id): + user_employment_skill = UserEmploymentSkill( + user_employment_id=user_employment_id, + skill_id=skill_id, + ) + user_employment_skill.save() + return user_employment_skill diff --git a/factories/__init__.py b/factories/__init__.py index 0d0dc66..057332b 100755 --- a/factories/__init__.py +++ b/factories/__init__.py @@ -3,5 +3,10 @@ from .user_role_factory import UserRoleFactory from .user_factory import UserFactory from .location_factory import LocationFactory -from .skill_category_factory import SkillsCategoryFactory, SkillsCategoryFactoryFake +from .skill_category_factory import ( + SkillCategoryFactory, + SkillCategoryFactoryFake, + SkillFactory, + SkillFactoryFake, +) from .user_employment_factory import UserEmploymentFactory, UserEmploymentFactoryFake diff --git a/factories/skill_category_factory.py b/factories/skill_category_factory.py index 72e7216..2e7a2bb 100644 --- a/factories/skill_category_factory.py +++ b/factories/skill_category_factory.py @@ -1,6 +1,7 @@ import factory +from app.models import Skill from app.utils import db -from app.models.skills_category import SkillsCategory +from app.models.skill_category import SkillCategory from faker import Faker from faker.providers import misc @@ -9,9 +10,9 @@ fake.add_provider(misc) -class SkillsCategoryFactory(factory.alchemy.SQLAlchemyModelFactory): +class SkillCategoryFactory(factory.alchemy.SQLAlchemyModelFactory): class Meta: - model = SkillsCategory + model = SkillCategory sqlalchemy_session = db.session id = factory.Sequence(lambda n: n) @@ -21,12 +22,58 @@ class Meta: is_deleted = fake.boolean(chance_of_getting_true=0) -class SkillsCategoryFactoryFake(factory.Factory): +class CategoryWithSkillsFactory(SkillCategoryFactory): + @factory.post_generation + def skills(obj, create, extracted, **kwargs): + """ + If called like: CategoryWithSkillsFactory(skills=4) it generates a Skill Category with 4 + skills. If called without `skills` argument, it generates a + random amount of skills for this category + """ + if not create: + # Build, not create related + return + + if extracted: + for n in range(extracted): + SkillFactory(skill_category=obj) + else: + import random + + number_of_units = random.randint(1, 10) + for n in range(number_of_units): + SkillFactory(skill_category=obj) + + +class SkillCategoryFactoryFake(factory.Factory): class Meta: - model = SkillsCategory + model = SkillCategory id = factory.Sequence(lambda n: n) name = factory.Faker("name") help = factory.Faker("paragraph") is_active = fake.boolean(chance_of_getting_true=75) is_deleted = fake.boolean(chance_of_getting_true=0) + + +class SkillFactory(factory.alchemy.SQLAlchemyModelFactory): + class Meta: + model = Skill + sqlalchemy_session = db.session + + name = fake.job() + skill_category = factory.SubFactory(SkillCategoryFactory) + skill_category_id = factory.SelfAttribute("skill_category.id") + is_active = True + is_deleted = False + + +class SkillFactoryFake(factory.Factory): + class Meta: + model = Skill + + name = fake.job() + skill_category = factory.SubFactory(SkillCategoryFactory) + skill_category_id = factory.SelfAttribute("skill_category.id") + is_active = True + is_deleted = False diff --git a/factories/user_employment_factory.py b/factories/user_employment_factory.py index 6501e6f..ab68bc3 100644 --- a/factories/user_employment_factory.py +++ b/factories/user_employment_factory.py @@ -2,8 +2,9 @@ from faker import Faker from faker.providers import internet, company, job, date_time -from app.models import UserEmployment +from app.models import UserEmployment, UserEmploymentSkill from app.utils import db +from factories.skill_category_factory import SkillFactory from factories.user_factory import UserFactory fake = Faker() @@ -37,3 +38,24 @@ class Meta: start_date = fake.date_between() end_date = fake.date_between() is_current = False + + +class UserEmploymentSkillFactory(factory.alchemy.SQLAlchemyModelFactory): + class Meta: + model = UserEmploymentSkill + sqlalchemy_session = db.session + + user_employment = factory.SubFactory(UserEmploymentFactory) + user_employment_id = factory.SelfAttribute("user_employment.id") + skill = factory.SubFactory(SkillFactory) + skill_id = factory.SelfAttribute("skill.id") + + +class UserEmploymentSkillFactoryFake(factory.Factory): + class Meta: + model = UserEmploymentSkill + + user_employment = factory.SubFactory(UserEmploymentFactory) + user_employment_id = factory.SelfAttribute("user_employment.id") + skill = factory.SubFactory(SkillFactory) + skill_id = factory.SelfAttribute("skill.id") diff --git a/migrations/versions/3bf61cf107f2_.py b/migrations/versions/3bf61cf107f2_.py new file mode 100644 index 0000000..84646ee --- /dev/null +++ b/migrations/versions/3bf61cf107f2_.py @@ -0,0 +1,47 @@ +"""empty message + +Revision ID: 3bf61cf107f2 +Revises: 5340044cdb8e +Create Date: 2021-01-15 11:53:18.378540 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "3bf61cf107f2" +down_revision = "5340044cdb8e" +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column("skills", sa.Column("skill_category_id", sa.Integer(), nullable=True)) + op.drop_constraint("skills_skills_category_id_fkey", "skills", type_="foreignkey") + op.create_foreign_key( + None, "skills", "skill_categories", ["skill_category_id"], ["id"] + ) + op.drop_column("skills", "skills_category_id") + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column( + "skills", + sa.Column( + "skills_category_id", sa.INTEGER(), autoincrement=False, nullable=True + ), + ) + op.drop_constraint(None, "skills", type_="foreignkey") + op.create_foreign_key( + "skills_skills_category_id_fkey", + "skills", + "skill_categories", + ["skills_category_id"], + ["id"], + ) + op.drop_column("skills", "skill_category_id") + # ### end Alembic commands ### diff --git a/migrations/versions/5340044cdb8e_.py b/migrations/versions/5340044cdb8e_.py new file mode 100644 index 0000000..a5d51d1 --- /dev/null +++ b/migrations/versions/5340044cdb8e_.py @@ -0,0 +1,97 @@ +"""empty message + +Revision ID: 5340044cdb8e +Revises: 5e71e985eb70 +Create Date: 2021-01-15 10:42:55.831392 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = "5340044cdb8e" +down_revision = "5e71e985eb70" +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column("skill_categories", sa.Column("help", sa.Text(), nullable=True)) + op.add_column( + "skill_categories", sa.Column("is_active", sa.Boolean(), nullable=True) + ) + op.add_column( + "skill_categories", sa.Column("name", sa.String(length=100), nullable=False) + ) + op.alter_column( + "skill_categories", "is_deleted", existing_type=sa.BOOLEAN(), nullable=True + ) + op.drop_column("skill_categories", "date_of_birth") + op.drop_column("skill_categories", "gender") + op.add_column("skills", sa.Column("is_active", sa.Boolean(), nullable=True)) + op.alter_column("skills", "is_deleted", existing_type=sa.BOOLEAN(), nullable=True) + op.add_column( + "user_employment_skills", + sa.Column("user_employment_id", sa.Integer(), nullable=True), + ) + op.drop_constraint( + "user_employment_skills_user_employement_id_fkey", + "user_employment_skills", + type_="foreignkey", + ) + op.create_foreign_key( + None, + "user_employment_skills", + "user_employments", + ["user_employment_id"], + ["id"], + ) + op.drop_column("user_employment_skills", "user_employement_id") + op.add_column( + "user_employments", sa.Column("is_current", sa.Boolean(), nullable=True) + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column("user_employments", "is_current") + op.add_column( + "user_employment_skills", + sa.Column( + "user_employement_id", sa.INTEGER(), autoincrement=False, nullable=True + ), + ) + op.drop_constraint(None, "user_employment_skills", type_="foreignkey") + op.create_foreign_key( + "user_employment_skills_user_employement_id_fkey", + "user_employment_skills", + "user_employments", + ["user_employement_id"], + ["id"], + ) + op.drop_column("user_employment_skills", "user_employment_id") + op.alter_column("skills", "is_deleted", existing_type=sa.BOOLEAN(), nullable=False) + op.drop_column("skills", "is_active") + op.add_column( + "skill_categories", + sa.Column( + "gender", + postgresql.ENUM("male", "female", name="gender"), + autoincrement=False, + nullable=True, + ), + ) + op.add_column( + "skill_categories", + sa.Column("date_of_birth", sa.DATE(), autoincrement=False, nullable=False), + ) + op.alter_column( + "skill_categories", "is_deleted", existing_type=sa.BOOLEAN(), nullable=False + ) + op.drop_column("skill_categories", "name") + op.drop_column("skill_categories", "is_active") + op.drop_column("skill_categories", "help") + # ### end Alembic commands ### diff --git a/tests/integration/endpoints/test_skills_category_endpoints.py b/tests/integration/endpoints/test_skills_category_endpoints.py index 6e04006..0c4be01 100644 --- a/tests/integration/endpoints/test_skills_category_endpoints.py +++ b/tests/integration/endpoints/test_skills_category_endpoints.py @@ -1,7 +1,7 @@ from tests.base_test_case import BaseTestCase from factories import ( - SkillsCategoryFactory, - SkillsCategoryFactoryFake, + SkillCategoryFactory, + SkillCategoryFactoryFake, PermissionFactory, UserRoleFactory, RoleFactory, @@ -29,6 +29,7 @@ def test_create_skill_category_endpoint(self): headers=self.headers(), ) response_json = self.decode_from_json_string(response.data.decode("utf-8")) + print(response_json) payload = response_json["payload"] self.assertEqual(response.status_code, 201) @@ -38,7 +39,7 @@ def test_create_skill_category_endpoint(self): def test_list_skill_categories_endpoint(self): - SkillsCategoryFactory.create_batch(3) + SkillCategoryFactory.create_batch(3) role1 = RoleFactory.create(name="admin") user_id = BaseTestCase.user_id() @@ -58,7 +59,7 @@ def test_list_skill_categories_endpoint(self): def test_get_specific_skill_category_endpoint(self): role = RoleFactory.create() user_id = BaseTestCase.user_id() - skills_category = SkillsCategoryFactory.create() + skills_category = SkillCategoryFactory.create() PermissionFactory.create(keyword="view_skills_categories", role=role) UserRoleFactory.create(user_id=user_id, role=role) @@ -81,7 +82,7 @@ def test_update_skill_categories_endpoint(self): RoleFactory.create() role1 = RoleFactory.create(name="admin") user_id = BaseTestCase.user_id() - skills_category = SkillsCategoryFactory.create() + skills_category = SkillCategoryFactory.create() PermissionFactory.create(keyword="update_skills_categories", role=role1) UserRoleFactory.create(user_id=user_id, role=role1) @@ -115,7 +116,7 @@ def test_invalid_update(self): def test_delete_skill_category_endpoint_with_right_permission(self): role = RoleFactory.create() - skills_category = SkillsCategoryFactory.create() + skills_category = SkillCategoryFactory.create() user_id = BaseTestCase.user_id() PermissionFactory.create(keyword="delete_skills_categories", role=role) @@ -147,7 +148,7 @@ def test_delete_skill_category_endpoint_without_right_permission(self): def test_delete_skill_category_endpoint_with_wrong_skill_category_id(self): role1 = RoleFactory.create(name="admin") - SkillsCategoryFactory.create() + SkillCategoryFactory.create() user_id = BaseTestCase.user_id() PermissionFactory.create( keyword="delete_skills_categories", diff --git a/tests/unit/controllers/test_skills_category_controller.py b/tests/unit/controllers/test_skills_category_controller.py index 5307043..cc1fd94 100644 --- a/tests/unit/controllers/test_skills_category_controller.py +++ b/tests/unit/controllers/test_skills_category_controller.py @@ -3,22 +3,22 @@ from datetime import datetime from unittest.mock import patch, MagicMock -from app.controllers.skills_category_controller import SkillsCategoryController +from app.controllers.skill_category_controller import SkillCategoryController from app.models import User from app.models.permission import Permission -from app.models.skills_category import SkillsCategory +from app.models.skill_category import SkillCategory from app.repositories import UserRepo -from app.repositories.skills_category_repo import SkillsCategoryRepo +from app.repositories.skill_category_repo import SkillCategoryRepo from app.repositories.permission_repo import PermissionRepo # from app.services.andela import AndelaService from tests.base_test_case import BaseTestCase -class TestSkillsCategoryController(BaseTestCase): +class TestSkillCategoryController(BaseTestCase): def setUp(self): self.BaseSetUp() - self.mock_skills_category = SkillsCategory( + self.mock_skills_category = SkillCategory( id=1, created_at=datetime.now(), updated_at=datetime.now(), @@ -29,8 +29,8 @@ def setUp(self): def tearDown(self): self.BaseTearDown() - @patch.object(SkillsCategoryController, "pagination_meta") - @patch.object(SkillsCategoryRepo, "filter_by") + @patch.object(SkillCategoryController, "pagination_meta") + @patch.object(SkillCategoryRepo, "filter_by") def test_list_skills_categorys_ok_response( self, mock_skills_category_repo_filter_by, @@ -49,7 +49,7 @@ def test_list_skills_categorys_ok_response( mock_skills_category_repo_filter_by.return_value.items = [ self.mock_skills_category, ] - skills_category_controller = SkillsCategoryController(self.request_context) + skills_category_controller = SkillCategoryController(self.request_context) # Act result = skills_category_controller.list_skills_categories() @@ -58,7 +58,7 @@ def test_list_skills_categorys_ok_response( assert result.status_code == 200 assert result.get_json()["msg"] == "OK" - @patch.object(SkillsCategoryRepo, "get") + @patch.object(SkillCategoryRepo, "get") def test_get_skills_category_when_invalid_or_missing( self, mock_skills_category_repo_get ): @@ -66,7 +66,7 @@ def test_get_skills_category_when_invalid_or_missing( # Arrange with self.app.app_context(): mock_skills_category_repo_get.return_value = None - skills_category_controller = SkillsCategoryController(self.request_context) + skills_category_controller = SkillCategoryController(self.request_context) # Act result = skills_category_controller.get_skills_category(1) @@ -75,13 +75,13 @@ def test_get_skills_category_when_invalid_or_missing( assert result.status_code == 400 assert result.get_json()["msg"] == "Invalid or Missing skills_category_id" - @patch.object(SkillsCategoryRepo, "get") + @patch.object(SkillCategoryRepo, "get") def test_get_skills_category_ok_response(self, mock_skills_category_repo_get): """Test get_skills_category OK response.""" # Arrange with self.app.app_context(): mock_skills_category_repo_get.return_value = self.mock_skills_category - skills_category_controller = SkillsCategoryController(self.request_context) + skills_category_controller = SkillCategoryController(self.request_context) # Act result = skills_category_controller.get_skills_category(1) @@ -90,8 +90,8 @@ def test_get_skills_category_ok_response(self, mock_skills_category_repo_get): assert result.status_code == 200 assert result.get_json()["msg"] == "OK" - @patch.object(SkillsCategoryController, "request_params") - @patch.object(SkillsCategoryRepo, "find_first") + @patch.object(SkillCategoryController, "request_params") + @patch.object(SkillCategoryRepo, "find_first") def test_create_skills_category_when_name_already_exists( self, mock_skills_category_repo_find_first, @@ -107,7 +107,7 @@ def test_create_skills_category_when_name_already_exists( mock_skills_category_repo_find_first.return_value = ( self.mock_skills_category ) - skills_category_controller = SkillsCategoryController(self.request_context) + skills_category_controller = SkillCategoryController(self.request_context) # Act result = skills_category_controller.create_skills_category() @@ -119,8 +119,8 @@ def test_create_skills_category_when_name_already_exists( " exists" ) - @patch.object(SkillsCategoryController, "request_params") - @patch.object(SkillsCategoryRepo, "find_first") + @patch.object(SkillCategoryController, "request_params") + @patch.object(SkillCategoryRepo, "find_first") def test_create_skills_category_ok_response( self, mock_skills_category_repo_find_first, @@ -134,7 +134,7 @@ def test_create_skills_category_ok_response( "Mock help", ) mock_skills_category_repo_find_first.return_value = None - skills_category_controller = SkillsCategoryController(self.request_context) + skills_category_controller = SkillCategoryController(self.request_context) # Act result = skills_category_controller.create_skills_category() @@ -143,8 +143,8 @@ def test_create_skills_category_ok_response( assert result.status_code == 201 assert result.get_json()["msg"] == "OK" - @patch.object(SkillsCategoryController, "request_params") - @patch.object(SkillsCategoryRepo, "get") + @patch.object(SkillCategoryController, "request_params") + @patch.object(SkillCategoryRepo, "get") def test_update_skills_category_when_skills_category_doesnot_exist( self, mock_skills_category_repo_get, @@ -155,7 +155,7 @@ def test_update_skills_category_when_skills_category_doesnot_exist( with self.app.app_context(): mock_skills_category_repo_get.return_value = None mock_skills_category_controller_request_params.return_value = (None, None) - skills_category_controller = SkillsCategoryController(self.request_context) + skills_category_controller = SkillCategoryController(self.request_context) # Act result = skills_category_controller.update_skills_category(1) @@ -167,9 +167,9 @@ def test_update_skills_category_when_skills_category_doesnot_exist( "skills_category_id provided" ) - @patch.object(SkillsCategoryRepo, "find_first") - @patch.object(SkillsCategoryController, "request_params") - @patch.object(SkillsCategoryRepo, "get") + @patch.object(SkillCategoryRepo, "find_first") + @patch.object(SkillCategoryController, "request_params") + @patch.object(SkillCategoryRepo, "get") def test_update_skills_category_when_name_is_already_taken( self, mock_skills_category_repo_get, @@ -187,7 +187,7 @@ def test_update_skills_category_when_name_is_already_taken( "Mock name", "Mock help", ) - skills_category_controller = SkillsCategoryController(self.request_context) + skills_category_controller = SkillCategoryController(self.request_context) # Act result = skills_category_controller.update_skills_category(1) @@ -199,9 +199,9 @@ def test_update_skills_category_when_name_is_already_taken( " already exists" ) - @patch.object(SkillsCategoryRepo, "find_first") - @patch.object(SkillsCategoryController, "request_params") - @patch.object(SkillsCategoryRepo, "get") + @patch.object(SkillCategoryRepo, "find_first") + @patch.object(SkillCategoryController, "request_params") + @patch.object(SkillCategoryRepo, "get") def test_update_skills_category_ok_response( self, mock_skills_category_repo_get, @@ -217,7 +217,7 @@ def test_update_skills_category_ok_response( "Mock name", "Mock help", ) - skills_category_controller = SkillsCategoryController(self.request_context) + skills_category_controller = SkillCategoryController(self.request_context) # Act result = skills_category_controller.update_skills_category(1) @@ -226,7 +226,7 @@ def test_update_skills_category_ok_response( assert result.status_code == 200 assert result.get_json()["msg"] == "OK" - @patch.object(SkillsCategoryRepo, "get") + @patch.object(SkillCategoryRepo, "get") def test_delete_skills_category_when_skills_category_is_invalid( self, mock_skills_category_repo_get ): @@ -234,7 +234,7 @@ def test_delete_skills_category_when_skills_category_is_invalid( # Arrange with self.app.app_context(): mock_skills_category_repo_get.return_value = None - skills_category_controler = SkillsCategoryController(self.request_context) + skills_category_controler = SkillCategoryController(self.request_context) # Act result = skills_category_controler.delete_skills_category(1) @@ -246,8 +246,8 @@ def test_delete_skills_category_when_skills_category_is_invalid( "skills_category_id provided" ) - @patch.object(SkillsCategoryRepo, "get") - @patch.object(SkillsCategoryRepo, "update") + @patch.object(SkillCategoryRepo, "get") + @patch.object(SkillCategoryRepo, "update") def test_delete_skills_category_ok_response( self, mock_skills_category_repo_update, mock_skills_category_repo_get ): @@ -256,7 +256,7 @@ def test_delete_skills_category_ok_response( with self.app.app_context(): mock_skills_category_repo_get.return_value = self.mock_skills_category mock_skills_category_repo_update.return_value = self.mock_skills_category - skills_category_controler = SkillsCategoryController(self.request_context) + skills_category_controler = SkillCategoryController(self.request_context) # Act result = skills_category_controler.delete_skills_category(1) diff --git a/tests/unit/controllers/test_user_employment_controller.py b/tests/unit/controllers/test_user_employment_controller.py index 5753982..1766d89 100644 --- a/tests/unit/controllers/test_user_employment_controller.py +++ b/tests/unit/controllers/test_user_employment_controller.py @@ -5,14 +5,27 @@ from unittest.mock import patch from app.controllers.user_employment_controller import UserEmploymentController -from app.models import User, UserEmployment +from app.models import User, UserEmployment, UserEmploymentSkill from app.repositories.user_employment_repo import UserEmploymentRepo +from factories.skill_category_factory import ( + CategoryWithSkillsFactory, + SkillFactory, + SkillFactoryFake, +) from tests.base_test_case import BaseTestCase class TestUserEmploymentController(BaseTestCase): def setUp(self): self.BaseSetUp() + self.skill_category = CategoryWithSkillsFactory.create(skills=4) + self.skill_category.save() + print(self.skill_category) + print(self.skill_category.__dict__) + self.skill_one = self.skill_category.skills[0] + self.skill_two = self.skill_category.skills[1] + self.skill_three = self.skill_category.skills[2] + self.skill_four = self.skill_category.skills[3] self.mock_user = User( id=1, first_name="test", @@ -35,6 +48,9 @@ def setUp(self): created_at=datetime.now(), updated_at=datetime.now(), ) + self.mock_user_employment_skill = UserEmploymentSkill( + user_employment_id=self.mock_user_employment.id, skill_id=self.skill_one.id + ) def tearDown(self): self.BaseTearDown() @@ -47,7 +63,6 @@ def test_list_user_employments_ok_response( """Test list_user_employments OK response.""" # Arrange with self.app.app_context(): - mock_user_employment_repo_get_unpaginated.return_value.items = [ self.mock_user_employment, ] @@ -94,6 +109,10 @@ def test_get_user_employment_ok_response(self, mock_user_employment_repo_get): # Assert assert result.status_code == 200 assert result.get_json()["msg"] == "OK" + # import pdb + # pdb.set_trace() + # assert result.get_json()["payload"]["user_employment"]["skills"][0] == "OK" + # assert result.get_json()["msg"] == "OK" @patch.object(UserEmploymentController, "request_params") def test_create_user_employment_start_date_less_than_end_date_response( @@ -114,6 +133,7 @@ def test_create_user_employment_start_date_less_than_end_date_response( date(year=2028, month=1, day=31), date(year=2020, month=1, day=31), False, + [self.skill_one.id, self.skill_two.id], ) user_employment_controller = UserEmploymentController(self.request_context) @@ -144,6 +164,7 @@ def test_create_user_employment_ok_response( date(year=2018, month=1, day=31), date(year=2020, month=1, day=31), False, + [self.skill_one.id, self.skill_two.id], ) mock_user_employment_repo_find_first.return_value = None user_employment_controller = UserEmploymentController(self.request_context) @@ -154,6 +175,10 @@ def test_create_user_employment_ok_response( # Assert assert result.status_code == 201 assert result.get_json()["msg"] == "OK" + assert ( + result.get_json()["payload"]["user_employment"]["skills"][0]["name"] + == self.skill_one.name + ) @patch.object(UserEmploymentController, "request_params") @patch.object(UserEmploymentRepo, "get") @@ -174,6 +199,7 @@ def test_update_user_employment_when_user_employment_doesnot_exist( None, None, None, + None, ) user_employment_controller = UserEmploymentController(self.request_context) @@ -209,6 +235,7 @@ def test_update_user_employment_ok_response( date(year=2018, month=1, day=31), date(year=2020, month=1, day=31), True, + [self.skill_one.id, self.skill_two.id], ) user_employment_controller = UserEmploymentController(self.request_context) @@ -218,6 +245,10 @@ def test_update_user_employment_ok_response( # Assert assert result.status_code == 200 assert result.get_json()["msg"] == "OK" + assert ( + result.get_json()["payload"]["user_employment"]["skills"][0]["name"] + == self.skill_one.name + ) @patch.object(UserEmploymentRepo, "get") def test_delete_user_employment_when_user_employment_is_invalid( @@ -257,3 +288,37 @@ def test_delete_user_employment_ok_response( # Assert assert result.status_code == 200 assert result.get_json()["msg"] == "user employment deleted" + + @patch.object(UserEmploymentController, "request_params") + @patch.object(UserEmploymentRepo, "find_first") + def test_user_employment_create_with_skills_valid( + self, + mock_user_employment_repo_find_first, + mock_user_employment_controller_request_params, + ): + """ + Test create_user_employment with skills OK response. + """ + # Arrange + with self.app.app_context(): + mock_user_employment_controller_request_params.return_value = ( + 1, + "Institution name", + "Job title", + date(year=2018, month=1, day=31), + date(year=2020, month=1, day=31), + False, + [self.skill_one.id, self.skill_two.id], + ) + mock_user_employment_repo_find_first.return_value = None + user_employment_controller = UserEmploymentController(self.request_context) + + # Act + result = user_employment_controller.create_user_employment() + + # Assert + assert result.status_code == 201 + assert result.get_json()["msg"] == "OK" + + def test_user_employment_create_with_skills_invalid_skills(self): + pass diff --git a/tests/unit/repositories/test_skills_category_repo.py b/tests/unit/repositories/test_skills_category_repo.py index b4d118e..8cd31b1 100644 --- a/tests/unit/repositories/test_skills_category_repo.py +++ b/tests/unit/repositories/test_skills_category_repo.py @@ -1,23 +1,23 @@ -from app.models import SkillsCategory -from app.repositories.skills_category_repo import SkillsCategoryRepo -from factories.skill_category_factory import SkillsCategoryFactoryFake +from app.models import SkillCategory +from app.repositories.skill_category_repo import SkillCategoryRepo +from factories.skill_category_factory import SkillCategoryFactoryFake from tests.base_test_case import BaseTestCase -class TestSkillsCategoryRepo(BaseTestCase): +class TestSkillCategoryRepo(BaseTestCase): def setUp(self): self.BaseSetUp() - self.repo = SkillsCategoryRepo() + self.repo = SkillCategoryRepo() def tearDown(self): self.BaseTearDown() def test_new_category_method_returns_new_category_object(self): - skill_category = SkillsCategoryFactoryFake.build() + skill_category = SkillCategoryFactoryFake.build() - new_skill_category = self.repo.new_skills_category( + new_skill_category = self.repo.new_skill_category( skill_category.name, skill_category.help, ) - self.assertIsInstance(new_skill_category, SkillsCategory) + self.assertIsInstance(new_skill_category, SkillCategory) self.assertEqual(new_skill_category.name, skill_category.name) diff --git a/tests/unit/repositories/test_user_employment_skill_repo.py b/tests/unit/repositories/test_user_employment_skill_repo.py new file mode 100644 index 0000000..4c98f33 --- /dev/null +++ b/tests/unit/repositories/test_user_employment_skill_repo.py @@ -0,0 +1,40 @@ +from app.models import UserEmploymentSkill +from tests.base_test_case import BaseTestCase +from factories.user_employment_factory import ( + UserEmploymentSkillFactoryFake, + UserEmploymentFactory, + SkillFactory, +) +from factories.user_factory import UserFactory +from app.repositories.user_employment_skill_repo import UserEmploymentSkillRepo + + +class TestUserEmploymentSkillRepo(BaseTestCase): + def setUp(self): + self.BaseSetUp() + self.repo = UserEmploymentSkillRepo() + + def tearDown(self): + self.BaseTearDown() + + def test_new_user_employment_skill_method_returns_new_user_employment_skill_object( + self, + ): + user = UserFactory.create() + user.save() + + user_employment = UserEmploymentFactory.create() + user_employment.save() + + skill = SkillFactory() + skill.save() + + user_employment_skill = UserEmploymentSkillFactoryFake.build( + user_employment_id=user_employment.id, skill_id=skill.id + ) + new_user_employment_skill = self.repo.new_user_employment_skill( + user_employment_id=user_employment_skill.user_employment_id, + skill_id=user_employment_skill.skill_id, + ) + self.assertIsInstance(new_user_employment_skill, UserEmploymentSkill) + self.assertEqual(str(new_user_employment_skill.skill_id), str(skill.id))