Skip to content

Commit cd9260e

Browse files
committed
feat: ApplicationFileAttachmentViewSet
1 parent 0b4ee68 commit cd9260e

File tree

3 files changed

+37
-21
lines changed

3 files changed

+37
-21
lines changed

backend/samfundet/models/recruitment.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from django.contrib.auth.models import UserManager
1313

1414
from root.utils.mixins import CustomBaseModel, FullCleanSaveMixin
15+
from samfundet.utils import upload_to_app
1516

1617
from .general import Gang, User, Campus, GangSection, Organization
1718
from .model_choices import RecruitmentStatusChoices, RecruitmentApplicantStates, RecruitmentPriorityChoices
@@ -167,7 +168,7 @@ class RecruitmentPosition(CustomBaseModel):
167168
# TODO: Implement interviewer functionality
168169
interviewers = models.ManyToManyField(to=User, help_text='Interviewers for the position', blank=True, related_name='interviewers')
169170

170-
#FIX: Add functionality for setting allowed attachments for application
171+
# FIX: Add functionality for setting allowed attachments for application
171172
recruitment = models.ForeignKey(
172173
Recruitment,
173174
on_delete=models.CASCADE,
@@ -320,15 +321,16 @@ def resolve_gang(self, *, return_id: bool = False) -> Gang | int:
320321
return self.room.resolve_gang(return_id=return_id)
321322

322323

323-
324324
class RecruitmentApplication(CustomBaseModel):
325325
# UUID so that applicants cannot see recruitment info with their own id number
326326
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
327327
application_text = models.TextField(help_text='Application text')
328328
recruitment_position = models.ForeignKey(
329329
RecruitmentPosition, on_delete=models.CASCADE, help_text='The position which is recruiting', related_name='applications'
330330
)
331-
recruitment = models.ForeignKey(Recruitment, on_delete=models.CASCADE, null=True, help_text='The recruitment that is recruiting', related_name='applications')
331+
recruitment = models.ForeignKey(
332+
Recruitment, on_delete=models.CASCADE, null=True, help_text='The recruitment that is recruiting', related_name='applications'
333+
)
332334
user = models.ForeignKey(User, on_delete=models.CASCADE, help_text='The user that is applying', related_name='applications')
333335
applicant_priority = models.PositiveIntegerField(null=True, blank=True, help_text='The priority of the application')
334336

@@ -492,22 +494,24 @@ def update_applicant_state(self) -> None:
492494
application.applicant_state = RecruitmentApplicantStates.NOT_WANTED
493495
application.save()
494496

497+
495498
class ApplicationFileAttachment(CustomBaseModel):
496-
application = models.ForeignKey(RecruitmentApplication,
497-
on_delete=models.CASCADE,
498-
related_name="attachments",
499-
help_text="The recruitment application this file is attached to")
500-
application_file = models.FileField(upload_to="some/path")
499+
application = models.ForeignKey(
500+
RecruitmentApplication, on_delete=models.CASCADE, related_name='attachments', help_text='The recruitment application this file is attached to'
501+
)
502+
application_file = models.FileField(upload_to='recruitment/application_attachments/')
501503
application_file_type = models.CharField(max_length=50, blank=True)
502504

503505
def clean(self) -> None:
504506
super().clean()
505-
if self.file:
506-
file_type = self.file.content_type
507-
self.file_type = file_type
507+
if self.application_file:
508+
file_type = self.application_file.content_type
509+
self.application_file_type = file_type or ''
508510
allowed_types = [
509-
'image/jpeg', 'image/png', # Images
510-
'video/mp4' # Video
511+
'image/jpeg',
512+
'image/png', # Images
513+
'video/mp4', # Video
514+
'application/pdf',
511515
]
512516
if file_type not in allowed_types:
513517
raise ValidationError('Wrong filetype')
@@ -517,6 +521,7 @@ def clean(self) -> None:
517521
def __str__(self):
518522
return f'Attachment for {self.application} - {self.file.name}'
519523

524+
520525
class RecruitmentInterviewAvailability(CustomBaseModel):
521526
"""This models all possible times for interviews for the given recruitment.
522527

backend/samfundet/serializers.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,15 @@
8484
class ApplicationFileAttachmentSerializer(CustomBaseSerializer):
8585
class Meta:
8686
model = ApplicationFileAttachment
87+
fields = (
88+
'id',
89+
'application',
90+
'application_file',
91+
'application_file_type',
92+
)
8793

8894
def validate(self, attrs: dict) -> dict:
89-
admission_image = attrs.get('admission_image')
90-
91-
# if admission_image:
92-
# is_image_valid(admission_image)
93-
# else:
94-
# msg = 'Image is invalid'
95-
# raise serializers.ValidationError(msg, code="authorization")
96-
# if
95+
return attrs
9796

9897

9998
class TagSerializer(CustomBaseSerializer):

backend/samfundet/views.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
from .homepage import homepage
5151
from .models.role import Role, UserOrgRole, UserGangRole, UserGangSectionRole
5252
from .serializers import (
53+
ApplicationFileAttachmentSerializer,
5354
TagSerializer,
5455
GangSerializer,
5556
MenuSerializer,
@@ -143,6 +144,7 @@
143144
UserFeedbackModel,
144145
)
145146
from .models.recruitment import (
147+
ApplicationFileAttachment,
146148
Interview,
147149
Recruitment,
148150
InterviewRoom,
@@ -690,6 +692,16 @@ def delete(self, request: Request) -> Response:
690692
# =============================== #
691693

692694

695+
class ApplicationFileAttachmentViewSet(ModelViewSet):
696+
serializer_class = ApplicationFileAttachmentSerializer
697+
queryset = ApplicationFileAttachment.objects.all()
698+
699+
# Typically, you might want extra permission logic here:
700+
# - Only the applicant or a recruiter with certain perms can read attachments
701+
# - Only the applicant can create attachments for *their own* application
702+
# etc.
703+
704+
693705
@method_decorator(ensure_csrf_cookie, 'dispatch')
694706
class RecruitmentView(ModelViewSet):
695707
permission_classes = (DjangoModelPermissionsOrAnonReadOnly,)

0 commit comments

Comments
 (0)