From 09a36dc12bedb653dc4d8216ddaad75da2c5ac9c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Mon, 10 Oct 2022 08:57:36 +0200
Subject: [PATCH 1/2] misc: allow |filter_by & |filter_value for some fake
 fields (#68943)

fake fields: status, user, internal_id, number
---
 tests/test_formdata.py | 84 ++++++++++++++++++++++++------------------
 wcs/variables.py       | 12 +++---
 2 files changed, 56 insertions(+), 40 deletions(-)

diff --git a/tests/test_formdata.py b/tests/test_formdata.py
index d9a3dfe57..2f1dd549f 100644
--- a/tests/test_formdata.py
+++ b/tests/test_formdata.py
@@ -1498,8 +1498,19 @@ def test_lazy_formdata_queryset_filter(pub, variable_test_data):
 
     # test |filter_by_user
     context = pub.substitutions.get_context_variables(mode='lazy')
-    tmpl = Template('{{form_objects|filter_by_user:form_user|filter_by:"foo_foo"|filter_value:"foo"|count}}')
-    assert tmpl.render(context) == '1'
+    for tpl in ['filter_by_user', 'filter_by:"user"|filter_value']:
+        tmpl = Template('{{form_objects|%s:form_user|filter_by:"foo_foo"|filter_value:"foo"|count}}' % tpl)
+        assert tmpl.render(context) == '1'
+        tmpl = Template(
+            '{{form_objects|%s:form_user_email|filter_by:"foo_foo"|filter_value:"foo"|count}}' % tpl
+        )
+        assert tmpl.render(context) == '1'
+        tmpl = Template(
+            '{{form_objects|%s:form_user_nameid|filter_by:"foo_foo"|filter_value:"foo"|count}}' % tpl
+        )
+        assert tmpl.render(context) == '1'
+        tmpl = Template('{{form_objects|%s:"foo@bar"|filter_by:"foo_foo"|filter_value:"foo"|count}}' % tpl)
+        assert tmpl.render(context) == '0'
     assert (
         LazyFormData(formdata)
         .objects.filter_by_user(lazy_formdata.user)
@@ -1508,16 +1519,15 @@ def test_lazy_formdata_queryset_filter(pub, variable_test_data):
         .count
         == 1
     )
-    tmpl = Template(
-        '{{form_objects|filter_by_user:form_user_email|filter_by:"foo_foo"|filter_value:"foo"|count}}'
-    )
-    assert tmpl.render(context) == '1'
-    tmpl = Template(
-        '{{form_objects|filter_by_user:form_user_nameid|filter_by:"foo_foo"|filter_value:"foo"|count}}'
+    assert (
+        LazyFormData(formdata)
+        .objects.filter_by('user')
+        .apply_filter_value(lazy_formdata.user)
+        .filter_by('foo_foo')
+        .apply_filter_value('foo')
+        .count
+        == 1
     )
-    assert tmpl.render(context) == '1'
-    tmpl = Template('{{form_objects|filter_by_user:"foo@bar"|filter_by:"foo_foo"|filter_value:"foo"|count}}')
-    assert tmpl.render(context) == '0'
 
     # test |current_user
     pub.get_request()._user = ()  # reset cache
@@ -1527,24 +1537,27 @@ def test_lazy_formdata_queryset_filter(pub, variable_test_data):
     assert tmpl.render(context) == '1'
 
     # test |filter_by_status
-    context = pub.substitutions.get_context_variables(mode='lazy')
-    tmpl = Template('{{form_objects|filter_by_status:"Just Submitted"|count}}')
-    assert tmpl.render(context) == '7'
-    tmpl = Template(
-        '{{form_objects|filter_by_status:"Just Submitted"|filter_by:"foo_foo"|filter_value:"foo"|count}}'
-    )
-    assert tmpl.render(context) == '0'
+    for tpl in ['filter_by_status', 'filter_by:"status"|filter_value']:
+        context = pub.substitutions.get_context_variables(mode='lazy')
+        tmpl = Template('{{form_objects|%s:"Just Submitted"|count}}' % tpl)
+        assert tmpl.render(context) == '7'
+        tmpl = Template(
+            '{{form_objects|%s:"Just Submitted"|filter_by:"foo_foo"|filter_value:"foo"|count}}' % tpl
+        )
+        assert tmpl.render(context) == '0'
     assert LazyFormData(formdata).objects.filter_by_status('Just Submitted').count == 7
+    assert LazyFormData(formdata).objects.filter_by('status').apply_filter_value('Just Submitted').count == 7
     assert (
         LazyFormData(formdata)
-        .objects.filter_by_status('Just Submitted')
+        .objects.filter_by('status')
+        .apply_filter_value('Just Submitted')
         .filter_by('foo_foo')
         .apply_filter_value('foo')
         .count
         == 0
     )
-    assert LazyFormData(formdata).objects.filter_by_status('Finished').count == 4
-    assert LazyFormData(formdata).objects.filter_by_status('Unknown').count == 0
+    assert LazyFormData(formdata).objects.filter_by('status').apply_filter_value('Finished').count == 4
+    assert LazyFormData(formdata).objects.filter_by('status').apply_filter_value('Unknown').count == 0
 
     # test |pending
     context = pub.substitutions.get_context_variables(mode='lazy')
@@ -1562,22 +1575,23 @@ def test_lazy_formdata_queryset_filter(pub, variable_test_data):
 
     # test |filter_by_internal_id
     context = pub.substitutions.get_context_variables(mode='lazy')
-    tmpl = Template('{{form_objects|filter_by_internal_id:"%s"|count}}' % finished_formdata.id)
-    assert tmpl.render(context) == '1'
-    tmpl = Template('{{form_objects|filter_by_internal_id:"%s"|count}}' % '0')
-    assert tmpl.render(context) == '0'
-    tmpl = Template('{{form_objects|filter_by_internal_id:"%s"|count}}' % 'invalid value')
-    assert tmpl.render(context) == '0'
-    assert pub.loggederror_class.count() == 4
-    logged_error = pub.loggederror_class.select(order_by='id')[3]
-    assert logged_error.summary == 'Invalid value "invalid value" for "filter_by_internal_id"'
+    for tpl in ['filter_by_internal_id', 'filter_by:"internal_id"|filter_value']:
+        tmpl = Template('{{form_objects|%s:"%s"|count}}' % (tpl, finished_formdata.id))
+        assert tmpl.render(context) == '1'
+        tmpl = Template('{{form_objects|%s:"%s"|count}}' % (tpl, '0'))
+        assert tmpl.render(context) == '0'
+        tmpl = Template('{{form_objects|%s:"%s"|count}}' % (tpl, 'invalid value'))
+        assert tmpl.render(context) == '0'
+        assert pub.loggederror_class.count() == 4
+        logged_error = pub.loggederror_class.select(order_by='id')[3]
+        assert logged_error.summary == 'Invalid value "invalid value" for filter "internal_id"'
 
     # test |filter_by_number
-    context = pub.substitutions.get_context_variables(mode='lazy')
-    tmpl = Template('{{form_objects|filter_by_number:"%s"|count}}' % finished_formdata.get_display_id())
-    assert tmpl.render(context) == '1'
-    tmpl = Template('{{form_objects|filter_by_number:"%s"|count}}' % 'invalid value')
-    assert tmpl.render(context) == '0'
+    for tpl in ['filter_by_number', 'filter_by:"number"|filter_value']:
+        tmpl = Template('{{form_objects|%s:"%s"|count}}' % (tpl, finished_formdata.get_display_id()))
+        assert tmpl.render(context) == '1'
+        tmpl = Template('{{form_objects|%s:"%s"|count}}' % (tpl, 'invalid value'))
+        assert tmpl.render(context) == '0'
 
     # test |is_empty
     tmpl = Template('{{form_objects|pending|is_empty}}')
diff --git a/wcs/variables.py b/wcs/variables.py
index 7c132edef..2fd441155 100644
--- a/wcs/variables.py
+++ b/wcs/variables.py
@@ -115,14 +115,14 @@ class LazyFormDefObjectsManager:
     def current_user(self):  # filter on current user
         return self.filter_by_user(get_request().user)
 
-    def filter_by_user(self, user):
+    def filter_by_user(self, user, op='eq'):
         if isinstance(user, str):
             user = get_publisher().user_class.lookup_by_string(user)
         if not user:
             return self.none()
         return self._clone(self._criterias + [Equal('user_id', str(user.id))])
 
-    def filter_by_status(self, status):
+    def filter_by_status(self, status, op='eq'):
         for wfs in self._formdef.workflow.possible_status:
             if wfs.name == status:
                 wf_status = 'wf-%s' % wfs.id
@@ -194,18 +194,18 @@ class LazyFormDefObjectsManager:
         qs.pending_attr = attribute
         return qs
 
-    def filter_by_internal_id(self, value):
+    def filter_by_internal_id(self, value, op='eq'):
         try:
             int(value)
         except ValueError:
             get_publisher().record_error(
-                _('Invalid value "%s" for "filter_by_internal_id"') % (value),
+                _('Invalid value "%s" for filter "internal_id"') % (value),
                 formdata=self._formdata,
             )
             return self.none()
         return self._clone(self._criterias + [Equal('id', str(value))])
 
-    def filter_by_number(self, value):
+    def filter_by_number(self, value, op='eq'):
         return self._clone(self._criterias + [Equal('id_display', str(value))])
 
     def get_fields(self, key):
@@ -233,6 +233,8 @@ class LazyFormDefObjectsManager:
     def apply_filter_value(self, value, exclude=False):
         assert self.pending_attr
         op = 'ne' if exclude else getattr(self, 'pending_op', 'eq')
+        if self.pending_attr in ['status', 'user', 'internal_id', 'number']:
+            return getattr(self, 'filter_by_%s' % self.pending_attr)(value, op)
 
         fields = list(self.get_fields(self.pending_attr))
         if not fields:
-- 
2.35.1

