Skip to content

Commit

Permalink
Feature/cointerviews (#1399)
Browse files Browse the repository at this point in the history
* feat: add adminpanel for shared interviewgroup

* first draft

* fix

* fix

* fix

* fix migration

* more fix

* fix

* fix

* feat: fix

* fix

* fix

* fucking paths

* fuck this

* lol fix

* it works?

* fix up merge

* fix requests

---------

Co-authored-by: magsyg <[email protected]>
  • Loading branch information
magsyg and magsyg authored Oct 29, 2024
1 parent 8cfc22f commit 3120471
Show file tree
Hide file tree
Showing 25 changed files with 353 additions and 79 deletions.
2 changes: 2 additions & 0 deletions backend/root/management/commands/seed_scripts/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
recruitment_separate_position,
recruitment_interviewavailability,
recruitment_position_interviewers,
recruitment_sharedinterviewgroups,
)

# Insert seed scripts here (in order of priority)
Expand All @@ -50,6 +51,7 @@
('merch', merch.seed),
('recruitment', recruitment.seed),
('recruitment_position', recruitment_position.seed),
('recruitment_position_shared_interview', recruitment_sharedinterviewgroups.seed),
('recruitment_interviewavailability', recruitment_interviewavailability.seed),
('recruitment_separate_position', recruitment_separate_position.seed),
('recruitment_applications', recruitment_applications.seed),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from __future__ import annotations

import random

from root.utils.samfundet_random import words

from samfundet.models.recruitment import Recruitment, RecruitmentPosition, RecruitmentPositionSharedInterviewGroup


def seed():
yield 0, 'recruitment_positions_shared_interview'
RecruitmentPositionSharedInterviewGroup.objects.all().delete()
yield 0, 'Deleted old recruitmentpositionsharedgroup'

recruitments = Recruitment.objects.all()
created_count = 0
for recruitment in recruitments:
for i in range(3):
RecruitmentPositionSharedInterviewGroup.objects.create(recruitment=recruitment, name_nb=f'{words(2)} {i}', name_en=f'{words(2)} {i}')
created_count += 1
shared_groups = list(RecruitmentPositionSharedInterviewGroup.objects.filter(recruitment=recruitment))
positions = random.sample(list(RecruitmentPosition.objects.filter(recruitment=recruitment)), 6)
for pos in positions:
pos.shared_interview_group = random.choice(shared_groups)
pos.save()

yield 100, f'Created {created_count} recruitment_position_shared_groups'
10 changes: 10 additions & 0 deletions backend/root/utils/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,15 @@
admin__samfundet_recruitmentapplication_delete = 'admin:samfundet_recruitmentapplication_delete'
admin__samfundet_recruitmentapplication_change = 'admin:samfundet_recruitmentapplication_change'
adminsamfundetrecruitmentapplication__objectId = ''
admin__samfundet_recruitmentpositionsharedinterviewgroup_permissions = 'admin:samfundet_recruitmentpositionsharedinterviewgroup_permissions'
admin__samfundet_recruitmentpositionsharedinterviewgroup_permissions_manage_user = 'admin:samfundet_recruitmentpositionsharedinterviewgroup_permissions_manage_user'
admin__samfundet_recruitmentpositionsharedinterviewgroup_permissions_manage_group = 'admin:samfundet_recruitmentpositionsharedinterviewgroup_permissions_manage_group'
admin__samfundet_recruitmentpositionsharedinterviewgroup_changelist = 'admin:samfundet_recruitmentpositionsharedinterviewgroup_changelist'
admin__samfundet_recruitmentpositionsharedinterviewgroup_add = 'admin:samfundet_recruitmentpositionsharedinterviewgroup_add'
admin__samfundet_recruitmentpositionsharedinterviewgroup_history = 'admin:samfundet_recruitmentpositionsharedinterviewgroup_history'
admin__samfundet_recruitmentpositionsharedinterviewgroup_delete = 'admin:samfundet_recruitmentpositionsharedinterviewgroup_delete'
admin__samfundet_recruitmentpositionsharedinterviewgroup_change = 'admin:samfundet_recruitmentpositionsharedinterviewgroup_change'
adminsamfundetrecruitmentpositionsharedinterviewgroup__objectId = ''
admin__samfundet_organization_permissions = 'admin:samfundet_organization_permissions'
admin__samfundet_organization_permissions_manage_user = 'admin:samfundet_organization_permissions_manage_user'
admin__samfundet_organization_permissions_manage_group = 'admin:samfundet_organization_permissions_manage_group'
Expand Down Expand Up @@ -575,6 +584,7 @@
samfundet__recruitment_positions = 'samfundet:recruitment_positions'
samfundet__recruitment_show_unprocessed_applicants = 'samfundet:recruitment_show_unprocessed_applicants'
samfundet__recruitment_positions_gang_for_applicants = 'samfundet:recruitment_positions_gang_for_applicants'
samfundet__recruitment_shared_interviews = 'samfundet:recruitment_shared_interviews'
samfundet__recruitment_positions_gang_for_gangs = 'samfundet:recruitment_positions_gang_for_gangs'
samfundet__recruitment_set_interview = 'samfundet:recruitment_set_interview'
samfundet__recruitment_application_states_choices = 'samfundet:recruitment_application_states_choices'
Expand Down
23 changes: 23 additions & 0 deletions backend/samfundet/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
RecruitmentApplication,
RecruitmentSeparatePosition,
RecruitmentInterviewAvailability,
RecruitmentPositionSharedInterviewGroup,
)

