Ejemplo n.º 1
0
class ExportCountryHistory(BaseSearchModel):
    """OpenSearch representation of CompanyExportCountryHistory model."""

    id = Keyword()
    history_date = Date(index=False)
    history_user = fields.id_unindexed_name_field()
    history_type = Keyword(index=True)
    country = fields.id_unindexed_name_field()

    company = fields.id_unindexed_name_field()
    status = Keyword(index=False)
    # Adding `date` field, mapping to `history_date` for sorting across entities
    # export_country_history and interaction.
    date = Date()

    MAPPINGS = {
        'history_user': dict_utils.id_name_dict,
        'country': dict_utils.id_name_dict,
        'company': dict_utils.id_name_dict,
    }

    COMPUTED_MAPPINGS = {
        'id': lambda obj: obj.history_id,  # Id required for indexing
        'date': lambda obj: obj.history_date,
    }
Ejemplo n.º 2
0
def sector_field():
    """Sector field."""
    ancestors = Object(properties={
        'id': Keyword(),
    }, )

    return Object(properties={
        'id': Keyword(),
        'name': NormalizedKeyword(),
        'ancestors': ancestors,
    }, )
Ejemplo n.º 3
0
def _export_country_field():
    return Object(properties={
        'id':
        Keyword(index=False),
        'country':
        Object(properties={
            'id': Keyword(),
            'name': Text(index=False),
        }, ),
        'status':
        Text(index=False),
    }, )
Ejemplo n.º 4
0
def interaction_field():
    """Interaction field with id, subject and date."""
    return Object(properties={
        'id': Keyword(),
        'subject': Text(index=False),
        'date': Date(),
    }, )
Ejemplo n.º 5
0
class Person(InnerDoc):
    """Inner doc for a person (e.g. a contact or an adviser)."""

    id = Keyword()
    first_name = Text(index=False)
    last_name = Text(index=False)
    name = TextWithTrigram()
Ejemplo n.º 6
0
def _related_investment_project_field():
    """Field for a related investment project."""
    return Object(
        properties={
            'id': Keyword(),
            'name': fields.NormalizedKeyword(),
            'project_code': fields.NormalizedKeyword(),
        })
Ejemplo n.º 7
0
def _contact_field():
    return Object(properties={
        'id': Keyword(index=False),
        'first_name': Text(index=False),
        'last_name': Text(index=False),
        'name': Text(fields={
            'trigram': TrigramText(),
        }, ),
    }, )
Ejemplo n.º 8
0
def _adviser_field_with_indexed_id():
    return Object(
        properties={
            'id': Keyword(),
            'first_name': Text(index=False),
            'last_name': Text(index=False),
            'name': Text(index=False),
        },
    )
Ejemplo n.º 9
0
def id_name_partial_field():
    """Object field with id and name sub-fields, and with partial matching on name."""
    return Object(properties={
        'id':
        Keyword(),
        'name':
        Text(fields={
            'keyword': NormalizedKeyword(),
            'trigram': TrigramText(),
        }, ),
    }, )
Ejemplo n.º 10
0
class SearchRelatedModel(BaseSearchModel):
    """OpenSearch representation of SimpleModel model."""

    id = Keyword()
    simpleton = fields.id_name_field()

    MAPPINGS = {
        'simpleton': dict_utils.id_name_dict,
    }

    SEARCH_FIELDS = ('simpleton.name',)
Ejemplo n.º 11
0
def company_field():
    """Company field with id, name, trading_names and trigrams."""
    return Object(properties={
        'id':
        Keyword(),
        'name':
        Text(fields={
            'trigram': TrigramText(),
            'keyword': NormalizedKeyword(),
        }, ),
        'trading_names':
        TextWithTrigram(),
    }, )
Ejemplo n.º 12
0
def contact_or_adviser_field(include_dit_team=False):
    """Object field for advisers and contacts."""
    props = {
        'id':
        Keyword(),
        'first_name':
        NormalizedKeyword(),
        'last_name':
        NormalizedKeyword(),
        'name':
        Text(fields={
            'keyword': NormalizedKeyword(),
            'trigram': TrigramText(),
        }, ),
    }

    if include_dit_team:
        props['dit_team'] = id_name_field()

    return Object(properties=props)
Ejemplo n.º 13
0
class SearchSimpleModel(BaseSearchModel):
    """OpenSearch representation of SimpleModel model."""

    id = Keyword()
    name = Text(fields={
        'keyword': fields.NormalizedKeyword(),
        'trigram': fields.TrigramText(),
    }, )
    country = Text(fields={
        'keyword': fields.NormalizedKeyword(),
        'trigram': fields.TrigramText(),
    }, )
    address = Text(fields={
        'trigram': fields.TrigramText(),
    }, )
    date = Date()

    SEARCH_FIELDS = (
        'name',
        'name.trigram',
        'country.trigram',
        'address.trigram',
    )
Ejemplo n.º 14
0
def id_name_field():
    """Object field with id and name sub-fields."""
    return Object(properties={
        'id': Keyword(),
        'name': NormalizedKeyword(),
    }, )
