示例#1
0
def test_updated_interaction_synced(opensearch_with_signals):
    """Test that when export country history is updated, it is synced to OpenSearch."""
    export_country_history = CompanyExportCountryHistoryFactory(
        history_type=CompanyExportCountryHistory.HistoryType.INSERT, )
    history_type = CompanyExportCountryHistory.HistoryType.UPDATE
    export_country_history.history_type = history_type
    export_country_history.save()
    opensearch_with_signals.indices.refresh()

    result = opensearch_with_signals.get(
        index=ExportCountryHistoryApp.search_model.get_write_index(),
        id=export_country_history.pk,
    )

    assert result['_source'] == {
        '_document_type': ExportCountryHistoryApp.name,
        'history_user': {
            'id': str(export_country_history.history_user.id),
            'name': export_country_history.history_user.name,
        },
        'country': {
            'id': str(export_country_history.country.id),
            'name': export_country_history.country.name,
        },
        'company': {
            'id': str(export_country_history.company.id),
            'name': export_country_history.company.name,
        },
        'id': str(export_country_history.pk),
        'history_type': export_country_history.history_type,
        'history_date': export_country_history.history_date.isoformat(),
        'date': export_country_history.history_date.isoformat(),
        'status': str(export_country_history.status),
    }
示例#2
0
def test_export_country_history_to_dict(es):
    """Test for export country history search model"""
    export_country_history = CompanyExportCountryHistoryFactory()
    result = ExportCountryHistory.db_object_to_dict(export_country_history)

    assert result == {
        '_document_type': ExportCountryHistoryApp.name,
        'id': export_country_history.pk,
        'company': {
            'id': str(export_country_history.company.pk),
            'name': export_country_history.company.name,
        },
        'country': {
            'id': str(export_country_history.country.pk),
            'name': export_country_history.country.name,
        },
        'history_date': export_country_history.history_date,
        'date': export_country_history.history_date,
        'history_type': export_country_history.history_type,
        'history_user': {
            'id': str(export_country_history.history_user.pk),
            'name': export_country_history.history_user.name,
        },
        'status': export_country_history.status,
    }
    def test_filtering_by_country_excludes_non_matches(self,
                                                       es_with_collector):
        """Test that filtering by country excludes non-matching objects."""
        countries = list(Country.objects.order_by('?')[:2])
        filter_country = countries[0]
        other_country = countries[1]

        # Non-export country interactions should be excluded
        CompanyInteractionFactory()

        # Unrelated countries should be excluded
        CompanyExportCountryHistoryFactory(country=other_country,
                                           history_type=HistoryType.INSERT)
        ExportCountriesInteractionFactory(
            export_countries__country=other_country)

        es_with_collector.flush_and_refresh()

        response = self.api_client.post(
            export_country_history_search_url,
            data={
                'country': filter_country.pk,
            },
        )
        assert response.status_code == status.HTTP_200_OK

        response_data = response.json()
        assert response_data['count'] == 0
        assert response_data['results'] == []
示例#4
0
    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
示例#5
0
def test_new_export_country_history_synced(opensearch_with_signals):
    """Test that new export country history is synced to OpenSearch."""
    company_export_country_history = CompanyExportCountryHistoryFactory()
    opensearch_with_signals.indices.refresh()

    assert opensearch_with_signals.get(
        index=ExportCountryHistoryApp.search_model.get_write_index(),
        id=company_export_country_history.pk,
    )
示例#6
0
def test_new_export_country_history_synced(es_with_signals):
    """Test that new export country history is synced to ES."""
    company_export_country_history = CompanyExportCountryHistoryFactory()
    es_with_signals.indices.refresh()

    assert es_with_signals.get(
        index=ExportCountryHistoryApp.es_model.get_write_index(),
        doc_type=ExportCountryHistoryApp.name,
        id=company_export_country_history.pk,
    )
示例#7
0
    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_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
示例#9
0
    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
