summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2024-06-19 16:06:43 +0200
committerÉtienne Loks <etienne.loks@iggdrasil.net>2024-06-19 16:06:43 +0200
commite9b24d11368bf0e5c92b3005f4ad45fa1e6c002c (patch)
treeb4bed675666dc1d997298a40410a54a1ae68aab9
parentbaa8b37fe683828cb2471f1616d5d8ad36e91920 (diff)
downloadIshtar-e9b24d11368bf0e5c92b3005f4ad45fa1e6c002c.tar.bz2
Ishtar-e9b24d11368bf0e5c92b3005f4ad45fa1e6c002c.zip
✨ criteria search: relative search for number criteria (refs #5349)
-rw-r--r--archaeological_context_records/models.py1
-rw-r--r--archaeological_finds/models_finds.py1
-rw-r--r--archaeological_finds/tests.py29
-rw-r--r--archaeological_operations/models.py1
-rw-r--r--ishtar_common/views_item.py74
5 files changed, 98 insertions, 8 deletions
diff --git a/archaeological_context_records/models.py b/archaeological_context_records/models.py
index 940b7347f..1e5d108bc 100644
--- a/archaeological_context_records/models.py
+++ b/archaeological_context_records/models.py
@@ -564,6 +564,7 @@ class ContextRecord(
"documents__associated_file__isnull",
"documents__associated_url__isnull",
]
+ NUMBER_FIELDS = ["operation__year"]
RELATION_TYPES_PREFIX = {
"ope_relation_types": "operation__",
"cr_relation_types": "",
diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py
index fff692917..7a8715f1b 100644
--- a/archaeological_finds/models_finds.py
+++ b/archaeological_finds/models_finds.py
@@ -1259,6 +1259,7 @@ class Find(
"museum_allocation_date__lte",
"museum_allocation_date__gte",
]
+ NUMBER_FIELDS = ["base_finds__context_record__operation__year"]
BASE_REQUEST = {"downstream_treatment__isnull": True}
EXTRA_REQUEST_KEYS = {
"all_base_finds__context_record": "base_finds__context_record__context_record_tree_parent__cr_parent_id",
diff --git a/archaeological_finds/tests.py b/archaeological_finds/tests.py
index 60dcb5a5d..346aa0b1e 100644
--- a/archaeological_finds/tests.py
+++ b/archaeological_finds/tests.py
@@ -1591,6 +1591,35 @@ class FindSearchTest(FindInit, TestCase, SearchText):
result = [('-{}="{}"'.format(key, "*"), models.Find.objects.count() - 1)]
self._test_search(c, result, context="-* description Search")
+ def test_number_search(self):
+ # test year search with "=>" notation
+ ope1 = self.operations[0]
+ ope1.year = 2000
+ ope1.save()
+ ope2 = self.operations[1]
+ ope2.year = 2020
+ ope2.save()
+ self.create_finds()
+ self.create_finds()
+
+ c = Client()
+ c.login(username=self.username, password=self.password)
+
+ key = str(pgettext_lazy("key for text search", "year"))
+
+ result = [('{}="{}"'.format(key, 2000), 3)]
+ self._test_search(c, result, context="Exact year search")
+ result = [('{}="{}"'.format(key, 2020), 1)]
+ self._test_search(c, result, context="Exact year search")
+ result = [('{}=>"{}"'.format(key, 2019), 1)]
+ self._test_search(c, result, context="=> year search")
+ result = [('{}=>"{}"'.format(key, 1999), 4)]
+ self._test_search(c, result, context="=> year search")
+ result = [('{}=<"{}"'.format(key, 2001), 3)]
+ self._test_search(c, result, context="=< year search")
+ result = [('{}=>"{}" {}=<"{}"'.format(key, 2001, key, 2022), 1)]
+ self._test_search(c, result, context="=> and =< year search")
+
def test_address_operation_search(self):
operation = self.operations[0]
operation.address = "Street somewhere 29478 NOWHERE"
diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py
index 760ce1b4b..9764b8dba 100644
--- a/archaeological_operations/models.py
+++ b/archaeological_operations/models.py
@@ -1025,6 +1025,7 @@ class Operation(
"finds_deadline__gte",
"finds_deposit_date",
]
+ NUMBER_FIELDS = ["year", "operation_code"]
EXTRA_REQUEST_KEYS = {
"operation_type__label": "operation_type__label",
"common_name": "common_name__icontains",
diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py
index 9f2fbb7b5..a622fdb9f 100644
--- a/ishtar_common/views_item.py
+++ b/ishtar_common/views_item.py
@@ -976,6 +976,67 @@ def _manage_many_counted_fields(fields, reversed_fields, dct, excluded_dct):
excluded_dct[k] = False
+def __manage_relative_search(value):
+ """
+ Parse search to manage "=", "=>" and "=<" searches
+ :param value: value
+ :return: value, search type ("eq", "lte" or "gte")
+ """
+ value = value.replace('"', "").strip()
+ search_type = "eq"
+ if value.startswith(">"):
+ value = value[1:]
+ search_type = "gte"
+ elif value.startswith("<"):
+ value = value[1:]
+ search_type = "lte"
+ return value, search_type
+
+
+def _manage_number(k, dct):
+ """
+ Manage number from a search query
+ :param k: number key
+ :param dct: search dict
+ :return: None -> search dict is modified
+ """
+ values = dct[k].split(";")
+ results = []
+ for value in values:
+ value, search_type = __manage_relative_search(value)
+ try:
+ value = str(float(value.replace(",", ".")))
+ if value.endswith(".0"):
+ value = value[:-2]
+ results.append((search_type, value))
+ except ValueError:
+ continue
+ mins = [value for dt, value in results if dt == "gte"]
+ maxs = [value for dt, value in results if dt == "lte"]
+ eqs = [value for dt, value in results if dt == "eq"]
+ if eqs and not mins and not maxs: # TODO: min and max not available
+ dct[k] = ";".join(eqs)
+ return
+ dct.pop(k)
+ if mins:
+ dct[k + "__gte"] = min(mins)
+ if maxs:
+ dct[k + "__lte"] = max(maxs)
+
+
+def _manage_number_fields(fields, dct):
+ keys = list(dct.keys())
+ for key in fields:
+ res = [j for j in keys if j.startswith(key)]
+ if not res:
+ continue
+ for k in res:
+ if not dct[k]:
+ dct.pop(k)
+ continue
+ _manage_number(k, dct)
+
+
today_lbl = pgettext_lazy("key for text search", "today")
TODAYS = ["today"]
@@ -995,14 +1056,7 @@ def _manage_date(k, dct):
values = dct[k].split(";")
results = []
for value in values:
- value = value.replace('"', "").strip()
- date_type = "eq"
- if value.startswith(">"):
- value = value[1:]
- date_type = "gte"
- elif value.startswith("<"):
- value = value[1:]
- date_type = "lte"
+ value, date_type = __manage_relative_search(value)
has_today = False
for today in TODAYS:
if value.startswith(today):
@@ -2020,6 +2074,7 @@ def get_item(
reversed_many_counted_fields = getattr(
model, "REVERSED_MANY_COUNTED_FIELDS", None
)
+ my_number_fields = getattr(model, "NUMBER_FIELDS", [])[:]
if not dated_fields and hasattr(model, "DATED_FIELDS"):
my_dated_fields = model.DATED_FIELDS[:]
@@ -2295,6 +2350,9 @@ def get_item(
_manage_dated_fields(my_dated_fields, dct)
_manage_dated_fields(my_dated_fields, excluded_dct)
+ _manage_number_fields(my_number_fields, dct)
+ _manage_number_fields(my_number_fields, excluded_dct)
+
_manage_hierarchic_fields(model, dct, and_reqs)
_manage_hierarchic_fields(model, excluded_dct, exc_and_reqs)