<commit_before># -*- coding: utf-8 -*-
from __future__ import unicode_literals
from datetime import date
from django.core.exceptions import PermissionDenied
from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django.utils import timezone
from rest_framework import status as statuses, serializers
from rest_framework.views import APIView
from rest_framework.generics import (
    ListCreateAPIView,
    ListAPIView,
    CreateAPIView,
    RetrieveUpdateAPIView,
    RetrieveAPIView,
    DestroyAPIView,
)
from rest_framework.response import Response
from rest_framework.filters import OrderingFilter

from django_filters.rest_framework import DjangoFilterBackend

from account.models import User
from agency.permissions import AgencyPermission
from common.consts import CFEI_TYPES, DIRECT_SELECTION_SOURCE
from common.pagination import SmallPagination
from common.permissions import HasUNPPPermission, has_unpp_permission
from common.mixins import PartnerIdsMixin
from notification.consts import NotificationType
from notification.helpers import (
    get_partner_users_for_application_queryset,
    send_notification_cfei_completed,
    send_agency_updated_application_notification,
    send_notification_application_created,
    send_notification,
    send_cfei_review_required_notification, user_received_notification_recently,
    send_partner_made_decision_notification)
from partner.permissions import PartnerPermission
from project.exports import ApplicationCompareSpreadsheetGenerator
from project.models import Assessment, Application, EOI, Pin, ApplicationFeedback
from project.serializers import (
    BaseProjectSerializer,
    DirectProjectSerializer,
    CreateProjectSerializer,
    PartnerProjectSerializer,
    CreateDirectProjectSerializer,
    ApplicationFullSerializer,
    ApplicationFullEOISerializer,
    AgencyUnsolicitedApplicationSerializer,
    CreateDirectApplicationNoCNSerializer,
    ApplicationsListSerializer,
    ReviewersApplicationSerializer,
    ReviewerAssessmentsSerializer,
    CreateUnsolicitedProjectSerializer,
    ApplicationPartnerOpenSerializer,
    ApplicationPartnerUnsolicitedDirectSerializer,
    ApplicationPartnerDirectSerializer,
    ApplicationFeedbackSerializer,
    ConvertUnsolicitedSerializer,
    ReviewSummarySerializer,
    EOIReviewersAssessmentsSerializer,
    AwardedPartnersSerializer,
    CompareSelectedSerializer,
    AgencyProjectSerializer,
)

from project.filters import (
    BaseProjectFilter,
    ApplicationsFilter,
    ApplicationsEOIFilter,
    ApplicationsUnsolicitedFilter,
)


class BaseProjectAPIView(ListCreateAPIView):
    """
    Base endpoint for Call of Expression of Interest.
    """
    permission_classes = (
        HasUNPPPermission(
            agency_permissions=[
                AgencyPermission.CFEI_VIEW_LIST,
            ],
            partner_permissions=[
                PartnerPermission.CFEI_VIEW
            ]
        ),
    )
    queryset = EOI.objects.select_related("agency").prefetch_related("specializations").distinct()
    serializer_class = BaseProjectSerializer
    pagination_class = SmallPagination
    filter_backends = (DjangoFilterBackend, OrderingFilter)
    filter_class = BaseProjectFilter
    ordering_fields = (
        'deadline_date', 'created', 'start_date', 'status', 'completed_date'
    )


class OpenProjectAPIView(BaseProjectAPIView):
    """
    Endpoint for getting OPEN Call of Expression of Interest.
    """

    def get_queryset(self):
        queryset = self.queryset.filter(display_type=CFEI_TYPES.open)

        if self.request.user.is_agency_user:
            return queryset

        return queryset.filter(deadline_date__gte=date.today(), is_completed=False)

    @has_unpp_permission(agency_permissions=[AgencyPermission.CFEI_DRAFT_CREATE])
    def post(self, request, *args, **kwargs):
        serializer = CreateProjectSerializer(data=request.data, context={'request': request})
        serializer.is_valid(raise_exception=True)
        instance = serializer.save()

        if instance.reviewers.exists():
            send_notification(NotificationType.SELECTED_AS_CFEI_REVIEWER, instance, instance.reviewers.all())

        return Response(serializer.data, status=statuses.HTTP_201_CREATED)


