def test_company_export_country_history_delete(self): """ Test that deleting an existing CompanyExportCountry record sets up a corresponding history record. """ export_country = CompanyExportCountryFactory( status=CompanyExportCountry.EXPORT_INTEREST_STATUSES. future_interest, ) history = CompanyExportCountryHistory.objects.filter( id=export_country.id) assert len(history) == 1 assert history[0].id == export_country.id assert history[0].company == export_country.company assert history[0].country == export_country.country assert history[0].status == export_country.status assert history[ 0].history_type == CompanyExportCountryHistory.HISTORY_TYPES.insert export_country_id = export_country.id export_country.delete() history = CompanyExportCountryHistory.objects.filter( id=export_country_id, ).order_by('history_date') assert len(history) == 2 assert history[0].id == export_country_id assert history[ 0].status == CompanyExportCountry.EXPORT_INTEREST_STATUSES.future_interest assert history[ 0].history_type == CompanyExportCountryHistory.HISTORY_TYPES.insert assert history[1].id == export_country_id assert history[ 1].status == CompanyExportCountry.EXPORT_INTEREST_STATUSES.future_interest assert history[ 1].history_type == CompanyExportCountryHistory.HISTORY_TYPES.delete
def test_merge_allowed_when_source_company_has_export_countries(self): """Test that merging is allowed if the source company has export countries.""" source_company = CompanyFactory() CompanyExportCountryFactory(company=source_company) CompanyExportCountryHistoryFactory(company=source_company) target_company = CompanyFactory() user = AdviserFactory() merge_time = datetime(2011, 2, 1, 14, 0, 10, tzinfo=utc) with freeze_time(merge_time): merge_companies(source_company, target_company, user) 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.TransferReason.DUPLICATE assert source_company.transferred_by == user assert source_company.transferred_on == merge_time assert source_company.transferred_to == target_company
def test_update_company_export_countries_with_empty_list_deletes_all( self, ): """ Test when updating company export countries with an empty list and make sure all items are removed. """ company = CompanyFactory() export_country_one, export_country_two = CompanyExportCountryFactory.create_batch( 2) company.export_countries.set([export_country_one, export_country_two]) input_export_countries = { 'export_countries': [], } 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_get_company_with_export_countries(self): """ Tests the company response has export countries that are in the new CompanyExportCountry model. """ company = CompanyFactory() export_country_one, export_country_two = CompanyExportCountryFactory.create_batch( 2) company.export_countries.set([export_country_one, export_country_two]) user = create_test_user(permission_codenames=( 'view_company', 'view_companyexportcountry', ), ) api_client = self.create_api_client(user=user) url = reverse('api-v4:company:item', kwargs={'pk': company.id}) response = api_client.get(url) assert response.status_code == status.HTTP_200_OK assert response.json().get('export_countries', []) is not [] export_countries_response = response.json().get('export_countries') assert export_countries_response == [{ 'country': { 'id': str(item.country.pk), 'name': item.country.name, }, 'status': item.status, } for item in company.export_countries.order_by('pk')]
def test_unique_constraint(self): """ Test unique constraint a company and country combination can't be added more than once """ company_1 = CompanyFactory() country = random_obj_for_model(Country) CompanyExportCountryFactory( company=company_1, country=country, ) with pytest.raises(IntegrityError): CompanyExportCountryFactory( company=company_1, country=country, )
def test_company_export_country_history_create(self): """ Test that creating new CompanyExportCountry record sets up a corresponding history record. """ export_country = CompanyExportCountryFactory() history = CompanyExportCountryHistory.objects.filter( id=export_country.id) assert len(history) == 1 assert history[0].id == export_country.id assert history[0].company == export_country.company assert history[0].country == export_country.country assert history[0].status == export_country.status assert history[ 0].history_type == CompanyExportCountryHistory.HISTORY_TYPES.insert
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
def test_company_export_country_history_update(self): """ Test that updating an existing CompanyExportCountry record sets up a corresponding history record. """ company = CompanyFactory() country = random_obj_for_model(CountryModel) 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, ) # update it, by changing status company.add_export_country( country, CompanyExportCountry.Status.CURRENTLY_EXPORTING, now(), adviser, True, ) history = CompanyExportCountryHistory.objects.filter( id=export_country.id, ).order_by('history_date') assert history.count() == 2 assert history[0].id == export_country.id assert history[0].company == export_country.company assert history[0].country == export_country.country assert history[0].status == export_country.status assert history[ 0].history_type == CompanyExportCountryHistory.HistoryType.INSERT assert history[1].id == export_country.id assert history[1].company == export_country.company assert history[1].country == export_country.country assert history[ 1].status == CompanyExportCountry.Status.CURRENTLY_EXPORTING assert history[ 1].history_type == CompanyExportCountryHistory.HistoryType.UPDATE
def test_company_export_country_history_update_with_no_change(self): """ Test that submitting an update for a CompanyExportCountry record that doesn't change any field (i.e status) does not create a history record. """ company = CompanyFactory() country = random_obj_for_model(CountryModel) 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, ) history = CompanyExportCountryHistory.objects.filter( id=export_country.id) assert history.count() == 1 assert history[ 0].history_type == CompanyExportCountryHistory.HistoryType.INSERT # update it, but don't modify the status company.add_export_country( country, CompanyExportCountry.Status.FUTURE_INTEREST, company.created_on, adviser, True, ) # export country history records should be unchanged history = CompanyExportCountryHistory.objects.filter( id=export_country.id) assert history.count() == 1 assert history[ 0].history_type == CompanyExportCountryHistory.HistoryType.INSERT
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_delete_company_export_country_no_signal(self): """ Test that attempting to delete an nonexisting CompanyExportCountry record won't send a signal and won't track history """ company = CompanyFactory() countries = CountryModel.objects.order_by('name')[:2] adviser = AdviserFactory() export_country = CompanyExportCountryFactory( company=company, country=countries[0], status=CompanyExportCountry.Status.FUTURE_INTEREST, ) company.delete_export_country(countries[1].id, adviser) history = CompanyExportCountryHistory.objects.filter( id=export_country.id, history_type=CompanyExportCountryHistory.HistoryType.DELETE, ) assert history.count() == 0
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
def test_company_export_country_history_delete(self): """ Test that deleting an existing CompanyExportCountry record sets up a corresponding history record. """ company = CompanyFactory() country = CountryModel.objects.order_by('name')[0] adviser = AdviserFactory() export_country = CompanyExportCountryFactory( company=company, country=country, status=CompanyExportCountry.Status.FUTURE_INTEREST, ) company.delete_export_country(country.id, adviser) history = CompanyExportCountryHistory.objects.filter( id=export_country.id, history_type=CompanyExportCountryHistory.HistoryType.DELETE, ) assert history.count() == 1 assert history[0].id == export_country.id assert history[0].status == CompanyExportCountry.Status.FUTURE_INTEREST assert history[0].history_type == CompanyExportCountryHistory.HistoryType.DELETE
def setup_data(opensearch_with_collector): """Sets up data for the tests.""" country_uk = constants.Country.united_kingdom.value.id country_us = constants.Country.united_states.value.id country_anguilla = constants.Country.anguilla.value.id uk_region = constants.UKRegion.south_east.value.id company1 = CompanyFactory( name='abc defg ltd', trading_names=['helm', 'nop'], address_1='1 Fake Lane', address_town='Downtown', address_country_id=country_uk, registered_address_country_id=country_uk, uk_region_id=uk_region, ) CompanyExportCountryFactory( company=company1, country_id=constants.Country.france.value.id, status=CompanyExportCountry.Status.CURRENTLY_EXPORTING, ) CompanyExportCountryFactory( company=company1, country_id=constants.Country.japan.value.id, status=CompanyExportCountry.Status.FUTURE_INTEREST, ) CompanyExportCountryFactory( company=company1, country_id=constants.Country.united_states.value.id, status=CompanyExportCountry.Status.FUTURE_INTEREST, ) company2 = CompanyFactory( name='abc defg us ltd', trading_names=['helm', 'nop', 'qrs'], address_1='1 Fake Lane', address_town='Downtown', address_country_id=country_us, registered_address_country_id=country_us, ) CompanyExportCountryFactory( company=company2, country_id=constants.Country.canada.value.id, status=CompanyExportCountry.Status.CURRENTLY_EXPORTING, ) CompanyExportCountryFactory( company=company2, country_id=constants.Country.france.value.id, status=CompanyExportCountry.Status.CURRENTLY_EXPORTING, ) CompanyExportCountryFactory( company=company2, country_id=constants.Country.japan.value.id, status=CompanyExportCountry.Status.FUTURE_INTEREST, ) CompanyFactory( name='archived', trading_names=[], address_1='Main Lane', address_town='Somewhere', address_country_id=country_anguilla, registered_address_country_id=country_anguilla, archived=True, ) opensearch_with_collector.flush_and_refresh()
def test_export( self, opensearch_with_collector, request_sortby, orm_ordering, ): """Test export of company search results.""" companies_1 = CompanyFactory.create_batch( 3, turnover=None, is_turnover_estimated=None, number_of_employees=None, is_number_of_employees_estimated=None, ) companies_2 = CompanyFactory.create_batch( 2, hq=True, turnover=100, is_turnover_estimated=True, number_of_employees=95, is_number_of_employees_estimated=True, ) for company in (*companies_1, *companies_2): CompanyExportCountryFactory.create_batch( 3, company=company, country=factory.Iterator(Country.objects.order_by('?'), ), status=factory.Iterator([ CompanyExportCountry.Status.CURRENTLY_EXPORTING, CompanyExportCountry.Status.FUTURE_INTEREST, CompanyExportCountry.Status.CURRENTLY_EXPORTING, ], ), ) opensearch_with_collector.flush_and_refresh() data = {} if request_sortby: data['sortby'] = request_sortby url = reverse('api-v4:search:company-export') with freeze_time('2018-01-01 11:12:13'): response = self.api_client.post(url, data=data) assert response.status_code == status.HTTP_200_OK assert parse_header(response.get('Content-Type')) == ('text/csv', { 'charset': 'utf-8' }) assert parse_header(response.get('Content-Disposition')) == ( 'attachment', { 'filename': 'Data Hub - Companies - 2018-01-01-11-12-13.csv' }, ) sorted_company = Company.objects.order_by(orm_ordering, 'pk') reader = DictReader(StringIO(response.getvalue().decode('utf-8-sig'))) assert reader.fieldnames == list( SearchCompanyExportAPIView().field_titles.values()) expected_row_data = [{ 'Name': company.name, 'Link': f'{settings.DATAHUB_FRONTEND_URL_PREFIXES["company"]}/{company.pk}', 'Sector': get_attr_or_none(company, 'sector.name'), 'Area': get_attr_or_none(company, 'address_area.name'), 'Country': get_attr_or_none(company, 'address_country.name'), 'UK region': get_attr_or_none(company, 'uk_region.name'), 'Countries exported to': ', '.join([ e.country.name for e in company.export_countries.filter( status=CompanyExportCountry.Status.CURRENTLY_EXPORTING, ).order_by('country__name') ]), 'Countries of interest': ', '.join([ e.country.name for e in company.export_countries.filter( status=CompanyExportCountry.Status.FUTURE_INTEREST, ).order_by('country__name') ]), 'Archived': company.archived, 'Date created': company.created_on, 'Number of employees': (company.number_of_employees if company.number_of_employees is not None else get_attr_or_none( company, 'employee_range.name')), 'Annual turnover': (f'${company.turnover}' if company.turnover is not None else get_attr_or_none(company, 'turnover_range.name')), 'Headquarter type': (get_attr_or_none(company, 'headquarter_type.name') or '').upper(), } for company in sorted_company] assert list(dict(row) for row in reader) == format_csv_data(expected_row_data)
def test_successfully_copies_from_company_model_when_duplicates_involved( self, monkeypatch, num_objects, batch_size, expected_batches, ): """Test that the task copies data for various batch sizes.""" new_countries = list(Country.objects.order_by('?')[:7]) new_export_to_countries = new_countries[:3] new_future_interest_countries = new_countries[:5] task_mock = Mock( wraps=copy_export_countries_to_company_export_country_model, ) monkeypatch.setattr( 'datahub.dbmaintenance.tasks.copy_export_countries_to_company_export_country_model', task_mock, ) companies_to_update = CompanyFactory.create_batch( num_objects, export_to_countries=new_export_to_countries, future_interest_countries=new_future_interest_countries, ) # populate destination table with countries that overlap # with the countries we're adding through the task for company in companies_to_update: for country in new_future_interest_countries: CompanyExportCountryFactory( company=company, country=country, status='future_interest', ) result_currently_exporting = task_mock.apply_async(kwargs={ 'batch_size': batch_size, 'status': 'currently_exporting', }, ) assert result_currently_exporting.successful() updated_countries = CompanyExportCountry.objects.filter( company__in=companies_to_update) assert set([ export_country.company for export_country in updated_countries ]) == set(companies_to_update) assert all([[ item.country in set(new_future_interest_countries) - set(new_export_to_countries) and item.country not in new_export_to_countries for item in CompanyExportCountry.objects.filter( country_id=export_country.country.pk, ) ] for export_country in updated_countries.filter( status='future_interest')]) assert all([[ item.country in new_export_to_countries for item in CompanyExportCountry.objects.filter( country_id=export_country.country.pk, status='currently_exporting', ) ] for export_country in updated_countries.filter( status='currently_exporting')])
def test_successfully_copies_from_company_model_currently_exporting( self, monkeypatch, num_objects, batch_size, expected_batches, ): """Test that the task copies data for various batch sizes.""" task_mock = Mock( wraps=copy_export_countries_to_company_export_country_model, ) monkeypatch.setattr( 'datahub.dbmaintenance.tasks.copy_export_countries_to_company_export_country_model', task_mock, ) countries = list(Country.objects.order_by('?')[:num_objects + 5]) mock_export_to_countries = countries[:num_objects] other_countries_list = countries[num_objects:] companies_to_update = CompanyFactory.create_batch( num_objects, export_to_countries=mock_export_to_countries, ) current_countries_already_in_the_new_table = CompanyExportCountryFactory.create_batch( 5, company=factory.SubFactory(CompanyFactory), country=factory.Iterator(other_countries_list), status='currently_exporting', ) result_currently_exporting = task_mock.apply_async(kwargs={ 'batch_size': batch_size, 'status': 'currently_exporting', }, ) assert result_currently_exporting.successful() updated_countries = CompanyExportCountry.objects.filter( company__in=companies_to_update) assert set([ export_country.company for export_country in updated_countries ]) == set(companies_to_update) assert set(item.country for item in set(updated_countries)) == set( mock_export_to_countries) assert all([ set( CompanyExportCountry.objects.filter( ~Q( country_id__in=[ export_country.country.pk for export_country in updated_countries ], status='currently_exporting', ), )) == set(current_countries_already_in_the_new_table), ], )
def test_str(self): """Test the human friendly string representation of the object""" export_country = CompanyExportCountryFactory() status = f'{export_country.company} {export_country.country} {export_country.status}' assert str(export_country) == status