From 6c49c0c2c4b2941ea0af343ac1e784ed670880f1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Mon, 12 Apr 2021 15:57:59 +0200
Subject: [PATCH] general: add queryset filter on form_number (#52763)

(and fallbacks so |filter_by can be used with specialized filters)
---
 tests/test_formdata.py            | 27 +++++++++++++++++++++++++++
 wcs/qommon/templatetags/qommon.py |  5 +++++
 wcs/variables.py                  | 11 +++++++++++
 3 files changed, 43 insertions(+)

diff --git a/tests/test_formdata.py b/tests/test_formdata.py
index 204b38efb..aa508e0df 100644
--- a/tests/test_formdata.py
+++ b/tests/test_formdata.py
@@ -1126,6 +1126,8 @@ def test_lazy_formdata_queryset_filter(pub, variable_test_data):
         formdata.jump_status('finished')
         formdata.store()
 
+    finished_formdata = formdata
+
     formdata = data_class()
     formdata.data = {'0': 'bar', 'bo1': 'plop1'}
     formdata.status = 'draft'
@@ -1280,6 +1282,16 @@ def test_lazy_formdata_queryset_filter(pub, variable_test_data):
         .count
         == 1
     )
+    # alternative form, using filter_by/apply_filter_value
+    assert (
+        LazyFormData(formdata)
+        .objects.filter_by('form_user')
+        .apply_filter_value(lazy_formdata.user)
+        .filter_by('foo_foo')
+        .apply_filter_value('foo')
+        .count
+        == 1
+    )
 
     # test |current_user
     pub.get_request()._user = ()  # reset cache
@@ -1307,6 +1319,8 @@ def test_lazy_formdata_queryset_filter(pub, variable_test_data):
     )
     assert LazyFormData(formdata).objects.filter_by_status('Finished').count == 4
     assert LazyFormData(formdata).objects.filter_by_status('Unknown').count == 0
+    # alternative form, using filter_by/apply_filter_value
+    assert LazyFormData(formdata).objects.filter_by('status').apply_filter_value('Finished').count == 4
 
     # test |pending
     context = pub.substitutions.get_context_variables(mode='lazy')
@@ -1317,6 +1331,19 @@ def test_lazy_formdata_queryset_filter(pub, variable_test_data):
     assert LazyFormData(formdata).objects.pending().count == 7
     assert LazyFormData(formdata).objects.pending().filter_by('foo_foo').apply_filter_value('foo').count == 0
 
+    # test |filter_by_form_number
+    context = pub.substitutions.get_context_variables(mode='lazy')
+    tmpl = Template('{{form_objects|filter_by_form_number:"%s"|count}}' % finished_formdata.get_display_id())
+    assert tmpl.render(context) == '1'
+    tmpl = Template('{{form_objects|filter_by_form_number:"%s"|count}}' % 'invalid value')
+    assert tmpl.render(context) == '0'
+    # alternative form, using filter_by/apply_filter_value
+    tmpl = Template(
+        '{{form_objects|filter_by:"form_number"|filter_value:"%s"|count}}'
+        % finished_formdata.get_display_id()
+    )
+    assert tmpl.render(context) == '1'
+
     # test |is_empty
     tmpl = Template('{{form_objects|pending|is_empty}}')
     assert tmpl.render(context) == 'False'
diff --git a/wcs/qommon/templatetags/qommon.py b/wcs/qommon/templatetags/qommon.py
index 97e3d6ec6..587ce5267 100644
--- a/wcs/qommon/templatetags/qommon.py
+++ b/wcs/qommon/templatetags/qommon.py
@@ -639,6 +639,11 @@ def filter_by_status(queryset, status):
     return queryset.filter_by_status(status)
 
 
+@register.filter
+def filter_by_form_number(queryset, form_number):
+    return queryset.filter_by_form_number(form_number)
+
+
 @register.filter
 def pending(queryset):
     return queryset.pending()
diff --git a/wcs/variables.py b/wcs/variables.py
index 965fe5fa0..ee2e839d7 100644
--- a/wcs/variables.py
+++ b/wcs/variables.py
@@ -167,6 +167,9 @@ class LazyFormDefObjectsManager:
         qs.pending_attr = attribute
         return qs
 
+    def filter_by_form_number(self, value):
+        return self._clone(self._criterias + [Equal('id_display', str(value))])
+
     def get_field(self, key):
         for field in self._formdef.get_all_fields():
             if getattr(field, 'varname', None) == key:
@@ -177,6 +180,14 @@ class LazyFormDefObjectsManager:
 
         field = self.get_field(self.pending_attr)
         if field is None:
+            # fallback to specialized filters for some attributes
+            if self.pending_attr in ('status', 'form_status'):
+                return self.filter_by_status(value)
+            elif self.pending_attr in ('user', 'form_user'):
+                return self.filter_by_user(value)
+            elif self.pending_attr == 'form_number':
+                return self.filter_by_form_number(value)
+
             get_publisher().record_error(
                 _('Invalid filter "%s"') % self.pending_attr, formdata=self._formdata
             )
-- 
2.31.0

