[FIX] models: filtered_domain on Falsy date/datetime fields

The purpose of this patch is to avoid `filtered_domain` to crash with
domains on date/datetime fields when the fields are `False` on some
records:

    records.filtered_domain([('date', '<', '2019-10-28')])

closes odoo/odoo#39449

X-original-commit: dae379adebedb3ed9bd38a2d6925ba6aefef1e7f
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
This commit is contained in:
Raphael Collet
2019-10-28 13:27:35 +00:00
committed by fw-bot
parent 16f548ed7a
commit eccfdd5512
2 changed files with 39 additions and 15 deletions
@@ -617,6 +617,15 @@ class TestFields(common.TransactionCase):
self.assertTrue(record.filtered_domain([('date', '<', '2012-05-02')]))
self.assertTrue(record.filtered_domain([('date', '<', date(2012, 5, 2))]))
self.assertTrue(record.filtered_domain([('date', '<', datetime(2012, 5, 2, 12, 0, 0))]))
self.assertTrue(record.filtered_domain([('date', '!=', False)]))
self.assertFalse(record.filtered_domain([('date', '=', False)]))
record.date = None
self.assertFalse(record.filtered_domain([('date', '<', '2012-05-02')]))
self.assertFalse(record.filtered_domain([('date', '<', date(2012, 5, 2))]))
self.assertFalse(record.filtered_domain([('date', '<', datetime(2012, 5, 2, 12, 0, 0))]))
self.assertFalse(record.filtered_domain([('date', '!=', False)]))
self.assertTrue(record.filtered_domain([('date', '=', False)]))
def test_21_datetime(self):
""" test datetime fields """
@@ -647,6 +656,15 @@ class TestFields(common.TransactionCase):
self.assertTrue(record.filtered_domain([('moment', '<', '2012-05-02')]))
self.assertTrue(record.filtered_domain([('moment', '<', date(2012, 5, 2))]))
self.assertTrue(record.filtered_domain([('moment', '<', datetime(2012, 5, 1, 12, 0, 0))]))
self.assertTrue(record.filtered_domain([('moment', '!=', False)]))
self.assertFalse(record.filtered_domain([('moment', '=', False)]))
record.moment = None
self.assertFalse(record.filtered_domain([('moment', '<', '2012-05-02')]))
self.assertFalse(record.filtered_domain([('moment', '<', date(2012, 5, 2))]))
self.assertFalse(record.filtered_domain([('moment', '<', datetime(2012, 5, 2, 12, 0, 0))]))
self.assertFalse(record.filtered_domain([('moment', '!=', False)]))
self.assertTrue(record.filtered_domain([('moment', '=', False)]))
def test_21_date_datetime_helpers(self):
""" test date/datetime fields helpers """
+21 -15
View File
@@ -5132,7 +5132,15 @@ Record ids: %(records)s
(key, comparator, value) = d
if key.endswith('.id'):
key = key[:-3]
if key == 'id': key=''
if key == 'id':
key = ''
# determine the field with the final type for values
field = None
if key:
model = self.browse()
for fname in key.split('.'):
field = model._fields[fname]
model = model[fname]
if comparator in ('like', 'ilike', '=like', '=ilike', 'not ilike', 'not like'):
value_esc = value.replace('_', '?').replace('%', '*').replace('[', '?')
records = self.browse()
@@ -5149,16 +5157,14 @@ Record ids: %(records)s
data = data.mapped('display_name')
else:
data = data and data.ids or [False]
else:
true_data = next((d for d in data if d), None)
if isinstance(true_data, datetime.date):
# convert all date and datetime values to datetime
normalize = Datetime.to_datetime
if isinstance(value, (list, tuple)):
value = [normalize(v) for v in value]
else:
value = normalize(value)
data = [normalize(d) for d in data]
elif field and field.type in ('date', 'datetime'):
# convert all date and datetime values to datetime
normalize = Datetime.to_datetime
if isinstance(value, (list, tuple)):
value = [normalize(v) for v in value]
else:
value = normalize(value)
data = [normalize(d) for d in data]
if comparator in ('in', 'not in'):
if not (isinstance(value, list) or isinstance(value, tuple)):
value = [value]
@@ -5168,13 +5174,13 @@ Record ids: %(records)s
elif comparator == 'in':
ok = any(map(lambda x: x in data, value))
elif comparator == '<':
ok = any(map(lambda x: x < value, data))
ok = any(map(lambda x: x is not None and x < value, data))
elif comparator == '>':
ok = any(map(lambda x: x > value, data))
ok = any(map(lambda x: x is not None and x > value, data))
elif comparator == '<=':
ok = any(map(lambda x: x <= value, data))
ok = any(map(lambda x: x is not None and x <= value, data))
elif comparator == '>=':
ok = any(map(lambda x: x >= value, data))
ok = any(map(lambda x: x is not None and x >= value, data))
elif comparator in ('!=', '<>'):
ok = value not in data
elif comparator == 'not in':