Пример #1
0
def calculate_utc_range(org, input_value):
    """
    Calculates datetime range in UTC, we use it to check date containment
    """
    query_value = str_to_datetime(input_value, org.timezone, org.get_dayfirst(), fill_time=False)
    if not query_value:
        raise SearchException(_(f"Unable to parse the date '{input_value}'"))
    return date_to_utc_range(query_value.date(), org)
Пример #2
0
def calculate_utc_range(org, input_value):
    """
    Calculates datetime range in UTC, we use it to check date containment
    """
    query_value = str_to_datetime(input_value,
                                  org.timezone,
                                  org.get_dayfirst(),
                                  fill_time=False)
    if not query_value:
        raise SearchException(_(f"Unable to parse the date '{input_value}'"))
    return date_to_utc_range(query_value.date(), org)
Пример #3
0
    def _build_datetime_field_params(self, field):
        lookup = self.DATETIME_LOOKUPS.get(self.comparator)
        if not lookup:
            raise SearchException(
                _("Can't query date fields with %s") % self.comparator)

        # parse as localized date
        local_date = str_to_datetime(self.value,
                                     field.org.timezone,
                                     field.org.get_dayfirst(),
                                     fill_time=False)
        if not local_date:
            raise SearchException(
                _("Unable to parse the date %s") % self.value)

        # get the range of UTC datetimes for this local date
        utc_range = date_to_utc_range(local_date.date(), field.org)

        if lookup == '<equal>':
            return {
                'contact_field': field,
                'datetime_value__gte': utc_range[0],
                'datetime_value__lt': utc_range[1]
            }
        elif lookup == 'lt':
            return {'contact_field': field, 'datetime_value__lt': utc_range[0]}
        elif lookup == 'lte':
            return {'contact_field': field, 'datetime_value__lt': utc_range[1]}
        elif lookup == 'gt':
            return {
                'contact_field': field,
                'datetime_value__gte': utc_range[1]
            }
        elif lookup == 'gte':
            return {
                'contact_field': field,
                'datetime_value__gte': utc_range[0]
            }