Ejemplo n.º 15
0
class BaseSearchModel(Document):
    """Helps convert Django models to dictionaries."""

    # This is a replacement for the _type (mapping type name) field which is deprecated in
    # OpenSearch. It’s required for the aggregations used in global search.
    _document_type = Keyword()

    MAPPINGS = {}

    COMPUTED_MAPPINGS = {}

    SEARCH_FIELDS = ()

    # Fields that have been renamed in some way, and were used as part of a filter.
    # While an index migration is in progress, a composite filter must be used so that the
    # filter works with both the old and new index.
    # Such fields should be listed in this attribute it make it clear why they're being referenced.
    # Once the migration is complete in all environments, the composite filter can be updated
    # and the field removed from here.
    PREVIOUS_MAPPING_FIELDS = ()

    class Meta:
        dynamic = MetaField('false')

    @classmethod
    def get_app_name(cls):
        """Get the search app name for this search model."""
        return get_search_app_by_search_model(cls).name

    @classmethod
    def get_read_alias(cls):
        """Gets the alias to be used for read operations."""
        return f'{settings.OPENSEARCH_INDEX_PREFIX}-{cls.get_app_name()}-read'

    @classmethod
    def get_write_alias(cls):
        """Gets the alias to be used for write operations."""
        return f'{settings.OPENSEARCH_INDEX_PREFIX}-{cls.get_app_name()}-write'

    @classmethod
    def get_write_index(cls):
        """Gets the index currently referenced by the write alias."""
        indices, = get_indices_for_aliases(cls.get_write_alias())
        return _get_write_index(indices)

    @classmethod
    def get_read_and_write_indices(cls):
        """Gets the indices currently referenced by the read and write aliases."""
        read_indices, write_indices = get_indices_for_aliases(
            cls.get_read_alias(), cls.get_write_alias(),
        )
        return read_indices, _get_write_index(write_indices)

    @classmethod
    def get_index_prefix(cls):
        """Gets the prefix used for indices and aliases."""
        return f'{settings.OPENSEARCH_INDEX_PREFIX}-{cls.get_app_name()}-'

    @classmethod
    def get_target_mapping_hash(cls):
        """Gets a unique hash digest for mapping (as defined in the code base)."""
        mapping_data = serialise_mapping(cls._doc_type.mapping.to_dict())
        return blake2b(mapping_data, digest_size=16).hexdigest()

    @classmethod
    def get_current_mapping_hash(cls):
        """Extracts and returns the mapping hash from the current index name."""
        current_write_index = cls.get_write_index()
        prefix = cls.get_index_prefix()
        if not current_write_index.startswith(prefix):
            logger.warning(
                f'Unexpected index prefix for search model {cls.get_app_name()} and '
                f'index {current_write_index}. It may be a legacy index.',
            )
            return ''
        return current_write_index[len(prefix):]

    @classmethod
    def get_target_index_name(cls):
        """Generates a unique name for the index based on its mapping."""
        mapping_hash = cls.get_target_mapping_hash()
        prefix = cls.get_index_prefix()
        return f'{prefix}{mapping_hash}'

    @classmethod
    def is_migration_needed(cls):
        """Returns whether the active mapping is out of date and a migration is needed."""
        target_mapping_hash = cls.get_target_mapping_hash()
        return cls.get_current_mapping_hash() != target_mapping_hash

    @classmethod
    def was_migration_started(cls):
        """
        Returns whether a migration was started and has not completed.

        This could be a a migration still in progress, or an aborted migration.
        """
        read_indices, _ = cls.get_read_and_write_indices()
        return len(read_indices) != 1

    @classmethod
    def set_up_index_and_aliases(cls):
        """Creates the index and aliases for this model if they don't already exist."""
        if not alias_exists(cls.get_write_alias()):
            index_name = cls.get_target_index_name()
            alias_names = (cls.get_write_alias(), cls.get_read_alias())
            create_index(index_name, cls._doc_type.mapping, alias_names=alias_names)
            return True

        # Should not normally happen
        if not alias_exists(cls.get_read_alias()):
            logger.warning(
                f'Missing read alias {cls.get_read_alias()} detected, recreating the alias...',
            )
            associate_index_with_alias(cls.get_read_alias(), cls.get_write_index())

        return False

    @classmethod
    def to_document(cls, db_object, index=None, include_index=True, include_source=True):
        """
        Creates a dict representation an OpenSearch document.

        include_index and include_source can be set to False when the _index and/or _source keys
        aren't required (e.g. when using `datahub.search.deletion.delete_documents()`).
        """
        doc = {
            '_id': db_object.pk,
        }

        if include_index:
            doc['_index'] = index or cls.get_write_alias()

        if include_source:
            doc['_source'] = cls.db_object_to_dict(db_object)

        return doc

    @classmethod
    def db_object_to_dict(cls, db_object):
        """Converts a DB model object to a dictionary suitable for OpenSearch."""
        mapped_values = (
            (col, fn, getattr(db_object, col)) for col, fn in cls.MAPPINGS.items()
        )
        fields = get_model_non_mapped_field_names(cls)

        result = {
            **{col: fn(val) if val is not None else None for col, fn, val in mapped_values},
            **{col: fn(db_object) for col, fn in cls.COMPUTED_MAPPINGS.items()},
            **{field: getattr(db_object, field) for field in fields},
            '_document_type': cls.get_app_name(),
        }

        return result

    @classmethod
    def db_objects_to_documents(cls, db_objects, index=None):
        """Converts DB model objects to OpenSearch documents."""
        for db_object in db_objects:
            yield cls.to_document(db_object, index=index)