class EOIAPIView(RetrieveUpdateAPIView):
    permission_classes = (
        HasUNPPPermission(),
    )
    queryset = EOI.objects.all()

    def get_serializer_class(self, *args, **kwargs):
        return AgencyProjectSerializer if self.request.user.is_agency_user else PartnerProjectSerializer

    def perform_update(self, serializer):
        eoi = self.get_object()
        currently_invited_partners = list(eoi.invited_partners.all().values_list('id', flat=True))
        current_deadline = eoi.deadline_date
        current_reviewers = list(eoi.reviewers.all().values_list('id', flat=True))

        instance = serializer.save()

        # New partners added
        for partner in instance.invited_partners.exclude(id__in=currently_invited_partners):
            context = {
                'eoi_url': eoi.get_absolute_url()
            }
            send_notification(
                NotificationType.CFEI_INVITE, eoi, partner.get_users(), check_sent_for_source=False, context=context
            )

        # Deadline Changed
        if current_deadline != instance.deadline_date:
            users = get_partner_users_for_application_queryset(instance.applications.all())
            context = {
                'initial_date': current_deadline,
                'revised_date': instance.deadline_date,
                'eoi_url': eoi.get_absolute_url()
            }
            send_notification(NotificationType.CFEI_DEADLINE_UPDATE, eoi, users, context=context)

        # New Reviewers Added
        new_reviewer_ids = []
        for reviewer in instance.reviewers.all():
            if reviewer.id not in current_reviewers:
                new_reviewer_ids.append(reviewer.id)

            if new_reviewer_ids:
                send_notification(
                    NotificationType.SELECTED_AS_CFEI_REVIEWER, eoi, User.objects.filter(id__in=new_reviewer_ids)
                )

        # Completed
        if instance.is_completed:
            send_notification_cfei_completed(instance)


class DirectProjectAPIView(BaseProjectAPIView):
    """
    Endpoint for getting DIRECT Call of Expression of Interest.
    """
    serializer_class = DirectProjectSerializer

    def get_queryset(self):
        return self.queryset.filter(display_type=CFEI_TYPES.direct).distinct()

    @has_unpp_permission(agency_permissions=[AgencyPermission.CFEI_DIRECT_CREATE_DRAFT_MANAGE_FOCAL_POINTS])
    def post(self, request, *args, **kwargs):
        data = request.data or {}
        try:
            data['eoi']['created_by'] = request.user.id
            data['eoi']['selected_source'] = DIRECT_SELECTION_SOURCE.un
        except Exception:
            pass

        serializer = CreateDirectProjectSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=statuses.HTTP_201_CREATED)


class PinProjectAPIView(BaseProjectAPIView):
    """
    Endpoint for getting PINNED Call of Expression of Interest for User Partner.
    """

    permission_classes = (
        HasUNPPPermission(
            partner_permissions=[
                PartnerPermission.CFEI_VIEW
            ]
        ),
    )

    ERROR_MSG_WRONG_EOI_PKS = "At least one of given CFEIs could not be found."
    ERROR_MSG_WRONG_PARAMS = "Couldn't properly identify input parameters like 'eoi_ids' and 'pin'."

    def get_queryset(self):
        return self.queryset.filter(
            pins__partner_id=self.request.active_partner.id, deadline_date__gte=date.today()
        ).distinct()

    @has_unpp_permission(partner_permissions=[PartnerPermission.CFEI_PINNING])
    def patch(self, request, *args, **kwargs):
        eoi_ids = request.data.get("eoi_ids", [])
        pin = request.data.get("pin")
        if EOI.objects.filter(id__in=eoi_ids).count() != len(eoi_ids):
            raise serializers.ValidationError({
                'non_field_errors': self.ERROR_MSG_WRONG_EOI_PKS
            })

        partner_id = self.request.active_partner.id
        if pin and eoi_ids:
            Pin.objects.bulk_create([
                Pin(eoi_id=eoi_id, partner_id=partner_id, pinned_by=request.user) for eoi_id in eoi_ids
            ])

            return Response({"eoi_ids": eoi_ids}, status=statuses.HTTP_201_CREATED)
        elif pin is False and eoi_ids:
            Pin.objects.filter(eoi_id__in=eoi_ids, partner_id=partner_id, pinned_by=request.user).delete()

            return Response(status=statuses.HTTP_204_NO_CONTENT)
        else:
            raise serializers.ValidationError({
                'non_field_errors': self.ERROR_MSG_WRONG_PARAMS
            })