Пример #4
0
    def as_elasticsearch(self, org, prop_map):
        prop_type, field = prop_map[self.prop]

        if prop_type == ContactQuery.PROP_FIELD:
            field_uuid = str(field.uuid)
            es_query = es_Q("term", **{"fields.field": field_uuid})

            if field.value_type == Value.TYPE_TEXT:
                query_value = self.value.lower()

                if self.comparator == "=":
                    es_query &= es_Q("term", **{"fields.text": query_value})

                else:
                    raise SearchException(
                        _("Unknown text comparator: '%s'") %
                        (self.comparator, ))

            elif field.value_type == Value.TYPE_NUMBER:
                query_value = str(self._parse_number(self.value))

                if self.comparator == "=":
                    es_query &= es_Q("match", **{"fields.number": query_value})
                elif self.comparator == ">":
                    es_query &= es_Q("range",
                                     **{"fields.number": {
                                         "gt": query_value
                                     }})
                elif self.comparator == ">=":
                    es_query &= es_Q("range",
                                     **{"fields.number": {
                                         "gte": query_value
                                     }})
                elif self.comparator == "<":
                    es_query &= es_Q("range",
                                     **{"fields.number": {
                                         "lt": query_value
                                     }})
                elif self.comparator == "<=":
                    es_query &= es_Q("range",
                                     **{"fields.number": {
                                         "lte": query_value
                                     }})
                else:
                    raise SearchException(
                        _("Unknown number comparator: '%s'") %
                        (self.comparator, ))

            elif field.value_type == Value.TYPE_DATETIME:
                query_value = str_to_datetime(self.value,
                                              field.org.timezone,
                                              field.org.get_dayfirst(),
                                              fill_time=False)

                if not query_value:
                    raise SearchException(
                        _("Unable to parse the date '%s'") % self.value)

                utc_range = date_to_utc_range(query_value.date(), field.org)

                if self.comparator == "=":
                    es_query &= es_Q(
                        "range", **{
                            "fields.datetime": {
                                "gte": utc_range[0].isoformat(),
                                "lt": utc_range[1].isoformat()
                            }
                        })
                elif self.comparator == ">":
                    es_query &= es_Q(
                        "range", **{
                            "fields.datetime": {
                                "gte": utc_range[1].isoformat()
                            }
                        })
                elif self.comparator == ">=":
                    es_query &= es_Q(
                        "range", **{
                            "fields.datetime": {
                                "gte": utc_range[0].isoformat()
                            }
                        })
                elif self.comparator == "<":
                    es_query &= es_Q(
                        "range", **{
                            "fields.datetime": {
                                "lt": utc_range[0].isoformat()
                            }
                        })
                elif self.comparator == "<=":
                    es_query &= es_Q(
                        "range", **{
                            "fields.datetime": {
                                "lt": utc_range[1].isoformat()
                            }
                        })
                else:
                    raise SearchException(
                        _("Unknown datetime comparator: '%s'") %
                        (self.comparator, ))

            elif field.value_type in (Value.TYPE_STATE, Value.TYPE_DISTRICT,
                                      Value.TYPE_WARD):
                query_value = self.value.lower()

                if field.value_type == Value.TYPE_WARD:
                    field_name = "fields.ward"
                elif field.value_type == Value.TYPE_DISTRICT:
                    field_name = "fields.district"
                elif field.value_type == Value.TYPE_STATE:
                    field_name = "fields.state"
                else:  # pragma: no cover
                    raise SearchException(
                        _("Unknown location type: '%s'") %
                        (field.value_type, ))

                if self.comparator == "=":
                    field_name += "_keyword"
                    es_query &= es_Q("term", **{field_name: query_value})
                else:
                    raise SearchException(
                        _("Unsupported comparator '%s' for location field") %
                        self.comparator)

            else:  # pragma: no cover
                raise SearchException(
                    _("Unrecognized contact field type '%s'") %
                    field.value_type)

            return es_Q("nested", path="fields", query=es_query)

        elif prop_type == ContactQuery.PROP_ATTRIBUTE:
            query_value = self.value.lower()
            if field == "name":
                if self.comparator == "=":
                    field_name = "name.keyword"
                    es_query = es_Q("term", **{field_name: query_value})
                elif self.comparator == "~":
                    field_name = "name"
                    es_query = es_Q("match", **{field_name: query_value})
                else:
                    raise SearchException(
                        _("Unknown attribute comparator: '%s'") %
                        (self.comparator, ))
            elif field == "id":
                es_query = es_Q("ids", **{"values": [query_value]})
            else:  # pragma: no cover
                raise SearchException(
                    _("Unknown attribute field '%s'") % (field, ))
            return es_query

        elif prop_type == ContactQuery.PROP_SCHEME:
            query_value = self.value.lower()
            es_query = es_Q("term", **{"urns.scheme": field.lower()})

            if org.is_anon:
                return es_Q("ids", **{"values": [-1]})
            else:
                if self.comparator == "=":
                    es_query &= es_Q("term",
                                     **{"urns.path.keyword": query_value})
                elif self.comparator == "~":
                    es_query &= es_Q("match_phrase",
                                     **{"urns.path": query_value})
                else:
                    raise SearchException(
                        _("Unknown scheme comparator: '%s'") %
                        (self.comparator, ))

                return es_Q("nested", path="urns", query=es_query)
        else:  # pragma: no cover
            raise SearchException(
                _("Unrecognized contact field type '%s'") % prop_type)
