Beispiel #1
0
    def __init__(self, *args, **kwargs):
        self.user = kwargs["user"]
        del kwargs["user"]

        super().__init__(*args, **kwargs)
        self.fields["group"].initial = self.instance.group
        self.fields["group"].queryset = ContactGroup.get_user_groups(self.user.get_org(), ready_only=False)
Beispiel #2
0
    def __init__(self, *args, **kwargs):
        self.user = kwargs["user"]
        del kwargs["user"]

        super().__init__(*args, **kwargs)
        self.fields["group"].initial = self.instance.group
        self.fields["group"].queryset = ContactGroup.get_user_groups(self.user.get_org(), ready_only=False)
Beispiel #3
0
def omnibox_mixed_search(org, search, types):
    """
    Performs a mixed group, contact and URN search, returning the first N matches of each type.
    """
    search_terms = search.split(" ") if search else None
    search_types = types or (SEARCH_ALL_GROUPS, SEARCH_CONTACTS, SEARCH_URNS)
    per_type_limit = 25
    results = []

    if SEARCH_ALL_GROUPS in search_types or SEARCH_STATIC_GROUPS in search_types:
        groups = ContactGroup.get_user_groups(org)

        # exclude dynamic groups if not searching all groups
        if SEARCH_ALL_GROUPS not in search_types:
            groups = groups.filter(query=None)

        if search:
            groups = term_search(groups, ("name__icontains", ), search_terms)

        results += list(groups.order_by(Upper("name"))[:per_type_limit])

    if SEARCH_CONTACTS in search_types:
        contacts = Contact.objects.filter(org=org,
                                          is_active=True,
                                          is_blocked=False,
                                          is_stopped=False,
                                          is_test=False)

        try:
            search_id = int(search)
        except (ValueError, TypeError):
            search_id = None

        if org.is_anon and search_id is not None:
            contacts = contacts.filter(id=search_id)
        elif search:
            contacts = term_search(contacts, ("name__icontains", ),
                                   search_terms)

        results += list(contacts.order_by(Upper("name"))[:per_type_limit])

    if SEARCH_URNS in search_types:
        # only include URNs that are send-able
        from temba.channels.models import Channel

        allowed_schemes = org.get_schemes(
            Channel.ROLE_SEND) if not org.is_anon else []

        urns = ContactURN.objects.filter(
            org=org, scheme__in=allowed_schemes).exclude(contact=None)

        if search:
            urns = term_search(urns, ("path__icontains", ), search_terms)

        results += list(
            urns.prefetch_related("contact").order_by(
                Upper("path"))[:per_type_limit])

    return results  # sorted(results, key=lambda o: o.name if hasattr(o, 'name') else o.path)
Beispiel #4
0
    def __init__(self, *args, **kwargs):
        self.user = kwargs['user']
        del kwargs['user']

        super(UpdateCampaignForm, self).__init__(*args, **kwargs)
        self.fields['group'].initial = self.instance.group
        self.fields['group'].queryset = ContactGroup.get_user_groups(
            self.user.get_org(), ready_only=False)
