From 6da409ec5ba05e9e003b99f8984e960f3ce8e6ec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Fri, 2 Apr 2021 08:09:25 +0200
Subject: [PATCH] cards: make id lookup work with display id (#52647)

---
 tests/test_carddef.py   | 38 ++++++++++++++++++++++++++++++++++++++
 tests/test_workflows.py | 11 +++++++++++
 wcs/carddef.py          | 15 ++++++++++-----
 wcs/data_sources.py     |  8 +-------
 4 files changed, 60 insertions(+), 12 deletions(-)

diff --git a/tests/test_carddef.py b/tests/test_carddef.py
index 02eac3d8b..7a48619b3 100644
--- a/tests/test_carddef.py
+++ b/tests/test_carddef.py
@@ -330,6 +330,44 @@ def test_template_access(pub):
     assert tmpl.render(context) == '0'
 
 
+def test_data_source_access_by_id(pub):
+    CardDef.wipe()
+    carddef = CardDef()
+    carddef.name = 'foo'
+    carddef.fields = [
+        StringField(id='1', label='Test', type='string', varname='foo'),
+    ]
+    carddef.digest_template = '{{ form_var_foo }}'
+    carddef.store()
+    carddef.data_class().wipe()
+
+    carddata = carddef.data_class()()
+    carddata.data = {'1': 'hello world'}
+    carddata.just_created()
+    carddata.store()
+
+    carddata2 = carddef.data_class()()
+    carddata2.data = {'1': 'bye'}
+    carddata2.just_created()
+    carddata2.store()
+
+    cards = CardDef.get_data_source_items('carddef:foo', get_by_id=carddata.id)
+    assert len(cards) == 1
+    assert cards[0]['text'] == 'hello world'
+
+    cards = CardDef.get_data_source_items('carddef:foo', get_by_id=carddata2.id)
+    assert len(cards) == 1
+    assert cards[0]['text'] == 'bye'
+
+    cards = CardDef.get_data_source_items('carddef:foo', get_by_id=carddata.get_display_id())
+    assert len(cards) == 1
+    assert cards[0]['text'] == 'hello world'
+
+    cards = CardDef.get_data_source_items('carddef:foo', get_by_id=carddata2.get_display_id())
+    assert len(cards) == 1
+    assert cards[0]['text'] == 'bye'
+
+
 def test_data_source_access_invalid_id(pub):
     CardDef.wipe()
     carddef = CardDef()
diff --git a/tests/test_workflows.py b/tests/test_workflows.py
index 503167008..765bc37cc 100644
--- a/tests/test_workflows.py
+++ b/tests/test_workflows.py
@@ -4669,6 +4669,7 @@ def test_set_backoffice_field_card_item(two_pubs):
         }
         carddata.just_created()
         carddata.store()
+    latest_carddata = carddata
     latest_carddata_id = carddata.id
     ds = {'type': 'carddef:%s' % carddef.url_name}
 
@@ -4713,6 +4714,16 @@ def test_set_backoffice_field_card_item(two_pubs):
     assert formdata.data['bo1_display'] == 'baz'
     assert formdata.data['bo1_structured']['attr'] == 'attr2'
 
+    # reset, and get by display id value
+    formdata.data = {}
+    formdata.store()
+    item.fields = [{'field_id': 'bo1', 'value': latest_carddata.get_display_id()}]
+    item.perform(formdata)
+    formdata = formdef.data_class().get(formdata.id)
+    assert formdata.data['bo1'] == str(latest_carddata_id)
+    assert formdata.data['bo1_display'] == 'baz'
+    assert formdata.data['bo1_structured']['attr'] == 'attr2'
+
     # reset, and get by text value
     formdata.data = {}
     formdata.store()
diff --git a/wcs/carddef.py b/wcs/carddef.py
index df39ff6ec..18776051e 100644
--- a/wcs/carddef.py
+++ b/wcs/carddef.py
@@ -209,11 +209,16 @@ class CardDef(FormDef):
         if query:
             criterias.append(ILike('digest', query))
         if get_by_id:
-            if int(get_by_id) >= 2 ** 31:
-                # out of range for postgresql integer type; would raise
-                # DataError.
-                return []
-            criterias.append(Equal('id', get_by_id))
+            try:
+                if int(get_by_id) >= 2 ** 31:
+                    # out of range for postgresql integer type; would raise
+                    # DataError.
+                    return []
+            except ValueError:
+                # get_by_id not an integer, it could be id_display
+                criterias.append(Equal('id_display', get_by_id))
+            else:
+                criterias.append(Equal('id', get_by_id))
         if get_by_text:
             criterias.append(Equal('digest', get_by_text))
 
diff --git a/wcs/data_sources.py b/wcs/data_sources.py
index 459e496a2..a3687cddc 100644
--- a/wcs/data_sources.py
+++ b/wcs/data_sources.py
@@ -690,13 +690,7 @@ class NamedDataSource(XmlStorableObject):
     def get_card_structured_value_by_id(self, option_id):
         from wcs.carddef import CardDef
 
-        values = []
-        try:
-            int(option_id)
-        except ValueError:
-            pass
-        else:
-            values = CardDef.get_data_source_items(self.type, get_by_id=option_id)
+        values = CardDef.get_data_source_items(self.type, get_by_id=option_id)
         if not values:
             values = CardDef.get_data_source_items(self.type, get_by_text=option_id)
             if not values:
-- 
2.31.0