Пример #5
0
    def evaluate(self, contact_json, prop_map):
        prop_type, field = prop_map[self.prop]

        if prop_type == ContactQuery.PROP_FIELD:
            field_uuid = str(field.uuid)
            contact_fields = contact_json.get("fields")

            if field_uuid not in contact_fields:
                return False

            if field.value_type == Value.TYPE_TEXT:
                query_value = self.value.upper()
                contact_value = contact_fields.get(field_uuid).get(
                    "text").upper()

                if self.comparator == "=":
                    return contact_value == query_value
                else:
                    raise SearchException(
                        _("Unknown text comparator: '%s'") %
                        (self.comparator, ))

            elif field.value_type == Value.TYPE_NUMBER:
                query_value = self._parse_number(self.value)

                number_value = contact_fields.get(field_uuid).get(
                    "number",
                    contact_fields.get(field_uuid).get("decimal"))
                if number_value is None:
                    return False

                contact_value = self._parse_number(number_value)

                if self.comparator == "=":
                    return contact_value == query_value
                elif self.comparator == ">":
                    return contact_value > query_value
                elif self.comparator == ">=":
                    return contact_value >= query_value
                elif self.comparator == "<":
                    return contact_value < query_value
                elif self.comparator == "<=":
                    return contact_value <= query_value
                else:
                    raise SearchException(
                        _("Unknown number comparator: '%s'") %
                        (self.comparator, ))

            elif field.value_type == Value.TYPE_DATETIME:
                query_value = str_to_datetime(self.value,
                                              field.org.timezone,
                                              field.org.get_dayfirst(),
                                              fill_time=False)
                if not query_value:
                    raise SearchException(
                        _("Unable to parse the date '%s'") % self.value)

                datetime_value = contact_fields.get(field_uuid).get("datetime")
                if datetime_value is None:
                    return False

                contact_value = str_to_datetime(datetime_value,
                                                field.org.timezone)

                utc_range = date_to_utc_range(query_value.date(), field.org)

                if self.comparator == "=":
                    return contact_value >= utc_range[
                        0] and contact_value < utc_range[1]
                elif self.comparator == ">":
                    return contact_value >= utc_range[1]
                elif self.comparator == ">=":
                    return contact_value >= utc_range[0]
                elif self.comparator == "<":
                    return contact_value < utc_range[0]
                elif self.comparator == "<=":
                    return contact_value < utc_range[1]
                else:
                    raise SearchException(
                        _("Unknown datetime comparator: '%s'") %
                        (self.comparator, ))

            elif field.value_type in (Value.TYPE_STATE, Value.TYPE_DISTRICT,
                                      Value.TYPE_WARD):
                query_value = self.value.upper()

                if field.value_type == Value.TYPE_WARD:
                    ward_value = contact_fields.get(field_uuid).get("ward")
                    if ward_value is None:
                        ward_value = ""

                    contact_value = ward_value.upper().split(" > ")[-1]
                elif field.value_type == Value.TYPE_DISTRICT:
                    district_value = contact_fields.get(field_uuid).get(
                        "district")
                    if district_value is None:
                        district_value = ""

                    contact_value = district_value.upper().split(" > ")[-1]
                elif field.value_type == Value.TYPE_STATE:
                    state_value = contact_fields.get(field_uuid).get("state")
                    if state_value is None:
                        state_value = ""

                    contact_value = state_value.upper().split(" > ")[-1]
                else:  # pragma: no cover
                    raise SearchException(
                        _("Unknown location type: '%s'") %
                        (field.value_type, ))

                if self.comparator == "=":
                    return contact_value == query_value
                else:
                    raise SearchException(
                        _("Unsupported comparator '%s' for location field") %
                        self.comparator)

            else:  # pragma: no cover
                raise SearchException(
                    _("Unrecognized contact field type '%s'") %
                    field.value_type)

        elif prop_type == ContactQuery.PROP_SCHEME:
            for urn in contact_json.get("urns"):
                if urn.get("scheme") == field:
                    contact_value = urn.get("path").upper()
                    query_value = self.value.upper()

                    if self.comparator == "=":
                        if contact_value == query_value:
                            return True
                    elif self.comparator == "~":
                        if query_value in contact_value:
                            return True
                    else:
                        raise SearchException(
                            _("Unknown urn scheme comparator: '%s'") %
                            (self.comparator, ))

            return False

        else:
            raise SearchException(
                _("Unrecognized contact field type '%s'") % prop_type)
