def test_sort_by_first_and_last_name_of_first_contact(self, primary_field, secondary_field): """Test sorting interactions by the first and last names of the first contact.""" contacts = [ ContactFactory(**{primary_field: 'Alfred', secondary_field: 'Jones'}), ContactFactory(**{primary_field: 'Alfred', secondary_field: 'Terry'}), ContactFactory(**{primary_field: 'Thomas', secondary_field: 'Richards'}), ContactFactory(**{primary_field: 'Thomas', secondary_field: 'West'}), ] interactions = [ EventServiceDeliveryFactory(contacts=[contact]) for contact in sample(contacts, len(contacts)) ] url = reverse('api-v3:interaction:collection') response = self.api_client.get( url, data={ 'sortby': f'{primary_field}_of_first_contact,{secondary_field}_of_first_contact', }, ) assert response.status_code == status.HTTP_200_OK response_data = response.json() assert response_data['count'] == len(interactions) actual_ids = [ interaction['contacts'][0]['id'] for interaction in response_data['results'] ] expected_ids = [str(person.pk) for person in contacts] assert actual_ids == expected_ids
def test_audit_log(s3_stubber): """Test that reversion revisions are created.""" contact_without_change = ContactFactory(accepts_dit_email_marketing=True, ) contact_with_change = ContactFactory(accepts_dit_email_marketing=False, ) bucket = 'test_bucket' object_key = 'test_key' csv_content = f"""id,accepts_dit_email_marketing {contact_without_change.pk},True {contact_with_change.pk},True """ s3_stubber.add_response( 'get_object', { 'Body': BytesIO(csv_content.encode(encoding='utf-8')), }, expected_params={ 'Bucket': bucket, 'Key': object_key, }, ) call_command('update_contact_accepts_dit_email_marketing', bucket, object_key) versions = Version.objects.get_for_object(contact_without_change) assert versions.count() == 0 versions = Version.objects.get_for_object(contact_with_change) assert versions.count() == 1 assert versions[0].revision.get_comment( ) == 'Accepts DIT email marketing correction.'
def test_error_returned_if_contacts_dont_belong_to_company(self): """ Test that an error is returned if the contacts don't belong to the specified company. """ company = CompanyFactory() contacts = [ContactFactory(), ContactFactory(company=company)] communication_channel = random_obj_for_model(CommunicationChannel) url = reverse('api-v3:interaction:collection') request_data = { 'kind': Interaction.Kind.INTERACTION, 'communication_channel': communication_channel.pk, 'subject': 'whatever', 'date': date.today().isoformat(), 'dit_participants': [ {'adviser': self.user.pk}, ], 'company': { 'id': company.pk, }, 'contacts': [{ 'id': contact.pk, } for contact in contacts], 'service': { 'id': random_service().pk, }, 'was_policy_feedback_provided': False, } api_client = self.create_api_client() response = api_client.post(url, request_data) assert response.status_code == status.HTTP_400_BAD_REQUEST assert response.json() == { 'non_field_errors': ['The interaction contacts must belong to the specified company.'], }
def test_makes_api_call_to_consent_service( self, data_flow_api_client, consent_get_many_mock, ): """ Test that if consent feature flag is enabled then call is made to the consent service and values from that are in the response. """ FeatureFlagFactory(code=GET_CONSENT_FROM_CONSENT_SERVICE, is_active=True) contact1 = ContactFactory(email='[email protected]') contact2 = ContactFactory(email='[email protected]') contact3 = ContactFactory(email='[email protected]') consent_get_many_mock.return_value = { contact1.email: True, contact2.email: False, } response = data_flow_api_client.get(self.view_url) assert response.status_code == status.HTTP_200_OK consent_get_many_mock.assert_called_once_with( [contact1.email, contact2.email, contact3.email], ) response_results = response.json()['results'] assert response_results[0]['accepts_dit_email_marketing'] assert not response_results[1]['accepts_dit_email_marketing'] assert not response_results[2]['accepts_dit_email_marketing']
def test_archive_no_updates(self): """ Test contact archiving with no updates on contacts """ date = timezone.now() - relativedelta(days=10) with freeze_time(date): company1 = CompanyFactory() company2 = CompanyFactory() contact1 = ContactFactory(company=company1) contact2 = ContactFactory(company=company2) contact3 = ContactFactory(company=company2) for c in [contact1, contact2, contact3]: assert c.archived is False assert c.archived_reason is None assert c.archived_on is None # run task twice expecting same result for _ in range(2): task_result = automatic_contact_archive.apply_async( kwargs={'limit': 200}) assert task_result.successful() for c in [contact1, contact2, contact3]: c.refresh_from_db() assert c.archived is False assert c.archived_reason is None assert c.archived_on is None
def _company_factory( num_interactions=0, num_contacts=0, num_investment_projects=0, num_orders=0, num_referrals=0, num_company_list_items=0, num_pipeline_items=0, ): """ Factory for a company that has companies, interactions, investment projects and OMIS orders. """ company = CompanyFactory() ContactFactory.create_batch(num_contacts, company=company) CompanyInteractionFactory.create_batch(num_interactions, company=company) CompanyReferralFactory.create_batch(num_referrals, company=company, contact=None) OrderFactory.create_batch(num_orders, company=company) CompanyListItemFactory.create_batch(num_company_list_items, company=company) PipelineItemFactory.create_batch(num_pipeline_items, company=company) fields_iter = cycle(INVESTMENT_PROJECT_COMPANY_FIELDS) fields = islice(fields_iter, 0, num_investment_projects) InvestmentProjectFactory.create_batch( num_investment_projects, **{field: company for field in fields}, ) return company
def test_validate_project_instance_success(): """Tests validating a complete project section using a model instance.""" project = InvestmentProjectFactory( client_contacts=[ContactFactory().id, ContactFactory().id], ) errors = validate(instance=project, fields=CORE_FIELDS) assert not errors
def test_search_contact_sort_by_last_name_desc(self, opensearch_with_collector): """Tests sorting in descending order.""" ContactFactory(first_name='test_name', last_name='abcdef') ContactFactory(first_name='test_name', last_name='bcdefg') ContactFactory(first_name='test_name', last_name='cdefgh') ContactFactory(first_name='test_name', last_name='defghi') opensearch_with_collector.flush_and_refresh() term = 'test_name' url = reverse('api-v3:search:contact') response = self.api_client.post( url, data={ 'original_query': term, 'sortby': 'last_name:desc', }, ) assert response.status_code == status.HTTP_200_OK assert response.data['count'] == 4 assert [ 'defghi', 'cdefgh', 'bcdefg', 'abcdef', ] == [contact['last_name'] for contact in response.data['results']]
def _company_factory(num_interactions, num_contacts, num_orders): """Factory for a company that has companies, interactions and OMIS orders.""" company = CompanyFactory() ContactFactory.create_batch(num_contacts, company=company) CompanyInteractionFactory.create_batch(num_interactions, company=company) OrderFactory.create_batch(num_orders, company=company) return company
def setup_data(): """Sets up data for the tests.""" contacts = [ ContactFactory(first_name='abc', last_name='defg'), ContactFactory(first_name='first', last_name='last'), ] yield contacts
def test_search_contact_by_partial_company_name(self, setup_es, term, match): """Tests filtering by partially matching company name.""" matching_company = CompanyFactory( name='whiskers and tabby', alias='house lion and moggie', ) non_matching_company = CompanyFactory( name='Pluto and pippo', alias='Epsilon and lippo', ) matching_contact = ContactFactory(company=matching_company) ContactFactory(company=non_matching_company) setup_es.indices.refresh() url = reverse('api-v3:search:contact') response = self.api_client.post( url, data={ 'original_query': '', 'company_name': term, }, ) assert response.status_code == status.HTTP_200_OK if match: assert response.data['count'] == 1 assert len(response.data['results']) == 1 assert response.data['results'][0]['id'] == str( matching_contact.id) else: assert response.data['count'] == 0 assert len(response.data['results']) == 0
def test_all(self): """Test getting all contacts""" ContactFactory.create_batch(5) url = reverse('api-v3:contact:list') response = self.api_client.get(url) assert response.status_code == status.HTTP_200_OK assert response.data['count'] == 5
def test_does_not_allow_file_with_bad_utf8_after_header(self, monkeypatch): """ Test that the form rejects a CSV file with invalid UTF-8 after its header. As reading and decoding happens in chunks, we patch the the function to validate the columns in the form because it can decode text that is close to the header. (That means in reality, this check will only be triggered for invalid Unicode sequences that are relatively deep in the file.) """ monkeypatch.setattr( 'datahub.company.admin.contact.LoadEmailMarketingOptOutsForm._validate_columns', Mock(), ) creation_time = datetime(2011, 2, 1, 14, 0, 10, tzinfo=utc) with freeze_time(creation_time): contact = ContactFactory( email='test1@datahub', accepts_dit_email_marketing=True, ) csv_body = b""""email\r test1@datahub\r \xc3\x28 """ file = io.BytesIO( b''.join((BOM_UTF8, csv_body)), ) file.name = 'test.csv' url = reverse( admin_urlname(Contact._meta, 'load-email-marketing-opt-outs'), ) with freeze_time('2014-05-03 19:00:16'): response = self.client.post( url, data={ 'email_list': file, }, ) assert response.status_code == status.HTTP_200_OK messages = list(response.context['messages']) assert len(messages) == 1 assert messages[0].level == django_messages.ERROR assert messages[0].message == ( 'There was an error decoding the text in the file provided. No records have been ' 'modified.' ) # Changes should have been rolled back contact.refresh_from_db() assert contact.accepts_dit_email_marketing is True assert contact.modified_on == creation_time
def unrelated_objects(): """ Create some objects not related to a known company. This is used in tests below to make sure objects unrelated to the company being merged do not affect the counts of objects that will be affected by the merge. """ ContactFactory.create_batch(2) CompanyInteractionFactory.create_batch(2) OrderFactory.create_batch(2) InvestmentProjectFactory.create_batch(2)
def setup_data(setup_es): """Sets up data for the tests.""" with freeze_time('2017-01-01 13:00:00'): company = CompanyFactory(name='Mercury trading', alias='Uranus supplies') contact = ContactFactory(company=company, first_name='John', last_name='Doe') order = OrderFactory( reference='abcd', primary_market_id=constants.Country.japan.value.id, uk_region_id=constants.UKRegion.channel_islands.value.id, assignees=[], status=OrderStatus.draft, company=company, contact=contact, discount_value=0, delivery_date=dateutil_parse('2018-01-01').date(), vat_verified=False, ) OrderSubscriberFactory( order=order, adviser=AdviserFactory(dit_team_id=constants.Team.healthcare_uk.value.id), ) OrderAssigneeFactory( order=order, adviser=AdviserFactory(dit_team_id=constants.Team.tees_valley_lep.value.id), estimated_time=60, ) with freeze_time('2017-02-01 13:00:00'): company = CompanyFactory(name='Venus Ltd', alias='Earth outsourcing') contact = ContactFactory(company=company, first_name='Jenny', last_name='Cakeman') order = OrderWithAcceptedQuoteFactory( reference='efgh', primary_market_id=constants.Country.france.value.id, uk_region_id=constants.UKRegion.east_midlands.value.id, assignees=[], status=OrderStatus.quote_awaiting_acceptance, company=company, contact=contact, discount_value=0, delivery_date=dateutil_parse('2018-02-01').date(), vat_verified=False, ) OrderSubscriberFactory( order=order, adviser=AdviserFactory(dit_team_id=constants.Team.td_events_healthcare.value.id), ) OrderAssigneeFactory( order=order, adviser=AdviserFactory(dit_team_id=constants.Team.food_from_britain.value.id), estimated_time=120, ) setup_es.indices.refresh()
def setup_data(): """Sets up data for the tests.""" contacts = [ ContactFactory( first_name='abc', last_name='defg', company=CompanyFactory( address_country_id=Country.united_kingdom.value.id, ), ), ContactFactory(first_name='first', last_name='last'), ] yield contacts
def setup_data(): """Sets up the data and makes the ES client available.""" ContactFactory( first_name='abc', last_name='defg', company__name='name0', company__trading_names=['trading0'], ) ContactFactory( first_name='first', last_name='last', company__name='name1', company__trading_names=['trading1'], ) InvestmentProjectFactory( name='abc defg', description='investmentproject1', estimated_land_date=datetime.datetime(2011, 6, 13, 9, 44, 31, 62870), project_manager=AdviserFactory(first_name='name 0', last_name='surname 0'), project_assurance_adviser=AdviserFactory(first_name='name 1', last_name='surname 1'), investor_company=CompanyFactory(name='name3', trading_names=['trading3']), client_relationship_manager=AdviserFactory(first_name='name 2', last_name='surname 2'), referral_source_adviser=AdviserFactory(first_name='name 3', last_name='surname 3'), client_contacts=[], ) InvestmentProjectFactory( description='investmentproject2', estimated_land_date=datetime.datetime(2057, 6, 13, 9, 44, 31, 62870), project_manager=AdviserFactory(first_name='name 4', last_name='surname 4'), project_assurance_adviser=AdviserFactory(first_name='name 5', last_name='surname 5'), investor_company=CompanyFactory(name='name4', trading_names=['trading4']), client_relationship_manager=AdviserFactory(first_name='name 6', last_name='surname 6'), referral_source_adviser=AdviserFactory(first_name='name 7', last_name='surname 7'), client_contacts=[], ) country_uk = constants.Country.united_kingdom.value.id country_us = constants.Country.united_states.value.id CompanyFactory( name='abc defg ltd', trading_names=['abc defg trading ltd'], address_1='1 Fake Lane', address_town='Downtown', address_country_id=country_uk, ) CompanyFactory( name='abc defg us ltd', trading_names=['abc defg us trading ltd'], address_1='1 Fake Lane', address_town='Downtown', address_country_id=country_us, registered_address_country_id=country_us, )
def test_simulate(self, caplog, simulate): """ Test contact archiving simulate flag """ caplog.set_level(logging.INFO, logger='datahub.company.tasks.contact') date = timezone.now() - relativedelta(days=10) with freeze_time(date): company1 = CompanyFactory() company2 = CompanyFactory(archived=True) contact1 = ContactFactory(company=company1) contact2 = ContactFactory(company=company2) task_result = automatic_contact_archive.apply_async( kwargs={'simulate': simulate}) contact1.refresh_from_db() contact2.refresh_from_db() if simulate: assert caplog.messages == [ f'[SIMULATION] Automatically archived contact: {contact2.id}', ] else: assert task_result.successful() assert contact1.archived is False assert contact2.archived is True assert caplog.messages == [ f'Automatically archived contact: {contact2.id}' ]
def test_filter_by_contact(self): """Test filtering interactions by contact (using contacts__id).""" contact1 = ContactFactory() contact2 = ContactFactory() CompanyInteractionFactory.create_batch(3, contacts=[contact1]) interactions = CompanyInteractionFactory.create_batch(2, contacts=[contact1, contact2]) url = reverse('api-v3:interaction:collection') response = self.api_client.get(url, data={'contacts__id': contact2.id}) assert response.status_code == status.HTTP_200_OK assert response.data['count'] == 2 assert {i['id'] for i in response.data['results']} == {str(i.id) for i in interactions}
def test_updates_audit_log(self): """Test that audit log entries are created for modified contacts.""" creation_time = datetime(2011, 2, 1, 14, 0, 10, tzinfo=utc) with freeze_time(creation_time): contact_with_change = ContactFactory( email='test1@datahub', accepts_dit_email_marketing=True, ) contact_without_change = ContactFactory( email='test2@datahub', accepts_dit_email_marketing=True, ) contact_already_opted_out = ContactFactory( email='test1@datahub', accepts_dit_email_marketing=False, ) file = io.BytesIO("""email\r test1@datahub\r """.encode()) file.name = 'test.csv' url = reverse( admin_urlname(Contact._meta, 'load-email-marketing-opt-outs'), ) post_time = datetime(2014, 5, 3, 19, 0, 16, tzinfo=utc) with freeze_time(post_time): response = self.client.post( url, follow=True, data={ 'email_list': file, }, ) assert response.status_code == status.HTTP_200_OK assert len(response.redirect_chain) == 1 change_list_url = reverse(admin_urlname(Contact._meta, 'changelist')) assert response.redirect_chain[0][0] == change_list_url versions = Version.objects.get_for_object(contact_with_change) assert versions.count() == 1 assert versions[0].revision.get_comment() == 'Loaded bulk email opt-out list.' versions = Version.objects.get_for_object(contact_without_change) assert versions.count() == 0 versions = Version.objects.get_for_object(contact_already_opted_out) assert versions.count() == 0
def test_email_filter(self, opensearch_with_collector, contacts, filter_, expected): """Tests the email filter""" ContactFactory.create_batch(len(contacts), email=factory.Iterator(contacts)) opensearch_with_collector.flush_and_refresh() response = self.api_client.post( reverse('api-v3:search:contact'), data=dict(email=filter_), ) assert response.status_code == status.HTTP_200_OK assert {res['email'] for res in response.data['results']} == expected
def _company_factory( num_interactions=0, num_contacts=0, num_orders=0, num_referrals=0, num_company_list_items=0, ): """Factory for a company that has companies, interactions and OMIS orders.""" company = CompanyFactory() ContactFactory.create_batch(num_contacts, company=company) CompanyInteractionFactory.create_batch(num_interactions, company=company) CompanyReferralFactory.create_batch(num_referrals, company=company, contact=None) OrderFactory.create_batch(num_orders, company=company) CompanyListItemFactory.create_batch(num_company_list_items, company=company) return company
def test_all_without_view_document_permission(self): """Test getting all contacts without view document permission.""" ContactFactory.create_batch( 5, archived_documents_url_path='https://some-docs') user = create_test_user(permission_codenames=('view_contact', ), ) api_client = self.create_api_client(user=user) url = reverse('api-v3:contact:list') response = api_client.get(url) assert response.status_code == status.HTTP_200_OK assert response.data['count'] == 5 assert all('archived_documents_url_path' not in contact for contact in response.data['results'])
def test_filter_without_uk_region(self, opensearch_with_collector): """Tests matching contact without uk_region using multiple filters.""" company = CompanyFactory( registered_address_country_id=Country.united_states.value.id, address_country_id=Country.united_states.value.id, uk_region_id=None, sector_id=Sector.renewable_energy_wind.value.id, ) ContactFactory( address_same_as_company=True, company=company, ) opensearch_with_collector.flush_and_refresh() url = reverse('api-v3:search:contact') response = self.api_client.post( url, data={ 'company_name': company.name, 'company_sector': company.sector_id, 'address_country': company.address_country_id, }, ) assert response.status_code == status.HTTP_200_OK assert response.data['count'] == 1 contact = response.data['results'][0] assert contact['address_country']['id'] == company.address_country_id assert contact['company']['name'] == company.name assert contact['company_uk_region'] is None assert contact['company_sector']['id'] == company.sector_id
def test_filter_by_company(self): """Test getting contacts by company id""" company1 = CompanyFactory() company2 = CompanyFactory() ContactFactory.create_batch(3, company=company1) contacts = ContactFactory.create_batch(2, company=company2) url = reverse('api-v3:contact:list') response = self.api_client.get(url, data={'company_id': company2.id}) assert response.status_code == status.HTTP_200_OK assert response.data['count'] == 2 expected_contacts = {str(contact.id) for contact in contacts} assert {contact['id'] for contact in response.data['results']} == expected_contacts
def test_unarchive_wrong_method(self): """Tests that GET requests to the unarchive endpoint fail.""" contact = ContactFactory(archived=True, archived_reason='foo') url = reverse('api-v3:contact:unarchive', kwargs={'pk': contact.pk}) response = self.api_client.get(url) assert response.status_code == status.HTTP_405_METHOD_NOT_ALLOWED
def test_with_empty_order(self): """ Test that an order without any of the billing fields filled in is populated with the company/contact details. """ contact = ContactFactory() company = CompanyWithRegAddressFactory() order = OrderWithoutBillingDataFactory( company=company, contact=contact, ) populate_billing_data(order) assert not order.billing_contact_name assert not order.billing_email assert not order.billing_phone assert order.billing_company_name == company.name assert order.billing_address_1 == company.registered_address_1 assert order.billing_address_2 == company.registered_address_2 assert order.billing_address_town == company.registered_address_town assert order.billing_address_county == company.registered_address_county assert order.billing_address_postcode == company.registered_address_postcode assert order.billing_address_country == company.registered_address_country
def test_search_contact_has_sector_updated(self, opensearch_with_collector): """Tests if contact has a correct sector after company update.""" contact = ContactFactory(first_name='sector_update') # by default company has aerospace_assembly_aircraft sector assigned company = contact.company company.sector_id = Sector.renewable_energy_wind.value.id company.save() opensearch_with_collector.flush_and_refresh() term = 'sector_update' url = reverse('api-v3:search:contact') response = self.api_client.post( url, data={ 'original_query': term, }, ) assert response.status_code == status.HTTP_200_OK assert response.data['count'] == 1 sector_name = Sector.renewable_energy_wind.value.name assert sector_name == response.data['results'][0]['company_sector'][ 'name']
def test_can_create_a_referral_with_optional_fields(self): """Test that a referral can be created with all optional values filled in.""" company = CompanyFactory() contact = ContactFactory() recipient = AdviserFactory() subject = 'Test referral' notes = 'Some notes' request_data = { 'subject': subject, 'company': { 'id': company.pk, }, 'recipient': { 'id': recipient.pk, }, 'contact': { 'id': contact.pk, }, 'notes': notes, } response = self.api_client.post(collection_url, data=request_data) assert response.status_code == status.HTTP_201_CREATED response_data = response.json() assert response_data == { 'company': { 'id': str(company.pk), 'name': company.name, }, 'completed_on': None, 'contact': { 'id': str(contact.pk), 'name': contact.name, }, 'created_by': { 'contact_email': self.user.contact_email, 'dit_team': { 'id': str(self.user.dit_team.pk), 'name': self.user.dit_team.name, }, 'id': str(self.user.pk), 'name': self.user.name, }, 'created_on': format_date_or_datetime(FROZEN_DATETIME), 'id': ANY, 'notes': notes, 'recipient': { 'contact_email': recipient.contact_email, 'dit_team': { 'id': str(recipient.dit_team.pk), 'name': recipient.dit_team.name, }, 'id': str(recipient.pk), 'name': recipient.name, }, 'status': CompanyReferral.STATUSES.outstanding, 'subject': subject, }
def test_search_contact_has_own_address(self, opensearch_with_collector): """Tests if contact can have its own address.""" address = { 'address_same_as_company': False, 'address_1': 'Own Street', 'address_2': '', 'address_town': 'Super Town', } contact = ContactFactory( address_country_id=Country.united_kingdom.value.id, **address, ) opensearch_with_collector.flush_and_refresh() url = reverse('api-v3:search:contact') response = self.api_client.post( url, data={ 'original_query': contact.id, }, ) assert response.status_code == status.HTTP_200_OK assert response.data['count'] == 1 result = response.data['results'][0] for k, v in address.items(): assert v == result[k] assert contact.address_country.name == result['address_country'][ 'name']