def test_update_company_export_countries_with_pre_existing_company_fields_sync(
        self, ):
        """
        Test sync when company export_countries update, of a company with
        currently_exporting_to and future_interest_countries preset.
        """
        initial_countries = list(CountryModel.objects.order_by('id')[:5])
        initial_export_to_countries = initial_countries[:3]
        initial_future_interest_countries = initial_countries[3:]

        company = CompanyFactory(
            export_to_countries=initial_export_to_countries,
            future_interest_countries=initial_future_interest_countries,
        )

        countries_set = list(CountryModel.objects.order_by('name')[:10])
        data_items = [{
            'country': {
                'id': str(country.id),
                'name': country.name,
            },
            'status': self._get_export_interest_status(),
        } for country in countries_set]
        data = {
            'export_countries': data_items,
        }

        status_wise_items = {
            outer['status']: [
                inner['country']['id'] for inner in data_items
                if inner['status'] == outer['status']
            ]
            for outer in data_items
        }
        current_countries_request = status_wise_items.get(
            CompanyExportCountry.Status.CURRENTLY_EXPORTING,
            [],
        )
        future_countries_request = status_wise_items.get(
            CompanyExportCountry.Status.FUTURE_INTEREST,
            [],
        )

        url = reverse('api-v4:company:update-export-detail',
                      kwargs={'pk': company.pk})
        response = self.api_client.patch(url, data=data)
        assert response.status_code == status.HTTP_204_NO_CONTENT

        company.refresh_from_db()
        current_countries_response = [
            str(c.id) for c in company.export_to_countries.all()
        ]

        future_countries_response = [
            str(c.id) for c in company.future_interest_countries.all()
        ]

        assert current_countries_request == current_countries_response
        assert future_countries_request == future_countries_response
Example #2
0
def test_update_company_from_dnb_data_partial_fields(dnb_response_uk,
                                                     base_company_dict):
    """
    Test the update_company_from_dnb_data command when a subset of DNB fields are updated.
    """
    company = CompanyFactory(duns_number='123456789')
    original_company = Company.objects.get(id=company.id)
    task_result = update_company_from_dnb_data.apply_async(
        args=[dnb_response_uk['results'][0]],
        kwargs={'fields_to_update': ['global_ultimate_duns_number']},
    )
    assert task_result.successful()
    company.refresh_from_db()
    assert model_to_dict(company) == {
        **base_company_dict,
        'address_1': original_company.address_1,
        'address_2': original_company.address_2,
        'address_country': original_company.address_country_id,
        'address_county': original_company.address_county,
        'address_postcode': original_company.address_postcode,
        'address_area': original_company.address_area,
        'address_town': original_company.address_town,
        'archived_documents_url_path':
        original_company.archived_documents_url_path,
        'business_type': original_company.business_type_id,
        'created_by': original_company.created_by_id,
        'duns_number': original_company.duns_number,
        'employee_range': original_company.employee_range_id,
        'export_experience_category':
        original_company.export_experience_category_id,
        'global_ultimate_duns_number': '291332174',
        'id': original_company.id,
        'is_number_of_employees_estimated':
        original_company.is_number_of_employees_estimated,
        'is_turnover_estimated': original_company.is_turnover_estimated,
        'modified_by': original_company.modified_by_id,
        'name': original_company.name,
        'number_of_employees': original_company.number_of_employees,
        'registered_address_1': original_company.registered_address_1,
        'registered_address_2': original_company.registered_address_2,
        'registered_address_country':
        original_company.registered_address_country_id,
        'registered_address_county':
        original_company.registered_address_county,
        'registered_address_area': original_company.registered_address_area,
        'registered_address_postcode':
        original_company.registered_address_postcode,
        'registered_address_town': original_company.registered_address_town,
        'sector': original_company.sector_id,
        'export_segment': original_company.export_segment,
        'export_sub_segment': original_company.export_sub_segment,
        'trading_names': original_company.trading_names,
        'turnover': original_company.turnover,
        'turnover_range': original_company.turnover_range_id,
        'uk_region': original_company.uk_region_id,
        'website': original_company.website,
        'dnb_modified_on': now(),
    }
Example #3
0
def test_sync_company_with_dnb_all_fields(
    requests_mock,
    dnb_response_uk,
    base_company_dict,
    update_descriptor,
):
    """
    Test the sync_company_with_dnb task when all fields should be synced.
    """
    requests_mock.post(
        DNB_SEARCH_URL,
        json=dnb_response_uk,
    )
    company = CompanyFactory(duns_number='123456789')
    original_company = Company.objects.get(id=company.id)
    task_result = sync_company_with_dnb.apply_async(
        args=[company.id],
        kwargs={'update_descriptor': update_descriptor},
    )
    assert task_result.successful()
    company.refresh_from_db()
    uk_country = Country.objects.get(iso_alpha2_code='GB')
    assert model_to_dict_company(company) == {
        **base_company_dict,
        'address_1': 'Unit 10, Ockham Drive',
        'address_2': '',
        'address_country': uk_country.id,
        'address_county': '',
        'address_postcode': 'UB6 0F2',
        'address_town': 'GREENFORD',
        'archived_documents_url_path': original_company.archived_documents_url_path,
        'business_type': original_company.business_type_id,
        'company_number': '01261539',
        'created_by': original_company.created_by_id,
        'duns_number': '123456789',
        'employee_range': original_company.employee_range_id,
        'export_experience_category': original_company.export_experience_category_id,
        'global_ultimate_duns_number': '291332174',
        'id': original_company.id,
        'is_number_of_employees_estimated': True,
        'modified_by': original_company.modified_by_id,
        'name': 'FOO BICYCLE LIMITED',
        'number_of_employees': 260,
        'sector': original_company.sector_id,
        'turnover': 50651895,
        'turnover_range': original_company.turnover_range_id,
        'uk_region': original_company.uk_region_id,
        'dnb_modified_on': now(),
    }

    versions = list(Version.objects.get_for_object(company))
    assert len(versions) == 1
    version = versions[0]
    expected_update_descriptor = f'celery:sync_company_with_dnb:{task_result.id}'
    if update_descriptor:
        expected_update_descriptor = update_descriptor
    assert version.revision.comment == f'Updated from D&B [{expected_update_descriptor}]'
    assert version.revision.user is None