# Common fields:
Expand Down Expand Up @@ -715,6 +716,28 @@ class RecruitmentApplicationAdmin(CustomBaseAdmin):
list_select_related = True


@admin.register(RecruitmentPositionSharedInterviewGroup)
class RecruitmentPositionSharedInterviewGroupAdmin(CustomBaseAdmin):
sortable_by = [
'recruitment',
'name_en',
'name_nb',
'__str__',
]
list_display = [
'recruitment',
'name_en',
'name_nb',
'__str__',
]
search_fields = [
'recruitment',
'name_en',
'name_nb',
'__str__',
]


@admin.register(Organization)
class OrganizationAdmin(CustomBaseAdmin):
sortable_by = ['id', 'name']
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Generated by Django 5.1.1 on 2024-10-29 17:39

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("samfundet", "0008_event_entrance_en_event_entrance_nb"),
]

operations = [
migrations.AddField(
model_name="recruitmentpositionsharedinterviewgroup",
name="name_en",
field=models.CharField(
default="hi",
help_text="Name of the recruitmentgroup (EN)",
max_length=100,
),
preserve_default=False,
),
migrations.AddField(
model_name="recruitmentpositionsharedinterviewgroup",
name="name_nb",
field=models.CharField(
default="hi",
help_text="Name of the recruitmentgroup (NB)",
max_length=100,
),
preserve_default=False,
),
]
6 changes: 5 additions & 1 deletion backend/samfundet/models/recruitment.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,11 @@ class RecruitmentPositionSharedInterviewGroup(CustomBaseModel):
blank=True,
)

name_nb = models.CharField(max_length=100, null=False, blank=False, help_text='Name of the recruitmentgroup (NB)')
name_en = models.CharField(max_length=100, null=False, blank=False, help_text='Name of the recruitmentgroup (EN)')

def __str__(self) -> str:
return f'{self.recruitment} Interviewgroup {self.id}'
return f'{self.recruitment} Interviewgroup {self.name_nb} {", ".join(list(self.positions.values_list("name_nb", flat=True)))}'


class RecruitmentPosition(CustomBaseModel):
Expand Down Expand Up @@ -261,6 +264,7 @@ class Interview(CustomBaseModel):
help_text='Room where the interview is held',
related_name='interviews',
)

interviewers = models.ManyToManyField(to='samfundet.User', help_text='Interviewers for this interview', blank=True, related_name='interviews')
notes = models.TextField(help_text='Notes for the interview', null=True, blank=True)

