From 454a367ad6e7b7c1f31beaaa482a77f8a5f9000b Mon Sep 17 00:00:00 2001
From: "Audric Onockx (auon)" <auon@odoo.com>
Date: Thu, 26 Aug 2021 15:36:38 +0000
Subject: [PATCH] [FIX] web : Fixed datetime filter search based on wrong hours

Reproduce :
(With timezone GMT+3)
- Create any record R1 with previous day's date and time after 21:00.
- Create any record R2 with today's date and time after 21:00.
- Create a filter to show all todays records (Date is between "<TODAY'S DATE> 00:00:00 and <TODAY'S DATE> 23:59:59".

Result :
  Even though R1 is in yesterday's date, it will show in the list.
  R2 will not show in this list.

Explanation :
  This behaviour has been observed in several modules, for any timezone but UTC & only with custom filters default datetime values.
  The search was applied on [datetime(UTC) + 2 * offset] because the timezone wasn't correctly set.

Solution :
  Timezone is now correctly set on default datetime values.

closes odoo/odoo#75663

Signed-off-by: Nicolas Lempereur (nle) <nle@odoo.com>
---
 .../js/control_panel/custom_filter_item.js    |  4 +-
 .../control_panel/custom_filter_item_tests.js | 39 +++++++++++++++++++
 2 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/addons/web/static/src/js/control_panel/custom_filter_item.js b/addons/web/static/src/js/control_panel/custom_filter_item.js
index 8dd73f4f34c3..6682b660b781 100644
--- a/addons/web/static/src/js/control_panel/custom_filter_item.js
+++ b/addons/web/static/src/js/control_panel/custom_filter_item.js
@@ -118,9 +118,9 @@ odoo.define('web.CustomFilterItem', function (require) {
                     }
                     break;
                 case 'datetime':
-                    condition.value = [moment('00:00:00', 'hh:mm:ss')];
+                    condition.value = [moment('00:00:00', 'hh:mm:ss').utcOffset(0, true)];
                     if (operator.symbol === 'between') {
-                        condition.value.push(moment('23:59:59', 'hh:mm:ss'));
+                        condition.value.push(moment('23:59:59', 'hh:mm:ss').utcOffset(0, true));
                     }
                     break;
                 case 'selection':
diff --git a/addons/web/static/tests/control_panel/custom_filter_item_tests.js b/addons/web/static/tests/control_panel/custom_filter_item_tests.js
index 7add6c8491fe..496e9abd74ab 100644
--- a/addons/web/static/tests/control_panel/custom_filter_item_tests.js
+++ b/addons/web/static/tests/control_panel/custom_filter_item_tests.js
@@ -332,6 +332,45 @@ odoo.define('web.filter_menu_generator_tests', function (require) {
             cfi.destroy();
         });
 
+        QUnit.test('default custom filter datetime', async function (assert) {
+            assert.expect(5);
+
+            class MockedSearchModel extends ActionModel {
+                dispatch(method, ...args) {
+                    assert.strictEqual(method, 'createNewFilters');
+                    const domain = JSON.parse(args[0][0].domain);
+                    assert.strictEqual(domain[0][2].split(' ')[1],
+                        '04:00:00',
+                        "domain should be in UTC format");
+                    assert.strictEqual(domain[1][2].split(' ')[1],
+                        '03:59:59',
+                        "domain should be in UTC format");
+                }
+            }
+            const searchModel = new MockedSearchModel();
+            const cfi = await createComponent(CustomFilterItem, {
+                props: {
+                    fields: this.fields,
+                },
+                session: {
+                    getTZOffset() {
+                        return -240;
+                    },
+                },
+                env: { searchModel },
+            });
+
+            await cpHelpers.toggleAddCustomFilter(cfi);
+            await testUtils.fields.editSelect(cfi.el.querySelector('.o_generator_menu_field'), 'date_time_field');
+
+            assert.strictEqual(cfi.el.querySelector('.o_generator_menu_field').value, 'date_time_field');
+            assert.strictEqual(cfi.el.querySelector('.o_generator_menu_operator').value, 'between');
+
+            await cpHelpers.applyFilter(cfi);
+
+            cfi.destroy();
+        });
+
         QUnit.test('input value parsing', async function (assert) {
             assert.expect(7);
 
-- 
GitLab