Пример #1
0
def update_from_dnb(model_admin, request, object_id):
    """
    Tool to let admin users update company with a valid `duns_number`
    by pulling fresh data from D&B.

    The company record will be versioned after the update from
    D&B is applied.

    The `pending_dnb_investigation` field will
    be set to False.
    """
    if not model_admin.has_change_permission(request):
        raise PermissionDenied()

    dh_company = model_admin.get_object(request, object_id)

    company_change_page = reverse(
        admin_urlname(model_admin.model._meta, 'change'),
        kwargs={'object_id': dh_company.pk},
    )

    if dh_company is None or dh_company.duns_number is None:
        raise SuspiciousOperation()

    try:
        dnb_company = get_company(dh_company.duns_number, request)

    except DNBServiceInvalidRequestError:
        message = 'No matching company found in D&B database.'
        raise AdminError([message], company_change_page)

    except DNBServiceBaseError:
        message = 'Something went wrong in an upstream service.'
        raise AdminError([message], company_change_page)

    if request.method == 'GET':
        return TemplateResponse(
            request,
            'admin/company/company/update-from-dnb.html',
            {
                **model_admin.admin_site.each_context(request),
                'media':
                model_admin.media,
                'opts':
                model_admin.model._meta,
                'object':
                dh_company,
                'title':
                gettext_lazy('Confirm update from D&B'),
                'diff':
                format_company_diff(dh_company, dnb_company),
            },
        )

    try:
        update_company_from_dnb(dh_company, dnb_company, request.user)
        return HttpResponseRedirect(company_change_page)
    except serializers.ValidationError:
        message = 'Data from D&B did not pass the Data Hub validation checks.'
        raise AdminError([message], company_change_page)
Пример #2
0
def _sync_company_with_dnb(
    company_id,
    fields_to_update,
    task,
    update_descriptor,
    retry_failures=True,
):
    dh_company = Company.objects.get(id=company_id)

    try:
        dnb_company = get_company(dh_company.duns_number)
    except DNBServiceError as exc:
        if is_server_error(exc.status_code) and retry_failures:
            raise task.retry(exc=exc, countdown=60)
        raise
    except (DNBServiceConnectionError, DNBServiceTimeoutError) as exc:
        if retry_failures:
            raise task.retry(exc=exc, countdown=60)
        raise

    update_company_from_dnb(
        dh_company,
        dnb_company,
        fields_to_update=fields_to_update,
        update_descriptor=update_descriptor,
    )
Пример #3
0
def _get_company(duns_number, error_url, request=None):
    try:
        return get_company(duns_number, request)

    except DNBServiceInvalidRequestError:
        message = 'No matching company found in D&B database.'
        raise AdminError([message], error_url)

    except DNBServiceBaseError:
        message = 'Something went wrong in an upstream service.'
        raise AdminError([message], error_url)
Пример #4
0
def test_get_company_dnb_service_request_error(
    caplog,
    requests_mock,
    request_exception,
    expected_exception,
    expected_message,
):
    """
    Test if there is an error connecting to dnb-service, we log it and raise the exception with an
    appropriate message.
    """
    requests_mock.post(
        DNB_SEARCH_URL,
        exc=request_exception,
    )

    with pytest.raises(expected_exception) as e:
        get_company('123456789')

    assert str(e.value) == str(expected_message)
def _get_company(duns_number, error_url):
    try:
        return get_company(duns_number)

    except DNBServiceInvalidRequest:
        message = 'No matching company found in D&B database.'
        raise AdminException([message], error_url)

    except DNBServiceException:
        message = 'Something went wrong in an upstream service.'
        raise AdminException([message], error_url)
Пример #6
0
def test_get_company_invalid_request_response(
    caplog,
    requests_mock,
    search_results,
    expected_exception,
    expected_message,
):
    """
    Test if a given `duns_number` gets anything other than a single company
    from dnb-service, the get_company function raises an exception.
    """
    requests_mock.post(
        DNB_SEARCH_URL,
        json={'results': search_results},
    )

    with pytest.raises(expected_exception) as e:
        get_company('123456789')

    assert e.value.args[0] == expected_message
    assert len(caplog.records) == 1
    assert caplog.records[0].getMessage() == expected_message
Пример #7
0
def test_get_company_dnb_service_error(
    caplog,
    requests_mock,
    dnb_response_status,
):
    """
    Test if the dnb-service returns a status code that is not
    200, we log it and raise the exception with an appropriate
    message.
    """
    requests_mock.post(
        DNB_SEARCH_URL,
        status_code=dnb_response_status,
    )

    with pytest.raises(DNBServiceError) as e:
        get_company('123456789')

    expected_message = f'DNB service returned an error status: {dnb_response_status}'

    assert e.value.args[0] == expected_message
    assert len(caplog.records) == 1
    assert caplog.records[0].getMessage() == expected_message
Пример #8
0
def test_get_company_valid(
    caplog,
    requests_mock,
    dnb_response_uk,
):
    """
    Test if dnb-service returns a valid response, get_company
    returns a formatted dict.
    """
    requests_mock.post(
        DNB_V2_SEARCH_URL,
        json=dnb_response_uk,
    )

    dnb_company = get_company('123456789')

    assert dnb_company == {
        'company_number': '01261539',
        'name': 'FOO BICYCLE LIMITED',
        'duns_number': '123456789',
        'trading_names': [],
        'address': {
            'area': None,
            'country': UUID('80756b9a-5d95-e211-a939-e4115bead28a'),
            'county': '',
            'line_1': 'Unit 10, Ockham Drive',
            'line_2': '',
            'postcode': 'UB6 0F2',
            'town': 'GREENFORD',
        },
        'registered_address': {
            'area': None,
            'country': UUID('80756b9a-5d95-e211-a939-e4115bead28a'),
            'county': '',
            'line_1': 'C/O LONE VARY',
            'line_2': '',
            'postcode': 'UB6 0F2',
            'town': 'GREENFORD',
        },
        'number_of_employees': 260,
        'is_number_of_employees_estimated': True,
        'turnover': 50651895.0,
        'is_turnover_estimated': None,
        'uk_based': True,
        'website': 'http://foo.com',
        'global_ultimate_duns_number': '291332174',
    }
Пример #9
0
    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), )