Пример #6
0
    def as_elasticsearch(self, org, prop_map):
        prop_type, field = prop_map[self.prop]

        if prop_type == ContactQuery.PROP_FIELD:
            field_uuid = six.text_type(field.uuid)
            es_query = es_Q('term', **{'fields.field': field_uuid})

            if field.value_type == Value.TYPE_TEXT:
                query_value = self.value.lower()

                if self.comparator == '=':
                    es_query &= es_Q('term', **{'fields.text': query_value})

                else:
                    raise SearchException(
                        _("Unknown text comparator: '%s'") %
                        (self.comparator, ))

            elif field.value_type == Value.TYPE_NUMBER:
                query_value = six.text_type(self._parse_number(self.value))

                if self.comparator == '=':
                    es_query &= es_Q('match', **{'fields.number': query_value})
                elif self.comparator == '>':
                    es_query &= es_Q('range',
                                     **{'fields.number': {
                                         'gt': query_value
                                     }})
                elif self.comparator == '>=':
                    es_query &= es_Q('range',
                                     **{'fields.number': {
                                         'gte': query_value
                                     }})
                elif self.comparator == '<':
                    es_query &= es_Q('range',
                                     **{'fields.number': {
                                         'lt': query_value
                                     }})
                elif self.comparator == '<=':
                    es_query &= es_Q('range',
                                     **{'fields.number': {
                                         'lte': query_value
                                     }})
                else:
                    raise SearchException(
                        _("Unknown number comparator: '%s'") %
                        (self.comparator, ))

            elif field.value_type == Value.TYPE_DATETIME:
                query_value = str_to_datetime(self.value,
                                              field.org.timezone,
                                              field.org.get_dayfirst(),
                                              fill_time=False)

                if not query_value:
                    raise SearchException(
                        _("Unable to parse the date '%s'") % self.value)

                utc_range = date_to_utc_range(query_value.date(), field.org)

                if self.comparator == '=':
                    es_query &= es_Q(
                        'range', **{
                            'fields.datetime': {
                                'gte': utc_range[0].isoformat(),
                                'lt': utc_range[1].isoformat()
                            }
                        })
                elif self.comparator == '>':
                    es_query &= es_Q(
                        'range', **{
                            'fields.datetime': {
                                'gte': utc_range[1].isoformat()
                            }
                        })
                elif self.comparator == '>=':
                    es_query &= es_Q(
                        'range', **{
                            'fields.datetime': {
                                'gte': utc_range[0].isoformat()
                            }
                        })
                elif self.comparator == '<':
                    es_query &= es_Q(
                        'range', **{
                            'fields.datetime': {
                                'lt': utc_range[0].isoformat()
                            }
                        })
                elif self.comparator == '<=':
                    es_query &= es_Q(
                        'range', **{
                            'fields.datetime': {
                                'lt': utc_range[1].isoformat()
                            }
                        })
                else:
                    raise SearchException(
                        _("Unknown datetime comparator: '%s'") %
                        (self.comparator, ))

            elif field.value_type in (Value.TYPE_STATE, Value.TYPE_DISTRICT,
                                      Value.TYPE_WARD):
                query_value = self.value.lower()

                if field.value_type == Value.TYPE_WARD:
                    field_name = 'fields.ward'
                elif field.value_type == Value.TYPE_DISTRICT:
                    field_name = 'fields.district'
                elif field.value_type == Value.TYPE_STATE:
                    field_name = 'fields.state'
                else:  # pragma: no cover
                    raise SearchException(
                        _("Unknown location type: '%s'") %
                        (field.value_type, ))

                if self.comparator == '=':
                    field_name += '.keyword'
                    es_query &= es_Q('term', **{field_name: query_value})
                else:
                    raise SearchException(
                        _("Unsupported comparator '%s' for location field") %
                        self.comparator)

            else:  # pragma: no cover
                raise SearchException(
                    _("Unrecognized contact field type '%s'") %
                    field.value_type)

            return es_Q('nested', path='fields', query=es_query)

        elif prop_type == ContactQuery.PROP_ATTRIBUTE:
            query_value = self.value.lower()
            if field == 'name':
                if self.comparator == '=':
                    field_name = 'name.keyword'
                    es_query = es_Q('term', **{field_name: query_value})
                elif self.comparator == '~':
                    field_name = 'name'
                    es_query = es_Q('match', **{field_name: query_value})
                else:
                    raise SearchException(
                        _("Unknown attribute comparator: '%s'") %
                        (self.comparator, ))
            elif field == 'id':
                es_query = es_Q('ids', **{'values': [query_value]})
            else:  # pragma: no cover
                raise SearchException(
                    _("Unknown attribute field '%s'") % (field, ))
            return es_query

        elif prop_type == ContactQuery.PROP_SCHEME:
            query_value = self.value.lower()
            es_query = es_Q('term', **{'urns.scheme': field.lower()})

            if org.is_anon:
                return es_Q('ids', **{'values': [-1]})
            else:
                if self.comparator == '=':
                    es_query &= es_Q('term',
                                     **{'urns.path.keyword': query_value})
                elif self.comparator == '~':
                    es_query &= es_Q('match_phrase',
                                     **{'urns.path': query_value})
                else:
                    raise SearchException(
                        _("Unknown scheme comparator: '%s'") %
                        (self.comparator, ))

                return es_Q('nested', path='urns', query=es_query)
        else:  # pragma: no cover
            raise SearchException(
                _("Unrecognized contact field type '%s'") % prop_type)