Fakultas Ilmu Komputer UI

vacancies.py 12.8 KB
Newer Older
1
2
import requests
from django.conf import settings
3
from rest_framework import viewsets, status
4
from rest_framework.decorators import detail_route
5
from rest_framework.exceptions import ValidationError
6
from rest_framework.generics import get_object_or_404
7
from rest_framework.permissions import IsAuthenticated
8
from rest_framework.response import Response
9
from rest_framework.pagination import PageNumberPagination
10
from core.lib.mixins import MultiSerializerViewSetMixin
M. Reza Qorib's avatar
M. Reza Qorib committed
11
from core.lib.permissions import IsAdminOrStudent, IsAdminOrCompany, IsAdminOrVacancyOwner, AsAdminOrSupervisor, VacancyApprovalPermission
12
from core.models import Student, Company
13
from core.models.vacancies import Vacancy, Application
14
from core.serializers.vacancies import VacancySerializer, ApplicationSerializer, ApplicationStatusSerializer, \
15
    VacancyApplicationSerializer, PostVacancySerializer, VacancyVerifiedSerializer, SupervisorStudentApplicationSerializer
16
17


18
class VacancyViewSet(MultiSerializerViewSetMixin, viewsets.ModelViewSet):
19
    queryset = Vacancy.objects.all()
20
    serializer_class = VacancySerializer
21
22
23
    serializer_action_classes = {
        'create': PostVacancySerializer
    }
24
    permission_classes = [IsAdminOrCompany]
25
    pagination_class = PageNumberPagination
26

27
    def get_permissions(self):
28
        if self.action in ["retrieve", "list"]:
29
30
31
            return [IsAuthenticated()]
        return super(VacancyViewSet, self).get_permissions()

32
33
    def list(self, request, *args, **kwargs):
        vacancies = Vacancy.objects.all()
34
35
        verified = request.query_params['verified'] if 'verified' in request.query_params else "True"
        if verified.lower() in ("yes", "true", "t", "1"):
36
            vacancies = vacancies.filter(verified=True)
37
        if verified.lower() in {"no", "false", "f", "0"}:
38
            vacancies = vacancies.filter(verified=False)    
39
40
41
        page = self.paginate_queryset(vacancies)
        if page is not None:
            return self.get_paginated_response(VacancySerializer(page, many=True, context={'request': request}).data)
42
43
        return Response(VacancySerializer(vacancies, many=True, context={'request': request}).data)

44
45
46
47
48
49
50
    @detail_route(permission_classes=[IsAdminOrCompany])
    def count(self, request, pk=None):
        vacancy = self.get_object()
        count = Application.objects.filter(vacancy=vacancy).count()
        count_new = Application.objects.filter(vacancy=vacancy, status=Application.NEW).count()
        return Response({"count": count, "count_new": count_new}, status=status.HTTP_200_OK)