Expand Down
4 changes: 2 additions & 2 deletions backend/samfundet/models/tests/test_recruitment.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ def test_interview_group_autoadd_on_create(
assert fixture_recruitment_position2.shared_interview_group is None

# setup interview group
shared_group = RecruitmentPositionSharedInterviewGroup.objects.create(recruitment=fixture_recruitment)
shared_group = RecruitmentPositionSharedInterviewGroup.objects.create(recruitment=fixture_recruitment, name_en='name', name_nb='navn')
fixture_recruitment_position.shared_interview_group = shared_group
fixture_recruitment_position2.shared_interview_group = shared_group
fixture_recruitment_position.save()
Expand Down Expand Up @@ -288,7 +288,7 @@ def test_interview_group_autoset_on_set(
assert fixture_recruitment_application2.recruitment_position == fixture_recruitment_position2

# setup interview group
shared_group = RecruitmentPositionSharedInterviewGroup.objects.create(recruitment=fixture_recruitment)
shared_group = RecruitmentPositionSharedInterviewGroup.objects.create(recruitment=fixture_recruitment, name_en='name', name_nb='navn')
fixture_recruitment_position.shared_interview_group = shared_group
fixture_recruitment_position2.shared_interview_group = shared_group
fixture_recruitment_position.save()
Expand Down
15 changes: 15 additions & 0 deletions backend/samfundet/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
RecruitmentApplication,
RecruitmentSeparatePosition,
RecruitmentInterviewAvailability,
RecruitmentPositionSharedInterviewGroup,
)
from .models.model_choices import RecruitmentStatusChoices, RecruitmentPriorityChoices

Expand Down Expand Up @@ -858,6 +859,20 @@ class Meta:
]


class RecruitmentPositionSharedInterviewGroupSerializer(serializers.ModelSerializer):
positions = RecruitmentPositionForApplicantSerializer(many=True, read_only=True)

class Meta:
model = RecruitmentPositionSharedInterviewGroup
fields = [
'id',
'recruitment',
'positions',
'name_en',
'name_nb',
]


class RecruitmentApplicationForApplicantSerializer(CustomBaseSerializer):
interview = ApplicantInterviewSerializer(read_only=True)

Expand Down
5 changes: 5 additions & 0 deletions backend/samfundet/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@
views.RecruitmentPositionsPerGangForApplicantView.as_view(),
name='recruitment_positions_gang_for_applicants',
),
path(
'recruitment-shared-interview-groups/<int:recruitment_id>/',
views.RecruitmentInterviewGroupView.as_view(),
name='recruitment_shared_interviews',
),
path('recruitment-positions-gang-for-gangs/', views.RecruitmentPositionsPerGangForGangView.as_view(), name='recruitment_positions_gang_for_gangs'),
path('recruitment-set-interview/<slug:pk>/', views.RecruitmentApplicationSetInterviewView.as_view(), name='recruitment_set_interview'),
path(
Expand Down
16 changes: 16 additions & 0 deletions backend/samfundet/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
RecruitmentApplicationForRecruiterSerializer,
RecruitmentApplicationUpdateForGangSerializer,
RecruitmentShowUnprocessedApplicationsSerializer,
RecruitmentPositionSharedInterviewGroupSerializer,
)
from .models.event import (
Event,
Expand Down Expand Up @@ -137,6 +138,7 @@
RecruitmentApplication,
RecruitmentSeparatePosition,
RecruitmentInterviewAvailability,
RecruitmentPositionSharedInterviewGroup,
)
from .models.model_choices import RecruitmentStatusChoices, RecruitmentPriorityChoices

Expand Down Expand Up @@ -1109,6 +1111,20 @@ def get_queryset(self) -> Response:
return Recruitment.objects.filter(visible_from__lte=timezone.now(), actual_application_deadline__gte=timezone.now())


class RecruitmentInterviewGroupView(APIView):
permission_classes = [IsAuthenticated]

def get(
self,
request: Request,
recruitment_id: int,
) -> HttpResponse:
recruitment = get_object_or_404(Recruitment, id=recruitment_id)
interview_groups = RecruitmentPositionSharedInterviewGroup.objects.filter(recruitment=recruitment)

return Response(data=RecruitmentPositionSharedInterviewGroupSerializer(interview_groups, many=True).data, status=status.HTTP_200_OK)


class DownloadRecruitmentApplicationGangCSV(APIView):
permission_classes = [IsAuthenticated]

Expand Down
Loading

0 comments on commit 3120471

Please sign in to comment.