From 099aae6df1ccd296989ca1806bb1b554379fbb25 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Wed, 18 Dec 2019 15:56:58 +0100
Subject: [PATCH] backoffice: fix filtering on backoffice item/s fields
 (#38627)

---
 tests/test_backoffice_pages.py | 76 ++++++++++++++++++++++++++++++++++
 wcs/backoffice/management.py   |  5 ++-
 2 files changed, 79 insertions(+), 2 deletions(-)

diff --git a/tests/test_backoffice_pages.py b/tests/test_backoffice_pages.py
index d4520c0fe..3e0319f82 100644
--- a/tests/test_backoffice_pages.py
+++ b/tests/test_backoffice_pages.py
@@ -832,6 +832,82 @@ def test_backoffice_item_double_filter(pub):
     assert [x[0] for x in resp.form['filter-4-value'].options] == ['', 'a', 'b']
     assert [x[0] for x in resp.form['filter-5-value'].options] == ['', 'A', 'B', 'C']
 
+def test_backoffice_bofield_item_filter(pub):
+    create_superuser(pub)
+    create_environment(pub)
+    formdef = FormDef.get_by_urlname('form-title')
+    workflow = Workflow.get_default_workflow()
+    workflow.id = '2'
+    workflow.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(workflow)
+    workflow.backoffice_fields_formdef.fields = [
+            fields.ItemField(id='bo0-1', label='4th field', type='item',
+                items=['â', 'b', 'c', 'd'],
+                display_locations=['validation', 'summary', 'listings'])
+    ]
+    workflow.store()
+    formdef.workflow_id = workflow.id
+    formdef.store()
+
+    for i, formdata in enumerate(formdef.data_class().select()):
+        if i%4 == 0:
+            formdata.data['bo0-1'] = 'â'
+            formdata.data['bo0-1_display'] = 'â'
+        elif i%4 == 1:
+            formdata.data['bo0-1'] = 'b'
+            formdata.data['bo0-1_display'] = 'b'
+        elif i%4 == 2:
+            formdata.data['bo0-1'] = 'd'
+            formdata.data['bo0-1_display'] = 'd'
+        formdata.store()
+
+    app = login(get_app(pub))
+    resp = app.get('/backoffice/management/form-title/')
+    resp.form['filter-bo0-1'].checked = True
+    resp = resp.form.submit()
+
+    assert resp.form['filter-bo0-1-value'].value == ''
+
+    resp.form['filter-bo0-1-value'].value = 'â'
+    resp = resp.form.submit()
+    assert resp.text.count(u'<td>â</td>') > 0
+    assert resp.text.count(u'<td>b</td>') == 0
+    assert resp.text.count(u'<td>d</td>') == 0
+
+    resp.form['filter-bo0-1-value'].value = 'b'
+    resp = resp.form.submit()
+    assert resp.text.count(u'<td>â</td>') == 0
+    assert resp.text.count(u'<td>b</td>') > 0
+    assert resp.text.count(u'<td>d</td>') == 0
+
+    if not pub.is_using_postgresql():
+        # in pickle all options are always displayed
+        resp.form['filter-bo0-1-value'].value = 'c'
+        resp = resp.form.submit()
+        assert resp.text.count(u'<td>â</td>') == 0
+        assert resp.text.count(u'<td>b</td>') == 0
+        assert resp.text.count(u'<td>c</td>') == 0
+
+    else:
+        # in postgresql, option 'c' is never used so not even listed
+        with pytest.raises(ValueError):
+            resp.form['filter-bo0-1-value'].value = 'c'
+
+        # check json view used to fill select filters from javascript
+        resp2 = app.get(resp.request.path + 'filter-options?filter_field_id=bo0-1&' + resp.request.query_string)
+        assert [x['id'] for x in resp2.json['data']] == [u'â', u'b', u'd']
+        resp2 = app.get(resp.request.path + 'filter-options?filter_field_id=bo0-1&_search=d&' + resp.request.query_string)
+        assert [x['id'] for x in resp2.json['data']] == ['d']
+
+        for status in ('all', 'waiting', 'pending', 'done', 'accepted'):
+            resp.form['filter'] = status
+            resp = resp.form.submit()
+            resp2 = app.get(resp.request.path + 'filter-options?filter_field_id=bo0-1&' + resp.request.query_string)
+            if status == 'accepted':
+                assert [x['id'] for x in resp2.json['data']] == []
+            else:
+                assert [x['id'] for x in resp2.json['data']] == [u'â', u'b', u'd']
+
+
 def test_backoffice_items_filter(pub):
     create_superuser(pub)
     create_environment(pub)
diff --git a/wcs/backoffice/management.py b/wcs/backoffice/management.py
index 21600552f..a7d58dc6d 100644
--- a/wcs/backoffice/management.py
+++ b/wcs/backoffice/management.py
@@ -1070,9 +1070,10 @@ class FormPage(Directory):
             criterias.append(Contains('status', statuses))
         else:
             criterias.append(Equal('status', 'wf-%s' % selected_filter))
-        criterias.append(NotNull('f%s' % filter_field.id))
+        from wcs import sql
+        criterias.append(NotNull(sql.get_field_id(filter_field)))
         options = self.formdef.data_class().select_distinct(
-                ['f%s' % filter_field.id, 'f%s_display' % filter_field.id],
+                [sql.get_field_id(filter_field), '%s_display' % sql.get_field_id(filter_field)],
                 clause=criterias)
 
         if filter_field.type == 'items':
-- 
2.24.1

