From 3e2bed982cf45edfea95a92efdee91084a20133a Mon Sep 17 00:00:00 2001
From: Muhammad At Thoriq <muhammad.at@ui.ac.id>
Date: Sun, 6 Oct 2019 03:30:36 +0700
Subject: [PATCH] Merge branch 'master' into '1606918484-03'

# Conflicts:
#   kape/urls.py
---
 core/migrations/0015_merge_20191005_2038.py | 16 ++++
 core/migrations/0017_merge_20191006_0134.py | 16 ++++
 core/models/vacancies.py                    |  1 +
 core/serializers/vacancies.py               |  2 +-
 core/tests/test_vacancies.py                | 93 +++++++++++++++++++++
 core/views/vacancies.py                     | 20 +++++
 kape/urls.py                                |  3 +-
 7 files changed, 149 insertions(+), 2 deletions(-)
 create mode 100644 core/migrations/0015_merge_20191005_2038.py
 create mode 100644 core/migrations/0017_merge_20191006_0134.py

diff --git a/core/migrations/0015_merge_20191005_2038.py b/core/migrations/0015_merge_20191005_2038.py
new file mode 100644
index 00000000..d4afc1b8
--- /dev/null
+++ b/core/migrations/0015_merge_20191005_2038.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.5 on 2019-10-05 13:38
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0014_feedback'),
+        ('core', '0014_company_category'),
+    ]
+
+    operations = [
+    ]
diff --git a/core/migrations/0017_merge_20191006_0134.py b/core/migrations/0017_merge_20191006_0134.py
new file mode 100644
index 00000000..d41f21a8
--- /dev/null
+++ b/core/migrations/0017_merge_20191006_0134.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.5 on 2019-10-05 18:34
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0015_merge_20191005_2038'),
+        ('core', '0016_merge_20191005_2235'),
+    ]
+
+    operations = [
+    ]
diff --git a/core/models/vacancies.py b/core/models/vacancies.py
index f2b5dc49..8968e626 100644
--- a/core/models/vacancies.py
+++ b/core/models/vacancies.py
@@ -23,6 +23,7 @@ class Application(models.Model):
     BOOKMARKED = 2
     REJECTED = 3
     ACCEPTED = 4
+    ABORTED = 5
 
     cover_letter = models.TextField(null=True, blank=True)
     student = models.ForeignKey(Student, on_delete=models.CASCADE)
diff --git a/core/serializers/vacancies.py b/core/serializers/vacancies.py
index 313f2064..a2bd2e4f 100644
--- a/core/serializers/vacancies.py
+++ b/core/serializers/vacancies.py
@@ -61,7 +61,7 @@ class ApplicationStatusSerializer(serializers.ModelSerializer):
 
 class SupervisorStudentApplicationSerializer(serializers.ModelSerializer):
     def to_representation(self, instance):