class AgencyApplicationListAPIView(ListAPIView):
    """
    Endpoint to allow agencies to get applications
    """
    permission_classes = (
        HasUNPPPermission(
            agency_permissions=[
                AgencyPermission.CFEI_VIEW_APPLICATIONS,
            ]
        ),
    )

    filter_backends = (DjangoFilterBackend, OrderingFilter)
    filter_class = ApplicationsFilter
    serializer_class = ApplicationFullEOISerializer
    pagination_class = SmallPagination

    def get_queryset(self):
        return Application.objects.filter(
            Q(eoi__created_by=self.request.user) | Q(eoi__focal_points=self.request.user)
        )


class PartnerEOIApplicationDestroyAPIView(DestroyAPIView):
    """
    Destroy Application (concept note) created by partner.
    """
    permission_classes = (
        HasUNPPPermission(
            partner_permissions=[
                PartnerPermission.CFEI_SUBMIT_CONCEPT_NOTE
            ]
        ),
    )

    def get_queryset(self):
        return Application.objects.filter(partner=self.request.active_partner)


class PartnerEOIApplicationCreateAPIView(CreateAPIView):
    """
    Create Application for open EOI by partner.
    """
    permission_classes = (
        HasUNPPPermission(
            partner_permissions=[
                PartnerPermission.CFEI_SUBMIT_CONCEPT_NOTE,
            ]
        ),
    )
    serializer_class = ApplicationFullSerializer

    def perform_create(self, serializer):
        if self.request.partner_member.partner.is_hq:
            raise serializers.ValidationError(
                "You don't have the ability to submit an application if "
                "you are currently toggled under the HQ profile."
            )
        if not self.request.active_partner.has_finished:
            raise serializers.ValidationError(
                "You don't have the ability to submit an application if Your profile is not completed."
            )

        instance = serializer.save(
            eoi=get_object_or_404(EOI, id=self.kwargs.get('pk')),
            submitter_id=self.request.user.id,
            partner_id=self.request.active_partner.id,
            agency=self.eoi.agency
        )
        send_notification_application_created(instance)


class PartnerEOIApplicationRetrieveAPIView(RetrieveAPIView):

    permission_classes = (
        HasUNPPPermission(
            partner_permissions=[
                PartnerPermission.CFEI_VIEW,
            ]
        ),
    )
    queryset = Application.objects.all()
    serializer_class = ApplicationFullSerializer

    def get_object(self):
        return get_object_or_404(self.get_queryset(), **{
            'partner_id': self.request.active_partner.id,
            'eoi_id': self.kwargs.get(self.lookup_field),
        })


class AgencyEOIApplicationCreateAPIView(PartnerEOIApplicationCreateAPIView):
    """
    Create Application for direct EOI by agency.
    """
    permission_classes = (
        HasUNPPPermission(
            agency_permissions=[
                AgencyPermission.CFEI_DIRECT_INDICATE_CSO,
            ]
        ),
    )
    queryset = Application.objects.all()
    serializer_class = CreateDirectApplicationNoCNSerializer

    def perform_create(self, serializer):
        eoi = get_object_or_404(EOI, id=self.kwargs['pk'])
        instance = serializer.save(
            did_win=True, eoi=eoi, submitter_id=self.request.user.id, agency=eoi.agency
        )

        send_notification_application_created(instance)


class AgencyEOIApplicationDestroyAPIView(DestroyAPIView):

    permission_classes = (
        HasUNPPPermission(
            agency_permissions=[
                AgencyPermission.CFEI_DIRECT_INDICATE_CSO,
            ],
        ),
    )
    queryset = Application.objects.all()
    serializer_class = CreateDirectApplicationNoCNSerializer
    lookup_url_kwarg = 'eoi_id'

    def get_queryset(self):
        return super(AgencyEOIApplicationDestroyAPIView, self).get_queryset().filter(
            eoi__agency=self.request.user.agency
        )


