def calendar_data_fixture(): """ Create advisers, contacts and companies so that our email samples can be attributed to some DB entities. """ advisers = [ ('*****@*****.**', 'Adviser', '1'), ('*****@*****.**', 'Adviser', '2'), ] AdviserFactory.create_batch( len(advisers), email=factory.Iterator(advisers, getter=lambda a: a[0]), first_name=factory.Iterator(advisers, getter=lambda a: a[1]), last_name=factory.Iterator(advisers, getter=lambda a: a[2]), contact_email=factory.SelfAttribute('email'), ) AdviserFactory( email='*****@*****.**', first_name='Adviser', last_name='3', contact_email='*****@*****.**', ) company_1 = CompanyFactory(name='Company 1') company_2 = CompanyFactory(name='Company 2') contacts = [ ('Bill Adama', company_1), ('Saul Tigh', company_1), ('Laura Roslin', company_2), ('Sharon Valerii', company_1), ('Sharon Valerii', company_2), ] for name, company in contacts: first_name, last_name = name.split(' ') email_prefix = name.lower().replace(' ', '.') email = f'{email_prefix}@example.net' ContactFactory( first_name=first_name, last_name=last_name, email=email, company=company, ) # Ensure that our contact who appears on multiple companies # with a single email address has more interactions for the # contact attributed to 'Company 1' contact_with_interactions = Contact.objects.get( email='*****@*****.**', company=company_1, ) CompanyInteractionFactory(contacts=[contact_with_interactions], company=company_1) yield
def test_invalid_adviser(self): """ Test that calling PUT with an invalid adviser returns 400. """ advisers = AdviserFactory.create_batch(2) order = OrderFactory() url = reverse( 'api-v3:omis:order:subscriber-list', kwargs={'order_pk': order.id}, ) data = [{'id': adviser.id} for adviser in advisers] data.append({ 'id': '00000000-0000-0000-0000-000000000000', }) response = self.api_client.put(url, data) assert response.status_code == status.HTTP_400_BAD_REQUEST assert response.json() == [ {}, {}, { 'id': [ '00000000-0000-0000-0000-000000000000 is not a valid adviser' ] }, ]
def test_filter_by_dit_adviser_name(self, setup_es): """Tests filtering interaction by dit adviser name.""" advisers = AdviserFactory.create_batch(10) CompanyInteractionFactory.create_batch( len(advisers), dit_adviser=factory.Iterator(advisers), ) setup_es.indices.refresh() url = reverse('api-v3:search:interaction') request_data = { 'dit_adviser_name': advisers[5].name, } response = self.api_client.post(url, request_data) assert response.status_code == status.HTTP_200_OK response_data = response.json() assert response_data['count'] > 0 results = response_data['results'] # multiple records can match our filter, let's make sure at least one is exact match assert any(result['dit_adviser']['id'] == str(advisers[5].id) for result in results) assert any(result['dit_adviser']['name'] == advisers[5].name for result in results)
def test_non_empty(self): """ Test that calling GET returns the list of advisers subscribed to the order. """ advisers = AdviserFactory.create_batch(3) order = OrderFactory() for adviser in advisers[:2]: OrderSubscriberFactory(order=order, adviser=adviser) url = reverse( 'api-v3:omis:order:subscriber-list', kwargs={'order_pk': order.id}, ) response = self.api_client.get(url) assert response.status_code == status.HTTP_200_OK assert response.json() == [{ 'id': str(adviser.id), 'first_name': adviser.first_name, 'last_name': adviser.last_name, 'name': adviser.name, 'dit_team': { 'id': str(adviser.dit_team.id), 'name': adviser.dit_team.name, 'uk_region': { 'id': str(adviser.dit_team.uk_region.pk), 'name': adviser.dit_team.uk_region.name, }, }, } for adviser in advisers[:2]]
def test_filter_by_dit_adviser_id(self, setup_es): """Tests filtering interaction by dit adviser id.""" advisers = AdviserFactory.create_batch(10) CompanyInteractionFactory.create_batch( len(advisers), dit_adviser=factory.Iterator(advisers), ) setup_es.indices.refresh() url = reverse('api-v3:search:interaction') request_data = { 'dit_adviser': advisers[5].id, } response = self.api_client.post(url, request_data) assert response.status_code == status.HTTP_200_OK response_data = response.json() assert response_data['count'] == 1 results = response_data['results'] assert results[0]['dit_adviser']['id'] == str(advisers[5].id) assert results[0]['dit_adviser']['name'] == advisers[5].name
def test_non_empty(self): """ Test that calling GET returns the list of advisers assigned to the order. """ advisers = AdviserFactory.create_batch(3) order = OrderFactory(assignees=[]) for i, adviser in enumerate(advisers[:2]): OrderAssigneeFactory( order=order, adviser=adviser, estimated_time=(120 * i), ) url = reverse( 'api-v3:omis:order:assignee', kwargs={'order_pk': order.id}, ) response = self.api_client.get(url) assert response.status_code == status.HTTP_200_OK assert response.json() == [{ 'adviser': { 'id': str(adviser.id), 'first_name': adviser.first_name, 'last_name': adviser.last_name, 'name': adviser.name, }, 'estimated_time': (120 * i), 'actual_time': None, 'is_lead': False, } for i, adviser in enumerate(advisers[:2])]
def test_change_existing_list(self, allowed_status): """ Test that calling PUT with a different list of advisers completely changes the subscriber list: - advisers not in the list will be removed - new advisers will be added - existing advisers will be kept """ previous_advisers = AdviserFactory.create_batch(2) order = OrderFactory(status=allowed_status) subscriptions = [ OrderSubscriberFactory(order=order, adviser=adviser) for adviser in previous_advisers ] final_advisers = [ AdviserFactory(), # new previous_advisers[1], # existing ] url = reverse( 'api-v3:omis:order:subscriber-list', kwargs={'order_pk': order.id}, ) response = self.api_client.put( url, [{'id': adviser.id} for adviser in final_advisers], ) assert response.status_code == status.HTTP_200_OK assert {adv['id'] for adv in response.json()} == {str(adv.id) for adv in final_advisers} # check that the id of the existing subscription didn't change assert order.subscribers.filter(id=subscriptions[1].id).exists()
def test_get_one_list_group_core_team( self, build_company, with_global_account_manager, ): """ Test that `get_one_list_group_core_team` returns the Core Team of `self` if the company has no `global_headquarters` or the one of its `global_headquarters` otherwise. """ team_member_advisers = AdviserFactory.create_batch( 3, first_name=factory.Iterator( ('Adam', 'Barbara', 'Chris'), ), ) global_account_manager = team_member_advisers[0] if with_global_account_manager else None company = build_company(global_account_manager) group_global_headquarters = company.global_headquarters or company OneListCoreTeamMemberFactory.create_batch( len(team_member_advisers), company=group_global_headquarters, adviser=factory.Iterator(team_member_advisers), ) core_team = company.get_one_list_group_core_team() assert core_team == [ { 'adviser': adviser, 'is_global_account_manager': adviser is global_account_manager, } for adviser in team_member_advisers ]
def test_adviser_report_download(self): """Test the download of a report.""" AdviserFactory.create_batch(5) url = reverse('admin_report:download-report', kwargs={'report_id': 'all-advisers'}) user = create_test_user( permission_codenames=('view_advisor',), is_staff=True, password=self.PASSWORD, ) client = self.create_client(user=user) response = client.get(url) assert response.status_code == status.HTTP_200_OK # 7 = header + test user + the 5 test advisers assert len(response.getvalue().decode('utf-8').splitlines()) == 7
def test_can_update_core_team_members( self, one_list_company, one_list_editor, existing_team_count, new_team_count, ): """Test that core team members can be updated.""" api_client = self.create_api_client(user=one_list_editor) url = self._get_url(one_list_company) if existing_team_count: team_member_advisers = AdviserFactory.create_batch( existing_team_count) OneListCoreTeamMemberFactory.create_batch( len(team_member_advisers), company=one_list_company, adviser=factory.Iterator(team_member_advisers), ) old_core_team_members = [ core_team_member.adviser.id for core_team_member in one_list_company.one_list_core_team_members.all() ] new_core_team_members = [ adviser.id for adviser in AdviserFactory.create_batch(2) ] if new_team_count else [] response = api_client.patch( url, { 'core_team_members': [{ 'adviser': adviser_id, } for adviser_id in new_core_team_members], }, ) assert response.status_code == status.HTTP_204_NO_CONTENT core_team_members = [ core_team_member.adviser.id for core_team_member in one_list_company.one_list_core_team_members.all() ] assert core_team_members != old_core_team_members assert core_team_members == new_core_team_members
def test_multiple_participating_advisers_can_be_specified(self): """Test that an interaction can be created with multiple DIT participants.""" contact = ContactFactory() communication_channel = random_obj_for_model(CommunicationChannel) advisers = AdviserFactory.create_batch(5) advisers.sort(key=attrgetter('pk')) 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': { 'id': adviser.pk, }, } for adviser in advisers ], 'company': { 'id': contact.company.pk, }, 'contacts': [{ 'id': contact.pk, }], '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_201_CREATED response_data = response.json() response_data['dit_participants'].sort( key=lambda dit_participant: dit_participant['adviser']['id'], ) assert response_data['dit_participants'] == [ { 'adviser': { 'id': str(adviser.pk), 'first_name': adviser.first_name, 'last_name': adviser.last_name, 'name': adviser.name, }, 'team': { 'id': str(adviser.dit_team.pk), 'name': adviser.dit_team.name, }, } for adviser in advisers ]
def test_can_filter_by_is_active(self, filter_value): """Test filtering by is_active.""" AdviserFactory.create_batch(5, is_active=not filter_value) matching_advisers = AdviserFactory.create_batch(4, is_active=filter_value) if filter_value: matching_advisers.append(self.user) url = reverse('api-v1:advisor-list') response = self.api_client.get( url, data={ 'is_active': filter_value, }, ) assert response.status_code == status.HTTP_200_OK response_data = response.json() assert response_data['count'] == len(matching_advisers) actual_ids = Counter(str(adviser.pk) for adviser in matching_advisers) expected_ids = Counter(result['id'] for result in response_data['results']) assert actual_ids == expected_ids
def test_with_core_team_members(self, build_company, with_global_account_manager): """ Test that if there are Core Team members for a company's Global Headquarters, the endpoint returns a list with these advisers in it. """ team_member_advisers = AdviserFactory.create_batch( 3, first_name=factory.Iterator(('Adam', 'Barbara', 'Chris'), ), ) global_account_manager = team_member_advisers[ 0] if with_global_account_manager else None company = build_company(global_account_manager) group_global_headquarters = company.global_headquarters or company OneListCoreTeamMemberFactory.create_batch( len(team_member_advisers), company=group_global_headquarters, adviser=factory.Iterator(team_member_advisers), ) url = reverse( 'api-v4:company:one-list-group-core-team', kwargs={'pk': company.pk}, ) response = self.api_client.get(url) assert response.status_code == status.HTTP_200_OK assert response.json() == [{ 'adviser': { 'id': str(adviser.pk), 'name': adviser.name, 'first_name': adviser.first_name, 'last_name': adviser.last_name, 'contact_email': adviser.contact_email, 'dit_team': { 'id': str(adviser.dit_team.pk), 'name': adviser.dit_team.name, 'uk_region': { 'id': str(adviser.dit_team.uk_region.pk), 'name': adviser.dit_team.uk_region.name, }, 'country': { 'id': str(adviser.dit_team.country.pk), 'name': adviser.dit_team.country.name, }, }, }, 'is_global_account_manager': adviser is global_account_manager, } for adviser in team_member_advisers]
def test_can_add_participants(self): """Test that participants can be added to an interaction without any being removed.""" interaction = CompanyInteractionFactory(dit_participants=[]) dit_participants = InteractionDITParticipantFactory.create_batch( 3, interaction=interaction, ) new_advisers = [ *[dit_participant.adviser for dit_participant in dit_participants], *AdviserFactory.create_batch(2), ] new_advisers.sort(key=attrgetter('pk')) request_data = { 'dit_participants': [ { 'adviser': { 'id': adviser.pk, }, } for adviser in new_advisers ], } url = reverse('api-v3:interaction:item', kwargs={'pk': interaction.pk}) response = self.api_client.patch(url, data=request_data) assert response.status_code == status.HTTP_200_OK response_data = response.json() response_data['dit_participants'].sort( key=lambda dit_participant: dit_participant['adviser']['id'], ) expected_advisers_and_teams = [(adviser, adviser.dit_team) for adviser in new_advisers] assert response_data['dit_participants'] == [ { 'adviser': { 'id': str(adviser.pk), 'first_name': adviser.first_name, 'last_name': adviser.last_name, 'name': adviser.name, }, 'team': { 'id': str(team.pk), 'name': team.name, }, } for adviser, team in expected_advisers_and_teams ]
def test_remove_all(self, allowed_status): """ Test that calling PUT with an empty list, removes all the subscribers. """ advisers = AdviserFactory.create_batch(2) order = OrderFactory(status=allowed_status) for adviser in advisers: OrderSubscriberFactory(order=order, adviser=adviser) url = reverse( 'api-v3:omis:order:subscriber-list', kwargs={'order_pk': order.id}, ) response = self.api_client.put(url, []) assert response.status_code == status.HTTP_200_OK assert response.json() == []
def test_add_to_empty_list(self): """ Test that calling PUT with new advisers adds them to the subscriber list. """ advisers = AdviserFactory.create_batch(2) order = OrderFactory() url = reverse( 'api-v3:omis:order:subscriber-list', kwargs={'order_pk': order.id}, ) response = self.api_client.put( url, [{'id': adviser.id} for adviser in advisers], ) assert response.status_code == status.HTTP_200_OK assert {adv['id'] for adv in response.json()} == {str(adv.id) for adv in advisers}
def test_one_list_account_manager_filter( self, num_account_managers, opensearch_with_collector, ): """Test one list account manager filter.""" account_managers = AdviserFactory.create_batch(3) selected_account_managers = random.sample(account_managers, num_account_managers) CompanyFactory.create_batch(2) CompanyFactory.create_batch( 3, one_list_account_owner=factory.Iterator(account_managers)) opensearch_with_collector.flush_and_refresh() query = { 'one_list_group_global_account_manager': [ account_manager.id for account_manager in selected_account_managers ], } url = reverse('api-v4:search:company') response = self.api_client.post(url, query) assert response.status_code == status.HTTP_200_OK search_results = { company['one_list_group_global_account_manager']['id'] for company in response.data['results'] } expected_results = { str(account_manager.id) for account_manager in selected_account_managers } assert response.data['count'] == len(selected_account_managers) assert len(response.data['results']) == len(selected_account_managers) assert search_results == expected_results
def test_add(self): """Test that One List Core Team members can be added to a company.""" team_member_advisers = AdviserFactory.create_batch(2) team_size = len(team_member_advisers) company = CompanyFactory() assert company.one_list_core_team_members.count() == 0 url = reverse('admin:company_company_change', args=(company.id, )) data = { **get_required_company_form_data(company), 'one_list_core_team_members-TOTAL_FORMS': team_size, 'one_list_core_team_members-INITIAL_FORMS': 0, 'one_list_core_team_members-MIN_NUM_FORMS': 0, 'one_list_core_team_members-MAX_NUM_FORMS': 1000, } for index, adviser in enumerate(team_member_advisers): team_member_id = uuid.uuid4() data.update({ f'initial-one_list_core_team_members-{index}-id': team_member_id, f'one_list_core_team_members-{index}-id': team_member_id, f'one_list_core_team_members-{index}-company': company.pk, f'one_list_core_team_members-{index}-adviser': adviser.pk, }) response = self.client.post(url, data, follow=True) assert response.status_code == status.HTTP_200_OK assert company.one_list_core_team_members.count() == team_size
def test_add_core_team_members(self): """Test that core team members can be added to a company.""" team_member_advisers = AdviserFactory.create_batch(2) team_size = len(team_member_advisers) company = CompanyFactory() assert company.core_team_members.count() == 0 url = reverse('admin:company_company_change', args=(company.id, )) data = {} # populate data with required field values admin_form = CompanyAdmin(Company, site).get_form(mock.Mock()) for field_name, field in admin_form.base_fields.items(): if field.required: field_value = getattr(company, field_name) data[field_name] = field.prepare_value(field_value) # add inline related field data data.update({ 'core_team_members-TOTAL_FORMS': team_size, 'core_team_members-INITIAL_FORMS': 0, 'core_team_members-MIN_NUM_FORMS': 0, 'core_team_members-MAX_NUM_FORMS': 1000, }) for index, adviser in enumerate(team_member_advisers): team_member_id = uuid.uuid4() data.update({ f'initial-core_team_members-{index}-id': team_member_id, f'core_team_members-{index}-id': team_member_id, f'core_team_members-{index}-company': company.pk, f'core_team_members-{index}-adviser': adviser.pk, }) response = self.client.post(url, data, follow=True) assert response.status_code == status.HTTP_200_OK assert company.core_team_members.count() == team_size
class TestInteractionCSVRowForm: """Tests for InteractionCSVRowForm.""" @pytest.mark.parametrize( 'data,errors', ( # kind blank ( { 'kind': '' }, { 'kind': ['This field is required.'] }, ), # kind invalid ( { 'kind': 'invalid' }, { 'kind': [ 'Select a valid choice. invalid is not one of the available choices.' ] }, ), # date blank ( { 'date': '' }, { 'date': ['This field is required.'] }, ), # invalid date ( { 'date': '08/31/2020' }, { 'date': ['Enter a valid date.'] }, ), # invalid contact_email ( { 'contact_email': 'invalid' }, { 'contact_email': ['Enter a valid email address.'] }, ), # blank adviser_1 ( { 'adviser_1': '' }, { 'adviser_1': ['This field is required.'] }, ), # adviser_1 doesn't exist ( { 'adviser_1': 'Non-existent adviser' }, { 'adviser_1': [ADVISER_NOT_FOUND_MESSAGE] }, ), # multiple matching values for adviser_1 ( { 'adviser_1': lambda: AdviserFactory.create_batch( 2, first_name='Pluto', last_name='Doris', )[0].name, }, { 'adviser_1': [MULTIPLE_ADVISERS_FOUND_MESSAGE] }, ), # adviser_1 and team_1 mismatch ( { 'adviser_1': lambda: AdviserFactory( first_name='Pluto', last_name='Doris', dit_team__name='Team Advantage', ).name, 'team_1': lambda: TeamFactory(name='Team Disadvantage', ).name, }, { 'adviser_1': [ADVISER_WITH_TEAM_NOT_FOUND_MESSAGE] }, ), # adviser_2 doesn't exist ( { 'adviser_2': 'Non-existent adviser' }, { 'adviser_2': [ADVISER_NOT_FOUND_MESSAGE] }, ), # multiple matching values for adviser_2 ( { 'adviser_2': lambda: AdviserFactory.create_batch( 2, first_name='Pluto', last_name='Doris', )[0].name, }, { 'adviser_2': [MULTIPLE_ADVISERS_FOUND_MESSAGE] }, ), # adviser_2 and team_2 mismatch ( { 'adviser_2': lambda: AdviserFactory( first_name='Pluto', last_name='Doris', dit_team__name='Team Advantage', ).name, 'team_2': lambda: TeamFactory(name='Team Disadvantage', ).name, }, { 'adviser_2': [ADVISER_WITH_TEAM_NOT_FOUND_MESSAGE] }, ), # service doesn't exist ( { 'service': 'Non-existent service' }, { 'service': [ 'Select a valid choice. That choice is not one of the available choices.', ], }, ), # service is disabled ( { 'service': lambda: _random_service(disabled=True).name, }, { 'service': [OBJECT_DISABLED_MESSAGE], }, ), # Multiple matching services ( { 'service': lambda: ServiceFactory.create_batch(2, name='Duplicate')[0] .name, }, { 'service': ['There is more than one matching service.'], }, ), # communication_channel doesn't exist ( { 'communication_channel': 'Non-existent communication channel' }, { 'communication_channel': [ 'Select a valid choice. That choice is not one of the available choices.', ], }, ), # Multiple matching communication channels ( { 'communication_channel': lambda: CommunicationChannelFactory.create_batch( 2, name='Duplicate', )[0].name, }, { 'communication_channel': [ 'There is more than one matching communication channel.', ], }, ), # communication_channel is disabled ( { 'communication_channel': lambda: _random_communication_channel(disabled=True, ). name, }, { 'communication_channel': [OBJECT_DISABLED_MESSAGE], }, ), # event_id invalid ( { 'event_id': 'non_existent_event_id' }, { 'event_id': [ "'non_existent_event_id' is not a valid UUID.", ], }, ), # event_id is for a disabled event ( { 'event_id': lambda: str(DisabledEventFactory().pk), }, { 'event_id': [OBJECT_DISABLED_MESSAGE], }, ), # event_id non-existent ( { 'event_id': '00000000-0000-0000-0000-000000000000' }, { 'event_id': [ 'Select a valid choice. That choice is not one of the available ' 'choices.', ], }, ), # cannot specify event_id for an interaction ( { 'kind': Interaction.KINDS.interaction, 'event_id': lambda: str(EventFactory().pk), }, { 'event_id': [INTERACTION_CANNOT_HAVE_AN_EVENT_MESSAGE], }, ), ), ) def test_validation_errors(self, data, errors): """Test validation for various fields.""" adviser = AdviserFactory(first_name='Neptune', last_name='Doris') service = _random_service() resolved_data = { 'kind': 'interaction', 'date': '01/01/2018', 'adviser_1': adviser.name, 'contact_email': '*****@*****.**', 'service': service.name, **_resolve_data(data), } form = InteractionCSVRowForm(data=resolved_data) assert form.errors == errors @pytest.mark.parametrize( 'field,input_value,expected_value', ( # UK date format without leading zeroes ( 'date', '1/2/2013', date(2013, 2, 1), ), # UK date format with leading zeroes ( 'date', '03/04/2015', date(2015, 4, 3), ), # ISO date format ( 'date', '2016-05-04', date(2016, 5, 4), ), # Subject ( 'subject', 'A subject', 'A subject', ), # Notes (trailing blank lines are stripped) ( 'notes', 'Notes with\nmultiple lines\n', 'Notes with\nmultiple lines', ), ), ) def test_simple_value_cleaning(self, field, input_value, expected_value): """Test the conversion and cleaning of various non-relationship fields.""" adviser = AdviserFactory(first_name='Neptune', last_name='Doris') service = _random_service() resolved_data = { 'kind': 'interaction', 'date': '01/01/2018', 'adviser_1': adviser.name, 'contact_email': '*****@*****.**', 'service': service.name, field: input_value, } form = InteractionCSVRowForm(data=resolved_data) assert not form.errors assert form.cleaned_data[field] == expected_value @pytest.mark.parametrize( 'kind', (Interaction.KINDS.interaction, Interaction.KINDS.service_delivery), ) @pytest.mark.parametrize( 'field,object_creator,input_transformer', ( # adviser_1 look-up (same case) ( 'adviser_1', lambda: AdviserFactory( first_name='Pluto', last_name='Doris', ), lambda obj: obj.name, ), # adviser_1 look-up (case-insensitive) ( 'adviser_1', lambda: AdviserFactory( first_name='Pluto', last_name='Doris', ), lambda obj: obj.name.upper(), ), # adviser_2 look-up (same case) ( 'adviser_1', lambda: AdviserFactory( first_name='Pluto', last_name='Doris', ), lambda obj: obj.name, ), # adviser_2 look-up (case-insensitive) ( 'adviser_1', lambda: AdviserFactory( first_name='Pluto', last_name='Doris', ), lambda obj: obj.name.upper(), ), # service look-up (same case) ( 'service', lambda: ServiceFactory(name='UNIQUE EXPORT DEAL'), lambda obj: obj.name, ), # service look-up (case-insensitive) ( 'service', lambda: ServiceFactory(name='UNIQUE EXPORT DEAL'), lambda obj: obj.name.lower(), ), ), ) def test_common_relation_fields(self, kind, field, object_creator, input_transformer): """ Test the looking up of values for relationship fields common to interactions and service deliveries. """ adviser = AdviserFactory(first_name='Neptune', last_name='Doris') service = _random_service() obj = object_creator() resolved_data = { 'kind': kind, 'date': '01/01/2018', 'adviser_1': adviser.name, 'contact_email': '*****@*****.**', 'service': service.name, field: input_transformer(obj), } form = InteractionCSVRowForm(data=resolved_data) assert not form.errors assert form.cleaned_data[field] == obj @pytest.mark.parametrize( 'field,object_creator,input_transformer', ( # communication channel look-up (same case) ( 'communication_channel', lambda: _random_communication_channel(), lambda obj: obj.name, ), # communication channel look-up (case-insensitive) ( 'communication_channel', lambda: _random_communication_channel(), lambda obj: obj.name.upper(), ), ), ) def test_interaction_relation_fields(self, field, object_creator, input_transformer): """Test the looking up of values for relationship fields specific to interactions.""" adviser = AdviserFactory(first_name='Neptune', last_name='Doris') service = _random_service() obj = object_creator() resolved_data = { 'kind': 'interaction', 'date': '01/01/2018', 'adviser_1': adviser.name, 'contact_email': '*****@*****.**', 'service': service.name, field: input_transformer(obj), } form = InteractionCSVRowForm(data=resolved_data) assert not form.errors assert form.cleaned_data[field] == obj @pytest.mark.parametrize( 'field,object_creator,input_transformer,expected_value_transformer', ( # communication channel should be ignored ( 'communication_channel', lambda: _random_communication_channel(), lambda obj: obj.name, lambda obj: None, ), # event look-up ( 'event_id', lambda: EventFactory(), lambda obj: str(obj.pk), lambda obj: obj, ), ), ) def test_service_delivery_relation_fields( self, field, object_creator, input_transformer, expected_value_transformer, ): """Test the looking up of values for relationship fields specific to service deliveries.""" adviser = AdviserFactory(first_name='Neptune', last_name='Doris') service = _random_service() obj = object_creator() resolved_data = { 'kind': 'service_delivery', 'date': '01/01/2018', 'adviser_1': adviser.name, 'contact_email': '*****@*****.**', 'service': service.name, field: input_transformer(obj), } form = InteractionCSVRowForm(data=resolved_data) assert not form.errors assert form.cleaned_data[field] == expected_value_transformer(obj) @pytest.mark.parametrize( 'kind', (Interaction.KINDS.interaction, Interaction.KINDS.service_delivery), ) def test_subject_falls_back_to_service(self, kind): """Test that if subject is not specified, the name of the service is used instead.""" adviser = AdviserFactory(first_name='Neptune', last_name='Doris') service = _random_service() data = { 'kind': kind, 'date': '01/01/2018', 'adviser_1': adviser.name, 'contact_email': '*****@*****.**', 'service': service.name, } form = InteractionCSVRowForm(data=data) assert not form.errors assert form.cleaned_data['subject'] == service.name
def test_run(s3_stubber, caplog, reset_unmatched): """ Test that the command updates the specified records (ignoring ones with errors). If `reset_unmatched` is False, the existing records not in the CSV are kept untouched, otherwise they are set to None. """ caplog.set_level('ERROR') new_one_list_tier = random_obj_for_model(OneListTier) one_list_companies = CompanyFactory.create_batch( 8, one_list_tier=factory.LazyFunction( lambda: random_obj_for_queryset( OneListTier.objects.exclude(pk=new_one_list_tier.pk), ), ), one_list_account_owner=factory.SubFactory(AdviserFactory), ) non_one_list_companies = CompanyFactory.create_batch( 3, one_list_tier=None, one_list_account_owner=None, ) for company in chain(one_list_companies, non_one_list_companies): save_prev_fields(company, 'one_list_tier_id', 'one_list_account_owner_id') advisers = AdviserFactory.create_batch(4) bucket = 'test_bucket' object_key = 'test_key' csv_content = f"""id,one_list_tier_id,one_list_account_owner_id 00000000-0000-0000-0000-000000000000,test,test {one_list_companies[0].pk},{one_list_companies[0].one_list_tier_id},{one_list_companies[0].one_list_account_owner_id} {one_list_companies[1].pk},{one_list_companies[1].one_list_tier_id},{advisers[0].pk} {one_list_companies[2].pk},{new_one_list_tier.pk},{one_list_companies[2].one_list_account_owner_id} {one_list_companies[3].pk},null,null {one_list_companies[4].pk},00000000-0000-0000-0000-000000000000,{advisers[1].pk} {one_list_companies[5].pk},{new_one_list_tier.pk},00000000-0000-0000-0000-000000000000 {non_one_list_companies[0].pk},{new_one_list_tier.pk},{advisers[2].pk} {non_one_list_companies[1].pk},00000000-0000-0000-0000-000000000000,{advisers[3].pk} {non_one_list_companies[2].pk},{new_one_list_tier.pk},00000000-0000-0000-0000-000000000000 """ s3_stubber.add_response( 'get_object', {'Body': BytesIO(csv_content.encode(encoding='utf-8'))}, expected_params={ 'Bucket': bucket, 'Key': object_key, }, ) call_command('update_one_list_fields', bucket, object_key, reset_unmatched=reset_unmatched) for company in chain(one_list_companies, non_one_list_companies): company.refresh_from_db() # assert exceptions assert len(caplog.records) == 5 assert 'Company matching query does not exist' in caplog.records[ 0].exc_text assert 'OneListTier matching query does not exist' in caplog.records[ 1].exc_text assert 'Advisor matching query does not exist' in caplog.records[ 2].exc_text assert 'OneListTier matching query does not exist' in caplog.records[ 3].exc_text assert 'Advisor matching query does not exist' in caplog.records[ 4].exc_text # one_list_companies[0]: nothing changed assert_did_not_change(one_list_companies[0], 'one_list_tier_id', 'one_list_account_owner_id') # one_list_companies[1]: only one_list_account_owner_id changed assert_changed(one_list_companies[1], 'one_list_account_owner_id') assert_did_not_change(one_list_companies[1], 'one_list_tier_id') assert one_list_companies[1].one_list_account_owner == advisers[0] # one_list_companies[2]: only one_list_tier_id changed assert_did_not_change(one_list_companies[2], 'one_list_account_owner_id') assert_changed(one_list_companies[2], 'one_list_tier_id') assert one_list_companies[2].one_list_tier == new_one_list_tier # one_list_companies[3]: all changed assert_changed(one_list_companies[3], 'one_list_tier_id', 'one_list_account_owner_id') assert one_list_companies[3].one_list_tier_id is None assert one_list_companies[3].one_list_account_owner_id is None # one_list_companies[4]: nothing changed assert_did_not_change(one_list_companies[4], 'one_list_tier_id', 'one_list_account_owner_id') # one_list_companies[5]: nothing changed assert_did_not_change(one_list_companies[5], 'one_list_tier_id', 'one_list_account_owner_id') # non_one_list_companies[0]: all changed assert_changed(non_one_list_companies[0], 'one_list_tier_id', 'one_list_account_owner_id') assert non_one_list_companies[0].one_list_account_owner == advisers[2] assert non_one_list_companies[0].one_list_tier == new_one_list_tier # non_one_list_companies[1]: nothing changed assert_did_not_change( non_one_list_companies[1], 'one_list_tier_id', 'one_list_account_owner_id', ) # non_one_list_companies[2]: nothing changed assert_did_not_change( non_one_list_companies[2], 'one_list_tier_id', 'one_list_account_owner_id', ) # one_list_companies[6] / [7]: if reset_unmatched == False => nothing changed else all changed if reset_unmatched: assert_changed(one_list_companies[6], 'one_list_tier_id', 'one_list_account_owner_id') assert_changed(one_list_companies[7], 'one_list_tier_id', 'one_list_account_owner_id') assert one_list_companies[6].one_list_tier is None assert one_list_companies[6].one_list_account_owner is None assert one_list_companies[7].one_list_tier is None assert one_list_companies[7].one_list_account_owner is None else: assert_did_not_change( one_list_companies[6], 'one_list_tier_id', 'one_list_account_owner_id', ) assert_did_not_change( one_list_companies[7], 'one_list_tier_id', 'one_list_account_owner_id', )
def test_simulate(s3_stubber, caplog, reset_unmatched): """Test that the command simulates updates if --simulate is passed in.""" caplog.set_level('ERROR') new_one_list_tier = random_obj_for_model(OneListTier) one_list_companies = CompanyFactory.create_batch( 8, one_list_tier=factory.LazyFunction( lambda: random_obj_for_queryset( OneListTier.objects.exclude(pk=new_one_list_tier.pk), ), ), one_list_account_owner=factory.SubFactory(AdviserFactory), ) non_one_list_companies = CompanyFactory.create_batch( 3, one_list_tier=None, one_list_account_owner=None, ) for company in chain(one_list_companies, non_one_list_companies): save_prev_fields(company, 'one_list_tier_id', 'one_list_account_owner_id') advisers = AdviserFactory.create_batch(4) bucket = 'test_bucket' object_key = 'test_key' csv_content = f"""id,one_list_tier_id,one_list_account_owner_id 00000000-0000-0000-0000-000000000000,test,test {one_list_companies[0].pk},{one_list_companies[0].one_list_tier_id},{one_list_companies[0].one_list_account_owner_id} {one_list_companies[1].pk},{one_list_companies[1].one_list_tier_id},{advisers[0].pk} {one_list_companies[2].pk},{new_one_list_tier.pk},{one_list_companies[2].one_list_account_owner_id} {one_list_companies[3].pk},null,null {one_list_companies[4].pk},00000000-0000-0000-0000-000000000000,{advisers[1].pk} {one_list_companies[5].pk},{new_one_list_tier.pk},00000000-0000-0000-0000-000000000000 {non_one_list_companies[0].pk},{new_one_list_tier.pk},{advisers[2].pk} {non_one_list_companies[1].pk},00000000-0000-0000-0000-000000000000,{advisers[3].pk} {non_one_list_companies[2].pk},{new_one_list_tier.pk},00000000-0000-0000-0000-000000000000 """ s3_stubber.add_response( 'get_object', {'Body': BytesIO(csv_content.encode(encoding='utf-8'))}, expected_params={ 'Bucket': bucket, 'Key': object_key, }, ) call_command( 'update_one_list_fields', bucket, object_key, reset_unmatched=reset_unmatched, simulate=True, ) for company in chain(one_list_companies, non_one_list_companies): company.refresh_from_db() # assert exceptions assert len(caplog.records) == 5 assert 'Company matching query does not exist' in caplog.records[ 0].exc_text assert 'OneListTier matching query does not exist' in caplog.records[ 1].exc_text assert 'Advisor matching query does not exist' in caplog.records[ 2].exc_text assert 'OneListTier matching query does not exist' in caplog.records[ 3].exc_text assert 'Advisor matching query does not exist' in caplog.records[ 4].exc_text # assert that nothing really changed for company in chain(one_list_companies, non_one_list_companies): assert_did_not_change(company, 'one_list_tier_id', 'one_list_account_owner_id')