From bc88690693dd6d5fc12ac46ffeaf95f21d1f02ba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Mon, 8 Aug 2022 16:21:05 +0200
Subject: [PATCH] api: allow multi values for filter-internal-id and operators
 eq & ne (#68013)

---
 tests/api/test_formdata.py   | 42 +++++++++++++++++++++++++
 wcs/backoffice/management.py | 61 ++++++++++++++++++++----------------
 2 files changed, 76 insertions(+), 27 deletions(-)

diff --git a/tests/api/test_formdata.py b/tests/api/test_formdata.py
index c2c674c74..65b1cbc44 100644
--- a/tests/api/test_formdata.py
+++ b/tests/api/test_formdata.py
@@ -1368,6 +1368,48 @@ def test_api_list_formdata_internal_id_filter(pub, local_user):
     )
     assert resp.json['err_desc'] == 'Invalid value "blabla" for "filter-internal-id-value"'
 
+    # multi-ids
+    resp = get_app(pub).get(
+        sign_uri(
+            '/api/forms/test/list?filter-internal-id=1&filter-internal-id=3&filter-internal-id-operator=eq',
+            user=local_user,
+        )
+    )
+    assert len(resp.json) == 2
+    resp = get_app(pub).get(
+        sign_uri(
+            '/api/forms/test/list?filter-internal-id=1&filter-internal-id=3&filter-internal-id-operator=ne',
+            user=local_user,
+        )
+    )
+    assert len(resp.json) == 9
+    for operator in ['lt', 'lte', 'gt', 'gte']:
+        # list of values not allowed with theese operators
+        resp = get_app(pub).get(
+            sign_uri(
+                '/api/forms/test/list?filter-internal-id=1&filter-internal-id=3&filter-internal-id-operator=%s'
+                % operator,
+                user=local_user,
+            ),
+            status=400,
+        )
+        assert (
+            resp.json['err_desc']
+            == 'Invalid value "[\'1\', \'3\']" for "filter-internal-id" and operator "%s"' % operator
+        )
+
+    # not integers
+    resp = get_app(pub).get(
+        sign_uri(
+            '/api/forms/test/list?filter-internal-id=1&filter-internal-id=a&filter-internal-id-operator=eq',
+            user=local_user,
+        ),
+        status=400,
+    )
+    assert (
+        resp.json['err_desc'] == 'Invalid value "[\'1\', \'a\']" for "filter-internal-id" and operator "eq"'
+    )
+
 
 def test_api_list_formdata_number_filter(pub, local_user):
     pub.role_class.wipe()
diff --git a/wcs/backoffice/management.py b/wcs/backoffice/management.py
index f5ddcfc4e..4bd3a3f90 100644
--- a/wcs/backoffice/management.py
+++ b/wcs/backoffice/management.py
@@ -1877,6 +1877,26 @@ class FormPage(Directory):
 
             # check value types
             if filter_field.type == 'internal-id':
+
+                def _report_error(value, operator):
+                    if custom_view:
+                        get_publisher().record_error(
+                            _(
+                                'Invalid value "%s" for custom view "%s", CardDef "%s", field "internal-id", operator "%s"'
+                            )
+                            % (
+                                value,
+                                custom_view.slug,
+                                custom_view.formdef.name,
+                                operator,
+                            )
+                        )
+                    else:
+                        report_error(
+                            _('Invalid value "%s" for "filter-internal-id" and operator "%s"')
+                            % (value, operator)
+                        )
+
                 if Template.is_template_string(filter_field_value):
                     if keep_templates:
                         criterias.append(criteria('id', filter_field_value))
@@ -1891,34 +1911,21 @@ class FormPage(Directory):
                         criterias.append(Equal('status', '_none'))
                         continue
 
-                    def record_error(value, operator):
-                        get_publisher().record_error(
-                            _(
-                                'Invalid value "%s" for custom view "%s", CardDef "%s", field "internal-id", operator "%s"'
-                            )
-                            % (
-                                value,
-                                custom_view.slug,
-                                custom_view.formdef.name,
-                                operator,
-                            )
-                        )
-
-                    if isinstance(filter_field_value, list):
-                        try:
-                            [int(v) for v in filter_field_value]
-                        except ValueError:
-                            record_error(filter_field_value, filter_field_operator)
-                            criterias.append(Equal('status', '_none'))
-                            continue
-                        if filter_field_operator == 'eq':
-                            criterias.append(Contains('id', filter_field_value))
-                        elif filter_field_operator == 'ne':
-                            criterias.append(NotContains('id', filter_field_value))
-                        else:
-                            record_error(filter_field_value, filter_field_operator)
-                            criterias.append(Equal('status', '_none'))
+                if isinstance(filter_field_value, list):
+                    try:
+                        [int(v) for v in filter_field_value]
+                    except ValueError:
+                        _report_error(filter_field_value, filter_field_operator)
+                        criterias.append(Equal('status', '_none'))
                         continue
+                    if filter_field_operator == 'eq':
+                        criterias.append(Contains('id', filter_field_value))
+                    elif filter_field_operator == 'ne':
+                        criterias.append(NotContains('id', filter_field_value))
+                    else:
+                        _report_error(filter_field_value, filter_field_operator)
+                        criterias.append(Equal('status', '_none'))
+                    continue
                 try:
                     filter_field_value = int(filter_field_value)
                 except ValueError:
-- 
2.35.1