-        status_map = ["new", "read", "bookmarked", "rejected", "accepted" ]
+        status_map = ["new", "read", "bookmarked", "rejected", "accepted","aborted" ]
         return {
             'name' : instance.student.full_name,
             'npm' : instance.student.npm,
diff --git a/core/tests/test_vacancies.py b/core/tests/test_vacancies.py
index d8c654f6..f6ab7938 100644
--- a/core/tests/test_vacancies.py
+++ b/core/tests/test_vacancies.py
@@ -1,6 +1,7 @@
 from datetime import datetime
 from django.utils import timezone
 
+import json
 import requests_mock
 from django.contrib.auth.models import User
 from rest_framework import status
@@ -434,3 +435,95 @@ class SupervisorApprovalTests(APITestCase):
         response = self.client.patch(url, format='json')
         self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
         self.assertEqual(new_vacancy.verified, False)
+
+class AcceptOneOfferTests(APITestCase):        
+
+    def generateObject(self):
+        new_user = User.objects.create_user('dummy.company', 'dummy.company@company.com', 'lalala123')
+        new_company = Company.objects.create(user=new_user, description="lalala", status=Company.VERIFIED, logo=None,
+                                             address=None)
+        
+        new_user2 = User.objects.create_user('dummy.company2', 'dummy.company2@company.com', 'lalala123')
+        new_company2 = Company.objects.create(user=new_user2, description="lalala", status=Company.VERIFIED, logo=None,
+                                             address=None)
+
+        new_vacancy = Vacancy.objects.create(company=new_company, verified=True, open_time=datetime.fromtimestamp(0),
+                                             description="lalala", close_time=datetime.today())
+        
+        new_vacancy2 = Vacancy.objects.create(company=new_company2, verified=True, open_time=datetime.fromtimestamp(0),
+                                             description="lalala", close_time=datetime.today())
+
+        new_user3 = User.objects.create_user('dummy.student', 'dummy.student@company.com', 'lalala123')
+        new_student = Student.objects.create(user=new_user3, npm=1234123412)
+
+        return new_user3, new_vacancy, new_vacancy2, new_student
+
+    def test_number_of_content_response_object_given_id_auth(self):
+        
+        new_user3, new_vacancy, new_vacancy2, new_student = self.generateObject()
+        
+        self.client.force_authenticate(new_user3)
+
+        Application.objects.create(student=new_student, vacancy=new_vacancy, cover_letter="asdasdasd")
+        Application.objects.create(student=new_student, vacancy=new_vacancy2, cover_letter="asdasdasd")
+
+        url = '/api/acceptoffer/' + str(new_student.pk) + '/vacancy/' + str(new_vacancy.pk) + '/'
+
+        response = self.client.patch(url, format='json')
+        body = json.loads(response.content)
+
+        status_response = []
+        for app in body:
+            status_response.append(app['status'])        
+
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertTrue(len(body) >= 2)
+        self.assertFalse(len(body) == 0)
+        self.assertTrue('new' in status_response)
+        self.assertTrue('aborted' in status_response)
+
+    def test_student_not_exist_given_auth(self):
+        new_user3,new_vacancy, new_vacancy2, new_student = self.generateObject()
+
+        self.client.force_authenticate(new_user3)
+
+        user4 = User.objects.create_user('student_user_4', 'student_user_4@company.com', 'lalala123')
+        other_student = Student.objects.create(user=user4, npm=1098765432)
+
+        Application.objects.create(student=other_student, vacancy=new_vacancy, cover_letter="asdasdasd")
+        Application.objects.create(student=other_student, vacancy=new_vacancy2, cover_letter="asdasdasd")
+
+        url = '/api/acceptoffer/' + str(new_student.pk) + '/vacancy/' + str(new_vacancy.pk) + '/'
+
+        response = self.client.patch(url, format='json')
+        body = json.loads(response.content)  
+
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertTrue(len(body) == 0)
+
+    def test_type_error_if_input_null(self):
+        new_user3, new_vacancy, new_vacancy2, new_student = self.generateObject()
+
+        self.client.force_authenticate(new_user3)
+
+        Application.objects.create(student=new_student, vacancy=new_vacancy, cover_letter="asdasdasd")
+        Application.objects.create(student=new_student, vacancy=new_vacancy2, cover_letter="asdasdasd")
+
+        with self.assertRaises(TypeError):
+            url = '/api/acceptoffer/' + None + '/vacancy/' + str(new_vacancy.pk) + '/'
+        
+        with self.assertRaises(TypeError):
+            url = '/api/acceptoffer/' + str(new_student.pk) + '/vacancy/' + None + '/'
+    
+    def test_if_requester_is_not_authenticated(self):
+        new_user3, new_vacancy, new_vacancy2, new_student = self.generateObject()
+        
+        Application.objects.create(student=new_student, vacancy=new_vacancy, cover_letter="asdasdasd")
+        Application.objects.create(student=new_student, vacancy=new_vacancy2, cover_letter="asdasdasd")
+
+        url = '/api/acceptoffer/' + str(new_student.pk) + '/vacancy/' + str(new_vacancy.pk) + '/'
+
+        response = self.client.patch(url, format='json')
+        body = json.loads(response.content) 
+
+        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
diff --git a/core/views/vacancies.py b/core/views/vacancies.py
index 56165caa..2f805138 100644
--- a/core/views/vacancies.py
+++ b/core/views/vacancies.py
@@ -350,3 +350,23 @@ class BookmarkedVacancyByStudentViewSet(viewsets.GenericViewSet):
         student.bookmarked_vacancies.remove(vacancy)
         return Response(
             self.serializer_class(student.bookmarked_vacancies, many=True, context={'request': request}).data)
+
+class AcceptOfferByStudentViewSet(MultiSerializerViewSetMixin, viewsets.GenericViewSet):
+    queryset = Application.objects.all()
+    permission_classes = [IsAdminOrStudent]
+
+    def partial_update(self, request, student_id, pk=None):
+        """
+        Get list of a student {student_id}'s cancel offered vacancies
+        ---
+        """
+        student = get_object_or_404(Student.objects.all().order_by('-updated'), pk=student_id)
+        apps = Application.objects.filter(student=student)
+        
+        for a in apps:
+            if a.vacancy_id != int(pk):
+                serializer = ApplicationStatusSerializer(a, data={'status': 5}, partial=True)
+                if serializer.is_valid():
+                    serializer.save()
+        
+        return Response(SupervisorStudentApplicationSerializer(apps, many=True, context={'request': request}).data)
\ No newline at end of file
diff --git a/kape/urls.py b/kape/urls.py
index 5ae9c078..ade154c6 100755
--- a/kape/urls.py
+++ b/kape/urls.py
@@ -25,7 +25,7 @@ from core import apps
 from core.views.accounts import StudentViewSet, CompanyViewSet, SupervisorViewSet, UserViewSet, LoginViewSet, \
     CompanyRegisterViewSet
 from core.views.vacancies import VacancyViewSet, BookmarkedVacancyByStudentViewSet, StudentApplicationViewSet, \
-    CompanyApplicationViewSet, CompanyVacanciesViewSet, ApplicationViewSet
+    CompanyApplicationViewSet, CompanyVacanciesViewSet, ApplicationViewSet, AcceptOfferByStudentViewSet
 from core.views.feedbacks import FeedbackViewSet
 
 schema_view = get_swagger_view()
@@ -40,6 +40,7 @@ router.register(r'vacancies', VacancyViewSet)
 router.register(r'applications', ApplicationViewSet)
 router.register(r'feedbacks', FeedbackViewSet)
 # router.register(r'students/(?P<student_id>\d+)/profile', StudentProfileViewSet)
+router.register(r'acceptoffer/(?P<student_id>\d+)/vacancy', AcceptOfferByStudentViewSet)
 router.register(r'students/(?P<student_id>\d+)/bookmarked-vacancies', BookmarkedVacancyByStudentViewSet,
                 base_name='bookmarked-vacancy-list')
 router.register(r'students/(?P<student_id>\d+)/applied-vacancies', StudentApplicationViewSet,
-- 
GitLab