Ejemplo n.º 16
0
class InvestmentProject(BaseSearchModel):
    """OpenSearch representation of InvestmentProject."""

    id = Keyword()
    actual_land_date = Date()
    actual_uk_regions = fields.id_name_field()
    address_1 = Text()
    address_2 = Text()
    address_town = fields.NormalizedKeyword()
    address_postcode = Text()
    approved_commitment_to_invest = Boolean()
    approved_fdi = Boolean()
    approved_good_value = Boolean()
    approved_high_value = Boolean()
    approved_landed = Boolean()
    approved_non_fdi = Boolean()
    allow_blank_estimated_land_date = Boolean(index=False)
    allow_blank_possible_uk_regions = Boolean(index=False)
    anonymous_description = fields.EnglishText()
    archived = Boolean()
    archived_by = fields.contact_or_adviser_field()
    archived_on = Date()
    archived_reason = Text()
    associated_non_fdi_r_and_d_project = _related_investment_project_field()
    average_salary = fields.id_name_field()
    business_activities = fields.id_name_field()
    client_cannot_provide_foreign_investment = Boolean()
    client_cannot_provide_total_investment = Boolean()
    client_contacts = fields.contact_or_adviser_field()
    client_relationship_manager = fields.contact_or_adviser_field(
        include_dit_team=True)
    client_requirements = Text(index=False)
    comments = fields.EnglishText()
    country_investment_originates_from = fields.id_name_field()
    country_lost_to = Object(properties={
        'id': Keyword(index=False),
        'name': Text(index=False),
    }, )
    created_on = Date()
    created_by = fields.contact_or_adviser_field(include_dit_team=True)
    date_abandoned = Date()
    date_lost = Date()
    delivery_partners = fields.id_name_field()
    description = fields.EnglishText()
    estimated_land_date = Date()
    export_revenue = Boolean()
    fdi_type = fields.id_name_field()
    fdi_value = fields.id_name_field()
    foreign_equity_investment = Double()
    government_assistance = Boolean()
    incomplete_fields = Text()
    intermediate_company = fields.id_name_field()
    investor_company = fields.id_name_partial_field()
    investor_company_country = fields.id_name_field()
    investment_type = fields.id_name_field()
    investor_type = fields.id_name_field()
    level_of_involvement = fields.id_name_field()
    likelihood_to_land = fields.id_name_field()
    project_assurance_adviser = fields.contact_or_adviser_field(
        include_dit_team=True)
    project_manager = fields.contact_or_adviser_field(include_dit_team=True)
    name = Text(fields={
        'keyword': fields.NormalizedKeyword(),
        'trigram': fields.TrigramText(),
    }, )
    new_tech_to_uk = Boolean()
    non_fdi_r_and_d_budget = Boolean()
    number_new_jobs = Integer()
    number_safeguarded_jobs = Long()
    modified_on = Date()
    project_arrived_in_triage_on = Date()
    project_code = fields.NormalizedKeyword(fields={
        'trigram': fields.TrigramText(),
    }, )
    proposal_deadline = Date()
    other_business_activity = Text(index=False)
    quotable_as_public_case_study = Boolean()
    r_and_d_budget = Boolean()
    reason_abandoned = Text(index=False)
    reason_delayed = Text(index=False)
    reason_lost = Text(index=False)
    referral_source_activity = fields.id_name_field()
    referral_source_activity_event = fields.NormalizedKeyword()
    referral_source_activity_marketing = fields.id_name_field()
    referral_source_activity_website = fields.id_name_field()
    referral_source_adviser = Object(properties={
        'id': Keyword(index=False),
        'first_name': Text(index=False),
        'last_name': Text(index=False),
        'name': Text(index=False),
    }, )
    sector = fields.sector_field()
    site_decided = Boolean()
    some_new_jobs = Boolean()
    specific_programme = fields.id_name_field()
    stage = fields.id_name_field()
    status = fields.NormalizedKeyword()
    team_members = fields.contact_or_adviser_field(include_dit_team=True)
    total_investment = Double()
    uk_company = fields.id_name_partial_field()
    uk_company_decided = Boolean()
    uk_region_locations = fields.id_name_field()
    will_new_jobs_last_two_years = Boolean()
    level_of_involvement_simplified = Keyword()
    latest_interaction = fields.interaction_field()

    gross_value_added = Double()

    MAPPINGS = {
        'actual_uk_regions':
        lambda col: [dict_utils.id_name_dict(c) for c in col.all()],
        'archived_by':
        dict_utils.contact_or_adviser_dict,
        'associated_non_fdi_r_and_d_project':
        dict_utils.investment_project_dict,
        'average_salary':
        dict_utils.id_name_dict,
        'business_activities':
        lambda col: [dict_utils.id_name_dict(c) for c in col.all()],
        'client_contacts':
        lambda col: [dict_utils.contact_or_adviser_dict(c) for c in col.all()],
        'client_relationship_manager':
        dict_utils.adviser_dict_with_team,
        'country_lost_to':
        dict_utils.id_name_dict,
        'country_investment_originates_from':
        dict_utils.id_name_dict,
        'created_by':
        dict_utils.adviser_dict_with_team,
        'delivery_partners':
        lambda col: [dict_utils.id_name_dict(c) for c in col.all()],
        'fdi_type':
        dict_utils.id_name_dict,
        'fdi_value':
        dict_utils.id_name_dict,
        'intermediate_company':
        dict_utils.id_name_dict,
        'investment_type':
        dict_utils.id_name_dict,
        'investor_company':
        dict_utils.id_name_dict,
        'investor_company_country':
        dict_utils.id_name_dict,
        'investor_type':
        dict_utils.id_name_dict,
        'latest_interaction':
        dict_utils.interaction_dict,
        'level_of_involvement':
        dict_utils.id_name_dict,
        'likelihood_to_land':
        dict_utils.id_name_dict,
        'project_assurance_adviser':
        dict_utils.adviser_dict_with_team,
        'project_code':
        str,
        'project_manager':
        dict_utils.adviser_dict_with_team,
        'referral_source_activity':
        dict_utils.id_name_dict,
        'referral_source_activity_marketing':
        dict_utils.id_name_dict,
        'referral_source_activity_website':
        dict_utils.id_name_dict,
        'referral_source_adviser':
        dict_utils.contact_or_adviser_dict,
        'sector':
        dict_utils.sector_dict,
        'specific_programme':
        dict_utils.id_name_dict,
        'stage':
        dict_utils.id_name_dict,
        'team_members':
        lambda col: [
            dict_utils.contact_or_adviser_dict(c.adviser,
                                               include_dit_team=True)
            for c in col.all()
        ],
        'uk_company':
        dict_utils.id_name_dict,
        'uk_region_locations':
        lambda col: [dict_utils.id_name_dict(c) for c in col.all()],
    }

    SEARCH_FIELDS = (
        'id',
        'name',
        'name.trigram',
        'uk_company.name',
        'uk_company.name.trigram',
        'investor_company.name',
        'investor_company.name.trigram',
        'project_code',
        'sector.name',
    )