class ApplicationAPIView(RetrieveUpdateAPIView):
    permission_classes = (
        HasUNPPPermission(
            partner_permissions=[
                PartnerPermission.CFEI_VIEW,
            ],
            agency_permissions=[
                AgencyPermission.CFEI_VIEW_APPLICATIONS,
            ]
        ),
    )
    queryset = Application.objects.select_related(
        "partner", "eoi", "cn"
    ).prefetch_related("eoi__reviewers").all()
    serializer_class = ApplicationFullSerializer

    def get_queryset(self):
        queryset = super(ApplicationAPIView, self).get_queryset()
        if self.request.agency_member:
            return queryset.filter(eoi__agency=self.request.user.agency)
        elif self.request.active_partner:
            return queryset.filter(partner=self.request.active_partner)

        return queryset.none()

    @has_unpp_permission(
        partner_permissions=[
            PartnerPermission.CFEI_ANSWER_SELECTION,
        ],
        agency_permissions=[
            AgencyPermission.CFEI_PRESELECT_APPLICATIONS,
        ]
    )
    def perform_update(self, serializer):
        data = serializer.validated_data
        instance = serializer.save()
        if data.get('did_accept', False) or data.get('did_decline', False):
            instance.decision_date = timezone.now().date()
            instance.save()

        if self.request.agency_member:
            send_agency_updated_application_notification(instance)
        elif self.request.active_partner:
            send_partner_made_decision_notification(instance)


class EOIApplicationsListAPIView(ListAPIView):
    permission_classes = (
        HasUNPPPermission(
            # TODO: Permissions
        ),
    )
    queryset = Application.objects.select_related(
        "partner", "eoi", "cn"
    ).prefetch_related("assessments", "eoi__reviewers").all()
    serializer_class = ApplicationsListSerializer
    pagination_class = SmallPagination
    filter_backends = (DjangoFilterBackend, OrderingFilter)
    filter_class = ApplicationsEOIFilter
    ordering_fields = ('status', )
    lookup_field = lookup_url_kwarg = 'pk'

    def get_queryset(self, *args, **kwargs):
        eoi_id = self.kwargs.get(self.lookup_field)
        return self.queryset.filter(eoi_id=eoi_id)