Example #4
0
    def test_update(self, wb_record, expected_fields, commit):
        """
        Test that update_company_from_wb_record updates the company with the data from wb_record.
        """
        factory_data = {
            'duns_number': None,
            'name': 'Previous name',
            'trading_names': ['Previous trading name'],
            'company_number': '87654321',
            'number_of_employees': 999,
            'is_number_of_employees_estimated': False,
            'employee_range': random_obj_for_model(EmployeeRange),
            'turnover': 888,
            'is_turnover_estimated': False,
            'turnover_range': random_obj_for_model(TurnoverRange),
            'address_1': '999',
            'address_2': 'Street Main',
            'address_town': 'Manchester',
            'address_county': 'Manchester',
            'address_country_id': UNITED_KINGDOM_COUNTRY_UUID,
            'address_postcode': 'M90 1QX',
            'registered_address_1': '999',
            'registered_address_2': 'Street Main',
            'registered_address_town': 'Manchester',
            'registered_address_county': 'Manchester',
            'registered_address_country_id': UNITED_KINGDOM_COUNTRY_UUID,
            'registered_address_postcode': 'M90 1QX',
            'trading_address_1': '999',
            'trading_address_2': 'Street Main',
            'trading_address_town': 'Manchester',
            'trading_address_county': 'Manchester',
            'trading_address_country_id': UNITED_KINGDOM_COUNTRY_UUID,
            'trading_address_postcode': 'M90 1QX',
            'archived': False,
            'archived_on': None,
            'archived_reason': '',
        }
        company = CompanyFactory(**factory_data)
        updated_fields = update_company_from_wb_record(company,
                                                       wb_record,
                                                       commit=commit)

        company.refresh_from_db()
        if commit:
            actual_fields = {
                field_name: getattr(company, field_name)
                for field_name in expected_fields
            }
            assert actual_fields == expected_fields
        else:
            actual_fields = {
                field_name: getattr(company, field_name)
                for field_name in factory_data
            }
            assert actual_fields == factory_data

        assert set(updated_fields) == set(expected_fields)
Example #5
0
def test_sync_company_with_dnb_partial_fields(
    requests_mock,
    dnb_response_uk,
    base_company_dict,
):
    """
    Test the sync_company_with_dnb task when only a subset of fields should be synced.
    """
    requests_mock.post(
        DNB_SEARCH_URL,
        json=dnb_response_uk,
    )
    company = CompanyFactory(duns_number='123456789')
    original_company = Company.objects.get(id=company.id)
    task_result = sync_company_with_dnb.apply_async(
        args=[company.id],
        kwargs={'fields_to_update': ['global_ultimate_duns_number']},
    )
    assert task_result.successful()
    company.refresh_from_db()
    assert model_to_dict(company) == {
        **base_company_dict,
        'address_1': original_company.address_1,
        'address_2': original_company.address_2,
        'address_country': original_company.address_country_id,
        'address_county': original_company.address_county,
        'address_postcode': original_company.address_postcode,
        'address_town': original_company.address_town,
        'archived_documents_url_path': original_company.archived_documents_url_path,
        'business_type': original_company.business_type_id,
        'created_by': original_company.created_by_id,
        'duns_number': original_company.duns_number,
        'employee_range': original_company.employee_range_id,
        'export_experience_category': original_company.export_experience_category_id,
        'global_ultimate_duns_number': '291332174',
        'id': original_company.id,
        'is_number_of_employees_estimated': original_company.is_number_of_employees_estimated,
        'is_turnover_estimated': original_company.is_turnover_estimated,
        'modified_by': original_company.modified_by_id,
        'name': original_company.name,
        'number_of_employees': original_company.number_of_employees,
        'registered_address_1': original_company.registered_address_1,
        'registered_address_2': original_company.registered_address_2,
        'registered_address_country': original_company.registered_address_country_id,
        'registered_address_county': original_company.registered_address_county,
        'registered_address_postcode': original_company.registered_address_postcode,
        'registered_address_town': original_company.registered_address_town,
        'sector': original_company.sector_id,
        'trading_names': original_company.trading_names,
        'turnover': original_company.turnover,
        'turnover_range': original_company.turnover_range_id,
        'uk_region': original_company.uk_region_id,
        'website': original_company.website,
        'dnb_modified_on': now(),
    }
def test_link_company_with_dnb_success(
    requests_mock,
    dnb_response_uk,
    base_company_dict,
):
    """
    Test the link_company_with_dnb utility.
    """
    requests_mock.post(
        DNB_V2_SEARCH_URL,
        json=dnb_response_uk,
    )
    company = CompanyFactory()
    original_company = Company.objects.get(id=company.id)
    modifying_adviser = AdviserFactory()
    link_company_with_dnb(company.id, '123456789', modifying_adviser)
    company.refresh_from_db()
    uk_country = Country.objects.get(iso_alpha2_code='GB')
    assert model_to_dict_company(company) == {
        **base_company_dict,
        'address_1': 'Unit 10, Ockham Drive',
        'address_2': '',
        'address_country': uk_country.id,
        'address_county': '',
        'address_postcode': 'UB6 0F2',
        'address_area': None,
        'address_town': 'GREENFORD',
        'archived_documents_url_path': original_company.archived_documents_url_path,
        'business_type': original_company.business_type_id,
        'company_number': '01261539',
        'created_by': original_company.created_by_id,
        'duns_number': '123456789',
        'employee_range': original_company.employee_range_id,
        'export_experience_category': original_company.export_experience_category_id,
        'global_ultimate_duns_number': '291332174',
        'id': original_company.id,
        'modified_by': modifying_adviser.id,
        'name': 'FOO BICYCLE LIMITED',
        'is_number_of_employees_estimated': True,
        'number_of_employees': 260,
        'pending_dnb_investigation': False,
        'reference_code': '',
        'registered_address_area': None,
        'sector': original_company.sector_id,
        'export_segment': original_company.export_segment,
        'export_sub_segment': original_company.export_sub_segment,
        'turnover': 50651895,
        'turnover_range': original_company.turnover_range_id,
        'uk_region': original_company.uk_region_id,
        'dnb_modified_on': now(),
    }