Ejemplo n.º 17
0
def ch_company_field():
    """Object field with id and company_number sub-fields."""
    return Object(properties={
        'id': Keyword(),
        'company_number': NormalizedKeyword(),
    })
Ejemplo n.º 18
0
def area_field():
    """Area field with id, name and trigram."""
    return Object(properties={
        'id': Keyword(),
        'name': TextWithTrigram(),
    }, )
Ejemplo n.º 19
0
def test_creates_index(monkeypatch, mock_connection_for_create_index):
    """Test creates_index()."""
    monkeypatch.setattr(
        'django.conf.settings.OPENSEARCH_INDEX_SETTINGS',
        {
            'testsetting1': 'testval1',
        },
    )
    mapping = Mapping()
    mapping.field('test-field', Keyword())
    index = 'test-index'
    connection = mock_connection_for_create_index.return_value

    opensearch_client.create_index(index,
                                   mapping,
                                   alias_names=('alias1', 'alias2'))
    connection.indices.create.assert_called_once_with(
        index='test-index',
        body={
            'settings': {
                'testsetting1': 'testval1',
                'analysis': {
                    'analyzer': {
                        'trigram_analyzer': {
                            'tokenizer': 'trigram',
                            'char_filter': ['special_chars'],
                            'filter': ['lowercase'],
                            'type': 'custom',
                        },
                        'english_analyzer': {
                            'tokenizer':
                            'standard',
                            'filter': [
                                'english_possessive_stemmer',
                                'lowercase',
                                'english_stop',
                                'english_stemmer',
                            ],
                            'type':
                            'custom',
                        },
                    },
                    'tokenizer': {
                        'trigram': {
                            'min_gram': 3,
                            'max_gram': 3,
                            'token_chars': ('letter', 'digit'),
                            'type': 'nGram',
                        },
                    },
                    'char_filter': {
                        'special_chars': {
                            'mappings': ('-=>', ),
                            'type': 'mapping',
                        },
                    },
                    'filter': {
                        'english_possessive_stemmer': {
                            'language': 'possessive_english',
                            'type': 'stemmer',
                        },
                        'english_stop': {
                            'stopwords': '_english_',
                            'type': 'stop',
                        },
                        'english_stemmer': {
                            'language': 'english',
                            'type': 'stemmer',
                        },
                    },
                },
            },
            'aliases': {
                'alias1': {},
                'alias2': {},
            },
            'mappings': {
                'properties': {
                    'test-field': {
                        'type': 'keyword',
                    },
                },
            },
        },
    )
