Ejemplo n.º 1
0
 def test_has_permissions(self, required_permissions, user_permissions, expected_result):
     """Tests has_permission() for various cases."""
     user = Mock(has_perm=lambda perm: perm in user_permissions)
     request = Mock(user=user)
     view = Mock()
     has_permissions = HasPermissions(*required_permissions)
     assert has_permissions.has_permission(request, view) == expected_result
Ejemplo n.º 2
0
class DNBCompanyChangeRequestView(APIView):
    """
    View for requesting change/s to DNB companies.
    """

    permission_classes = (HasPermissions(
        f'company.{CompanyPermission.view_company}',
        f'company.{CompanyPermission.change_company}',
    ), )

    @method_decorator(enforce_request_content_type('application/json'))
    def post(self, request):
        """
        A thin wrapper around the dnb-service change request API.
        """
        change_request_serializer = DNBCompanyChangeRequestSerializer(
            data=request.data)
        change_request_serializer.is_valid(raise_exception=True)

        try:
            response = request_changes(
                **change_request_serializer.validated_data)

        except (
                DNBServiceConnectionError,
                DNBServiceTimeoutError,
                DNBServiceError,
        ) as exc:
            raise APIUpstreamException(str(exc))

        return Response(response)

    def get(self, request):
        """
        A thin wrapper around the dnb-service change request API.
        """
        duns_number = request.query_params.get('duns_number', None)
        status = request.query_params.get('status', None)

        change_request_serializer = DNBGetCompanyChangeRequestSerializer(data={
            'duns_number':
            duns_number,
            'status':
            status
        }, )

        change_request_serializer.is_valid(raise_exception=True)

        try:
            response = get_change_request(
                **change_request_serializer.validated_data)

        except (
                DNBServiceConnectionError,
                DNBServiceTimeoutError,
                DNBServiceError,
        ) as exc:
            raise APIUpstreamException(str(exc))

        return Response(response)
Ejemplo n.º 3
0
class DNBCompanyCreateView(APIView):
    """
    View for creating datahub company from DNB data.
    """

    required_scopes = (Scope.internal_front_end, )
    permission_classes = (
        IsAuthenticatedOrTokenHasScope,
        HasPermissions(
            f'company.{CompanyPermission.view_company}',
            f'company.{CompanyPermission.add_company}',
        ),
    )

    def post(self, request):
        """
        Given a duns_number, get the data for the company from dnb-service
        and create a record in DataHub.
        """
        duns_serializer = DUNSNumberSerializer(data=request.data)
        duns_serializer.is_valid(raise_exception=True)
        duns_number = duns_serializer.validated_data['duns_number']

        try:
            dnb_company = get_company(duns_number)

        except (DNBServiceConnectionError, DNBServiceError,
                DNBServiceInvalidResponse) as exc:
            raise APIUpstreamException(str(exc))

        except DNBServiceInvalidRequest as exc:
            raise APIBadRequestException(str(exc))

        company_serializer = DNBCompanySerializer(data=dnb_company, )

        try:
            company_serializer.is_valid(raise_exception=True)
        except serializers.ValidationError:
            message = 'Company data from DNB failed DH serializer validation'
            extra_data = {
                'formatted_dnb_company_data': dnb_company,
                'dh_company_serializer_errors': company_serializer.errors,
            }
            logger.error(message, extra=extra_data)
            raise

        datahub_company = company_serializer.save(
            created_by=request.user,
            modified_by=request.user,
            dnb_modified_on=now(),
        )

        statsd.incr(f'dnb.create.company')
        return Response(
            company_serializer.to_representation(datahub_company), )