Example #7
0
def test_update_company_from_dnb_data(dnb_response_uk, base_company_dict):
    """
    Test the update_company_from_dnb_data command when all DNB fields are updated.
    """
    company = CompanyFactory(duns_number='123456789')
    original_company = Company.objects.get(id=company.id)
    update_descriptor = 'foobar'
    task_result = update_company_from_dnb_data.apply_async(
        args=[dnb_response_uk['results'][0]],
        kwargs={'update_descriptor': update_descriptor},
    )
    assert task_result.successful()
    company.refresh_from_db()
    uk_country = Country.objects.get(iso_alpha2_code='GB')
    assert model_to_dict_company(company) == {
        **base_company_dict,
        'address_1': 'Unit 10, Ockham Drive',
        'address_2': '',
        'address_country': uk_country.id,
        'address_county': '',
        'address_postcode': 'UB6 0F2',
        'address_area': None,
        'address_town': 'GREENFORD',
        'archived_documents_url_path':
        original_company.archived_documents_url_path,
        'business_type': original_company.business_type_id,
        'company_number': '01261539',
        'created_by': original_company.created_by_id,
        'duns_number': '123456789',
        'employee_range': original_company.employee_range_id,
        'export_experience_category':
        original_company.export_experience_category_id,
        'global_ultimate_duns_number': '291332174',
        'id': original_company.id,
        'is_number_of_employees_estimated': True,
        'modified_by': original_company.modified_by_id,
        'name': 'FOO BICYCLE LIMITED',
        'number_of_employees': 260,
        'sector': original_company.sector_id,
        'export_segment': original_company.export_segment,
        'export_sub_segment': original_company.export_sub_segment,
        'turnover': 50651895,
        'turnover_range': original_company.turnover_range_id,
        'uk_region': original_company.uk_region_id,
        'dnb_modified_on': now(),
    }

    versions = list(Version.objects.get_for_object(company))
    assert len(versions) == 1
    version = versions[0]
    assert version.revision.comment == f'Updated from D&B [{update_descriptor}]'
Example #8
0
 def test_orders(
     self,
     automatic_company_archive_feature_flag,
 ):
     """
     Test that a company with OMIS orders is not archived.
     """
     gt_3m_ago = timezone.now() - relativedelta(months=3, days=1)
     with freeze_time(gt_3m_ago):
         company = CompanyFactory()
     OrderFactory(company=company)
     task_result = automatic_company_archive.apply_async(kwargs={'simulate': False})
     assert task_result.successful()
     company.refresh_from_db()
     assert not company.archived
Example #9
0
    def test_updates_with_update_company_from_dnb_data_with_failure(
        self,
        mocked_log_to_sentry,
        mocked_send_realtime_message,
        monkeypatch,
        dnb_company_updates_response_uk,
    ):
        """
        Test full integration for the `get_company_updates` task with the
        `update_company_from_dnb_data` task when all fields are updated and one company in the
        dnb-service result does not exist in Data Hub.
        """
        company = CompanyFactory(duns_number='123456789')
        missing_dnb_company = {
            **dnb_company_updates_response_uk['results'][0],
            'duns_number': '999999999',
        }
        dnb_company_updates_response_uk['results'].append(missing_dnb_company)
        mock_get_company_update_page = mock.Mock(
            return_value=dnb_company_updates_response_uk,
        )
        monkeypatch.setattr(
            'datahub.dnb_api.tasks.update.get_company_update_page',
            mock_get_company_update_page,
        )
        task_result = get_company_updates.apply()

        company.refresh_from_db()
        dnb_company = dnb_company_updates_response_uk['results'][0]
        assert company.name == dnb_company['primary_name']
        expected_gu_number = dnb_company['global_ultimate_duns_number']
        assert company.global_ultimate_duns_number == expected_gu_number
        mocked_log_to_sentry.assert_called_with(
            'get_company_updates task completed.',
            extra={
                'success_count': 1,
                'failure_count': 1,
                'updated_company_ids': [str(company.pk)],
                'producer_task_id': task_result.id,
                'start_time': '2019-01-02T02:00:00+00:00',
                'end_time': '2019-01-02T02:00:00+00:00',
            },
        )
        expected_message = (
            'datahub.dnb_api.tasks.update.get_company_updates '
            'updated: 1; failed to update: 1'
        )
        mocked_send_realtime_message.assert_called_once_with(expected_message)
    def test_delete_company_export_countries_check_history_tracks_correct_user(
            self):
        """
        Check that history correctly tracks the user who deletes the export country
        """
        company = CompanyFactory()
        country = CountryModel.objects.order_by('name')[0]
        adviser = AdviserFactory()
        export_country = CompanyExportCountryFactory(
            company=company,
            country=country,
            status=CompanyExportCountry.Status.FUTURE_INTEREST,
            created_by=adviser,
        )
        CompanyExportCountryHistoryFactory(
            id=export_country.id,
            company=export_country.company,
            country=export_country.country,
            status=export_country.status,
            history_type=CompanyExportCountryHistory.HistoryType.INSERT,
            history_user=export_country.created_by,
        )

        new_user = create_test_user(permission_codenames=(
            'change_company',
            'change_companyexportcountry',
        ), )
        api_client = self.create_api_client(user=new_user)
        url = reverse('api-v4:company:update-export-detail',
                      kwargs={'pk': company.pk})
        response = api_client.patch(
            url,
            data={
                'export_countries': [],
            },
        )
        assert response.status_code == status.HTTP_204_NO_CONTENT

        company.refresh_from_db()
        assert company.export_countries.count() == 0
        delete_history = CompanyExportCountryHistory.objects.filter(
            company=company,
            history_type=CompanyExportCountryHistory.HistoryType.DELETE,
        )
        assert delete_history.count() == 1
        assert delete_history[0].country == country
        assert delete_history[0].history_user == new_user
Example #11
0
def test_sync_outdated_companies_limit_most_recently_interacted_updated(
    requests_mock,
    dnb_response_uk,
):
    """
    Test that running sync_outdated_companies_with_dnb with a limit will update
    the most recently interacted company.
    """
    requests_mock.post(
        DNB_SEARCH_URL,
        json=dnb_response_uk,
    )

    company_most_recent_interaction = CompanyFactory(
        duns_number='123456789',
        dnb_modified_on=now() - timedelta(days=1),
    )
    CompanyInteractionFactory(company=company_most_recent_interaction,
                              date=now())

    company_least_recent_interaction = CompanyFactory(
        duns_number='123456788',
        dnb_modified_on=now() - timedelta(days=1),
    )
    CompanyInteractionFactory(
        company=company_least_recent_interaction,
        date=now() - timedelta(days=1),
    )

    task_result = sync_outdated_companies_with_dnb.apply_async(kwargs={
        'fields_to_update': ['global_ultimate_duns_number'],
        'dnb_modified_on_before':
        now() + timedelta(days=1),
        'simulate':
        False,
        'limit':
        1,
    }, )

    company_least_recent_interaction.refresh_from_db()
    company_most_recent_interaction.refresh_from_db()
    assert task_result.successful()
    # We expect the least recently interacted company to be unmodified
    assert company_least_recent_interaction.dnb_modified_on == now(
    ) - timedelta(days=1)
    # We expect most recently interacted company to be modified
    assert company_most_recent_interaction.dnb_modified_on == now()