示例#10
0
    def test_export_country_history_response_body(self,
                                                  opensearch_with_collector):
        """Test the format of an export country history result in the response body."""
        history_object = CompanyExportCountryHistoryFactory(
            history_type=HistoryType.INSERT)
        opensearch_with_collector.flush_and_refresh()

        response = self.api_client.post(
            export_country_history_search_url,
            data={
                # The view requires a filter
                'company': history_object.company.pk,
            },
        )
        assert response.status_code == status.HTTP_200_OK

        results = response.json()['results']
        assert len(results) == 1
        assert results[0] == {
            'company': {
                'id': str(history_object.company.pk),
                'name': history_object.company.name,
            },
            'country': {
                'id': str(history_object.country.pk),
                'name': history_object.country.name,
            },
            'date': history_object.history_date.isoformat(),
            'history_date': history_object.history_date.isoformat(),
            'history_type': history_object.history_type,
            'history_user': {
                'id': str(history_object.history_user.pk),
                'name': history_object.history_user.name,
            },
            'id': str(history_object.pk),
            'status': history_object.status,
        }
示例#11
0
def _make_dated_export_country_history(history_date, **kwargs):
    with freeze_time(history_date):
        return CompanyExportCountryHistoryFactory(
            history_type=HistoryType.INSERT, **kwargs)