Ejemplo n.º 4
0
class DNBCompanyLinkView(APIView):
    """
    View for linking a company to a DNB record.
    """

    required_scopes = (Scope.internal_front_end, )
    permission_classes = (
        IsAuthenticatedOrTokenHasScope,
        HasPermissions(
            f'company.{CompanyPermission.view_company}',
            f'company.{CompanyPermission.change_company}',
        ),
    )

    @method_decorator(enforce_request_content_type('application/json'))
    def post(self, request):
        """
        Given a Data Hub Company ID and a duns-number, link the Data Hub
        Company to the D&B record.
        """
        link_serializer = DNBCompanyLinkSerializer(data=request.data)

        link_serializer.is_valid(raise_exception=True)

        # This bit: validated_data['company_id'].id is weird but the alternative
        # is to rename the field to `company_id` which would (1) still be weird
        # and (2) leak the weirdness to the API
        company_id = link_serializer.validated_data['company_id'].id
        duns_number = link_serializer.validated_data['duns_number']

        try:
            company = link_company_with_dnb(company_id, duns_number,
                                            request.user)

        except (
                DNBServiceConnectionError,
                DNBServiceInvalidResponse,
                DNBServiceError,
        ) as exc:
            raise APIUpstreamException(str(exc))

        except (
                DNBServiceInvalidRequest,
                CompanyAlreadyDNBLinkedException,
        ) as exc:
            raise APIBadRequestException(str(exc))

        return Response(CompanySerializer().to_representation(company), )
Ejemplo n.º 5
0
class DNBCompanyCreateInvestigationView(APIView):
    """
    View for creating a company for DNB to investigate.

    This view is not inheriting from CoreViewSet because
    `format_dnb_company_investigation` mutates `request.data`
    which when shoehorned into CoreViewSet does not result in
    less or more readable code.
    """

    required_scopes = (Scope.internal_front_end, )
    permission_classes = (
        IsAuthenticatedOrTokenHasScope,
        HasPermissions(
            f'company.{CompanyPermission.view_company}',
            f'company.{CompanyPermission.add_company}',
        ),
    )

    def post(self, request):
        """
        Given a minimal set of fields that may be necessary for DNB investigation,
        create a Company record in DataHub.
        """
        formatted_company_data = format_dnb_company_investigation(request.data)
        company_serializer = DNBCompanyInvestigationSerializer(
            data=formatted_company_data)

        try:
            company_serializer.is_valid(raise_exception=True)
        except serializers.ValidationError:
            message = 'Company investigation payload failed serializer validation'
            extra_data = {
                'formatted_dnb_company_data': formatted_company_data,
                'dh_company_serializer_errors': company_serializer.errors,
            }
            logger.error(message, extra=extra_data)
            raise

        datahub_company = company_serializer.save(
            created_by=request.user,
            modified_by=request.user,
            pending_dnb_investigation=True,
        )

        statsd.incr(f'dnb.create.investigation')
        return Response(
            company_serializer.to_representation(datahub_company), )
Ejemplo n.º 6
0
class CompanyTimelineViewSet(CoreViewSet):
    """Company timeline views."""

    required_scopes = (Scope.internal_front_end,)
    permission_classes = (
        IsAuthenticatedOrTokenHasScope,
        HasPermissions(
            f'company.{CompanyPermission.view_company}',
            f'company.{CompanyPermission.view_company_timeline}',
        ),
    )
    queryset = Company.objects.all()
    serializer_class = TimelineEventSerializer

    def list(self, request, *args, **kwargs):
        """Lists timeline events (paginated)."""
        company = self.get_object()
        events = _get_events_for_company(company)
        page = self.paginator.paginate_queryset(events, self.request)
        serializer = self.get_serializer(page, many=True)
        return self.get_paginated_response(serializer.data)
Ejemplo n.º 7
0
class DNBCompanyInvestigationView(APIView):
    """
    View for creating a new investigation to get D&B to investigate and create a company record.
    """

    permission_classes = (HasPermissions(
        f'company.{CompanyPermission.view_company}',
        f'company.{CompanyPermission.change_company}',
    ), )

    @method_decorator(enforce_request_content_type('application/json'))
    def post(self, request):
        """
        A wrapper around the investigation API endpoint for dnb-service.
        """
        investigation_serializer = DNBCompanyInvestigationSerializer(
            data=request.data)
        investigation_serializer.is_valid(raise_exception=True)

        data = {'company_details': investigation_serializer.validated_data}
        company = data['company_details'].pop('company')

        try:
            response = create_investigation(data)

        except (
                DNBServiceConnectionError,
                DNBServiceTimeoutError,
                DNBServiceError,
        ) as exc:
            raise APIUpstreamException(str(exc))

        company.dnb_investigation_id = response['id']
        company.pending_dnb_investigation = True
        company.save()

        return Response(response)