Example #12
0
def test_dnb_company_serializer_partial_save(db):
    """
    Test DNBCompanySerializer.partial_save() method.
    """
    dh_company = CompanyFactory()
    original_company = Company.objects.get(id=dh_company.id)
    serializer = DNBCompanySerializer(
        dh_company,
        data={'name': 'foobar'},
        partial=True,
    )
    serializer.is_valid()
    serializer.partial_save(duns_number='123456789')
    dh_company.refresh_from_db()
    assert dh_company.name == 'foobar'
    assert dh_company.duns_number == '123456789'
    assert dh_company.modified_on == original_company.modified_on
Example #13
0
    def test_updates_with_update_company_from_dnb_data(
        self,
        mocked_log_to_sentry,
        mocked_send_realtime_message,
        caplog,
        monkeypatch,
        dnb_company_updates_response_uk,
    ):
        """
        Test full integration for the `get_company_updates` task with the
        `update_company_from_dnb_data` task when all fields are updated.
        """
        caplog.set_level('INFO')
        company = CompanyFactory(duns_number='123456789')
        mock_get_company_update_page = mock.Mock(
            return_value=dnb_company_updates_response_uk,
        )
        monkeypatch.setattr(
            'datahub.dnb_api.tasks.update.get_company_update_page',
            mock_get_company_update_page,
        )
        task_result = get_company_updates.apply_async()

        company.refresh_from_db()
        dnb_company = dnb_company_updates_response_uk['results'][0]
        assert company.name == dnb_company['primary_name']
        expected_gu_number = dnb_company['global_ultimate_duns_number']
        assert company.global_ultimate_duns_number == expected_gu_number
        mocked_log_to_sentry.assert_called_with(
            'get_company_updates task completed.',
            extra={
                'success_count': 1,
                'failure_count': 0,
                'updated_company_ids': [str(company.pk)],
                'producer_task_id': task_result.id,
                'start_time': '2019-01-02T02:00:00+00:00',
                'end_time': '2019-01-02T02:00:00+00:00',
            },
        )
        expected_message = (
            'datahub.dnb_api.tasks.update.get_company_updates '
            'updated: 1; failed to update: 0'
        )
        mocked_send_realtime_message.assert_called_once_with(expected_message)
        assert 'get_company_updates total update count: 1' in caplog.text
Example #14
0
 def test_investment_projects(
     self,
     automatic_company_archive_feature_flag,
     investment_projects_status,
     expected_archived,
 ):
     """
     Test that a company with active investment projects is not
     archived.
     """
     gt_3m_ago = timezone.now() - relativedelta(months=3, days=1)
     with freeze_time(gt_3m_ago):
         company = CompanyFactory()
     for status in investment_projects_status:
         InvestmentProjectFactory(investor_company=company, status=status)
     task_result = automatic_company_archive.apply_async(kwargs={'simulate': False})
     assert task_result.successful()
     company.refresh_from_db()
     assert company.archived == expected_archived
    def test_update_company_export_countries_with_new_list_deletes_old_ones(
        self, ):
        """
        Test when updating company export countries with a new list
        and make sure old ones are removed.
        """
        company = CompanyFactory()
        new_countries = list(CountryModel.objects.order_by('id')[:3])
        CompanyExportCountryFactory(
            country=new_countries.pop(0),
            company=company,
        )

        input_data_items = [{
            'country': {
                'id': str(country.id),
                'name': country.name,
            },
            'status': self._get_export_interest_status(),
        } for country in new_countries]
        input_export_countries = {
            'export_countries': input_data_items,
        }

        url = reverse('api-v4:company:update-export-detail',
                      kwargs={'pk': company.pk})
        response = self.api_client.patch(url, data=input_export_countries)
        assert response.status_code == status.HTTP_204_NO_CONTENT

        company.refresh_from_db()
        company_data_items = [{
            'country': {
                'id': str(export_country.country.id),
                'name': export_country.country.name,
            },
            'status': export_country.status,
        } for export_country in company.export_countries.all().order_by(
            'country__id')]
        company_export_countries = {
            'export_countries': company_data_items,
        }
        assert company_export_countries == input_export_countries
    def test_update_company_with_something_check_export_countries(self, ):
        """
        Test when updating company with something else other than export countries
        will not affect export countries.
        """
        company = CompanyFactory()
        export_country_one, export_country_two = CompanyExportCountryFactory.create_batch(
            2)
        company.export_countries.set([export_country_one, export_country_two])

        input_data = {
            'website': 'www.google.com',
        }

        url = reverse('api-v4:company:item', kwargs={'pk': company.pk})
        response = self.api_client.patch(url, data=input_data)
        assert response.status_code == status.HTTP_200_OK

        company.refresh_from_db()
        assert len(company.export_countries.all()) == 2
Example #17
0
 def test_created_on(
     self,
     automatic_company_archive_feature_flag,
     created_on_delta,
     expected_archived,
 ):
     """
     Test that a company created_on dates around the 3m boundary
     are archived or not as expected.
     """
     created_on = timezone.now() - created_on_delta
     with freeze_time(created_on):
         company = CompanyFactory()
     CompanyInteractionFactory(
         company=company,
         date=timezone.now() - relativedelta(years=8, days=1),
     )
     task_result = automatic_company_archive.apply_async(kwargs={'simulate': False})
     assert task_result.successful()
     company.refresh_from_db()
     assert company.archived == expected_archived
Example #18
0
 def test_interactions(
     self,
     automatic_company_archive_feature_flag,
     interaction_date_delta,
     expected_archived,
 ):
     """
     Test that a company with interactions on various dates
     around the 8y boundary are archived or not as expected.
     """
     gt_3m_ago = timezone.now() - relativedelta(months=3, days=1)
     with freeze_time(gt_3m_ago):
         company = CompanyFactory()
     CompanyInteractionFactory(
         company=company,
         date=timezone.now() - interaction_date_delta,
     )
     task_result = automatic_company_archive.apply_async(
         kwargs={'simulate': False}, )
     assert task_result.successful()
     company.refresh_from_db()
     assert company.archived == expected_archived
