diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2025-08-07 12:49:17 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2025-08-07 12:49:17 +0200 |
commit | a9505657720e0617dc744a314379d2512fb8b3e0 (patch) | |
tree | 1b964ded9356fb8282739fade48a75fca9788b6a | |
parent | d838bd7bf35c687ae534857313cf89de1ed68dac (diff) | |
download | Ishtar-a9505657720e0617dc744a314379d2512fb8b3e0.tar.bz2 Ishtar-a9505657720e0617dc744a314379d2512fb8b3e0.zip |
🐛 searches: fix exact date searches for datetime fields (refs #6411)
-rw-r--r-- | archaeological_finds/models_treatments.py | 6 | ||||
-rw-r--r-- | archaeological_operations/tests.py | 22 | ||||
-rw-r--r-- | ishtar_common/models.py | 9 | ||||
-rw-r--r-- | ishtar_common/models_common.py | 1 | ||||
-rw-r--r-- | ishtar_common/views_item.py | 22 |
5 files changed, 46 insertions, 14 deletions
diff --git a/archaeological_finds/models_treatments.py b/archaeological_finds/models_treatments.py index 200ea6c4c..429c9c3f3 100644 --- a/archaeological_finds/models_treatments.py +++ b/archaeological_finds/models_treatments.py @@ -178,6 +178,12 @@ class Treatment( } ALT_NAMES.update(BaseHistorizedItem.ALT_NAMES) ALT_NAMES.update(DocumentItem.ALT_NAMES) + DATED_FIELDS = BaseHistorizedItem.DATED_FIELDS + [ + "start_date", + "end_date", + "creation_date" + ] + DATETIME_FIELDS = BaseHistorizedItem.DATETIME_FIELDS + ["creation_date"] DEFAULT_SEARCH_FORM = ("archaeological_finds.forms_treatments", "TreatmentSelect") diff --git a/archaeological_operations/tests.py b/archaeological_operations/tests.py index 8baf02727..caadbc94f 100644 --- a/archaeological_operations/tests.py +++ b/archaeological_operations/tests.py @@ -3315,6 +3315,28 @@ class OperationSearchTest(TestCase, OperationInitTest, SearchText): ] self._test_search(c, result, context="Boolean search") + # date searches + search_created_q = str(pgettext("key for text search", "created")) + today = datetime.date.today().strftime('%Y-%m-%d') + result = [ + (f'{search_created_q}="{today}"', len(self.operations)), + ] + self._test_search(c, result, context="Exact date search") + yesterday = (datetime.date.today() - datetime.timedelta(days=1)).strftime('%Y-%m-%d') + result = [ + (f'{search_created_q}="{yesterday}"', 0), + ] + self._test_search(c, result, context="Exact date search - no match") + result = [ + (f'{search_created_q}=>"{yesterday}"', len(self.operations)), + ] + self._test_search(c, result, context="After date search") + tomorrow = (datetime.date.today() + datetime.timedelta(days=1)).strftime('%Y-%m-%d') + result = [ + (f'{search_created_q}=<"{tomorrow}"', len(self.operations)), + ] + self._test_search(c, result, context="Before date search") + def test_mixed_search_vector(self): operation_1 = models.Operation.objects.get(pk=self.operations[0].pk) operation_1.common_name = "Opération : Château de Fougères" diff --git a/ishtar_common/models.py b/ishtar_common/models.py index b370624fb..00c3b49ce 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -4529,12 +4529,9 @@ class Document( # search parameters REVERSED_BOOL_FIELDS = ["image__isnull", "associated_file__isnull"] DATED_FIELDS = BaseHistorizedItem.DATED_FIELDS + [ - "receipt_date__lte", - "receipt_date__gte", - "receipt_date_in_documentation__lte", - "receipt_date_in_documentation__gte", - "creation_date__lte", - "creation_date__gte", + "receipt_date", + "receipt_date_in_documentation", + "creation_date", ] objects = ExternalIdManager() diff --git a/ishtar_common/models_common.py b/ishtar_common/models_common.py index 89471972b..5a32953fe 100644 --- a/ishtar_common/models_common.py +++ b/ishtar_common/models_common.py @@ -1605,6 +1605,7 @@ class BaseHistorizedItem( "created", "last_modified", ] + DATETIME_FIELDS = ["created", "last_modified", "history_date"] BOOL_FIELDS = ["locked"] diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py index 48d8e229b..ed1c0c5bb 100644 --- a/ishtar_common/views_item.py +++ b/ishtar_common/views_item.py @@ -1058,11 +1058,12 @@ for language_code, language_lbl in settings.LANGUAGES: deactivate() -def _manage_date(k, dct): +def _manage_date(k, dct, datetime_fields): """ Manage date from a search query :param k: date key :param dct: search dict + :param datetime_fields: list of known datetime fields to force conversion :return: None -> search dict is modified """ if not isinstance(dct[k], str): @@ -1121,17 +1122,21 @@ def _manage_date(k, dct): 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 when using single dates + dct.pop(k) + root_k = k.split("__")[-1] + if root_k in datetime_fields: + k += "__date" # force date conversion for datetime fields + if eqs and not mins and not maxs: + # TODO: min and max not available when using single dates dct[k] = ";".join(eqs) return - dct.pop(k) if mins: dct[k + "__gte"] = min(mins) if maxs: dct[k + "__lte"] = max(maxs) -def _manage_dated_fields(dated_fields, dct): +def _manage_dated_fields(dated_fields, datetime_fields, dct): keys = list(dct.keys()) for key in dated_fields: res = [j for j in keys if j.startswith(key)] @@ -1143,7 +1148,7 @@ def _manage_dated_fields(dated_fields, dct): if not dct[k]: dct.pop(k) continue - _manage_date(k, dct) + _manage_date(k, dct, datetime_fields) def _clean_type_val(val): @@ -1955,7 +1960,7 @@ def _get_table_cols(data_type, own_table_cols, full, model): DEFAULT_ROW_NUMBER = 10 # length is used by ajax DataTables requests EXCLUDED_FIELDS = ["length"] -BASE_DATED_FIELDS = ["created", "last_modified"] +BASE_DATED_FIELDS = ["created", "last_modified", "history_date"] def get_item( @@ -2112,6 +2117,7 @@ def get_item( else: my_dated_fields = dated_fields[:] if dated_fields else [] my_dated_fields += BASE_DATED_FIELDS + datetime_fields = getattr(model, "DATETIME_FIELDS", []) if not associated_models and hasattr(model, "ASSOCIATED_MODELS"): my_associated_models = model.ASSOCIATED_MODELS[:] else: @@ -2391,8 +2397,8 @@ def get_item( filtered_dated_fields.append(field_name) my_dated_fields = filtered_dated_fields - _manage_dated_fields(my_dated_fields, dct) - _manage_dated_fields(my_dated_fields, excluded_dct) + _manage_dated_fields(my_dated_fields, datetime_fields, dct) + _manage_dated_fields(my_dated_fields, datetime_fields, excluded_dct) _manage_number_fields(my_number_fields, dct) _manage_number_fields(my_number_fields, excluded_dct) |