Ejemplo n.º 20
0
class Company(BaseSearchModel):
    """
    OpenSearch representation of Company model.
    """

    id = Keyword()
    archived = Boolean()
    archived_by = fields.contact_or_adviser_field()
    archived_on = Date()
    archived_reason = Text()
    business_type = fields.id_name_field()
    company_number = fields.NormalizedKeyword()
    created_on = Date()
    description = fields.EnglishText()
    employee_range = fields.id_name_field()
    export_experience_category = fields.id_name_field()
    export_to_countries = fields.id_name_field()
    future_interest_countries = fields.id_name_field()
    global_headquarters = fields.id_name_field()
    headquarter_type = fields.id_name_field()
    modified_on = Date()
    name = Text(
        fields={
            'keyword': fields.NormalizedKeyword(),
            'trigram': fields.TrigramText(),
        },
    )
    reference_code = fields.NormalizedKeyword()
    sector = fields.sector_field()
    address = fields.address_field()
    registered_address = fields.address_field()
    one_list_group_global_account_manager = _adviser_field_with_indexed_id()
    trading_names = fields.TextWithTrigram()
    turnover_range = fields.id_name_field()
    uk_region = fields.id_name_field()
    uk_based = Boolean()
    uk_address_postcode = fields.PostcodeKeyword()
    uk_registered_address_postcode = fields.PostcodeKeyword()
    vat_number = Keyword(index=False)
    duns_number = Keyword()
    website = Text()
    latest_interaction_date = Date()
    export_segment = Text()
    export_sub_segment = Text()

    COMPUTED_MAPPINGS = {
        'address': partial(dict_utils.address_dict, prefix='address'),
        'registered_address': partial(dict_utils.address_dict, prefix='registered_address'),
        'one_list_group_global_account_manager': dict_utils.computed_field_function(
            'get_one_list_group_global_account_manager',
            dict_utils.contact_or_adviser_dict,
        ),
        'export_to_countries': lambda obj: [
            dict_utils.id_name_dict(o.country) for o in obj.export_countries.all()
            if o.status == CompanyExportCountry.Status.CURRENTLY_EXPORTING
        ],
        'future_interest_countries': lambda obj: [
            dict_utils.id_name_dict(o.country) for o in obj.export_countries.all()
            if o.status == CompanyExportCountry.Status.FUTURE_INTEREST
        ],
        'latest_interaction_date': lambda obj: obj.latest_interaction_date,
        'uk_address_postcode': lambda obj: obj.address_postcode if obj.uk_based else '',
        'uk_registered_address_postcode':
            lambda obj: obj.registered_address_postcode if obj.uk_based else '',
    }

    MAPPINGS = {
        'archived_by': dict_utils.contact_or_adviser_dict,
        'business_type': dict_utils.id_name_dict,
        'employee_range': dict_utils.id_name_dict,
        'export_experience_category': dict_utils.id_name_dict,
        'global_headquarters': dict_utils.id_name_dict,
        'headquarter_type': dict_utils.id_name_dict,
        'sector': dict_utils.sector_dict,

        'turnover_range': dict_utils.id_name_dict,
        'uk_based': bool,
        'uk_region': dict_utils.id_name_dict,
    }

    SEARCH_FIELDS = (
        'id',
        'name',  # to find 2-letter words
        'name.trigram',
        'company_number',
        'trading_names',  # to find 2-letter words
        'trading_names.trigram',
        'reference_code',
        'sector.name',
        'address.line_1.trigram',
        'address.line_2.trigram',
        'address.town.trigram',
        'address.county.trigram',
        'address.area.name.trigram',
        'address.postcode',
        'address.country.name.trigram',
        'registered_address.line_1.trigram',
        'registered_address.line_2.trigram',
        'registered_address.town.trigram',
        'registered_address.county.trigram',
        'registered_address.area.name.trigram',
        'registered_address.postcode',
        'registered_address.country.name.trigram',
    )
Ejemplo n.º 21
0
class Event(BaseSearchModel):
    """OpenSearch representation of Event model."""

    id = Keyword()
    address_1 = Text()
    address_2 = Text()
    address_town = fields.NormalizedKeyword()
    address_county = fields.NormalizedKeyword()
    address_postcode = fields.TextWithTrigram()
    address_country = fields.id_name_partial_field()
    created_on = Date()
    disabled_on = Date()
    end_date = Date()
    event_type = fields.id_name_partial_field()
    lead_team = fields.id_name_field()
    location_type = fields.id_name_field()
    modified_on = Date()
    name = Text(fields={
        'keyword': fields.NormalizedKeyword(),
        'trigram': fields.TrigramText(),
    }, )
    notes = fields.EnglishText()
    organiser = fields.contact_or_adviser_field()
    related_programmes = fields.id_name_partial_field()
    service = fields.id_name_field()
    start_date = Date()
    teams = fields.id_name_partial_field()
    uk_region = fields.id_name_partial_field()

    MAPPINGS = {
        'address_country':
        dict_utils.id_name_dict,
        'event_type':
        dict_utils.id_name_dict,
        'lead_team':
        dict_utils.id_name_dict,
        'location_type':
        dict_utils.id_name_dict,
        'organiser':
        dict_utils.contact_or_adviser_dict,
        'related_programmes':
        lambda col: [dict_utils.id_name_dict(c) for c in col.all()],
        'service':
        dict_utils.id_name_dict,
        'teams':
        lambda col: [dict_utils.id_name_dict(c) for c in col.all()],
        'uk_region':
        dict_utils.id_name_dict,
    }

    COMPUTED_MAPPINGS = {}

    SEARCH_FIELDS = (
        'id',
        'name',
        'name.trigram',
        'address_country.name.trigram',
        'address_postcode',
        'uk_region.name.trigram',
        'organiser.name.trigram',
        'teams.name',
        'teams.name.trigram',
        'related_programmes.name',
        'related_programmes.name.trigram',
        'event_type.name',
        'event_type.name.trigram',
    )
