diff --git a/ki/actions/seed.py b/ki/actions/seed.py index 854bf89..64e69c8 100644 --- a/ki/actions/seed.py +++ b/ki/actions/seed.py @@ -6,7 +6,8 @@ import csv import logging from app import app, db -from ki.models import Address, Contact, ContactType, Language, Skill, Profile, ProfileLanguage, ProfileSkill, User +from ki.models import Address, Contact, ContactType, Language, Skill, Profile, ProfileLanguage, ProfileSearchtopic, \ + ProfileSkill, User def seed_contacttypes(): @@ -91,6 +92,12 @@ def seed(dev: bool): peters_php_skill = ProfileSkill(profile=peters_profile, skill_id=1, level=5) db.session.add(peters_php_skill) + peters_python_searchtopic = ProfileSearchtopic(profile=peters_profile, skill_id=3) + db.session.add(peters_python_searchtopic) + + peters_php_searchtopic = ProfileSearchtopic(profile=peters_profile, skill_id=1) + db.session.add(peters_php_searchtopic) + peter_de = ProfileLanguage(profile=peters_profile, language_id="de", level=5) db.session.add(peter_de) diff --git a/ki/handlers/update_profile.py b/ki/handlers/update_profile.py index 75d5fd1..880ac13 100644 --- a/ki/handlers/update_profile.py +++ b/ki/handlers/update_profile.py @@ -5,7 +5,8 @@ from flask import make_response, request from sqlalchemy import not_ -from ki.models import Address, Contact, ContactType, Language, User, Profile, ProfileLanguage, ProfileSkill, Skill +from ki.models import Address, Contact, ContactType, Language, User, Profile, ProfileLanguage, ProfileSearchtopic, \ + ProfileSkill, Skill from app import db @@ -71,6 +72,30 @@ def update_skills(profile, skills_data): not_(ProfileSkill.skill_id.in_(profile_skill_ids))).delete() +def update_searchtopics(profile, searchtopics_data): + profile_searchtopics_ids = [] + + for searchtopic_data in searchtopics_data: + skill_name = searchtopic_data["skill"]["name"] + skill = Skill.query.filter(Skill.name == skill_name).first() + + if (skill is None): + skill = Skill(name=skill_name) + db.session.add(skill) + + profile_searchtopic = ProfileSearchtopic.query.filter(ProfileSearchtopic.profile == profile, + ProfileSearchtopic.skill == skill).first() + + if (profile_searchtopic is None): + profile_searchtopic = ProfileSearchtopic(profile=profile, skill=skill) + db.session.add(profile_searchtopic) + + profile_searchtopics_ids.append(skill.id) + + ProfileSearchtopic.query.filter(ProfileSearchtopic.profile == profile, + not_(ProfileSearchtopic.skill_id.in_(profile_searchtopics_ids))).delete() + + def update_contacts(profile, contacts_data): contact_ids_to_be_deleted = list(map(lambda c: c.id, profile.contacts)) @@ -116,6 +141,7 @@ def update_profile(user_id: int): update_address(profile, request.json.get("address", {})) update_contacts(profile, request.json.get("contacts", {})) update_skills(profile, request.json.get("skills", {})) + update_searchtopics(profile, request.json.get("searchtopics")) update_languages(profile, request.json.get("languages", {})) db.session.commit() diff --git a/ki/models.py b/ki/models.py index 400df5b..77cd1b4 100644 --- a/ki/models.py +++ b/ki/models.py @@ -40,6 +40,7 @@ class Profile(db.Model): contacts = relationship("Contact") address = relationship("Address", uselist=False, back_populates="profile") skills = relationship("ProfileSkill", back_populates="profile") + searchtopics = relationship("ProfileSearchtopic", back_populates="profile") languages = relationship("ProfileLanguage", back_populates="profile") def to_dict(self): @@ -53,6 +54,7 @@ class Profile(db.Model): "address": self.address.to_dict(), "contacts": list(map(lambda contact: contact.to_dict(), self.contacts)), "skills": list(map(lambda skill: skill.to_dict(), self.skills)), + "searchtopics": list(map(lambda searchtopic: searchtopic.to_dict(), self.searchtopics)), "languages": list(map(lambda language: language.to_dict(), self.languages)) } @@ -135,6 +137,7 @@ class Skill(db.Model): name = Column(String(25), unique=True, nullable=False) profiles = relationship("ProfileSkill", back_populates="skill") + searchtopics = relationship("ProfileSearchtopic", back_populates="skill") def to_dict(self): return {"id": self.id, "name": self.name, "icon_url": "/skills/{}/icon".format(self.id)} @@ -154,6 +157,19 @@ class ProfileSkill(db.Model): return {"profile_id": self.profile_id, "skill": self.skill.to_dict(), "level": self.level} +class ProfileSearchtopic(db.Model): + __tablename__ = "profile_searchtopic" + + profile_id = Column(Integer, ForeignKey("profile.id"), primary_key=True) + skill_id = Column(Integer, ForeignKey("skill.id"), primary_key=True) + + profile = relationship("Profile", back_populates="searchtopics") + skill = relationship("Skill", back_populates="searchtopics") + + def to_dict(self): + return {"profile_id": self.profile_id, "skill": self.skill.to_dict()} + + class Language(db.Model): __tablename__ = "language" diff --git a/ki/test/test_profile_endpoint.py b/ki/test/test_profile_endpoint.py index b48def5..5128283 100644 --- a/ki/test/test_profile_endpoint.py +++ b/ki/test/test_profile_endpoint.py @@ -70,6 +70,19 @@ class TestProfileEndpoint(ApiTest): }, "level": 5 }], + "searchtopics": [{ + "profile_id": 1, + "skill": { + "id": 3, + "name": "Python", + "icon_url": "/skills/3/icon" + } + }, { + "profile_id": 1, + "skill": { + "name": "Assembler" + } + }], "languages": [{ "id": 1, "language": { @@ -132,6 +145,17 @@ class TestProfileEndpoint(ApiTest): self.assertEqual(second_skill.skill.name, "Tschunkproduktion") self.assertEqual(second_skill.level, 5) + searchtopics = profile.searchtopics + self.assertEqual(len(searchtopics), 2) + + first_searchtopic = searchtopics[0] + self.assertEqual(first_searchtopic.skill.id, 3) + self.assertEqual(first_searchtopic.skill.name, "Python") + + second_searchtopic = searchtopics[1] + self.assertEqual(second_searchtopic.skill.id, 14) + self.assertEqual(second_searchtopic.skill.name, "Assembler") + languages = profile.languages self.assertEqual(len(languages), 2) @@ -213,6 +237,21 @@ class TestProfileEndpoint(ApiTest): }, "level": 3 }], + "searchtopics": [{ + "profile_id": 1, + "skill": { + "id": 1, + "name": "PHP", + "icon_url": "/skills/1/icon" + } + }, { + "profile_id": 1, + "skill": { + "id": 3, + "name": "Python", + "icon_url": "/skills/3/icon" + } + }], "languages": [{ "profile_id": 1, "language": { diff --git a/migrations/README b/migrations/README new file mode 100644 index 0000000..98e4f9c --- /dev/null +++ b/migrations/README @@ -0,0 +1 @@ +Generic single-database configuration. \ No newline at end of file diff --git a/migrations/alembic.ini b/migrations/alembic.ini index 3819021..ec9d45c 100644 --- a/migrations/alembic.ini +++ b/migrations/alembic.ini @@ -1,7 +1,3 @@ -; SPDX-FileCopyrightText: WTF Kooperative eG -; -; SPDX-License-Identifier: AGPL-3.0-or-later - # A generic, single database configuration. [alembic] diff --git a/migrations/env.py b/migrations/env.py index a5a8114..68feded 100644 --- a/migrations/env.py +++ b/migrations/env.py @@ -1,7 +1,3 @@ -# SPDX-FileCopyrightText: WTF Kooperative eG -# -# SPDX-License-Identifier: AGPL-3.0-or-later - from __future__ import with_statement import logging diff --git a/migrations/versions/ebb2dd1fb371_initial_migration.py b/migrations/versions/1e1b2be49756_initial_migration.py similarity index 90% rename from migrations/versions/ebb2dd1fb371_initial_migration.py rename to migrations/versions/1e1b2be49756_initial_migration.py index e339d05..2661213 100644 --- a/migrations/versions/ebb2dd1fb371_initial_migration.py +++ b/migrations/versions/1e1b2be49756_initial_migration.py @@ -1,12 +1,8 @@ -# SPDX-FileCopyrightText: WTF Kooperative eG -# -# SPDX-License-Identifier: AGPL-3.0-or-later - """Initial migration. -Revision ID: ebb2dd1fb371 +Revision ID: 1e1b2be49756 Revises: -Create Date: 2021-07-02 16:20:18.160228 +Create Date: 2021-07-05 20:36:04.047270 """ from alembic import op @@ -14,7 +10,7 @@ import sqlalchemy as sa # revision identifiers, used by Alembic. -revision = 'ebb2dd1fb371' +revision = '1e1b2be49756' down_revision = None branch_labels = None depends_on = None @@ -80,6 +76,13 @@ def upgrade(): sa.ForeignKeyConstraint(['profile_id'], ['profile.id'], ), sa.PrimaryKeyConstraint('profile_id', 'language_id') ) + op.create_table('profile_searchtopic', + sa.Column('profile_id', sa.Integer(), nullable=False), + sa.Column('skill_id', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['profile_id'], ['profile.id'], ), + sa.ForeignKeyConstraint(['skill_id'], ['skill.id'], ), + sa.PrimaryKeyConstraint('profile_id', 'skill_id') + ) op.create_table('profile_skill', sa.Column('profile_id', sa.Integer(), nullable=False), sa.Column('skill_id', sa.Integer(), nullable=False), @@ -111,6 +114,7 @@ def downgrade(): op.drop_table('token') op.drop_table('user') op.drop_table('profile_skill') + op.drop_table('profile_searchtopic') op.drop_table('profile_language') op.drop_table('contact') op.drop_table('address')