Example #19
0
def test_sync_outdated_companies_limit_least_recently_synced_is_updated(
    requests_mock,
    dnb_response_uk,
):
    """
    Test that running sync_outdated_companies_with_dnb with a limit will update
    the least recently synced company.
    """
    requests_mock.post(
        DNB_SEARCH_URL,
        json=dnb_response_uk,
    )
    company_1 = CompanyFactory(
        duns_number='123456788',
        dnb_modified_on=now() - timedelta(days=1),
    )
    original_company_1 = Company.objects.get(id=company_1.id)
    company_2 = CompanyFactory(
        duns_number='123456789',
        dnb_modified_on=now() - timedelta(days=2),
    )

    task_result = sync_outdated_companies_with_dnb.apply_async(kwargs={
        'fields_to_update': ['global_ultimate_duns_number'],
        'dnb_modified_on_before':
        now() + timedelta(days=1),
        'simulate':
        False,
        'limit':
        1,
    }, )

    assert task_result.successful()
    company_1.refresh_from_db()
    company_2.refresh_from_db()
    # We expect company_1 to be unmodified
    assert company_1.dnb_modified_on == original_company_1.dnb_modified_on
    # We expect company_2 to be modified, as it was least recently synced with D&B
    assert company_2.dnb_modified_on == now()
def test_audit_log(s3_stubber):
    """Test that reversion revisions are created."""
    company_without_change = CompanyFactory(
        great_profile_status=Company.GREAT_PROFILE_STATUSES.published,
    )
    company_with_change = CompanyFactory(
        great_profile_status=Company.GREAT_PROFILE_STATUSES.unpublished,
    )

    bucket = 'test_bucket'
    object_key = 'test_key'
    csv_content = f"""datahub_company_id,is_published_find_a_supplier,has_find_a_supplier_profile
{company_without_change.pk},t,t
{company_with_change.pk},t,t
"""

    s3_stubber.add_response(
        'get_object',
        {
            'Body': BytesIO(csv_content.encode(encoding='utf-8')),
        },
        expected_params={
            'Bucket': bucket,
            'Key': object_key,
        },
    )

    call_command('update_company_great_profile_status', bucket, object_key)

    company_without_change.refresh_from_db()
    assert company_without_change.great_profile_status == Company.GREAT_PROFILE_STATUSES.published
    versions = Version.objects.get_for_object(company_without_change)
    assert versions.count() == 0

    company_with_change.refresh_from_db()
    assert company_with_change.great_profile_status == Company.GREAT_PROFILE_STATUSES.published
    versions = Version.objects.get_for_object(company_with_change)
    assert versions.count() == 1
    assert versions[0].revision.get_comment() == 'GREAT profile status updated.'
Example #21
0
def test_sync_outdated_companies_simulation(caplog):
    """
    Test that using simulation mode does not modify companies and logs correctly.
    """
    caplog.set_level('INFO')
    company = CompanyFactory(
        duns_number='123456789',
        dnb_modified_on=now() - timedelta(days=5),
    )
    original_company = Company.objects.get(id=company.id)

    task_result = sync_outdated_companies_with_dnb.apply_async(kwargs={
        'fields_to_update': ['global_ultimate_duns_number'],
        'dnb_modified_on_before':
        now() - timedelta(days=1),
    }, )

    assert task_result.successful()
    company.refresh_from_db()
    # We expect the company to be unmodified
    assert company.dnb_modified_on == original_company.dnb_modified_on
    expected_message = f'[SIMULATION] Syncing dnb-linked company "{company.id}" Succeeded'
    assert expected_message in caplog.text
Example #22
0
def test_link_company_with_dnb_sync_task_failure(
    requests_mock,
    dnb_response_uk,
):
    """
    Test link_company_with_dnb when the sync_company_with_dnb task encounters
    a failure - expect the exception to bubble up.
    """
    malformed_response = dnb_response_uk.copy()
    del malformed_response['results']
    requests_mock.post(
        DNB_V2_SEARCH_URL,
        json=malformed_response,
    )
    company = CompanyFactory()
    original_company = Company.objects.get(id=company.id)
    modifying_adviser = AdviserFactory()
    with pytest.raises(DNBServiceInvalidRequestError):
        link_company_with_dnb(company.id, '123456789', modifying_adviser)
    company.refresh_from_db()
    # Ensure that any changes to the record were rolled back due to the task failure
    assert company.duns_number is None
    assert company.modified_by == original_company.modified_by
Example #23
0
def test_audit_log(s3_stubber):
    """Test that reversion revisions are created."""
    company_without_change = CompanyFactory(
        export_potential=Company.EXPORT_POTENTIAL_SCORES.high, )
    company_with_change = CompanyFactory(
        export_potential=Company.EXPORT_POTENTIAL_SCORES.medium, )

    bucket = 'test_bucket'
    object_key = 'test_key'
    csv_content = f"""datahub_company_id,export_propensity
{company_without_change.pk},High
{company_with_change.pk},Very high
"""

    s3_stubber.add_response(
        'get_object',
        {
            'Body': BytesIO(csv_content.encode(encoding='utf-8')),
        },
        expected_params={
            'Bucket': bucket,
            'Key': object_key,
        },
    )

    call_command('update_company_export_potential', bucket, object_key)

    company_without_change.refresh_from_db()
    assert company_without_change.export_potential == Company.EXPORT_POTENTIAL_SCORES.high
    versions = Version.objects.get_for_object(company_without_change)
    assert versions.count() == 0

    company_with_change.refresh_from_db()
    assert company_with_change.export_potential == Company.EXPORT_POTENTIAL_SCORES.very_high
    versions = Version.objects.get_for_object(company_with_change)
    assert versions.count() == 1
    assert versions[0].revision.get_comment() == 'Export potential updated.'