Ejemplo n.º 22
0
class LargeInvestorProfile(BaseSearchModel):
    """OpenSearch representation of LargeInvestorProfile."""

    id = Keyword()

    investor_company = fields.company_field()
    country_of_origin = fields.country_field()
    asset_classes_of_interest = fields.id_unindexed_name_field()
    created_by = fields.contact_or_adviser_field(include_dit_team=True)

    investor_type = fields.id_unindexed_name_field()
    global_assets_under_management = Long()
    investable_capital = Long()
    required_checks_conducted = fields.id_unindexed_name_field()

    deal_ticket_sizes = fields.id_unindexed_name_field()
    investment_types = fields.id_unindexed_name_field()
    minimum_return_rate = fields.id_unindexed_name_field()
    time_horizons = fields.id_unindexed_name_field()
    restrictions = fields.id_unindexed_name_field()
    construction_risks = fields.id_unindexed_name_field()
    minimum_equity_percentage = fields.id_unindexed_name_field()
    desired_deal_roles = fields.id_unindexed_name_field()

    uk_region_locations = fields.id_unindexed_name_field()
    other_countries_being_considered = fields.country_field()

    investor_description = fields.EnglishText()
    notes_on_locations = fields.EnglishText()

    created_on = Date()
    modified_on = Date()

    _MAIN_FIELD_MAPPINGS = {
        'asset_classes_of_interest': _get_many_to_many_list,
        'country_of_origin': dict_utils.id_name_dict,
        'investor_company': dict_utils.company_dict,
        'created_by': dict_utils.adviser_dict_with_team,
    }

    _DETAIL_FIELD_MAPPINGS = {
        'investor_type': dict_utils.id_name_dict,
        'required_checks_conducted': dict_utils.id_name_dict,
    }

    _REQUIREMENT_FIELD_MAPPINGS = {
        'deal_ticket_sizes': _get_many_to_many_list,
        'investment_types': _get_many_to_many_list,
        'minimum_return_rate': dict_utils.id_name_dict,
        'time_horizons': _get_many_to_many_list,
        'restrictions': _get_many_to_many_list,
        'construction_risks': _get_many_to_many_list,
        'minimum_equity_percentage': dict_utils.id_name_dict,
        'desired_deal_roles': _get_many_to_many_list,
    }

    _LOCATION_FIELD_MAPPINGS = {
        'uk_region_locations': _get_many_to_many_list,
        'other_countries_being_considered': _get_many_to_many_list,
    }

    MAPPINGS = {
        **_MAIN_FIELD_MAPPINGS,
        **_DETAIL_FIELD_MAPPINGS,
        **_REQUIREMENT_FIELD_MAPPINGS,
        **_LOCATION_FIELD_MAPPINGS,
    }
Ejemplo n.º 23
0
class Contact(BaseSearchModel):
    """OpenSearch representation of Contact model."""

    id = Keyword()
    address_1 = Text()
    address_2 = Text()
    address_town = fields.NormalizedKeyword()
    address_county = fields.NormalizedKeyword()
    address_postcode = Text()
    address_country = fields.id_name_field()
    address_area = fields.id_name_field()
    address_same_as_company = Boolean()
    adviser = fields.contact_or_adviser_field()
    archived = Boolean()
    archived_by = fields.contact_or_adviser_field()
    archived_on = Date()
    archived_reason = Text()
    company = fields.company_field()
    company_sector = fields.sector_field()
    company_uk_region = fields.id_name_field()
    created_by = fields.contact_or_adviser_field(include_dit_team=True)
    created_on = Date()
    email = fields.NormalizedKeyword()
    first_name = Text(fields={
        'keyword': fields.NormalizedKeyword(),
    }, )
    job_title = Text(fields={
        'keyword': fields.NormalizedKeyword(),
        'trigram': fields.TrigramText(),
    }, )
    last_name = Text(fields={
        'keyword': fields.NormalizedKeyword(),
    }, )
    modified_on = Date()
    name = Text(fields={
        'keyword': fields.NormalizedKeyword(),
        'trigram': fields.TrigramText(),
    }, )
    name_with_title = Text(fields={
        'keyword': fields.NormalizedKeyword(),
        'trigram': fields.TrigramText(),
    }, )
    notes = fields.EnglishText()
    primary = Boolean()
    full_telephone_number = Keyword()
    title = fields.id_name_field()

    MAPPINGS = {
        'adviser': dict_utils.contact_or_adviser_dict,
        'archived_by': dict_utils.contact_or_adviser_dict,
        'company': dict_utils.company_dict,
        'created_by': dict_utils.adviser_dict_with_team,
        'title': dict_utils.id_name_dict,
    }

    COMPUTED_MAPPINGS = {
        'address_1':
        contact_dict_utils.computed_address_field('address_1'),
        'address_2':
        contact_dict_utils.computed_address_field('address_2'),
        'address_town':
        contact_dict_utils.computed_address_field('address_town'),
        'address_county':
        contact_dict_utils.computed_address_field('address_county'),
        'address_postcode':
        contact_dict_utils.computed_address_field('address_postcode'),
        'address_country':
        contact_dict_utils.computed_address_field('address_country'),
        'address_area':
        contact_dict_utils.computed_address_field('address_area'),
        'company_sector':
        dict_utils.computed_nested_sector_dict('company.sector'),
        'company_uk_region':
        dict_utils.computed_nested_id_name_dict('company.uk_region'),
    }

    SEARCH_FIELDS = (
        'id',
        'name',
        'name.trigram',
        'name_with_title',
        'name_with_title.trigram',
        'email',
        'company.name',
        'company.name.trigram',
        'job_title',
        'job_title.trigram',
        'full_telephone_number',
    )