51
52
53
54
55
56
57
58
59
    @detail_route(methods=['patch'], permission_classes=[VacancyApprovalPermission], serializer_class=VacancyVerifiedSerializer)
    def verify(self, request, pk=None):
        vacancy = self.get_object()
        serializer = self.get_serializer_class()(vacancy, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response({"error" : "bad request"}, status=status.HTTP_400_BAD_REQUEST)

60

61
class ApplicationViewSet(viewsets.GenericViewSet):
62
    serializer_class = ApplicationSerializer
63
    permission_classes = [IsAdminOrStudent]
64
    pagination_class = PageNumberPagination
65

66
    def list(self, request, student_id):
67
        """
68
        Get list of a student {student_id}'s applied vacancies
69
70
        ---
        """
71
        student = get_object_or_404(Student.objects.all(), pk=student_id)
72
73
74
75
76
77
        vacancy_ids = Application.objects.filter(student=student).values('vacancy')
        vacancies = Vacancy.objects.filter(id__in=vacancy_ids)
        page = self.paginate_queryset(vacancies)
        if page is not None:
            return self.get_paginated_response(VacancySerializer(page, many=True, context={'request': request}).data)
        return Response(VacancySerializer(vacancies, many=True, context={'request': request}).data)
78
79

    def create(self, request, student_id):
80
81
82
83
84
        """
        Create a new application for student {student_id}
        ---
        parameters:
            - name: body
85
              description: JSON object containing an integer 'vacancy_id' and a string 'cover_letter'
86
87
88
89
              required: true
              type: string
              paramType: body
        """
90
91
        cover_letter = request.data.get('cover_letter')
        vacancy = get_object_or_404(Vacancy.objects.all(), pk=request.data.get('vacancy_id'))
92
        student = get_object_or_404(Student.objects.all(), pk=student_id)
93
94
        if Application.objects.filter(vacancy=vacancy, student=student).exists():
            raise ValidationError("You have already applied for the vacancy")
95
96
97
        application = Application(vacancy=vacancy, student=student, cover_letter=cover_letter)
        application.save()
        return Response(ApplicationSerializer(application, context={'request': request}).data)
98
99

    def destroy(self, request, student_id, pk):
100
101
102
103
        """
        Remove a application {id} for student {student_id}
        ---
        """
104
105
        vacancy = get_object_or_404(Vacancy.objects.all(), pk=pk)
        student = get_object_or_404(Student.objects.all(), pk=student_id)
106
        application = get_object_or_404(Application.objects.all(), student=student, vacancy=vacancy)
107
        application.delete()
108
        return Response(ApplicationSerializer(application, context={'request': request}).data)
109

110

111
112
class CompanyApplicationViewSet(viewsets.GenericViewSet):
    queryset = Application.objects.all()
113
    permission_classes = [IsAdminOrCompany]
114
    pagination_class = PageNumberPagination
115
116
117
118
119
120
121

    def list(self, request, company_id):
        """
        Get list of company {company_id}'s applications
        ---
        """
        company = get_object_or_404(Company.objects.all(), pk=company_id)
122
123
        if not request.user.is_superuser and request.user != company.user:
            return Response({"error": "forbidden"}, status=status.HTTP_403_FORBIDDEN)
124
125
126
127
        vacancies = Vacancy.objects.filter(company=company)
        applications = Application.objects.filter(vacancy__in=vacancies)
        if 'status' in request.query_params:
            applications = applications.filter(status=request.query_params['status'])
128
129
130
        page = self.paginate_queryset(applications)
        if page is not None:
            return self.get_paginated_response(ApplicationSerializer(page, many=True, context={'request': request}).data)
131
132
        return Response(ApplicationSerializer(applications, many=True, context={'request': request}).data)

133
134
135
136
137
138
139
140
141
142
143
    @detail_route(methods=["get"])
    def by_vacancy(self, request, company_id, pk=None):
        if pk is None:
            return list(self, request, company_id)
        company = get_object_or_404(Company.objects.all().order_by('-updated'), pk=company_id)
        if not request.user.is_superuser and request.user != company.user:
            return Response({"error": "forbidden"}, status=status.HTTP_403_FORBIDDEN)
        vacancy = get_object_or_404(Vacancy.objects.all(), pk=pk)
        if vacancy.company != company:
            return Response({"error": "forbidden"}, status=status.HTTP_403_FORBIDDEN)
        applications = Application.objects.filter(vacancy=vacancy)
144
145
146
147
148
149
150
151
152
153
154
        st = request.query_params.get('status', None)
        if st is not None:
            try:
                st = int(st)
                if st < 0 or st > 4:
                    return Response({"error": "status must be an integer between 0 and 4"},
                                    status=status.HTTP_400_BAD_REQUEST)
                applications = applications.filter(status=st)
            except:
                return Response({"error": "status must be an integer between 0 and 4"}, \
                                status=status.HTTP_400_BAD_REQUEST)
155
156
157
158
159
160
        page = self.paginate_queryset(applications)
        if page is not None:
            return self.get_paginated_response(
                ApplicationSerializer(page, many=True, context={'request': request}).data)
        return Response(ApplicationSerializer(applications, many=True, context={'request': request}).data)

161

162
163
164
165
166
167
168
169
170
171
172
173
174
175
class CompanyApplicationStatusViewSet(viewsets.GenericViewSet):
    queryset = Application.objects.all()
    serializer_class = ApplicationStatusSerializer
    permission_classes = [IsAdminOrVacancyOwner]

    def partial_update(self, request, pk=None):
        application = self.get_object()
        serializer = self.get_serializer_class()(application, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_202_ACCEPTED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

176
177
178
179
180
181
182
183
    def retrieve(self, request, pk=None):
        application = self.get_object()
        student = application.student
        if student.show_transcript:
            s = requests.Session()
            credentials = settings.API_CS_CREDENTIALS
            s.get('https://api.cs.ui.ac.id/api-auth/login/')
            csrf = s.cookies['csrftoken']
184
            resp = s.post('https://api.cs.ui.ac.id/api-auth/login/', data={'username' : credentials["user"], 'password' : credentials["password"], 'csrfmiddlewaretoken' : csrf})
185
            response = s.get('https://api.cs.ui.ac.id/siakngcs/mahasiswa/' + str(student.npm) + '/riwayat/')
186
            return Response({'name' : student.full_name, 'transcript' : response.json()}, status=status.HTTP_200_OK)
187
        else:
188
            return Response({'name' : student.full_name, 'error' : 'student does not allow transcript to be shown'}, status=status.HTTP_200_OK)
189

190

191
class CompanyVacanciesViewSet(viewsets.GenericViewSet):
192
    queryset = Vacancy.objects.all()
193
    pagination_class = PageNumberPagination
194
    permission_classes = [IsAdminOrCompany]
195
196
197
198
199
200

    def list(self, request, company_id):
        """
        Get list of company {company_id}'s vacancies
        ---
        """
201
        company = get_object_or_404(Company.objects.all().order_by('-updated'), pk=company_id)
202
203
        if not request.user.is_superuser and request.user != company.user:
            return Response({"error": "forbidden"}, status=status.HTTP_403_FORBIDDEN)
204
        vacancies = Vacancy.objects.filter(company=company)
205
206
207
        page = self.paginate_queryset(vacancies)
        if page is not None:
            return self.get_paginated_response(VacancySerializer(page, many=True, context={'request': request}).data)
208
209
210
        return Response(VacancySerializer(vacancies, many=True, context={'request': request}).data)


211
212
213
214
215
class BookmarkedVacancyByStudentViewSet(viewsets.GenericViewSet):
    serializer_class = VacancySerializer
    permission_classes = [IsAdminOrStudent]

    def list(self, request, student_id):
216
217
218
219
        """
        Get list of a student {student_id}'s bookmarked vacancies
        ---
        """
220
        student = get_object_or_404(Student.objects.all(), pk=student_id)
221
222
223
224
225
        vacancies = student.bookmarked_vacancies.all()
        page = self.paginate_queryset(vacancies)
        if page is not None:
            return self.get_paginated_response(VacancySerializer(page, many=True, context={'request': request}).data)
        return Response(VacancySerializer(vacancies, many=True, context={'request': request}).data)
226
227

    def create(self, request, student_id):
228
229
230
231
232
233
234
235
236
237
        """
        Bookmarks a vacancy for student {student_id}
        ---
        parameters:
            - name: body
              description: JSON object containing only one string: vacancy_id
              required: true
              type: string
              paramType: body
        """
238
239
240
241
242
243
        vacancy = get_object_or_404(Vacancy.objects.all(), pk=request.data['vacancy_id'])
        student = get_object_or_404(Student.objects.all(), pk=student_id)
        student.bookmarked_vacancies.add(vacancy)
        return Response(self.serializer_class(student.bookmarked_vacancies, many=True, context={'request': request}).data)

    def destroy(self, request, student_id, pk):
244
245
246
247
        """
        Remove bookmark {id} for student {student_id}
        ---
        """
248
249
250
251
        vacancy = get_object_or_404(Vacancy.objects.all(), pk=pk)
        student = get_object_or_404(Student.objects.all(), pk=student_id)
        student.bookmarked_vacancies.remove(vacancy)
        return Response(self.serializer_class(student.bookmarked_vacancies, many=True, context={'request': request}).data)
252
253
254
255
256
257
258
259
260
261
262
263
264
265


class SupervisorStudentApplicationViewSet(viewsets.GenericViewSet):
    queryset = Student.objects.all()
    serializer_class = SupervisorStudentApplicationSerializer
    pagination_class = PageNumberPagination
    permission_classes = [AsAdminOrSupervisor]

    def list(self, request):
        applications = Application.objects.order_by('student')
        page = self.paginate_queryset(applications)
        if page is not None:
            return self.get_paginated_response(self.serializer_class(applications, many=True, context={'request': request}).data)
        return Response(self.serializer_class(applications, many=True, context={'request': request}).data)