diff --git a/core/lib/permissions.py b/core/lib/permissions.py index 71e53560835927daabb86b521fca31a8fee0559f..2b3b549a80ab61a262d827e9aad979a6f93f2308 100644 --- a/core/lib/permissions.py +++ b/core/lib/permissions.py @@ -4,7 +4,7 @@ from rest_framework.exceptions import APIException from core.models import Company from core.models import Student from core.models import Supervisor - +from core.models import Application def is_admin_or_student(user): return user.is_superuser or hasattr(user, "student") @@ -122,3 +122,19 @@ class IsAdminOrSupervisorOrCompanyOrSelf(permissions.IsAuthenticated): ) return hasattr(user, "student") and user.student == student return False + + +class IsAdminOrVacancyOwner(permissions.BasePermission): + def has_permission(self, request, view): + return is_admin_or_company(request.user) + + def has_object_permission(self, request, view, obj): + user = request.user + if user.is_superuser: + return True + if isinstance(obj, Application): + return user.company == obj.vacancy.company + else: + raise APIException( + "Checking owner permission on non-application object" + ) diff --git a/core/migrations/0007_auto_20170425_1550.py b/core/migrations/0007_auto_20170425_1550.py new file mode 100644 index 0000000000000000000000000000000000000000..ce925a3660d2ec0cbfe24dfe1d646afeef47ea00 --- /dev/null +++ b/core/migrations/0007_auto_20170425_1550.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2017-04-25 15:50 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0006_auto_20170328_1950'), + ] + + operations = [ + migrations.RemoveField( + model_name='application', + name='allow_transcript', + ), + migrations.AddField( + model_name='application', + name='status', + field=models.IntegerField(default=0), + ), + ] diff --git a/core/models/vacancies.py b/core/models/vacancies.py index f165a2b562545ef8feddf717ffda2f1db3063f7f..96335453c6a69cfe396983af798406a5ef2fe8c5 100644 --- a/core/models/vacancies.py +++ b/core/models/vacancies.py @@ -15,10 +15,16 @@ class Vacancy(models.Model): class Application(models.Model): + NEW = 0 + READ = 1 + BOOKMARKED = 2 + REJECTED = 3 + ACCEPTED = 4 + cover_letter = models.TextField(null=True, blank=True) - allow_transcript = models.BooleanField(null=False, default=True) student = models.ForeignKey(Student, on_delete=models.CASCADE) vacancy = models.ForeignKey(Vacancy, on_delete=models.CASCADE) + status = models.IntegerField(default=NEW) class Meta: unique_together = (("student", "vacancy"),) diff --git a/core/serializers/vacancies.py b/core/serializers/vacancies.py index 3926965db88f6265a4b99def6c14d3da21c3026d..77a1e84c871ebebb6d6fa15e457df9289df049c0 100644 --- a/core/serializers/vacancies.py +++ b/core/serializers/vacancies.py @@ -24,5 +24,8 @@ class ApplicationSerializer(serializers.ModelSerializer): fields = '__all__' +class ApplicationStatusSerializer(serializers.ModelSerializer): - + class Meta: + model = Application + fields = ['status'] diff --git a/core/views/vacancies.py b/core/views/vacancies.py index ff761057fe3bf58ac38a1d22db1663739f6c5ee7..bd3d2ec9e4f9125b5115c5eae6a4362d1f971356 100644 --- a/core/views/vacancies.py +++ b/core/views/vacancies.py @@ -1,13 +1,14 @@ -from rest_framework import viewsets +from rest_framework import viewsets, status from rest_framework.exceptions import ValidationError from rest_framework.generics import get_object_or_404 from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response +from rest_framework.decorators import detail_route -from core.lib.permissions import IsAdminOrStudent, IsAdminOrCompany +from core.lib.permissions import IsAdminOrStudent, IsAdminOrCompany, IsAdminOrVacancyOwner from core.models import Student, Company from core.models.vacancies import Vacancy, Application -from core.serializers.vacancies import VacancySerializer, ApplicationSerializer +from core.serializers.vacancies import VacancySerializer, ApplicationSerializer, ApplicationStatusSerializer class VacancyViewSet(viewsets.ModelViewSet): @@ -28,6 +29,13 @@ class VacancyViewSet(viewsets.ModelViewSet): return Response(VacancySerializer(vacancies, many=True, context={'request': request}).data) + @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) + class ApplicationViewSet(viewsets.GenericViewSet): serializer_class = ApplicationSerializer @@ -76,6 +84,7 @@ class ApplicationViewSet(viewsets.GenericViewSet): class CompanyApplicationViewSet(viewsets.GenericViewSet): queryset = Application.objects.all() + permission_classes = [IsAdminOrCompany] def list(self, request, company_id): """ @@ -88,8 +97,23 @@ class CompanyApplicationViewSet(viewsets.GenericViewSet): return Response(ApplicationSerializer(applications, many=True, context={'request': request}).data) +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) + + class CompanyVacanciesViewSet(viewsets.GenericViewSet): - queryset = Vacancy. objects.all() + queryset = Vacancy.objects.all() def list(self, request, company_id): """ diff --git a/kape/urls.py b/kape/urls.py index 4b40a29e2a47484b68b61d399225aba958649153..d45f6e677994b87e1ff8b81d469327e81d5a27ed 100755 --- a/kape/urls.py +++ b/kape/urls.py @@ -22,9 +22,15 @@ from rest_framework import routers from rest_framework_swagger.views import get_swagger_view from core import apps +<<<<<<< HEAD from core.views.accounts import StudentViewSet, CompanyViewSet, SupervisorViewSet, UserViewSet, LoginViewSet, \ CompanyRegisterViewSet, StudentProfileViewSet from core.views.vacancies import VacancyViewSet, BookmarkedVacancyByStudentViewSet, ApplicationViewSet, CompanyApplicationViewSet, CompanyVacanciesViewSet +======= +from core.views.accounts import StudentViewSet, CompanyViewSet, SupervisorViewSet, UserViewSet, LoginViewSet, CompanyRegisterViewSet +from core.views.vacancies import VacancyViewSet, BookmarkedVacancyByStudentViewSet, ApplicationViewSet, \ + CompanyApplicationViewSet, CompanyVacanciesViewSet, CompanyApplicationStatusViewSet +>>>>>>> ca12893633723b0b5543f4e23d9be11a968295a9 schema_view = get_swagger_view() router = routers.DefaultRouter() @@ -36,6 +42,7 @@ router.register(r'login', LoginViewSet) router.register(r'register', CompanyRegisterViewSet) router.register(r'vacancies', VacancyViewSet) router.register(r'profiles/students', StudentProfileViewSet) +router.register(r'applications', CompanyApplicationStatusViewSet) 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', ApplicationViewSet,