Ejemplo n.º 24
0
def id_unindexed_name_field():
    """Object field with id and unindexed name sub-fields."""
    return Object(properties={
        'id': Keyword(),
        'name': Keyword(index=False),
    }, )
Ejemplo n.º 25
0
class Interaction(BaseSearchModel):
    """OpenSearch representation of Interaction model."""

    id = Keyword()
    company = fields.company_field()
    companies = fields.company_field()
    company_sector = fields.sector_field()
    company_one_list_group_tier = fields.id_unindexed_name_field()
    communication_channel = fields.id_unindexed_name_field()
    contacts = _contact_field()
    created_on = Date()
    date = Date()
    dit_participants = Object(_DITParticipant)
    event = fields.id_name_partial_field()
    investment_project = fields.id_unindexed_name_field()
    investment_project_sector = fields.sector_field()
    is_event = Boolean(index=False)
    grant_amount_offered = Double(index=False)
    kind = Keyword()
    modified_on = Date()
    net_company_receipt = Double(index=False)
    notes = fields.Text(index=False)
    policy_areas = fields.id_unindexed_name_field()
    policy_issue_types = fields.id_unindexed_name_field()
    service = fields.id_name_partial_field()
    service_delivery_status = fields.id_unindexed_name_field()
    subject = fields.NormalizedKeyword(fields={
        'english': fields.EnglishText(),
    }, )
    was_policy_feedback_provided = Boolean()
    were_countries_discussed = Boolean()
    export_countries = _export_country_field()

    MAPPINGS = {
        'company': dict_utils.company_dict,
        'companies': _companies_list,
        'communication_channel': dict_utils.id_name_dict,
        'contacts': dict_utils.contact_or_adviser_list_of_dicts,
        'dit_participants': _dit_participant_list,
        'export_countries': _export_countries_list,
        'event': dict_utils.id_name_dict,
        'investment_project': dict_utils.id_name_dict,
        'policy_areas': dict_utils.id_name_list_of_dicts,
        'policy_issue_types': dict_utils.id_name_list_of_dicts,
        'service': dict_utils.id_name_dict,
        'service_delivery_status': dict_utils.id_name_dict,
    }

    COMPUTED_MAPPINGS = {
        'company_sector':
        dict_utils.computed_nested_sector_dict('company.sector'),
        'company_one_list_group_tier':
        lambda obj: dict_utils.id_name_dict(
            obj.company.get_one_list_group_tier() if obj.company else None, ),
        'investment_project_sector':
        dict_utils.computed_nested_sector_dict('investment_project.sector', ),
        'is_event':
        attrgetter('is_event'),
    }

    SEARCH_FIELDS = (
        'id',
        'company.name',
        'company.name.trigram',
        'companies.name',
        'companies.name.trigram',
        'contacts.name',  # to find 2-letter words
        'contacts.name.trigram',
        'event.name',
        'event.name.trigram',
        'service.name',
        'service.name.trigram',
        'subject.english',
        'dit_participants.adviser.name',
        'dit_participants.adviser.name.trigram',
        'dit_participants.team.name',
        'dit_participants.team.name.trigram',
    )
Ejemplo n.º 26
0
class LargeCapitalOpportunity(BaseSearchModel):
    """OpenSearch representation of LargeCapitalOpportunity."""

    id = Keyword()

    name = Text(fields={
        'keyword': fields.NormalizedKeyword(),
        'trigram': fields.TrigramText(),
    }, )
    type = fields.id_unindexed_name_field()

    description = Text(fields={
        'keyword': fields.NormalizedKeyword(),
        'trigram': fields.TrigramText(),
    }, )
    uk_region_locations = fields.id_unindexed_name_field()

    promoters = fields.company_field()

    required_checks_conducted = fields.id_unindexed_name_field()
    required_checks_conducted_by = fields.contact_or_adviser_field(
        include_dit_team=True)
    required_checks_conducted_on = Date()

    lead_dit_relationship_manager = fields.contact_or_adviser_field(
        include_dit_team=True)
    other_dit_contacts = fields.contact_or_adviser_field(include_dit_team=True)

    asset_classes = fields.id_unindexed_name_field()
    opportunity_value_type = fields.id_unindexed_name_field()
    opportunity_value = Long()
    construction_risks = fields.id_unindexed_name_field()

    total_investment_sought = Long()
    current_investment_secured = Long()
    investment_types = fields.id_unindexed_name_field()
    estimated_return_rate = fields.id_unindexed_name_field()
    time_horizons = fields.id_unindexed_name_field()
    investment_projects = fields.id_unindexed_name_field()
    status = fields.id_unindexed_name_field()
    sources_of_funding = fields.id_unindexed_name_field()
    dit_support_provided = Boolean()
    reasons_for_abandonment = fields.id_unindexed_name_field()

    created_by = fields.contact_or_adviser_field(include_dit_team=True)
    created_on = Date()
    modified_on = Date()

    _MAIN_FIELD_MAPPINGS = {
        'type': dict_utils.id_name_dict,
        'status': dict_utils.id_name_dict,
        'created_by': dict_utils.adviser_dict_with_team,
    }

    _DETAIL_FIELD_MAPPINGS = {
        'uk_region_locations': _get_many_to_many_list,
        'promoters': _get_company_list,
        'required_checks_conducted': dict_utils.id_name_dict,
        'required_checks_conducted_by': dict_utils.adviser_dict_with_team,
        'lead_dit_relationship_manager': dict_utils.adviser_dict_with_team,
        'other_dit_contacts': _get_adviser_list,
        'asset_classes': _get_many_to_many_list,
        'opportunity_value_type': dict_utils.id_name_dict,
        'construction_risks': _get_many_to_many_list,
        'investment_projects': _get_investment_project_list,
        'sources_of_funding': _get_many_to_many_list,
        'reasons_for_abandonment': _get_many_to_many_list,
    }

    _REQUIREMENT_FIELD_MAPPINGS = {
        'investment_types': _get_many_to_many_list,
        'estimated_return_rate': dict_utils.id_name_dict,
        'time_horizons': _get_many_to_many_list,
    }

    MAPPINGS = {
        **_MAIN_FIELD_MAPPINGS,
        **_DETAIL_FIELD_MAPPINGS,
        **_REQUIREMENT_FIELD_MAPPINGS,
    }