示例#12
0
class TestSearchExportCountryHistory(APITestMixin):
    """Tests search views."""
    @pytest.mark.parametrize(
        'permission_codenames,expected_status',
        (
            (
                [],
                status.HTTP_403_FORBIDDEN,
            ),
            (
                ['view_companyexportcountry'],
                status.HTTP_403_FORBIDDEN,
            ),
            (
                [InteractionPermission.view_all],
                status.HTTP_403_FORBIDDEN,
            ),
            (
                ['view_companyexportcountry', InteractionPermission.view_all],
                status.HTTP_200_OK,
            ),
        ),
    )
    @pytest.mark.usefixtures('es')
    def test_permission_checking(self, permission_codenames, expected_status,
                                 api_client):
        """Test that the expected status is returned for various user permissions."""
        user = create_test_user(permission_codenames=permission_codenames,
                                dit_team=None)
        api_client = self.create_api_client(user=user)
        response = api_client.post(
            export_country_history_search_url,
            data={
                'company': uuid4(),
            },
        )
        assert response.status_code == expected_status

    def test_export_country_history_search_with_empty_request(
            self, es_with_collector):
        """Should return 400."""
        es_with_collector.flush_and_refresh()
        error_response = 'Request must include either country or company parameters'

        response = self.api_client.post(export_country_history_search_url,
                                        data={})

        assert response.status_code == status.HTTP_400_BAD_REQUEST
        assert response.json()['non_field_errors'][0] == error_response

    def test_export_country_history_response_body(self, es_with_collector):
        """Test the format of an export country history result in the response body."""
        history_object = CompanyExportCountryHistoryFactory(
            history_type=HistoryType.INSERT)
        es_with_collector.flush_and_refresh()

        response = self.api_client.post(
            export_country_history_search_url,
            data={
                # The view requires a filter
                'company': history_object.company.pk,
            },
        )
        assert response.status_code == status.HTTP_200_OK

        results = response.json()['results']
        assert len(results) == 1
        assert results[0] == {
            'company': {
                'id': str(history_object.company.pk),
                'name': history_object.company.name,
            },
            'country': {
                'id': str(history_object.country.pk),
                'name': history_object.country.name,
            },
            'date': history_object.history_date.isoformat(),
            'history_date': history_object.history_date.isoformat(),
            'history_type': history_object.history_type,
            'history_user': {
                'id': str(history_object.history_user.pk),
                'name': history_object.history_user.name,
            },
            'id': str(history_object.pk),
            'status': history_object.status,
        }

    def test_interaction_response_body(self, es_with_collector):
        """Test the format of an interaction result in the response body."""
        interaction = ExportCountriesInteractionFactory()
        es_with_collector.flush_and_refresh()

        response = self.api_client.post(
            export_country_history_search_url,
            data={
                # The view requires a filter
                'company': interaction.company.pk,
            },
        )
        assert response.status_code == status.HTTP_200_OK

        results = response.json()['results']
        assert len(results) == 1

        result = results[0]
        result['contacts'].sort(key=itemgetter('id'))
        result['dit_participants'].sort(
            key=lambda participant: participant['adviser']['id'])
        result['export_countries'].sort(
            key=lambda export_country: export_country['country']['id'])

        assert result == {
            'company': {
                'id': str(interaction.company.pk),
                'name': interaction.company.name,
                'trading_names': interaction.company.trading_names,
            },
            'contacts': [{
                'id': str(contact.pk),
                'first_name': contact.first_name,
                'name': contact.name,
                'last_name': contact.last_name,
            } for contact in sorted(interaction.contacts.all(),
                                    key=attrgetter('id'))],
            'date':
            interaction.date.isoformat(),
            'dit_participants': [{
                'adviser': {
                    'id': str(dit_participant.adviser.pk),
                    'first_name': dit_participant.adviser.first_name,
                    'name': dit_participant.adviser.name,
                    'last_name': dit_participant.adviser.last_name,
                },
                'team': {
                    'id': str(dit_participant.team.pk),
                    'name': dit_participant.team.name,
                },
            } for dit_participant in interaction.dit_participants.order_by(
                'adviser__pk')],
            'export_countries': [{
                'country': {
                    'id': str(export_country.country.pk),
                    'name': export_country.country.name,
                },
                'status': export_country.status,
            } for export_country in interaction.export_countries.order_by(
                'country__pk')],
            'kind':
            interaction.kind,
            'id':
            str(interaction.pk),
            'service': {
                'id': str(interaction.service.pk),
                'name': interaction.service.name,
            },
            'subject':
            interaction.subject,
        }

    @pytest.mark.parametrize(
        'factory',
        (
            lambda: CompanyExportCountryHistoryFactory(history_type=HistoryType
                                                       .INSERT),
            lambda: CompanyExportCountryHistoryFactory(history_type=HistoryType
                                                       .DELETE),
            ExportCountriesInteractionFactory,
            ExportCountriesServiceDeliveryFactory,
        ),
    )
    def test_filtering_by_company_returns_matches(self, es_with_collector,
                                                  factory):
        """Test that filtering by company includes matching objects."""
        obj = factory()
        es_with_collector.flush_and_refresh()

        response = self.api_client.post(
            export_country_history_search_url,
            data={
                'company': obj.company.pk,
            },
        )
        assert response.status_code == status.HTTP_200_OK

        response_data = response.json()
        assert response_data['count'] == 1
        assert response_data['results'][0]['id'] == str(obj.pk)

    def test_filtering_by_company_excludes_non_matches(self,
                                                       es_with_collector):
        """Test that filtering by company excludes non-matching objects."""
        company = CompanyFactory()

        # Non-export country interactions should be excluded
        CompanyInteractionFactory(company=company)

        # Unrelated companies should be excluded
        CompanyExportCountryHistoryFactory(history_type=HistoryType.INSERT)
        ExportCountriesInteractionFactory()

        es_with_collector.flush_and_refresh()

        response = self.api_client.post(
            export_country_history_search_url,
            data={
                'company': company.pk,
            },
        )
        assert response.status_code == status.HTTP_200_OK

        response_data = response.json()
        assert response_data['count'] == 0
        assert response_data['results'] == []

    @pytest.mark.parametrize(
        'factory',
        (
            lambda: CompanyExportCountryHistoryFactory(history_type=HistoryType
                                                       .INSERT),
            lambda: CompanyExportCountryHistoryFactory(history_type=HistoryType
                                                       .DELETE),
        ),
    )
    def test_filtering_by_country_returns_matching_history_objects(
        self,
        es_with_collector,
        factory,
    ):
        """Test that filtering by country includes matching export country history objects."""
        obj = factory()
        es_with_collector.flush_and_refresh()

        response = self.api_client.post(
            export_country_history_search_url,
            data={
                'country': obj.country.pk,
            },
        )
        assert response.status_code == status.HTTP_200_OK

        response_data = response.json()
        assert response_data['count'] == 1
        assert response_data['results'][0]['id'] == str(obj.pk)

    @pytest.mark.parametrize(
        'factory',
        (
            ExportCountriesInteractionFactory,
            ExportCountriesServiceDeliveryFactory,
        ),
    )
    def test_filtering_by_country_returns_matching_interactions(
            self, es_with_collector, factory):
        """Test that filtering by country includes matching interactions."""
        obj = factory()
        es_with_collector.flush_and_refresh()

        response = self.api_client.post(
            export_country_history_search_url,
            data={
                'country': obj.export_countries.first().country.pk,
            },
        )
        assert response.status_code == status.HTTP_200_OK

        response_data = response.json()
        assert response_data['count'] == 1
        assert response_data['results'][0]['id'] == str(obj.pk)

    def test_filtering_by_country_excludes_non_matches(self,
                                                       es_with_collector):
        """Test that filtering by country excludes non-matching objects."""
        countries = list(Country.objects.order_by('?')[:2])
        filter_country = countries[0]
        other_country = countries[1]

        # Non-export country interactions should be excluded
        CompanyInteractionFactory()

        # Unrelated countries should be excluded
        CompanyExportCountryHistoryFactory(country=other_country,
                                           history_type=HistoryType.INSERT)
        ExportCountriesInteractionFactory(
            export_countries__country=other_country)

        es_with_collector.flush_and_refresh()

        response = self.api_client.post(
            export_country_history_search_url,
            data={
                'country': filter_country.pk,
            },
        )
        assert response.status_code == status.HTTP_200_OK

        response_data = response.json()
        assert response_data['count'] == 0
        assert response_data['results'] == []

    @pytest.mark.parametrize(
        'request_args,is_reversed',
        (
            # default sorting
            ({}, True),
            ({
                'sortby': 'date:asc'
            }, False),
            ({
                'sortby': 'date:desc'
            }, True),
        ),
    )
    def test_sorts_results(self, es_with_collector, request_args, is_reversed):
        """
        Test sorting in various cases.

        Note that a filter is mandatory in this view, hence the test filters by company.
        """
        datetimes = [
            datetime(2001, 1, 22, tzinfo=utc),
            datetime(2002, 2, 23, 1, 2, 3, tzinfo=utc),
            datetime(2003, 3, 24, tzinfo=utc),
            datetime(2004, 4, 25, 1, 2, 3, tzinfo=utc),
        ]
        company = CompanyFactory()

        objects = [
            ExportCountriesInteractionFactory(date=datetimes.pop(0),
                                              company=company),
            _make_dated_export_country_history(datetimes.pop(0),
                                               company=company),
            ExportCountriesInteractionFactory(date=datetimes.pop(0),
                                              company=company),
            _make_dated_export_country_history(datetimes.pop(0),
                                               company=company),
        ]

        if is_reversed:
            objects.reverse()

        es_with_collector.flush_and_refresh()

        response = self.api_client.post(
            export_country_history_search_url,
            data={
                'company': company.pk,
                **request_args,
            },
        )
        assert response.status_code == status.HTTP_200_OK

        expected_result_ids = [str(obj.pk) for obj in objects]
        actual_result_ids = [
            result['id'] for result in response.json()['results']
        ]

        assert actual_result_ids == expected_result_ids
示例#13
0
 def test_str(self):
     """Test the human friendly string representation of the object"""
     history = CompanyExportCountryHistoryFactory()
     status = f'{history.company} {history.country} {history.status}'
     assert str(history) == status