Example #24
0
    def test_updates_with_update_company_from_dnb_data_partial_fields(
        self,
        mocked_log_to_sentry,
        monkeypatch,
        dnb_company_updates_response_uk,
    ):
        """
        Test full integration for the `get_company_updates` task with the
        `update_company_from_dnb_data` task when the fields are only partially updated.
        """
        company = CompanyFactory(duns_number='123456789')
        mock_get_company_update_page = mock.Mock(
            return_value=dnb_company_updates_response_uk,
        )
        monkeypatch.setattr(
            'datahub.dnb_api.tasks.get_company_update_page',
            mock_get_company_update_page,
        )
        task_result = get_company_updates.apply(kwargs={'fields_to_update': ['name']})

        company.refresh_from_db()
        dnb_company = dnb_company_updates_response_uk['results'][0]
        assert company.name == dnb_company['primary_name']
        assert company.global_ultimate_duns_number == ''

        mocked_log_to_sentry.assert_called_with(
            'get_company_updates task completed.',
            extra={
                'success_count': 1,
                'failure_count': 0,
                'updated_company_ids': [str(company.pk)],
                'producer_task_id': task_result.id,
                'start_time': '2019-01-02T02:00:00+00:00',
                'end_time': '2019-01-02T02:00:00+00:00',
            },
        )
Example #25
0
def test_sync_outdated_companies_with_dnb_partial_fields(
    requests_mock,
    dnb_response_uk,
    base_company_dict,
    existing_company_dnb_modified_on,
    caplog,
):
    """
    Test the sync_outdated_companies_with_dnb task when only a subset of fields should be synced.
    """
    caplog.set_level('INFO')
    if callable(existing_company_dnb_modified_on):
        existing_company_dnb_modified_on = existing_company_dnb_modified_on()
    requests_mock.post(
        DNB_SEARCH_URL,
        json=dnb_response_uk,
    )
    company = CompanyFactory(
        duns_number='123456789',
        dnb_modified_on=existing_company_dnb_modified_on,
    )
    original_company = Company.objects.get(id=company.id)
    task_result = sync_outdated_companies_with_dnb.apply_async(kwargs={
        'fields_to_update': ['global_ultimate_duns_number'],
        'dnb_modified_on_before':
        now() + timedelta(days=1),
        'simulate':
        False,
    }, )
    assert task_result.successful()
    company.refresh_from_db()
    assert model_to_dict(company) == {
        **base_company_dict,
        'address_1': original_company.address_1,
        'address_2': original_company.address_2,
        'address_country': original_company.address_country_id,
        'address_county': original_company.address_county,
        'address_postcode': original_company.address_postcode,
        'address_town': original_company.address_town,
        'archived_documents_url_path':
        original_company.archived_documents_url_path,
        'business_type': original_company.business_type_id,
        'company_number': original_company.company_number,
        'created_by': original_company.created_by_id,
        'duns_number': original_company.duns_number,
        'employee_range': original_company.employee_range_id,
        'export_experience_category':
        original_company.export_experience_category_id,
        'global_ultimate_duns_number': '291332174',
        'id': original_company.id,
        'is_number_of_employees_estimated':
        original_company.is_number_of_employees_estimated,
        'is_turnover_estimated': original_company.is_turnover_estimated,
        'modified_by': original_company.modified_by_id,
        'name': original_company.name,
        'number_of_employees': original_company.number_of_employees,
        'registered_address_1': original_company.registered_address_1,
        'registered_address_2': original_company.registered_address_2,
        'registered_address_country':
        original_company.registered_address_country_id,
        'registered_address_county':
        original_company.registered_address_county,
        'registered_address_postcode':
        original_company.registered_address_postcode,
        'registered_address_town': original_company.registered_address_town,
        'sector': original_company.sector_id,
        'trading_names': original_company.trading_names,
        'turnover': original_company.turnover,
        'turnover_range': original_company.turnover_range_id,
        'uk_region': original_company.uk_region_id,
        'website': original_company.website,
        'dnb_modified_on': now(),
    }
    expected_message = f'Syncing dnb-linked company "{company.id}" Succeeded'
    assert expected_message in caplog.text
Example #26
0
def test_sync_outdated_companies_with_dnb_all_fields(
    requests_mock,
    dnb_response_uk,
    base_company_dict,
    existing_company_dnb_modified_on,
    caplog,
):
    """
    Test the sync_outdated_companies_with_dnb task when all fields should be synced.
    """
    caplog.set_level('INFO')
    if callable(existing_company_dnb_modified_on):
        existing_company_dnb_modified_on = existing_company_dnb_modified_on()
    requests_mock.post(
        DNB_SEARCH_URL,
        json=dnb_response_uk,
    )
    company = CompanyFactory(
        duns_number='123456789',
        dnb_modified_on=existing_company_dnb_modified_on,
    )
    original_company = Company.objects.get(id=company.id)
    task_result = sync_outdated_companies_with_dnb.apply_async(kwargs={
        'dnb_modified_on_before':
        now() + timedelta(days=1),
        'simulate':
        False,
    }, )
    assert task_result.successful()
    company.refresh_from_db()
    uk_country = Country.objects.get(iso_alpha2_code='GB')
    assert model_to_dict_company(company) == {
        **base_company_dict,
        'address_1': 'Unit 10, Ockham Drive',
        'address_2': '',
        'address_country': uk_country.id,
        'address_county': '',
        'address_postcode': 'UB6 0F2',
        'address_town': 'GREENFORD',
        'archived_documents_url_path':
        original_company.archived_documents_url_path,
        'business_type': original_company.business_type_id,
        'company_number': '01261539',
        'created_by': original_company.created_by_id,
        'duns_number': '123456789',
        'employee_range': original_company.employee_range_id,
        'export_experience_category':
        original_company.export_experience_category_id,
        'global_ultimate_duns_number': '291332174',
        'id': original_company.id,
        'is_number_of_employees_estimated': True,
        'modified_by': original_company.modified_by_id,
        'name': 'FOO BICYCLE LIMITED',
        'number_of_employees': 260,
        'sector': original_company.sector_id,
        'turnover': 50651895,
        'turnover_range': original_company.turnover_range_id,
        'uk_region': original_company.uk_region_id,
        'dnb_modified_on': now(),
    }
    expected_message = f'Syncing dnb-linked company "{company.id}" Succeeded'
    assert expected_message in caplog.text