Ejemplo n.º 27
0
class IDNameTrigram(InnerDoc):
    """Inner doc for a named object, with a trigram sub-field on name."""

    id = Keyword()
    name = TextWithTrigram()
Ejemplo n.º 28
0
def country_field():
    """Country field with id, name and trigram."""
    return Object(properties={
        'id': Keyword(),
        'name': TextWithTrigram(),
    }, )
Ejemplo n.º 29
0
class Order(BaseSearchModel):
    """OpenSearch representation of Order model."""

    id = Keyword()
    reference = fields.NormalizedKeyword(
        fields={
            'trigram': fields.TrigramText(),
        },
    )
    status = fields.NormalizedKeyword()
    company = fields.company_field()
    contact = fields.contact_or_adviser_field()
    created_by = fields.contact_or_adviser_field(include_dit_team=True)
    created_on = Date()
    modified_on = Date()
    primary_market = fields.id_name_field()
    sector = fields.sector_field()
    uk_region = fields.id_name_field()
    description = fields.EnglishText()
    contacts_not_to_approach = Text()
    further_info = Text()
    existing_agents = Text(index=False)
    delivery_date = Date()
    service_types = fields.id_name_field()
    contact_email = fields.NormalizedKeyword()
    contact_phone = Keyword()
    subscribers = fields.contact_or_adviser_field(include_dit_team=True)
    assignees = fields.contact_or_adviser_field(include_dit_team=True)
    po_number = Keyword(index=False)
    discount_value = Integer(index=False)
    vat_status = Keyword(index=False)
    vat_number = Keyword(index=False)
    vat_verified = Boolean(index=False)
    net_cost = Integer(index=False)
    subtotal_cost = Integer(
        fields={
            'keyword': Keyword(),
        },
    )
    vat_cost = Integer(index=False)
    total_cost = Integer(
        fields={
            'keyword': Keyword(),
        },
    )
    payment_due_date = Date()
    paid_on = Date()
    completed_by = fields.contact_or_adviser_field()
    completed_on = Date()
    cancelled_by = fields.contact_or_adviser_field()
    cancelled_on = Date()
    cancellation_reason = fields.id_name_field()

    billing_company_name = Text()
    billing_contact_name = Text()
    billing_email = fields.NormalizedKeyword()
    billing_phone = fields.NormalizedKeyword()
    billing_address_1 = Text()
    billing_address_2 = Text()
    billing_address_town = fields.NormalizedKeyword()
    billing_address_county = fields.NormalizedKeyword()
    billing_address_postcode = Text()
    billing_address_country = fields.id_name_field()

    MAPPINGS = {
        'company': dict_utils.company_dict,
        'contact': dict_utils.contact_or_adviser_dict,
        'created_by': dict_utils.adviser_dict_with_team,
        'primary_market': dict_utils.id_name_dict,
        'sector': dict_utils.sector_dict,
        'uk_region': dict_utils.id_name_dict,
        'service_types': lambda col: [dict_utils.id_name_dict(c) for c in col.all()],
        'subscribers': lambda col: [
            dict_utils.contact_or_adviser_dict(c.adviser, include_dit_team=True) for c in col.all()
        ],
        'assignees': lambda col: [
            dict_utils.contact_or_adviser_dict(c.adviser, include_dit_team=True) for c in col.all()
        ],
        'billing_address_country': dict_utils.id_name_dict,
        'completed_by': dict_utils.contact_or_adviser_dict,
        'cancelled_by': dict_utils.contact_or_adviser_dict,
        'cancellation_reason': dict_utils.id_name_dict,
    }

    COMPUTED_MAPPINGS = {
        'payment_due_date': lambda x: x.invoice.payment_due_date if x.invoice else None,
    }

    SEARCH_FIELDS = (
        'id',
        'reference.trigram',
        'company.name',
        'company.name.trigram',
        'contact.name',
        'contact.name.trigram',
        'total_cost.keyword',
        'subtotal_cost.keyword',
        'sector.name',
        'uk_region.name',
    )