diff --git a/odoo/addons/test_read_group/tests/test_fill_temporal.py b/odoo/addons/test_read_group/tests/test_fill_temporal.py index 6f178f0190f..07dcb0ed19b 100644 --- a/odoo/addons/test_read_group/tests/test_fill_temporal.py +++ b/odoo/addons/test_read_group/tests/test_fill_temporal.py @@ -777,6 +777,66 @@ class TestFillTemporal(common.TransactionCase): self.assertEqual(groups, expected) + def test_with_bounds_groupby_week(self): + """Test data with weeks starting on Sunday and forced boundaries.""" + self.Model.create([ + {'date': '1916-08-19', 'value': 4}, # saturday W34 + {'date': '1916-08-20', 'value': 13}, # sunday W35 + {'date': '1916-09-10', 'value': 5}, # sunday W38 + {'date': '1916-08-18', 'value': 3}, # friday W34 + {'date': '1916-09-11', 'value': 4}, # monday W38 + {'date': '1916-09-12', 'value': 11}, # tuesday W38 + ]) + + expected = [{ + '__domain': ['&', ('date', '>=', '1916-08-06'), ('date', '<', '1916-08-13')], + '__range': {'date:week': {'from': '1916-08-06', 'to': '1916-08-13'}}, + 'date:week': 'W33 1916', + 'date_count': 0, + 'value': 0, + }, { + '__domain': ['&', ('date', '>=', '1916-08-13'), ('date', '<', '1916-08-20')], + '__range': {'date:week': {'from': '1916-08-13', 'to': '1916-08-20'}}, + 'date:week': 'W34 1916', + 'date_count': 2, + 'value': 7, + }, { + '__domain': ['&', ('date', '>=', '1916-08-20'), ('date', '<', '1916-08-27')], + '__range': {'date:week': {'from': '1916-08-20', 'to': '1916-08-27'}}, + 'date:week': 'W35 1916', + 'date_count': 1, + 'value': 13, + }, { + '__domain': ['&', ('date', '>=', '1916-08-27'), ('date', '<', '1916-09-03')], + '__range': {'date:week': {'from': '1916-08-27', 'to': '1916-09-03'}}, + 'date:week': 'W36 1916', + 'date_count': 0, + 'value': 0, + }, { + '__domain': ['&', ('date', '>=', '1916-09-03'), ('date', '<', '1916-09-10')], + '__range': {'date:week': {'from': '1916-09-03', 'to': '1916-09-10'}}, + 'date:week': 'W37 1916', + 'date_count': 0, + 'value': 0, + }, { + '__domain': ['&', ('date', '>=', '1916-09-10'), ('date', '<', '1916-09-17')], + '__range': {'date:week': {'from': '1916-09-10', 'to': '1916-09-17'}}, + 'date:week': 'W38 1916', + 'date_count': 3, + 'value': 20, + }, { + '__domain': ['&', ('date', '>=', '1916-09-17'), ('date', '<', '1916-09-24')], + '__range': {'date:week': {'from': '1916-09-17', 'to': '1916-09-24'}}, + 'date:week': 'W39 1916', + 'date_count': 0, + 'value': 0, + }] + + model_fill = self.Model.with_context(fill_temporal={"fill_from": '1916-08-10', "fill_to": '1916-09-20'}) + groups = model_fill.read_group([], fields=['date', 'value'], groupby=['date:week']) + + self.assertEqual(groups, expected) + def test_upper_bound(self): """Test the alternative dictionary format for the fill_temporal context key (fill_to). diff --git a/odoo/models.py b/odoo/models.py index 633b81307c7..c5c0a5cb095 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -2349,6 +2349,12 @@ class BaseModel(metaclass=MetaModel): return data granularity = first_group.split(':')[1] if ':' in first_group else 'month' + days_offset = 0 + if granularity == 'week': + # _read_group_process_groupby week groups are dependent on the + # locale, so filled groups should be too to avoid overlaps. + first_week_day = int(get_lang(self.env).week_start) - 1 + days_offset = first_week_day and 7 - first_week_day interval = READ_GROUP_TIME_GRANULARITY[granularity] tz = False if field.type == 'datetime' and self._context.get('tz') in pytz.all_timezones_set: @@ -2362,14 +2368,14 @@ class BaseModel(metaclass=MetaModel): existing_from, existing_to = existing[0], existing[-1] if fill_from: fill_from = odoo.fields.Datetime.to_datetime(fill_from) if isinstance(fill_from, datetime.datetime) else odoo.fields.Date.to_date(fill_from) - fill_from = date_utils.start_of(fill_from, granularity) + fill_from = date_utils.start_of(fill_from, granularity) - datetime.timedelta(days=days_offset) if tz: fill_from = tz.localize(fill_from) elif existing_from: fill_from = existing_from if fill_to: fill_to = odoo.fields.Datetime.to_datetime(fill_to) if isinstance(fill_to, datetime.datetime) else odoo.fields.Date.to_date(fill_to) - fill_to = date_utils.start_of(fill_to, granularity) + fill_to = date_utils.start_of(fill_to, granularity) - datetime.timedelta(days=days_offset) if tz: fill_to = tz.localize(fill_to) elif existing_to: