Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
139d34b
Fix possible migration errors because of 0008 core migration
IgorDuino Feb 1, 2024
9ec5a9c
Add skills from dataset migration
IgorDuino Feb 1, 2024
d5feb38
Add skills and skills categories to the django admin
IgorDuino Feb 1, 2024
b6112c1
refactored POST in RateProjects
sh1nkey Feb 29, 2024
ba8279b
Drop constrain migration
IgorDuino Mar 1, 2024
a5ae5e0
finished refactoring project_rates code
sh1nkey Mar 1, 2024
e41636c
Merge pull request #314 from PROCOLLAB-github/igorduino-pro-189
IgorDuino Mar 2, 2024
7ff9020
Merge branch 'dev' into tkdomigor-pro-88
IgorDuino Mar 2, 2024
71c4e22
Add new skills to Admin, upd skills_count
IgorDuino Mar 2, 2024
a95d14b
Update serializers for new skills
IgorDuino Mar 2, 2024
fe65298
fix key_skills migration
IgorDuino Mar 2, 2024
beb7d7f
fix key_skills reverse migration
IgorDuino Mar 2, 2024
d78c542
Skills serializers mixin refactor
IgorDuino Mar 2, 2024
a25a513
refactor skills exceptions handling in user serializers
IgorDuino Mar 3, 2024
15329f6
vacancy required skills migration
IgorDuino Mar 3, 2024
a847758
vacancy required skills admin,
IgorDuino Mar 3, 2024
45a9278
Update get_recommended_users for new required skills
IgorDuino Mar 3, 2024
fb8754e
feat skills filter for users
IgorDuino Mar 3, 2024
f0e11d0
feat serialize skill with category as object
IgorDuino Mar 3, 2024
5becb2d
feat inline and nested skills routes
IgorDuino Mar 3, 2024
8dffad6
remove redundant print
IgorDuino Mar 4, 2024
2a19a3e
fix contenttypes migration dependency
IgorDuino Mar 4, 2024
b7089d9
Handle required_skills_ids in vacancy routes
IgorDuino Mar 4, 2024
99d8dac
Update vacancy creation test for new required_skills from dataset
IgorDuino Mar 4, 2024
54b2862
minor cosmetic refactors
IgorDuino Mar 4, 2024
5477e04
docs typo
IgorDuino Mar 4, 2024
5421c87
minor refactor
IgorDuino Mar 4, 2024
cafd46a
Merge pull request #317 from PROCOLLAB-github/igorduino-pro-91
yakser Mar 4, 2024
db9ae2c
project_rates refactoring additions
sh1nkey Mar 4, 2024
06c3769
Merge pull request #322 from PROCOLLAB-github/flexivanov237-pro-209
sh1nkey Mar 10, 2024
6b5cac7
corrections made again
sh1nkey Mar 11, 2024
1928176
can't add dataclass cuz of importerrors((((
sh1nkey Mar 11, 2024
71272d3
Merge pull request #315 from PROCOLLAB-github/project_rates_finished_…
sh1nkey Mar 12, 2024
ab6510d
Merge pull request #318 from PROCOLLAB-github/flexivanov237-pro-212
sh1nkey Mar 12, 2024
fe6edfd
added deletion of vacancy after accepting person in
sh1nkey Mar 14, 2024
dfb5511
Merge pull request #328 from PROCOLLAB-github/flexivanov237-pro-227
sh1nkey Mar 15, 2024
1d3b178
fix poetry incompatibility with some pyyaml versions
IgorDuino Mar 26, 2024
714652c
deploy fix: add --no-input to startup.sh
IgorDuino Mar 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 44 additions & 1 deletion core/admin.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
from django.contrib import admin
from core.models import Like, View, Link, Specialization, SpecializationCategory
from django.contrib.contenttypes.admin import GenericStackedInline

from core.models import (
Like,
View,
Link,
Specialization,
SpecializationCategory,
Skill,
SkillCategory,
SkillToObject,
)


class SkillToObjectInline(GenericStackedInline):
model = SkillToObject
extra = 1
verbose_name = "Навык"
verbose_name_plural = "Навыки"


@admin.register(Like)
Expand All @@ -20,6 +38,31 @@ class LinkAdmin(admin.ModelAdmin):
list_display_links = ("id", "link", "content_type", "object_id", "content_object")


@admin.register(Skill)
class SkillAdmin(admin.ModelAdmin):
list_display = (
"id",
"name",
"category",
)
list_display_links = (
"id",
"name",
)


@admin.register(SkillCategory)
class SkillCategoryAdmin(admin.ModelAdmin):
list_display = (
"id",
"name",
)
list_display_links = (
"id",
"name",
)


@admin.register(Specialization)
class SpecializationAdmin(admin.ModelAdmin):
list_display = (
Expand Down
11 changes: 11 additions & 0 deletions core/filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from django_filters import rest_framework as filters

from core.models import Skill


class SkillFilter(filters.FilterSet):
name__icontains = filters.Filter(field_name="name", lookup_expr="icontains")

class Meta:
model = Skill
fields = ("name",)
8 changes: 3 additions & 5 deletions core/migrations/0011_auto_20240128_2214.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,17 +137,15 @@ def fill_specializations(apps, schema_editor):
for spec, category in SPECIALIZATIONS:
spec = spec.strip()
category = category.strip()
if category not in categories_set:
category_obj = SpecializationCategory.objects.create(name=category)
category_obj.save()
if (category not in categories_set) and not SpecializationCategory.objects.filter(name=category).exists():
SpecializationCategory.objects.create(name=category)
categories_set.add(category)

if spec not in specs_set:
try:
category_obj = SpecializationCategory.objects.get(name=category)
specs_set.add(spec)
spec_obj = Specialization.objects.create(name=spec, category=category_obj)
spec_obj.save()
Specialization.objects.create(name=spec, category=category_obj)
except Exception as error:
print('An error during migration:', error)

Expand Down
103 changes: 103 additions & 0 deletions core/migrations/0013_add_skills_from_dataset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Generated by Django 4.2.3 on 2024-02-01 09:12

from django.db import migrations
from core.models import SkillCategory, Skill

skills = {'Маркетинг': ['Ведение социальных сетей', 'Рилсмейкер', 'Копирайтер', 'Рерайтер', 'Email-кампании',
'Аналитика рекламных кампаний', 'Аналитика влияния социальных сетей', 'Инфлюенс-маркетинг',
'Аудиторская аналитика', 'Оптимизация для мобильных устройств', 'Таргетирование',
'Мобильный маркетинг', 'Анализ и оптимизация контент-стратегий', 'Звукорежиссура', 'MS Office',
'Копирайтинг', 'Создание контент-плана', 'SEO', 'SMM', 'Реклама', 'e-mail маркетинг',
'Создание воронок', 'Digital маркетинг', 'SWOT', 'web Аналитика', 'PEST', '5W анализ', 'crm',
'Холодные продажи', 'Продажи', 'Разработка стратегий продвижения',
'Разработка стратегий выхода на рынок', 'Наружная реклама', 'Ценообразование'],
'Нейросети': ['Midjourney', 'Word Embeddings', 'GANs', 'NLP', 'YOLO', 'DeepDream', 'LightGBM', 'U-Net', 'GPT',
'Transfer Learning', 'bert', 'AutoML', 'Apache Spark', 'Apache Airflow', 'Kafka', 'ML',
'catboost', 'pandas', 'scikit-learn', 'TensorRT', 'Tensorflow', 'Numpy', 'ETL', 'CV', 'PyTorch',
'Keras', 'Matplotlib', 'Prophet', 'Hadoop', 'SARIMA', 'Spark', 'LSTM'],
'Дизайн': ['Design thinking', 'Power point', 'Слайд-мейкинг', 'Motion design', 'AR', 'VR', 'VR/AR',
'Дизайн игр', 'readymag', 'Видеомонтаж', 'Adobe', 'Презентации', 'Видео', 'Фотография',
'Рилсмейкер', 'Прототипирование UI-UX', 'Работа с цветокоррекцией', 'UX проектирование',
'Иллюстрации Procreate', 'Adobe After Effects', 'JTBD', 'Lightroom', 'QT', 'UX', 'UI', 'FIGMA',
'Photoshop', 'Adobe illustrator', 'Inkscape', 'Adobe InDesign', 'GIMP', 'Graphic', 'Типографика',
'Дизайн упаковки продукции', 'Дизайн мобильных приложений', 'Визуализация данных', 'PainNET',
'Sketch', 'Paint3D', 'Создание презентации', 'Создание лендингов', 'CJM', 'Web-design', 'Canva',
'WIX', 'Tilda', 'UserFlow', 'Blender', 'Magicavoxel'],
'Soft skills': ['Вербальная и письменная коммуникация', 'Вовлеченность', 'Педагогика',
'Разрешение конфликтов', 'Латеральное мышление', 'Быстрая обучаемость', 'Поиск информации',
'Китайским (A2-B1)', 'Немецким А2', 'Основы бизнеса', 'Руководство', 'Нестандартное мышление',
'Креативность', 'Эрудиция', 'Урбанизм', 'Внимательность', 'Английский язык (B2)',
'Знание немецкого языка', 'Активность', 'Испанский', 'Финансовый учет', 'Самостоятельность',
'Социальное предпринимательство', 'Этика', 'Сбор данных', 'Деловые переговоры', 'Research',
'Целеустремленность', 'Ответственность', 'Коммуникабельность', 'Спикер',
'Навык работы в команде', 'Критическое мышление', 'Решение проблем',
'Адаптивность и гибкость', 'Умение обучаться и готовность к обучению', 'Организация времени',
'Умение принимать решения', 'Эмоциональный интеллект', 'Стрессоустойчивость', 'Толерантность',
'Эмпатия и умение понимать других', 'Управление конфликтами', 'Лидерские качества',
'Тактичность', 'Мотивация', 'Самоорганизация', 'Ответственность', 'Дипломатичность',
'Умение убеждать', 'Активный слушатель', 'Усидчивость', 'Пунктуальность',
'Умение находить общий язык', 'Творческое мышление', 'Самоменеджмент', 'Настойчивость',
'Автономность', 'Исполнительность', 'Скоропечатание', 'Восприятие критики', 'Красноречие',
'Риторика', 'Умение работать с обратной связью', 'Профессиональная этика', 'Смекалка',
'Дисциплина', 'Умение учиться на своих ошибках', 'Умение благодарить',
'Оптимизм и позитивное мышление', 'Умение дать и принять комплимент', 'Навык делегирования',
'Умение проводить встречи и презентации', 'Многозадачность', 'Публичные выступления',
'Тайм-менеджмент', 'Лидерство', 'Работа в команде'],
'Инженерия': ['1С', 'Написание протоколов', 'SaaS', 'LeoECS', 'KiCad', 'Ansys', 'Eagle',
'Информационная безопасность', 'Построение интернет сетей', 'Lightroom', 'Unreal Engine 4',
'Unreal Engine 5', 'Unity', 'Unity3D', 'Rockwell Automation', 'Paspberry Pi', 'Blender',
'Развитие транспортных систем городов', '1С:Предприятие', '3ds Max', 'Revit', 'ArchiCAD',
'Autodesk Maya', 'Autodesk AutoCAD', 'DesignSpark Mechanical', 'SketchUP',
'Autodesk Fusion 360', 'Cinema 4D', 'Houdini', 'ZBrush', 'SculptGL', 'Wings 3D', 'FreeCAD',
'Sweet Home 3D', 'LEGO Digital Designer', '3D Slash', 'Autodesk Tinkercad',
'Autodesk Meshmixer', 'Autodesk ReCap Pro', 'Конструирование', 'Компас-3D', 'Solid Works',
'Autodesk inventor', 'Робототехника', 'Работа с проектной документацией'],
'Менеджмент': ['Комьюнити-менеджмент', 'Адаптивность продуктов и проектов',
'Организация работы проектной группы', 'Аналитика', 'Мотивирование команды и отдельных людей',
'Разработка стратегии', 'Глубинное интервью', 'Управленческие компетенции', 'QA',
'Презентации проекта', 'Стратегия развития продукта', 'Формирование бэклога',
'Ведение проекта', 'Анализ конкурентов', 'SOLID', 'Анализ рынка', 'Ideation', 'а', 'Use Case',
'A/B тестирование', 'Unit-экономика', 'Диаграммы Ганта', 'Создание бизнес-модели', 'EduNet',
'CustDev', 'ClickUp', 'Создание карты эмпатии', 'Trello', 'Jira', 'Confluence', 'XMind',
'Bitrix', 'AmoCRM', 'Контроль команды', 'Координация команды', 'Организация команды',
'Планирование задач', 'Разработка ТЗ', 'Мотивация команды', 'Управление процессами',
'Управление задачами', 'Agile', 'SCRUM', 'Kanban', 'Введение документооборота',
'Риск-менеджмент', 'Управление бюджетами и затратами', 'Ведение переговоров',
'Расстановка приоритетов', 'Критическое мышление', 'Адаптивность', 'Lean', 'BPMN',
'Управление изменениями в организации', 'R&D', 'Управление качеством',
'Знание внедрения программ лояльности', 'Инновационное мышление и внедрение новых технологий',
'Waterfall', 'Six Sigma', 'PRINCE2', 'Growth-hacking', 'Miro', 'HR'],
'Back-end': ['Java', 'Docker', 'PHP', 'Ruby', 'Golang', 'Aiogram', 'Python', 'C++', 'C#', '1C', 'SQL',
'MYSQL', 'PostgreSQL', 'Yii2', 'FastApi', 'ASP.NET', 'Scala', 'Swagger', 'Redis', 'Linux',
'Django', 'Rust', 'Spring Framework', 'Flask', 'Express.js', 'Laravel', 'Ruby on Rails',
'Fiber Framework', 'CakePHP', 'Play Framework', 'NestJS', 'GitHub', 'Flutter', 'GitHub Actions',
'Django REST', 'Celery', 'Kotlin', 'PyTest', 'MongoDB', 'Postman', 'Dart', 'Apache Kafka',
'RabbitMQ', 'PyQT', 'DRF', 'MsSQL Server', 'Git', 'ООП', 'Google Cloud Storage', 'Telegram боты',
'NOSQL', 'grpc', 'vba', 'Directium', 'Kubernetes'],
'Front-end': ['Agile', 'Bubble', 'Creatium', 'Glide', 'Гугл форма', 'XML', 'No code', 'Web components',
'RxJS', 'Redux', 'D3.js', 'Node.js', 'Angular', 'Html', 'CSS', 'SCSS', 'JavaScript', 'NextJS',
'VueJS', 'ReactJS', 'Tailwind', 'TypeScript', 'Nginx', 'JQuery', 'EmberJS', 'BackboneJS',
'Elastic Search', 'Semantic-UI', 'BCPB', 'Foundation', 'Svelte', 'Preact', 'mjml', 'Swift']}


def fill_skills(apps, schema_editor):
for category_name, skills_list in skills.items():
category = SkillCategory.objects.create(name=category_name)

for skill_name in skills_list:
Skill.objects.create(name=skill_name, category=category)


def reverse(apps, schema_editor):
Skill.objects.all().delete()
SkillCategory.objects.all().delete()


class Migration(migrations.Migration):
dependencies = [
("core", "0012_alter_specialization_options_and_more"),
]

operations = [
migrations.RunPython(fill_skills, reverse_code=reverse),
]
33 changes: 33 additions & 0 deletions core/migrations/0014_migrate_key_skills_to_skills.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 4.2.3 on 2024-02-01 09:34
from django.contrib.contenttypes.models import ContentType
from django.db import migrations
from core.models import Skill, SkillToObject
from users.models import CustomUser


def migrate_key_skills_to_skills(apps, schema_editor):
for user in CustomUser.objects.all():
if user.key_skills:
for skill_name in user.key_skills.lower().split(','):
skill_name = skill_name.strip()
skill = Skill.objects.filter(name__iexact=skill_name).first()
if skill:
SkillToObject.objects.get_or_create(
skill=skill, content_type=ContentType.objects.get_for_model(CustomUser), object_id=user.id
)


def reverse(apps, schema_editor):
SkillToObject.objects.filter(content_type=ContentType.objects.get_for_model(CustomUser)).delete()


class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0001_initial'),
("core", "0013_add_skills_from_dataset"),
("users", "0044_auto_20240128_2236"),
]

operations = [
migrations.RunPython(migrate_key_skills_to_skills, reverse_code=reverse),
]
15 changes: 14 additions & 1 deletion core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ class SkillCategory(models.Model):

name = models.CharField(max_length=256, null=False)

def __str__(self):
return self.name

class Meta:
verbose_name = "Категория навыка"
verbose_name_plural = "Категории навыков"
Expand All @@ -126,10 +129,16 @@ class Skill(models.Model):
related_name="skills",
)

def __str__(self):
return self.name

def __repr__(self):
return f"Skill<name={self.name},id={self.id}>"

class Meta:
verbose_name = "Навык"
verbose_name_plural = "Навыки"
ordering = ["category", "name"]
ordering = ["id", "category", "name"]


class SkillToObject(models.Model):
Expand All @@ -151,6 +160,10 @@ class SkillToObject(models.Model):
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey("content_type", "object_id")

class Meta:
verbose_name = "Ссылка на навык"
verbose_name_plural = "Ссылки на навыки"


class SpecializationCategory(models.Model):
name = models.TextField()
Expand Down
37 changes: 37 additions & 0 deletions core/serializers.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,46 @@
from rest_framework import serializers

from .models import SkillToObject, SkillCategory, Skill


class SetLikedSerializer(serializers.Serializer):
is_liked = serializers.BooleanField()


class SetViewedSerializer(serializers.Serializer):
is_viewed = serializers.BooleanField()


class SkillCategorySerializer(serializers.ModelSerializer[SkillCategory]):
class Meta:
model = SkillCategory
fields = [
"id",
"name",
]


class SkillSerializer(serializers.ModelSerializer):
category = SkillCategorySerializer()

class Meta:
model = Skill
fields = ["id", "name", "category"]


class SkillToObjectSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(source="skill.id")
name = serializers.CharField(source="skill.name")
category = SkillCategorySerializer(source="skill.category")

class Meta:
model = SkillToObject
fields = ["id", "name", "category"]


class SkillsSerializer(serializers.ModelSerializer[SkillCategory]):
skills = SkillSerializer(many=True)

class Meta:
model = SkillCategory
fields = ["id", "name", "skills"]
13 changes: 13 additions & 0 deletions core/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from django.urls import path

from core.views import (
SkillsNestedView,
SkillsInlineView,
)

app_name = "core"

urlpatterns = [
path("skills/nested/", SkillsNestedView.as_view()),
path("skills/inline/", SkillsInlineView.as_view()),
]
34 changes: 34 additions & 0 deletions core/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from django_filters import rest_framework as filters
from rest_framework import status
from rest_framework.generics import (
GenericAPIView,
ListAPIView,
)
from rest_framework.response import Response

from core.filters import SkillFilter
from core.models import SkillCategory, Skill
from core.pagination import Pagination
from core.serializers import (
SkillsSerializer,
SkillSerializer,
)


class SkillsNestedView(GenericAPIView):
serializer_class = SkillsSerializer
queryset = SkillCategory.objects.all()

def get(self, request):
data = self.serializer_class(self.get_queryset(), many=True).data
return Response(status=status.HTTP_200_OK, data=data)


class SkillsInlineView(ListAPIView):
serializer_class = SkillSerializer
pagination_class = Pagination
filter_backends = (filters.DjangoFilterBackend,)
filterset_class = SkillFilter

def get_queryset(self):
return Skill.objects.all()
Loading