class TestUpdateFromDNB(AdminTestMixin):
    """
    Tests GET requests to 'Update from DNB'.
    """
    def _create_company(self, **kwargs):
        self.company = CompanyFactory(**kwargs)
        change_url = reverse(
            admin_urlname(Company._meta, 'change'),
            args=(self.company.pk, ),
        )
        update_url = reverse(
            admin_urlname(Company._meta, 'update-from-dnb'),
            args=(self.company.pk, ),
        )
        return (change_url, update_url)

    def test_get(self, requests_mock, dnb_response):
        """
        Test that the link exists for a company with duns_number
        and a user with the change company permission.
        """
        change_url, update_url = self._create_company(duns_number='123456789')
        requests_mock.post(
            DNB_SEARCH_URL,
            json=dnb_response,
        )
        response = self.client.get(change_url)
        assert update_url in response.rendered_content
        response = self.client.get(update_url)
        response.status_code == status.HTTP_200_OK

    def test_get_view_permission_only(self):
        """
        Test that the link does not exist for a company with duns_number
        but a user with only the view company permission.
        """
        change_url, update_url = self._create_company(duns_number='123456789')
        user = create_test_user(
            permission_codenames=(CompanyPermission.view_company, ),
            is_staff=True,
            password=self.PASSWORD,
        )
        client = self.create_client(user=user)
        response = client.get(change_url)
        assert update_url not in response.rendered_content
        response = client.get(update_url)
        assert response.status_code == status.HTTP_403_FORBIDDEN

    def test_get_no_duns_number(self):
        """
        Test that the link does not exist when the company does not
        have a duns_number.
        """
        change_url, update_url = self._create_company()
        response = self.client.get(change_url)
        assert update_url not in response.rendered_content
        response = self.client.get(update_url)
        assert response.status_code == status.HTTP_400_BAD_REQUEST

    def test_post(self, requests_mock, dnb_response):
        """
        Test that a post request to 'upddate-from-dnb' updates
        the company.
        """
        _, update_url = self._create_company(
            duns_number='123456789',
            pending_dnb_investigation=True,
        )
        requests_mock.post(
            DNB_SEARCH_URL,
            json=dnb_response,
        )
        response = self.client.post(update_url)
        assert response.status_code == status.HTTP_302_FOUND

        self.company.refresh_from_db()
        dnb_company = dnb_response['results'][0]

        assert self.company.name == dnb_company['primary_name']
        assert self.company.address_1 == dnb_company['address_line_1']
        assert self.company.address_2 == dnb_company['address_line_2']
        assert self.company.address_town == dnb_company['address_town']
        assert self.company.address_county == dnb_company['address_county']
        assert self.company.address_country.iso_alpha2_code == dnb_company[
            'address_country']
        assert not self.company.pending_dnb_investigation
        assert (self.company.global_ultimate_duns_number ==
                dnb_company['global_ultimate_duns_number'])

        versions = list(Version.objects.get_for_object(self.company))
        assert len(versions) == 1
        assert versions[0].revision.comment == 'Updated from D&B'

    @pytest.mark.parametrize(
        'dnb_response_code',
        (
            status.HTTP_400_BAD_REQUEST,
            status.HTTP_401_UNAUTHORIZED,
            status.HTTP_403_FORBIDDEN,
            status.HTTP_404_NOT_FOUND,
            status.HTTP_500_INTERNAL_SERVER_ERROR,
        ),
    )
    def test_post_dnb_error(self, requests_mock, dnb_response_code):
        """
        Tests that the users get an error message if the dnb-service
        doesn't return with a 200 status code.
        """
        _, update_url = self._create_company(duns_number='123456789')
        requests_mock.post(
            DNB_SEARCH_URL,
            status_code=dnb_response_code,
        )
        response = self.client.post(update_url)
        assert response.status_code == status.HTTP_302_FOUND

        messages = list(get_messages(response.wsgi_request))
        assert len(messages) == 1
        assert str(
            messages[0]) == 'Something went wrong in an upstream service.'

    @pytest.mark.parametrize(
        'search_results, expected_message',
        (
            (
                [],
                'No matching company found in D&B database.',
            ),
            (
                ['foo', 'bar'],
                'Something went wrong in an upstream service.',
            ),
            (
                [{
                    'duns_number': '012345678'
                }],
                'Something went wrong in an upstream service.',
            ),
        ),
    )
    def test_post_dnb_response_invalid(
        self,
        requests_mock,
        search_results,
        expected_message,
    ):
        """
        Test if we get anything other than a single company from dnb-service,
        we return an error message to the user.
        """
        _, update_url = self._create_company(duns_number='123456789')
        requests_mock.post(
            DNB_SEARCH_URL,
            json={'results': search_results},
        )
        response = self.client.post(update_url)
        assert response.status_code == status.HTTP_302_FOUND

        messages = list(get_messages(response.wsgi_request))
        assert len(messages) == 1
        assert str(messages[0]) == expected_message

    def test_post_dnb_data_invalid(
        self,
        requests_mock,
        dnb_response,
    ):
        """
        Tests that if the data returned from DNB does not
        clear DataHub validation, we show an appropriate
        message to our users.
        """
        _, update_url = self._create_company(duns_number='123456789')
        dnb_response['results'][0]['primary_name'] = None
        requests_mock.post(
            DNB_SEARCH_URL,
            json=dnb_response,
        )
        response = self.client.post(update_url)
        assert response.status_code == status.HTTP_302_FOUND

        messages = list(get_messages(response.wsgi_request))
        assert len(messages) == 1
        assert str(
            messages[0]
        ) == 'Data from D&B did not pass the Data Hub validation checks.'