class ReviewersStatusAPIView(ListAPIView):
    permission_classes = (
        HasUNPPPermission(
            agency_permissions=[<commit_msg>Added permission check to application list view<commit_after># -*- coding: utf-8 -*-
from __future__ import unicode_literals
from datetime import date
from django.core.exceptions import PermissionDenied
from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django.utils import timezone
from rest_framework import status as statuses, serializers
from rest_framework.views import APIView
from rest_framework.generics import (
    ListCreateAPIView,
    ListAPIView,
    CreateAPIView,
    RetrieveUpdateAPIView,
    RetrieveAPIView,
    DestroyAPIView,
)
from rest_framework.response import Response
from rest_framework.filters import OrderingFilter

from django_filters.rest_framework import DjangoFilterBackend

from account.models import User
from agency.permissions import AgencyPermission
from common.consts import CFEI_TYPES, DIRECT_SELECTION_SOURCE
from common.pagination import SmallPagination
from common.permissions import HasUNPPPermission, has_unpp_permission
from common.mixins import PartnerIdsMixin
from notification.consts import NotificationType
from notification.helpers import (
    get_partner_users_for_application_queryset,
    send_notification_cfei_completed,
    send_agency_updated_application_notification,
    send_notification_application_created,
    send_notification,
    send_cfei_review_required_notification, user_received_notification_recently,
    send_partner_made_decision_notification)
from partner.permissions import PartnerPermission
from project.exports import ApplicationCompareSpreadsheetGenerator
from project.models import Assessment, Application, EOI, Pin, ApplicationFeedback
from project.serializers import (
    BaseProjectSerializer,
    DirectProjectSerializer,
    CreateProjectSerializer,
    PartnerProjectSerializer,
    CreateDirectProjectSerializer,
    ApplicationFullSerializer,
    ApplicationFullEOISerializer,
    AgencyUnsolicitedApplicationSerializer,
    CreateDirectApplicationNoCNSerializer,
    ApplicationsListSerializer,
    ReviewersApplicationSerializer,
    ReviewerAssessmentsSerializer,
    CreateUnsolicitedProjectSerializer,
    ApplicationPartnerOpenSerializer,
    ApplicationPartnerUnsolicitedDirectSerializer,
    ApplicationPartnerDirectSerializer,
    ApplicationFeedbackSerializer,
    ConvertUnsolicitedSerializer,
    ReviewSummarySerializer,
    EOIReviewersAssessmentsSerializer,
    AwardedPartnersSerializer,
    CompareSelectedSerializer,
    AgencyProjectSerializer,
)

from project.filters import (
    BaseProjectFilter,
    ApplicationsFilter,
    ApplicationsEOIFilter,
    ApplicationsUnsolicitedFilter,
)


class BaseProjectAPIView(ListCreateAPIView):
    """
    Base endpoint for Call of Expression of Interest.
    """
    permission_classes = (
        HasUNPPPermission(
            agency_permissions=[
                AgencyPermission.CFEI_VIEW_LIST,
            ],
            partner_permissions=[
                PartnerPermission.CFEI_VIEW
            ]
        ),
    )
    queryset = EOI.objects.select_related("agency").prefetch_related("specializations").distinct()
    serializer_class = BaseProjectSerializer
    pagination_class = SmallPagination
    filter_backends = (DjangoFilterBackend, OrderingFilter)
    filter_class = BaseProjectFilter
    ordering_fields = (
        'deadline_date', 'created', 'start_date', 'status', 'completed_date'
    )


class OpenProjectAPIView(BaseProjectAPIView):
    """
    Endpoint for getting OPEN Call of Expression of Interest.
    """

    def get_queryset(self):
        queryset = self.queryset.filter(display_type=CFEI_TYPES.open)

        if self.request.user.is_agency_user:
            return queryset

        return queryset.filter(deadline_date__gte=date.today(), is_completed=False)

    @has_unpp_permission(agency_permissions=[AgencyPermission.CFEI_DRAFT_CREATE])
    def post(self, request, *args, **kwargs):
        serializer = CreateProjectSerializer(data=request.data, context={'request': request})
        serializer.is_valid(raise_exception=True)
        instance = serializer.save()

        if instance.reviewers.exists():
            send_notification(NotificationType.SELECTED_AS_CFEI_REVIEWER, instance, instance.reviewers.all())

        return Response(serializer.data, status=statuses.HTTP_201_CREATED)


class EOIAPIView(RetrieveUpdateAPIView):
    permission_classes = (
        HasUNPPPermission(),
    )
    queryset = EOI.objects.all()

    def get_serializer_class(self, *args, **kwargs):
        return AgencyProjectSerializer if self.request.user.is_agency_user else PartnerProjectSerializer

    def perform_update(self, serializer):
        eoi = self.get_object()
        currently_invited_partners = list(eoi.invited_partners.all().values_list('id', flat=True))
        current_deadline = eoi.deadline_date
        current_reviewers = list(eoi.reviewers.all().values_list('id', flat=True))

        instance = serializer.save()

        # New partners added
        for partner in instance.invited_partners.exclude(id__in=currently_invited_partners):
            context = {
                'eoi_url': eoi.get_absolute_url()
            }
            send_notification(
                NotificationType.CFEI_INVITE, eoi, partner.get_users(), check_sent_for_source=False, context=context
            )

        # Deadline Changed
        if current_deadline != instance.deadline_date:
            users = get_partner_users_for_application_queryset(instance.applications.all())
            context = {
                'initial_date': current_deadline,
                'revised_date': instance.deadline_date,
                'eoi_url': eoi.get_absolute_url()
            }
            send_notification(NotificationType.CFEI_DEADLINE_UPDATE, eoi, users, context=context)

        # New Reviewers Added
        new_reviewer_ids = []
        for reviewer in instance.reviewers.all():
            if reviewer.id not in current_reviewers:
                new_reviewer_ids.append(reviewer.id)

            if new_reviewer_ids:
                send_notification(
                    NotificationType.SELECTED_AS_CFEI_REVIEWER, eoi, User.objects.filter(id__in=new_reviewer_ids)
                )

        # Completed
        if instance.is_completed:
            send_notification_cfei_completed(instance)


class DirectProjectAPIView(BaseProjectAPIView):
    """
    Endpoint for getting DIRECT Call of Expression of Interest.
    """
    serializer_class = DirectProjectSerializer

    def get_queryset(self):
        return self.queryset.filter(display_type=CFEI_TYPES.direct).distinct()

    @has_unpp_permission(agency_permissions=[AgencyPermission.CFEI_DIRECT_CREATE_DRAFT_MANAGE_FOCAL_POINTS])
    def post(self, request, *args, **kwargs):
        data = request.data or {}
        try:
            data['eoi']['created_by'] = request.user.id
            data['eoi']['selected_source'] = DIRECT_SELECTION_SOURCE.un
        except Exception:
            pass

        serializer = CreateDirectProjectSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=statuses.HTTP_201_CREATED)


class PinProjectAPIView(BaseProjectAPIView):
    """
    Endpoint for getting PINNED Call of Expression of Interest for User Partner.
    """

    permission_classes = (
        HasUNPPPermission(
            partner_permissions=[
                PartnerPermission.CFEI_VIEW
            ]
        ),
    )

    ERROR_MSG_WRONG_EOI_PKS = "At least one of given CFEIs could not be found."
    ERROR_MSG_WRONG_PARAMS = "Couldn't properly identify input parameters like 'eoi_ids' and 'pin'."

    def get_queryset(self):
        return self.queryset.filter(
            pins__partner_id=self.request.active_partner.id, deadline_date__gte=date.today()
        ).distinct()

    @has_unpp_permission(partner_permissions=[PartnerPermission.CFEI_PINNING])
    def patch(self, request, *args, **kwargs):
        eoi_ids = request.data.get("eoi_ids", [])
        pin = request.data.get("pin")
        if EOI.objects.filter(id__in=eoi_ids).count() != len(eoi_ids):
            raise serializers.ValidationError({
                'non_field_errors': self.ERROR_MSG_WRONG_EOI_PKS
            })

        partner_id = self.request.active_partner.id
        if pin and eoi_ids:
            Pin.objects.bulk_create([
                Pin(eoi_id=eoi_id, partner_id=partner_id, pinned_by=request.user) for eoi_id in eoi_ids
            ])

            return Response({"eoi_ids": eoi_ids}, status=statuses.HTTP_201_CREATED)
        elif pin is False and eoi_ids:
            Pin.objects.filter(eoi_id__in=eoi_ids, partner_id=partner_id, pinned_by=request.user).delete()

            return Response(status=statuses.HTTP_204_NO_CONTENT)
        else:
            raise serializers.ValidationError({
                'non_field_errors': self.ERROR_MSG_WRONG_PARAMS
            })


class AgencyApplicationListAPIView(ListAPIView):
    """
    Endpoint to allow agencies to get applications
    """
    permission_classes = (
        HasUNPPPermission(
            agency_permissions=[
                AgencyPermission.CFEI_VIEW_APPLICATIONS,
            ]
        ),
    )

    filter_backends = (DjangoFilterBackend, OrderingFilter)
    filter_class = ApplicationsFilter
    serializer_class = ApplicationFullEOISerializer
    pagination_class = SmallPagination

    def get_queryset(self):
        return Application.objects.filter(
            Q(eoi__created_by=self.request.user) | Q(eoi__focal_points=self.request.user)
        )


class PartnerEOIApplicationDestroyAPIView(DestroyAPIView):
    """
    Destroy Application (concept note) created by partner.
    """
    permission_classes = (
        HasUNPPPermission(
            partner_permissions=[
                PartnerPermission.CFEI_SUBMIT_CONCEPT_NOTE
            ]
        ),
    )

    def get_queryset(self):
        return Application.objects.filter(partner=self.request.active_partner)


class PartnerEOIApplicationCreateAPIView(CreateAPIView):
    """
    Create Application for open EOI by partner.
    """
    permission_classes = (
        HasUNPPPermission(
            partner_permissions=[
                PartnerPermission.CFEI_SUBMIT_CONCEPT_NOTE,
            ]
        ),
    )
    serializer_class = ApplicationFullSerializer

    def perform_create(self, serializer):
        if self.request.partner_member.partner.is_hq:
            raise serializers.ValidationError(
                "You don't have the ability to submit an application if "
                "you are currently toggled under the HQ profile."
            )
        if not self.request.active_partner.has_finished:
            raise serializers.ValidationError(
                "You don't have the ability to submit an application if Your profile is not completed."
            )

        instance = serializer.save(
            eoi=get_object_or_404(EOI, id=self.kwargs.get('pk')),
            submitter_id=self.request.user.id,
            partner_id=self.request.active_partner.id,
            agency=self.eoi.agency
        )
        send_notification_application_created(instance)


class PartnerEOIApplicationRetrieveAPIView(RetrieveAPIView):

    permission_classes = (
        HasUNPPPermission(
            partner_permissions=[
                PartnerPermission.CFEI_VIEW,
            ]
        ),
    )
    queryset = Application.objects.all()
    serializer_class = ApplicationFullSerializer

    def get_object(self):
        return get_object_or_404(self.get_queryset(), **{
            'partner_id': self.request.active_partner.id,
            'eoi_id': self.kwargs.get(self.lookup_field),
        })


class AgencyEOIApplicationCreateAPIView(PartnerEOIApplicationCreateAPIView):
    """
    Create Application for direct EOI by agency.
    """
    permission_classes = (
        HasUNPPPermission(
            agency_permissions=[
                AgencyPermission.CFEI_DIRECT_INDICATE_CSO,
            ]
        ),
    )
    queryset = Application.objects.all()
    serializer_class = CreateDirectApplicationNoCNSerializer

    def perform_create(self, serializer):
        eoi = get_object_or_404(EOI, id=self.kwargs['pk'])
        instance = serializer.save(
            did_win=True, eoi=eoi, submitter_id=self.request.user.id, agency=eoi.agency
        )

        send_notification_application_created(instance)


class AgencyEOIApplicationDestroyAPIView(DestroyAPIView):

    permission_classes = (
        HasUNPPPermission(
            agency_permissions=[
                AgencyPermission.CFEI_DIRECT_INDICATE_CSO,
            ],
        ),
    )
    queryset = Application.objects.all()
    serializer_class = CreateDirectApplicationNoCNSerializer
    lookup_url_kwarg = 'eoi_id'

    def get_queryset(self):
        return super(AgencyEOIApplicationDestroyAPIView, self).get_queryset().filter(
            eoi__agency=self.request.user.agency
        )


class ApplicationAPIView(RetrieveUpdateAPIView):
    permission_classes = (
        HasUNPPPermission(
            partner_permissions=[
                PartnerPermission.CFEI_VIEW,
            ],
            agency_permissions=[
                AgencyPermission.CFEI_VIEW_APPLICATIONS,
            ]
        ),
    )
    queryset = Application.objects.select_related(
        "partner", "eoi", "cn"
    ).prefetch_related("eoi__reviewers").all()
    serializer_class = ApplicationFullSerializer

    def get_queryset(self):
        queryset = super(ApplicationAPIView, self).get_queryset()
        if self.request.agency_member:
            return queryset.filter(eoi__agency=self.request.user.agency)
        elif self.request.active_partner:
            return queryset.filter(partner=self.request.active_partner)

        return queryset.none()

    @has_unpp_permission(
        partner_permissions=[
            PartnerPermission.CFEI_ANSWER_SELECTION,
        ],
        agency_permissions=[
            AgencyPermission.CFEI_PRESELECT_APPLICATIONS,
        ]
    )
    def perform_update(self, serializer):
        data = serializer.validated_data
        instance = serializer.save()
        if data.get('did_accept', False) or data.get('did_decline', False):
            instance.decision_date = timezone.now().date()
            instance.save()

        if self.request.agency_member:
            send_agency_updated_application_notification(instance)
        elif self.request.active_partner:
            send_partner_made_decision_notification(instance)


class EOIApplicationsListAPIView(ListAPIView):
    permission_classes = (
        HasUNPPPermission(
            agency_permissions=[
                AgencyPermission.CFEI_VIEW_APPLICATIONS,
            ]
        ),
    )
    queryset = Application.objects.select_related(
        "partner", "eoi", "cn"
    ).prefetch_related("assessments", "eoi__reviewers").all()
    serializer_class = ApplicationsListSerializer
    pagination_class = SmallPagination
    filter_backends = (
        DjangoFilterBackend,
        OrderingFilter,
    )
    filter_class = ApplicationsEOIFilter
    ordering_fields = ('status', )
    lookup_field = lookup_url_kwarg = 'pk'

    def get_queryset(self, *args, **kwargs):
        return self.queryset.filter(eoi_id=self.kwargs.get(self.lookup_field))


class ReviewersStatusAPIView(ListAPIView):
    permission_classes = (
        HasUNPPPermission(
            agency_permissions=[
{'fraction_non_alphanumeric': 0.07594405142617179, 'fraction_numerical': 0.001615143586264819, 'mean_word_length': 3.008545901851612, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '807090', 'n_tokens_mistral': 8860, 'n_tokens_neox': 8632, 'n_words': 1469}