Files
odoo_source/odoo/addons/test_read_group/tests/test_empty.py
T
abd-msyukyu-odoo eed1e64a93 [IMP] core, web: add a range for date(time) read_group
1. Objective

  - We are in a Kanban view, and we group by a "date/datetime" field.

  - In order to "quick create" a record in a group, or to "drag & drop" a
    record between 2 groups, we need a default value for this date field.

  - In this case, a group represents a "range" of dates. A default value could
    be the last date of this range.

  - Prior to this commit, the view had only access to a display string for this
    date range. We want to have access to the concrete bounds (start/end dates)

  - Since some date/datetime fields have backend constraints, it would be
    difficult to generate a compliant global default value. As such, the use of
    the default value should be disabled by default and activated on a field by
    field basis.

2. Usage

  - Use the last day (for dates), or second (for datetimes) of the range to set
    a default value in kanban "quick create" and "drag & drop"

  - Use the end of the range of the last group from a read_group to be able to
    request the next group (chronological order) in subsequent read_group calls

3. What are the changes in this commit

  - read_group from the "core" "models.py", with the added __range for
    date(time) fields, a dictionary for each group. The keys are the field
    names and the values are a dictionary with the following keys: value:
    - from: starting date(time) of the range (inclusive)
    - to:   ending date(time) of the range (exclusive)

  - XML changes:

    - with a new xml attribute on <field> tag allow_group_range_value (for the
      kanban view):

      - we allow (or disallow) supported non-readonly fields to be:
        - draggable
        - quick created

      - this attribute can be used only on date(time) fields, and if not set,
        the default behavior is false

      - the naming is subject to contention because it relates to
        different features. The relation comes from the constraint:
        To perform a drag&drop or a quickCreate, we must be able to get the
        value from the group containing the record.

  - JS changes:

    - we add "group.range" after a read_group for date fields, which is a
      dictionary: {field_name: {from, to}}, for each date(time) groupby field

    - since date(time) fields can use the format "date_field:granularity" when
      used in a groupby, we have to properly split out the granularity to ensure
      compatibility with the code previously in place (drag&drop procedures)

    - update mock_server and sample_server to make use of the date range.
      Adding support for datetime grouping to both mock and sample servers, for
      tests and previews.

    - the default value for kanban drag&drop and quickCreate features is the
      last day/second of the range for date/datetime fields

4. Why can't this range be computed from the original display value with
  moment.js

The Babel python library that we use for date(time) formatting (2.6.0) is kept
at the same version as the package in stable Debian Linux. This version has
some issues with displaying weeks consistently around the new year in certain
locales.

We cannot reverse compute a date(time) label with moment.js to get a range since
nothing guarantees that the range will be the same one that Babel used to
output it.

5. read_group return format discussion

Prior to this commit, the format of the value for the groupBy field was
either :

  - String : used as a display value for the group.
    Most notably, for date and datetime, this value cannot be used as a field
    value in most cases. It would be more practical to also return the date
    range along with the display value, so that Drag&Drop and QuickCreate
    functionalities can be properly enabled in views
    example :
      "March 2021" has the range ['&', (field, '>=', 2021-03-01),
        (field, '<', 2021-04-01)]
      This information is lost at the end of the read_group.

  - Array : used to indicate a res_id in case of a many2one field
    res_id = array[0]
    field_diplay_value = array[1]

Since we cannot use the array format to send the date(time)s of the period range
because it could be confused with the many2one format, this commit introduces
the use of a new `__range` key which is a dictionary with specific related
keys to be used to defer usable data to the web client.

Task-ID: 2243913
PR odoo/odoo#69380
2021-06-30 09:51:42 +00:00

64 lines
2.0 KiB
Python

# -*- coding: utf-8 -*-
from odoo.tests import common
class TestEmptyDate(common.TransactionCase):
""" Test what happens when grouping on date fields and getting a "false"
grouping value
"""
def setUp(self):
super(TestEmptyDate, self).setUp()
self.Model = self.env['test_read_group.on_date']
def test_empty_only(self):
self.Model.create({'value': 1})
self.Model.create({'value': 2})
self.Model.create({'value': 3})
gb = self.Model.read_group([], ['date', 'value'], ['date'], lazy=False)
self.assertEqual(gb, [{
'__count': 3,
'__domain': [('date', '=', False)],
'__range': {'date': False},
'date': False,
'value': 6
}])
def test_empty_by_span(self):
self.Model.create({'value': 1})
self.Model.create({'value': 2})
self.Model.create({'value': 3})
gb = self.Model.read_group([], ['date', 'value'], ['date:quarter'], lazy=False)
self.assertEqual(gb, [{
'__count': 3,
'__domain': [('date', '=', False)],
'__range': {'date': False},
'date:quarter': False,
'value': 6
}])
def test_mixed(self):
self.Model.create({'date': False, 'value': 1})
self.Model.create({'date': False, 'value': 2})
self.Model.create({'date': '1916-12-18', 'value': 3})
self.Model.create({'date': '1916-12-18', 'value': 4})
gb = self.Model.read_group([], ['date', 'value'], ['date'], lazy=False)
self.assertSequenceEqual(sorted(gb, key=lambda r: r['date'] or ''), [{
'__count': 2,
'__domain': [('date', '=', False)],
'__range': {'date': False},
'date': False,
'value': 3,
}, {
'__count': 2,
'__domain': ['&', ('date', '>=', '1916-12-01'), ('date', '<', '1917-01-01')],
'__range': {'date': {'from': '1916-12-01', 'to': '1917-01-01'}},
'date': 'December 1916',
'value': 7,
}])