Example #28
0
    def test_update_company_from_dnb_all_fields(
        self,
        formatted_dnb_company,
        base_company_dict,
        adviser_callable,
        update_descriptor,
    ):
        """
        Test that update_company_from_dnb will update all fields when the fields
        kwarg is not specified.
        """
        duns_number = '123456789'
        company = CompanyFactory(duns_number=duns_number,
                                 pending_dnb_investigation=True)
        original_company = Company.objects.get(id=company.id)
        adviser = adviser_callable()
        update_company_from_dnb(
            company,
            formatted_dnb_company,
            user=adviser,
            update_descriptor=update_descriptor,
        )
        company.refresh_from_db()
        uk_country = Country.objects.get(iso_alpha2_code='GB')
        assert model_to_dict_company(company) == {
            **base_company_dict,
            'address_1':
            'Unit 10, Ockham Drive',
            'address_2':
            '',
            'address_country':
            uk_country.id,
            'address_county':
            '',
            'address_postcode':
            'UB6 0F2',
            'address_town':
            'GREENFORD',
            'archived_documents_url_path':
            original_company.archived_documents_url_path,
            'business_type':
            original_company.business_type.id,
            'company_number':
            '01261539',
            'created_by':
            original_company.created_by.id,
            'duns_number':
            '123456789',
            'employee_range':
            original_company.employee_range.id,
            'export_experience_category':
            original_company.export_experience_category.id,
            'global_ultimate_duns_number':
            '291332174',
            'id':
            original_company.id,
            'is_number_of_employees_estimated':
            True,
            'modified_by':
            adviser.id if adviser else original_company.modified_by.id,
            'name':
            'FOO BICYCLE LIMITED',
            'number_of_employees':
            260,
            'sector':
            original_company.sector.id,
            'turnover':
            50651895,
            'turnover_range':
            original_company.turnover_range.id,
            'uk_region':
            original_company.uk_region.id,
            'dnb_modified_on':
            now(),
        }

        versions = list(Version.objects.get_for_object(company))
        assert len(versions) == 1
        version = versions[0]

        if update_descriptor:
            assert version.revision.comment == f'Updated from D&B [{update_descriptor}]'
        else:
            assert version.revision.comment == 'Updated from D&B'

        assert version.revision.user == adviser
        if not adviser:
            assert company.modified_on == original_company.modified_on
Example #29
0
def test_update_company_from_dnb_data_partial_fields(dnb_response_uk):
    """
    Test the update_company_from_dnb_data command when a subset of DNB fields are updated.
    """
    company = CompanyFactory(duns_number='123456789')
    original_company = Company.objects.get(id=company.id)
    task_result = update_company_from_dnb_data.apply_async(
        args=[dnb_response_uk['results'][0]],
        kwargs={'fields_to_update': ['global_ultimate_duns_number']},
    )
    assert task_result.successful()
    company.refresh_from_db()
    assert model_to_dict(company) == {
        'address_1': original_company.address_1,
        'address_2': original_company.address_2,
        'address_country': original_company.address_country_id,
        'address_county': original_company.address_county,
        'address_postcode': original_company.address_postcode,
        'address_town': original_company.address_town,
        'archived': original_company.archived,
        'archived_by': original_company.archived_by,
        'archived_documents_url_path': original_company.archived_documents_url_path,
        'archived_on': original_company.archived_on,
        'archived_reason': original_company.archived_reason,
        'business_type': original_company.business_type_id,
        'company_number': original_company.company_number,
        'created_by': original_company.created_by_id,
        'description': original_company.description,
        'dnb_investigation_data': original_company.dnb_investigation_data,
        'duns_number': original_company.duns_number,
        'employee_range': original_company.employee_range_id,
        'export_experience_category': original_company.export_experience_category_id,
        'export_potential': original_company.export_potential,
        'export_to_countries': [],
        'future_interest_countries': [],
        'global_headquarters': original_company.global_headquarters,
        'global_ultimate_duns_number': '291332174',
        'great_profile_status': original_company.great_profile_status,
        'headquarter_type': original_company.headquarter_type,
        'id': original_company.id,
        'is_number_of_employees_estimated': original_company.is_number_of_employees_estimated,
        'is_turnover_estimated': original_company.is_turnover_estimated,
        'modified_by': original_company.modified_by_id,
        'name': original_company.name,
        'number_of_employees': original_company.number_of_employees,
        'one_list_account_owner': original_company.one_list_account_owner,
        'one_list_tier': original_company.one_list_tier,
        'pending_dnb_investigation': original_company.pending_dnb_investigation,
        'reference_code': original_company.reference_code,
        'registered_address_1': original_company.registered_address_1,
        'registered_address_2': original_company.registered_address_2,
        'registered_address_country': original_company.registered_address_country_id,
        'registered_address_county': original_company.registered_address_county,
        'registered_address_postcode': original_company.registered_address_postcode,
        'registered_address_town': original_company.registered_address_town,
        'sector': original_company.sector_id,
        'trading_names': original_company.trading_names,
        'transfer_reason': original_company.transfer_reason,
        'transferred_by': None,
        'transferred_on': None,
        'transferred_to': None,
        'turnover': original_company.turnover,
        'turnover_range': original_company.turnover_range_id,
        'uk_region': original_company.uk_region_id,
        'vat_number': original_company.vat_number,
        'website': original_company.website,
        'dnb_modified_on': now(),
    }
Example #30
0
    def test_merge_investment_projects_succeeds(self, fields):
        """
        Tests that perform_merge() moves investment projects to the target company and marks the
        source company as archived and transferred.
        """
        creation_time = datetime(2010, 12, 1, 15, 0, 10, tzinfo=utc)
        with freeze_time(creation_time):
            source_company = CompanyFactory()
            investment_project = InvestmentProjectFactory(
                **{field: source_company
                   for field in fields}, )

        target_company = CompanyFactory()
        user = AdviserFactory()

        merge_time = datetime(2011, 2, 1, 14, 0, 10, tzinfo=utc)

        with freeze_time(merge_time):
            result = merge_companies(source_company, target_company, user)

        other_fields = set(INVESTMENT_PROJECT_COMPANY_FIELDS) - set(fields)

        assert result == {
            # each interaction has a contact, that's why 4 contacts should be moved
            CompanyListItem: {
                'company': 0
            },
            Contact: {
                'company': 0
            },
            Interaction: {
                'company': 0
            },
            InvestmentProject: {
                **{field: 1
                   for field in fields},
                **{field: 0
                   for field in other_fields},
            },
            Order: {
                'company': 0
            },
        }

        investment_project.refresh_from_db()

        assert all(
            getattr(investment_project, field) == target_company
            for field in fields)
        assert all(
            getattr(investment_project, field) != target_company
            for field in other_fields)
        assert all(
            getattr(investment_project, field) != source_company
            for field in other_fields)

        assert investment_project.modified_on == creation_time

        source_company.refresh_from_db()

        assert source_company.archived
        assert source_company.archived_by == user
        assert source_company.archived_on == merge_time
        assert source_company.archived_reason == (
            f'This record is no longer in use and its data has been transferred '
            f'to {target_company} for the following reason: Duplicate record.')
        assert source_company.modified_by == user
        assert source_company.modified_on == merge_time
        assert source_company.transfer_reason == Company.TRANSFER_REASONS.duplicate
        assert source_company.transferred_by == user
        assert source_company.transferred_on == merge_time
        assert source_company.transferred_to == target_company