Beispiel #5
0
def omnibox_mixed_search(org, query, types):
    """
    Performs a mixed group, contact and URN search, returning the first N matches of each type.
    """
    query_terms = query.split(" ") if query else None
    search_types = types or (SEARCH_ALL_GROUPS, SEARCH_CONTACTS, SEARCH_URNS)
    per_type_limit = 25
    results = []

    if SEARCH_ALL_GROUPS in search_types or SEARCH_STATIC_GROUPS in search_types:
        groups = ContactGroup.get_user_groups(org, ready_only=True)

        # exclude dynamic groups if not searching all groups
        if SEARCH_ALL_GROUPS not in search_types:
            groups = groups.filter(query=None)

        if query:
            groups = term_search(groups, ("name__icontains", ), query_terms)

        results += list(groups.order_by(Upper("name"))[:per_type_limit])

    if SEARCH_CONTACTS in search_types:
        try:
            search_results = search_contacts(
                org,
                query,
                group=org.cached_active_contacts_group,
                sort="name")
            contacts = IDSliceQuerySet(Contact, search_results.contact_ids, 0,
                                       len(search_results.contact_ids))
            results += list(contacts[:per_type_limit])
            Contact.bulk_cache_initialize(org, contacts=results)

        except SearchException:
            pass

    if SEARCH_URNS in search_types:
        if not org.is_anon and query and len(query) >= 3:
            try:
                # build an OR'ed query of all sendable schemes
                sendable_schemes = org.get_schemes(Channel.ROLE_SEND)
                scheme_query = " OR ".join(f"{s} ~ {json.dumps(query)}"
                                           for s in sendable_schemes)
                search_results = search_contacts(
                    org,
                    scheme_query,
                    group=org.cached_active_contacts_group,
                    sort="name")
                urns = ContactURN.objects.filter(
                    contact_id__in=search_results.contact_ids,
                    scheme__in=sendable_schemes)
                results += list(
                    urns.prefetch_related("contact").order_by(
                        Upper("path"))[:per_type_limit])
            except SearchException:
                pass

    return results
Beispiel #6
0
    def include_groups(self):
        from temba.contacts.models import ContactGroup

        self.request["assets"].append({
            "type":
            "group_set",
            "url":
            "%s/group/" % self.base_assets_url,
            "content": [
                serialize_group(g)
                for g in ContactGroup.get_user_groups(self.org)
            ],
        })
        return self
Beispiel #7
0
    def include_groups(self):
        from temba.contacts.models import ContactGroup

        self.request['assets'].append({
            'type':
            "group_set",
            'url':
            '%s/group/' % self.base_assets_url,
            'content': [
                serialize_group(g)
                for g in ContactGroup.get_user_groups(self.org)
            ]
        })
        return self
    def include_groups(self, org):
        from temba.contacts.models import ContactGroup

        self.request['assets'].append({
            'type':
            "group",
            'url':
            get_assets_url(org, self.asset_timestamp, 'group'),
            'content':
            [serialize_group(g) for g in ContactGroup.get_user_groups(org)],
            'is_set':
            True
        })
        return self