Ejemplo n.º 8
0
class DNBCompanyChangeRequestView(APIView):
    """
    View for requesting change/s to DNB companies.
    """

    required_scopes = (Scope.internal_front_end, )

    permission_classes = (
        IsAuthenticatedOrTokenHasScope,
        HasPermissions(
            f'company.{CompanyPermission.view_company}',
            f'company.{CompanyPermission.change_company}',
        ),
    )

    @method_decorator(enforce_request_content_type('application/json'))
    def post(self, request):
        """
        A thin wrapper around the dnb-service change request API.
        """
        change_request_serializer = DNBCompanyChangeRequestSerializer(
            data=request.data)
        change_request_serializer.is_valid(raise_exception=True)

        try:
            response = request_changes(
                **change_request_serializer.validated_data)

        except (
                DNBServiceConnectionError,
                DNBServiceTimeoutError,
                DNBServiceError,
        ) as exc:
            raise APIUpstreamException(str(exc))

        return Response(response)
Ejemplo n.º 9
0
class CompanyViewSet(ArchivableViewSetMixin, CoreViewSet):
    """Company view set."""

    serializer_class = CompanySerializer
    unarchive_validators = (NotATransferredCompanyValidator(), )
    filter_backends = (DjangoFilterBackend, OrderingFilter)
    filterset_fields = ('global_headquarters_id',
                        'global_ultimate_duns_number')
    ordering_fields = ('name', 'created_on')
    queryset = Company.objects.select_related(
        'address_country',
        'archived_by',
        'business_type',
        'employee_range',
        'export_experience_category',
        'global_headquarters__one_list_account_owner__dit_team__country',
        'global_headquarters__one_list_account_owner__dit_team__uk_region',
        'global_headquarters__one_list_account_owner__dit_team',
        'global_headquarters__one_list_account_owner',
        'global_headquarters__one_list_tier',
        'global_headquarters',
        'headquarter_type',
        'one_list_account_owner__dit_team__country',
        'one_list_account_owner__dit_team__uk_region',
        'one_list_account_owner__dit_team',
        'one_list_account_owner',
        'one_list_tier',
        'registered_address_country',
        'transferred_to',
        'turnover_range',
        'uk_region',
    ).prefetch_related(
        Prefetch('contacts', queryset=get_contact_queryset()),
        Prefetch('investor_investment_projects',
                 queryset=get_slim_investment_project_queryset()),
        'export_to_countries',
        'future_interest_countries',
        'sector__parent__parent',
        'sector__parent',
        'sector',
        Prefetch('export_countries', queryset=get_export_country_queryset()),
    )

    @action(
        methods=['post'],
        detail=True,
        permission_classes=[
            HasPermissions(
                f'company.{CompanyPermission.change_company}',
                f'company.{CompanyPermission.change_regional_account_manager}',
            ),
        ],
        schema=StubSchema(),
    )
    def assign_regional_account_manager(self, request, *args, **kwargs):
        """
        Sets the company to be an international trade adviser-managed One List company, and
        assigns the requested user as the account manager.

        This means:

        - setting the One List tier to 'Tier D - Interaction Trade Adviser Accounts' (using the
        tier ID, not the name)
        - setting the requested user as the One List account manager (overwriting the
        existing value)

        The operation is not allowed if:

        - the company is a subsidiary of a One List company
        - the company is already a One List company on a different tier (i.e. not 'Tier D -
        Interaction Trade Adviser Accounts')
        """
        instance = self.get_object()
        serializer = AssignRegionalAccountManagerSerializer(instance=instance,
                                                            data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save(request.user)
        return Response(None, status=status.HTTP_204_NO_CONTENT)

    @action(
        methods=['post'],
        detail=True,
        permission_classes=[
            HasPermissions(
                f'company.{CompanyPermission.change_company}',
                f'company.{CompanyPermission.change_regional_account_manager}',
            ),
        ],
        schema=StubSchema(),
    )
    def self_assign_account_manager(self, request, *args, **kwargs):
        """
        Sets the company to be an international trade adviser-managed One List company, and
        assigns the authenticated user as the account manager.

        This means:

        - setting the One List tier to 'Tier D - Interaction Trade Adviser Accounts' (using the
        tier ID, not the name)
        - setting the authenticated user as the One List account manager (overwriting the
        existing value)

        The operation is not allowed if:

        - the company is a subsidiary of a One List company
        - the company is already a One List company on a different tier (i.e. not 'Tier D -
        Interaction Trade Adviser Accounts')
        """
        instance = self.get_object()
        serializer = SelfAssignAccountManagerSerializer(instance=instance,
                                                        data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save(request.user)
        return Response(None, status=status.HTTP_204_NO_CONTENT)

    @action(
        methods=['post'],
        detail=True,
        permission_classes=[
            HasPermissions(
                f'company.{CompanyPermission.change_company}',
                f'company.{CompanyPermission.change_regional_account_manager}',
            ),
        ],
        schema=StubSchema(),
    )
    def remove_account_manager(self, request, *args, **kwargs):
        """
        Remove the One List account manager and tier from a company if it is an international
        trade adviser-managed One List company.

        The operation is not allowed if the company is a One List company that isn't on
        'Tier D - Interaction Trade Adviser Accounts'.
        """
        instance = self.get_object()
        serializer = RemoveAccountManagerSerializer(instance=instance,
                                                    data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save(request.user)
        return Response(None, status=status.HTTP_204_NO_CONTENT)

    @action(
        methods=['post'],
        detail=True,
        permission_classes=[
            HasPermissions(
                f'company.{CompanyPermission.change_company}',
                f'company.{CompanyPermission.change_one_list_tier_and_global_account_manager}',
            ),
        ],
        schema=StubSchema(),
    )
    def assign_one_list_tier_and_global_account_manager(
            self, request, *args, **kwargs):
        """
        Assign One List tier and Global Account Manager.

        This endpoint enables a user with correct permissions to assign company one list tier
        and global account manager except when company is on
        'Tier D - Interaction Trade Adviser Accounts'.

        One List tier and Global Account Manager cannot be assigned to a subsidiary.
        """
        instance = self.get_object()
        serializer = AssignOneListTierAndGlobalAccountManagerSerializer(
            instance=instance,
            data=request.data,
        )
        serializer.is_valid(raise_exception=True)
        serializer.save(request.user)
        return Response(None, status=status.HTTP_204_NO_CONTENT)

    @action(
        methods=['post'],
        detail=True,
        permission_classes=[
            HasPermissions(
                f'company.{CompanyPermission.change_company}',
                f'company.{CompanyPermission.change_one_list_tier_and_global_account_manager}',
            ),
        ],
        schema=StubSchema(),
    )
    def remove_from_one_list(self, request, *args, **kwargs):
        """
        Remove company from One List.

        The operation is not allowed if the company is on
        'Tier D - Interaction Trade Adviser Accounts'.
        """
        instance = self.get_object()
        serializer = RemoveCompanyFromOneListSerializer(instance=instance,
                                                        data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save(request.user)
        return Response(None, status=status.HTTP_204_NO_CONTENT)

    @action(
        methods=['patch'],
        detail=True,
        permission_classes=[
            HasPermissions(
                f'company.{CompanyPermission.change_company}',
                f'company.{CompanyPermission.change_one_list_core_team_member}',
            ),
        ],
        schema=StubSchema(),
    )
    def update_one_list_core_team(self, request, *args, **kwargs):
        """Updates core team for the company."""
        instance = self.get_object()
        serializer = UpdateOneListCoreTeamMembersSerializer(
            instance=instance,
            data=request.data,
            partial=True,
        )
        serializer.is_valid(raise_exception=True)
        serializer.save(request.user)
        return Response(None, status=status.HTTP_204_NO_CONTENT)

    @action(
        methods=['patch'],
        permission_classes=[
            HasPermissions(
                f'company.{CompanyPermission.change_company}',
                'company.change_companyexportcountry',
            ),
        ],
        detail=True,
    )
    def update_export_detail(self, request, *args, **kwargs):
        """
        Update export related information for the company.
        """
        instance = self.get_object()
        serializer = UpdateExportDetailsSerializer(
            instance=instance,
            data=request.data,
            partial=True,
        )
        serializer.is_valid(raise_exception=True)
        serializer.save(request.user)
        return Response(None, status=status.HTTP_204_NO_CONTENT)
Ejemplo n.º 10
0
class ExportWinsForCompanyView(APIView):
    """
    View proxying export wins for a company that are retrieved from
    Export Wins system as is, based on the match id obtained from
    Company Matching Service.
    """

    queryset = Company.objects.prefetch_related('trasnferred_from', )
    permission_classes = (HasPermissions(
        f'company.{CompanyPermission.view_export_win}', ), )

    def _extract_match_ids(self, response):
        """
        Extracts match id out of company matching response.
        {
            'matches': [
                {
                    'id': '',
                    'match_id': 1234,
                    'similarity': '100000'
                },
            ]
        }
        """
        matches = response.json().get('matches', [])

        match_ids = [
            match['match_id'] for match in matches
            if match.get('match_id', None)
        ]
        return match_ids

    def _get_company(self, company_pk):
        """
        Returns the company for given pk
        raises Http404 if it doesn't exist.
        """
        try:
            return Company.objects.get(pk=company_pk)
        except Company.DoesNotExist:
            raise Http404

    def _get_match_ids(self, target_company, request=None):
        """
        Returns match ids matching the company and
        all companies that were merged into it, if there are any.
        """
        companies = [target_company]
        for company in target_company.transferred_from.all():
            companies.append(company)

        matching_response = match_company(companies, request)
        match_ids = self._extract_match_ids(matching_response)

        if len(match_ids) == 0:
            raise Http404

        return match_ids

    def get(self, request, pk):
        """
        Proxy to Export Wins API for GET requests for given company's match id
        is obtained from Company Matching Service.
        """
        company = self._get_company(pk)
        try:
            match_ids = self._get_match_ids(company, request)
            export_wins_results = get_export_wins(match_ids, request)
            return JsonResponse(export_wins_results.json())

        except (
                CompanyMatchingServiceConnectionError,
                CompanyMatchingServiceTimeoutError,
                CompanyMatchingServiceHTTPError,
                ExportWinsAPIConnectionError,
                ExportWinsAPITimeoutError,
                ExportWinsAPIHTTPError,
        ) as exc:
            raise APIUpstreamException(str(exc))
        else:
            return HttpResponse(
                status=status.HTTP_500_INTERNAL_SERVER_ERROR,
                content_type='application/json',
            )
Ejemplo n.º 11
0
class CompanyReferralViewSet(CoreViewSet):
    """Company referral view set."""

    serializer_class = CompanyReferralSerializer
    queryset = CompanyReferral.objects.select_related(
        'company',
        'contact',
        'completed_by__dit_team',
        'created_by__dit_team',
        'interaction',
        'recipient__dit_team',
    )

    def get_queryset(self):
        """
        Get a queryset for list action that is filtered to the authenticated user's sent and
        received referrals, otherwise return original queryset.
        """
        if self.action == 'list':
            return super().get_queryset().filter(
                Q(created_by=self.request.user) | Q(recipient=self.request.user),
            )

        return super().get_queryset()

    @action(
        methods=['post'],
        detail=True,
        schema=StubSchema(),
        permission_classes=[
            HasPermissions('company_referral.change_companyreferral'),
        ],
    )
    def complete(self, request, **kwargs):
        """
        View for completing a referral.

        Completing a referral involves creating an interaction and linking the referral and
        interaction together. Hence, this view creates an interaction and updates the referral
        object accordingly.
        """
        referral = self.get_object()
        context = {
            **self.get_serializer_context(),
            # Used by HasAssociatedInvestmentProjectValidator
            'check_association_permissions': False,
            'referral': referral,
            'user': request.user,
        }
        data = {
            **request.data,
            'company': {
                'id': referral.company.pk,
            },
        }
        serializer = CompleteCompanyReferralSerializer(
            data=data,
            context=context,
        )
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)
Ejemplo n.º 12
0
class ExportCountryHistoryView(SearchAPIView):
    """Export country history search view."""

    required_scopes = (Scope.internal_front_end, )
    search_app = ExportCountryHistoryApp

    permission_classes = (
        IsAuthenticatedOrTokenHasScope,
        # Note: This search view does not use SearchPermissions, as it requires multiple
        # permissions
        HasPermissions(
            f'company.view_companyexportcountry',
            f'interaction.{InteractionPermission.view_all}',
        ),
    )

    fields_to_include = (
        # Fields common to interactions and export country history objects
        'company',
        'date',
        'id',

        # Export country history object fields
        'country',
        'history_date',
        'history_type',
        'history_user',
        'status',

        # Interaction fields
        'contacts',
        'dit_participants',
        'export_countries',
        'kind',
        'service',
        'subject',
    )

    FILTER_FIELDS = [
        'country',
        'company',
    ]

    REMAP_FIELDS = {
        'company': 'company.id',
    }

    COMPOSITE_FILTERS = {
        'country': [
            'country.id',
            'export_countries.country.id',
        ],
    }

    serializer_class = SearchExportCountryHistorySerializer

    def get_entities(self):
        """
        Overriding to provide multiple entities
        """
        return [self.search_app.es_model, Interaction]

    def get_base_query(self, request, validated_data):
        """
        Get the base query.

        This is overridden to exclude UPDATE history items and interactions
        without export countries.
        """
        base_query = super().get_base_query(request, validated_data)

        is_relevant_interaction = Term(were_countries_discussed=True)
        is_relevant_history_entry = Term(
            _document_type=ExportCountryHistoryApp.name)

        return base_query.filter(is_relevant_interaction
                                 | is_relevant_history_entry)
Ejemplo n.º 13
0
class DNBCompanySearchView(APIView):
    """
    View for searching DNB companies.
    """

    required_scopes = (Scope.internal_front_end, )
    permission_classes = (
        IsAuthenticatedOrTokenHasScope,
        HasPermissions(f'company.{CompanyPermission.view_company}', ),
    )

    @method_decorator(enforce_request_content_type('application/json'))
    def post(self, request):
        """
        Proxy to DNB search API for POST requests.  This will also hydrate results
        with Data Hub company details if the company exists (and can be matched)
        on Data Hub.
        """
        upstream_response = search_dnb(request.data)

        if upstream_response.status_code == status.HTTP_200_OK:
            response_body = upstream_response.json()
            response_body['results'] = self._format_and_hydrate(
                response_body.get('results', []), )
            return JsonResponse(response_body)

        return HttpResponse(
            upstream_response.text,
            status=upstream_response.status_code,
            content_type=upstream_response.headers.get('content-type'),
        )

    def _get_datahub_companies_by_duns(self, duns_numbers):
        datahub_companies = get_company_queryset().filter(
            duns_number__in=duns_numbers)
        return {company.duns_number: company for company in datahub_companies}

    def _get_datahub_company_data(self, datahub_company):
        if datahub_company:
            return DNBMatchedCompanySerializer(
                datahub_company,
                context={
                    'request': self.request
                },
            ).data
        return None

    def _get_hydrated_results(self, dnb_results, datahub_companies_by_duns):
        dnb_datahub_company_pairs = ((
            dnb_company,
            self._get_datahub_company_data(
                datahub_companies_by_duns.get(dnb_company['duns_number']), ),
        ) for dnb_company in dnb_results)
        return [{
            'dnb_company': dnb_company,
            'datahub_company': datahub_company,
        } for dnb_company, datahub_company in dnb_datahub_company_pairs]

    def _format_and_hydrate(self, dnb_results):
        """
        Format each result from DNB such that there is a "dnb_company" key and
        a "datahub_company" key.  The value for "datahub_company" represents
        the corresponding Company entry on Data Hub for the DNB result, if it
        exists.

        This changes a DNB result entry from:

        {
          "duns_number": "999999999",
          "primary_name": "My Company LTD",
          ...
        }

        To:

        {
          "dnb_company": {
            "duns_number": "999999999",
            "primary_name": "My Company LTD",
            ...
          },
          "datahub_company": {
            "id": "0f5216e0-849f-11e6-ae22-56b6b6499611",
            "latest_interaction": {
              "id": "e8c3534f-4f60-4c93-9880-09c22e4fc011",
              "created_on": "2018-04-08T14:00:00Z",
              "date": "2018-06-06",
              "subject": "Meeting with Joe Bloggs"
            }
          }
        }

        """
        duns_numbers = [result['duns_number'] for result in dnb_results]
        datahub_companies_by_duns = self._get_datahub_companies_by_duns(
            duns_numbers)
        hydrated_results = self._get_hydrated_results(
            dnb_results, datahub_companies_by_duns)
        return hydrated_results
Ejemplo n.º 14
0
    )
    filterset_class = AdviserFilter
    ordering_fields = ('first_name', 'last_name', 'dit_team__name')
    _default_ordering = ('first_name', 'last_name', 'dit_team__name')

    def filter_queryset(self, queryset):
        """
        Applies the default ordering when the query set has not already been ordered.

        (The autocomplete filter automatically applies an ordering, hence we only set the
        default ordering when another one has not already been set.)
        """
        filtered_queryset = super().filter_queryset(queryset)

        if not filtered_queryset.ordered:
            return filtered_queryset.order_by(*self._default_ordering)

        return filtered_queryset


@api_view(['GET'])
@permission_classes(
    [HasPermissions(f'company.{CompanyPermission.view_export_win}')])
def export_wins_501_not_implemented(request, pk):
    """
    Get company export wins.
    The feature is not yet implemented.
    """
    raise APINotImplementedException(
        'Retriving export wins in not yet implemented.')
Ejemplo n.º 15
0
 def test_raises_error_if_no_permissions_provided(self):
     """Tests that an error is raised if no permissions are provided."""
     with pytest.raises(ValueError):
         HasPermissions()
Ejemplo n.º 16
0
class IProjectViewSet(ArchivableViewSetMixin, CoreViewSet):
    """Unified investment project views.

    This replaces the previous project, value, team and requirements endpoints.
    """

    permission_classes = (
        InvestmentProjectModelPermissions,
        IsAssociatedToInvestmentProjectPermission,
    )
    serializer_class = IProjectSerializer
    queryset = InvestmentProject.objects.select_related(
        'archived_by',
        'average_salary',
        'client_relationship_manager__dit_team',
        'client_relationship_manager',
        'country_lost_to',
        'country_investment_originates_from',
        'fdi_type',
        'intermediate_company',
        'investment_type',
        'investmentprojectcode',
        'investor_company',
        'investor_type',
        'level_of_involvement',
        'project_assurance_adviser__dit_team',
        'project_assurance_adviser',
        'project_manager__dit_team',
        'project_manager',
        'referral_source_activity_marketing',
        'referral_source_activity_website',
        'referral_source_activity',
        'referral_source_adviser',
        'specific_programme',
        'stage',
        'uk_company__address_country',
        'uk_company',
    ).prefetch_related(
        'actual_uk_regions',
        'business_activities',
        'client_contacts',
        'competitor_countries',
        'delivery_partners',
        'sector__parent__parent',
        'sector__parent',
        'sector',
        'strategic_drivers',
        'uk_region_locations',
        Prefetch('team_members', queryset=_team_member_queryset),
    )
    filter_backends = (
        DjangoFilterBackend,
        OrderingFilter,
        IsAssociatedToInvestmentProjectFilter,
    )
    filterset_fields = ('investor_company_id', )
    ordering = ('-created_on', )

    def get_view_name(self):
        """Returns the view set name for the DRF UI."""
        return 'Investment projects'

    def get_serializer_context(self):
        """Extra context provided to the serializer class."""
        return {
            **super().get_serializer_context(),
            'current_user':
            self.request.user if self.request else None,
        }

    @action(
        methods=['post'],
        detail=True,
        permission_classes=[
            HasPermissions(
                f'investment.{InvestmentProjectPermission.change_to_any_stage}'
            ),
        ],
        filter_backends=[],
        schema=StubSchema(),
    )
    def change_stage(self, request, *args, **kwargs):
        """Change the stage of an investment project"""
        instance = self.get_object()
        serializer = IProjectChangeStageSerializer(
            instance,
            data=request.data,
            context=self.get_serializer_context(),
        )
        serializer.is_valid(raise_exception=True)
        instance = serializer.change_stage(user=self.request.user)
        return Response(
            self.get_serializer(instance=instance).data,
            status=status.HTTP_200_OK,
        )