Beispiel #9
0
    def __init__(self, user, trigger_type, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.user = user
        self.org = user.get_org()
        self.trigger_type = Trigger.get_type(trigger_type)

        flow_types = self.trigger_type.allowed_flow_types
        flows = self.org.flows.filter(flow_type__in=flow_types, is_active=True, is_archived=False, is_system=False)

        self.fields["flow"].queryset = flows.order_by("name")

        groups = ContactGroup.get_user_groups(self.org, ready_only=False)

        self.fields["groups"].queryset = groups
        self.fields["exclude_groups"].queryset = groups
Beispiel #10
0
            def __init__(self, user, *args, **kwargs):
                super().__init__(*args, **kwargs)

                self.fields["group"].queryset = ContactGroup.get_user_groups(user.get_org()).order_by("name")
Beispiel #11
0
def omnibox_mixed_search(org, search, types):
    """
    Performs a mixed group, contact and URN search, returning the first N matches of each type.
    """
    search_terms = search.split(" ") if search else None
    search_types = types or (SEARCH_ALL_GROUPS, SEARCH_CONTACTS, SEARCH_URNS)
    per_type_limit = 25
    results = []

    if SEARCH_ALL_GROUPS in search_types or SEARCH_STATIC_GROUPS in search_types:
        groups = ContactGroup.get_user_groups(org, ready_only=True)

        # exclude dynamic groups if not searching all groups
        if SEARCH_ALL_GROUPS not in search_types:
            groups = groups.filter(query=None)

        if search:
            groups = term_search(groups, ("name__icontains", ), search_terms)

        results += list(groups.order_by(Upper("name"))[:per_type_limit])

    if SEARCH_CONTACTS in search_types:
        sort_struct = {
            "field_type": "attribute",
            "sort_direction": "asc",
            "field_name": "name.keyword"
        }

        try:
            search_id = int(search)
        except (ValueError, TypeError):
            search_id = None

        if org.is_anon and search_id is not None:
            search_text = f"id = {search_id}"
        elif search:
            search_text = " AND ".join(f"name ~ {search_term}"
                                       for search_term in search_terms)

        else:
            search_text = None

        from temba.utils.es import ES

        try:
            search_object, _ = contact_es_search(org,
                                                 search_text,
                                                 sort_struct=sort_struct)

            es_search = search_object.source(
                fields=("id", )).using(ES)[:per_type_limit].execute()
            contact_ids = list(mapEStoDB(Contact, es_search, only_ids=True))
            es_results = Contact.objects.filter(id__in=contact_ids).order_by(
                Upper("name"))

            results += list(es_results[:per_type_limit])

            Contact.bulk_cache_initialize(org, contacts=results)

        except SearchException:
            # ignore SearchException
            pass

    if SEARCH_URNS in search_types:
        # only include URNs that are send-able
        from temba.channels.models import Channel

        allowed_schemes = org.get_schemes(Channel.ROLE_SEND)

        from temba.utils.es import ES, ModelESSearch

        if search:
            # we use trigrams on Elasticsearch, minimum required length for a term is 3
            filtered_search_terms = (
                search_term for search_term in search_terms
                if search_term != ""  # and len(search_term) >= 3
            )

            must_condition = [{
                "match_phrase": {
                    "urns.path": search_term
                }
            } for search_term in filtered_search_terms]
        else:
            must_condition = []

        es_query = {
            "query": {
                "bool": {
                    "filter": [
                        {
                            "term": {
                                "org_id": org.id
                            }
                        },
                        {
                            "term": {
                                "groups":
                                str(org.cached_all_contacts_group.uuid)
                            }
                        },
                    ],
                    "must": [{
                        "nested": {
                            "path": "urns",
                            "query": {
                                "bool": {
                                    "must":
                                    must_condition,
                                    "should": [{
                                        "term": {
                                            "urns.scheme": scheme
                                        }
                                    } for scheme in allowed_schemes],
                                }
                            },
                        }
                    }],
                }
            },
            "sort": [{
                "name.keyword": {
                    "order": "asc"
                }
            }],
        }

        if not org.is_anon:
            search_object = ModelESSearch(
                model=Contact,
                index="contacts").from_dict(es_query).params(routing=org.id)

            es_search = search_object.source(
                fields=("id", )).using(ES)[:per_type_limit].execute()
            es_results = mapEStoDB(Contact, es_search, only_ids=True)

            # get ContactURNs for filtered Contacts
            urns = ContactURN.objects.filter(contact_id__in=list(es_results))

            # we got max `per_type_limit` contacts, but each contact can have multiple URNs and we need to limit the
            # results to the per type limit
            results += list(
                urns.prefetch_related("contact").order_by(
                    Upper("path"))[:per_type_limit])

    return results  # sorted(results, key=lambda o: o.name if hasattr(o, 'name') else o.path)
Beispiel #12
0
            def __init__(self, user, *args, **kwargs):
                super(CampaignCRUDL.Create.CampaignForm,
                      self).__init__(*args, **kwargs)

                self.fields['group'].queryset = ContactGroup.get_user_groups(
                    user.get_org()).order_by('name')
Beispiel #13
0
            def __init__(self, user, *args, **kwargs):
                super().__init__(*args, **kwargs)

                self.fields["group"].queryset = ContactGroup.get_user_groups(user.get_org()).order_by("name")
Beispiel #14
0
def omnibox_mixed_search(org, search, types):
    """
    Performs a mixed group, contact and URN search, returning the first N matches of each type.
    """
    search_terms = search.split(" ") if search else None
    search_types = types or (SEARCH_ALL_GROUPS, SEARCH_CONTACTS, SEARCH_URNS)
    per_type_limit = 25
    results = []

    if SEARCH_ALL_GROUPS in search_types or SEARCH_STATIC_GROUPS in search_types:
        groups = ContactGroup.get_user_groups(org)

        # exclude dynamic groups if not searching all groups
        if SEARCH_ALL_GROUPS not in search_types:
            groups = groups.filter(query=None)

        if search:
            groups = term_search(groups, ("name__icontains",), search_terms)

        results += list(groups.order_by(Upper("name"))[:per_type_limit])

    if SEARCH_CONTACTS in search_types:
        sort_struct = {"field_type": "attribute", "sort_direction": "asc", "field_name": "name.keyword"}

        try:
            search_id = int(search)
        except (ValueError, TypeError):
            search_id = None

        if org.is_anon and search_id is not None:
            search_text = f"id = {search_id}"
        elif search:
            # we use trigrams on Elasticsearch, minimum required length for a term is 3
            filtered_search_terms = (
                search_term for search_term in search_terms if search_term != "" and len(search_term) >= 3
            )

            search_text = " AND ".join(f"name ~ {search_term}" for search_term in filtered_search_terms)

        else:
            search_text = None

        from temba.utils.es import ES

        try:
            search_object, _ = contact_es_search(org, search_text, sort_struct=sort_struct)

            es_search = search_object.source(fields=("id",)).using(ES)[:per_type_limit].execute()
            contact_ids = list(mapEStoDB(Contact, es_search, only_ids=True))
            es_results = Contact.objects.filter(id__in=contact_ids).order_by(Upper("name"))

            results += list(es_results[:per_type_limit])

            Contact.bulk_cache_initialize(org, contacts=results)

        except SearchException:
            # ignore SearchException
            pass

    if SEARCH_URNS in search_types:
        # only include URNs that are send-able
        from temba.channels.models import Channel

        allowed_schemes = org.get_schemes(Channel.ROLE_SEND)

        from temba.utils.es import ES, ModelESSearch

        if search:
            # we use trigrams on Elasticsearch, minimum required length for a term is 3
            filtered_search_terms = (
                search_term for search_term in search_terms if search_term != "" and len(search_term) >= 3
            )

            must_condition = [{"match_phrase": {"urns.path": search_term}} for search_term in filtered_search_terms]
        else:
            must_condition = []

        es_query = {
            "query": {
                "bool": {
                    "filter": [
                        {"term": {"org_id": org.id}},
                        {"term": {"groups": str(org.cached_all_contacts_group.uuid)}},
                    ],
                    "must": [
                        {
                            "nested": {
                                "path": "urns",
                                "query": {
                                    "bool": {
                                        "must": must_condition,
                                        "should": [{"term": {"urns.scheme": scheme}} for scheme in allowed_schemes],
                                    }
                                },
                            }
                        }
                    ],
                }
            },
            "sort": [{"name.keyword": {"order": "asc"}}],
        }

        if not org.is_anon:
            search_object = ModelESSearch(model=Contact, index="contacts").from_dict(es_query).params(routing=org.id)

            es_search = search_object.source(fields=("id",)).using(ES)[:per_type_limit].execute()
            es_results = mapEStoDB(Contact, es_search, only_ids=True)

            # get ContactURNs for filtered Contacts
            urns = ContactURN.objects.filter(contact_id__in=list(es_results))

            # we got max `per_type_limit` contacts, but each contact can have multiple URNs and we need to limit the
            # results to the per type limit
            results += list(urns.prefetch_related("contact").order_by(Upper("path"))[:per_type_limit])

    return results  # sorted(results, key=lambda o: o.name if hasattr(o, 'name') else o.path)
Beispiel #15
0
    def __init__(self, user, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.fields["group"].queryset = ContactGroup.get_user_groups(user.get_org(), ready_only=False)