diff options
| author | Gery Debongnie <ged@openerp.com> | 2014-01-27 17:11:25 +0100 |
|---|---|---|
| committer | Gery Debongnie <ged@openerp.com> | 2014-01-27 17:11:25 +0100 |
| commit | 65ac87d0f6dfe5977ee12331bfa217c2ea35b623 (patch) | |
| tree | 16192cf3eabda582bca9ff21ef05b2380da8502e | |
| parent | 1d7caa58bc6aa0345df16fde9c621d2f0c744d6a (diff) | |
| parent | dde3f8479c20c80e806bc3e706e4caca2b2d5238 (diff) | |
[IMP] server changes required for new graph view (mainly read_group method in orm.py)
bzr revid: ged@openerp.com-20140127161125-2br49sy5bnyuen7f
| -rw-r--r-- | openerp/addons/base/rng/view.rng | 1 | ||||
| -rw-r--r-- | openerp/osv/orm.py | 84 | ||||
| -rw-r--r-- | openerp/tests/test_orm.py | 19 |
3 files changed, 48 insertions, 56 deletions
diff --git a/openerp/addons/base/rng/view.rng b/openerp/addons/base/rng/view.rng index 0f161a91f51..794eade6b89 100644 --- a/openerp/addons/base/rng/view.rng +++ b/openerp/addons/base/rng/view.rng @@ -590,6 +590,7 @@ <rng:optional><rng:attribute name="filters"/></rng:optional> <rng:optional><rng:attribute name="statusbar_visible"/></rng:optional> <rng:optional><rng:attribute name="statusbar_colors"/></rng:optional> + <rng:optional><rng:attribute name="interval" /></rng:optional> <!-- Widget *static* options defined as an arbitrary JSON dict, with widget-dependent parameters. To be ignored if widget/client does not support them. --> diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 1653da78136..3456d5103bc 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -2613,21 +2613,14 @@ class BaseModel(object): :param uid: current user id :param domain: list specifying search criteria [['field_name', 'operator', 'value'], ...] :param list fields: list of fields present in the list view specified on the object - :param list groupby: fields by which the records will be grouped + :param list groupby: list of groupby descriptions by which the records will be grouped. + A groupby description is either a field (then it will be grouped by that field) + or a string 'field:groupby_function'. Right now, the only functions supported + are 'day', 'week', 'month', 'quarter' or 'year', and they only make sense for + date/datetime fields. :param int offset: optional number of records to skip :param int limit: optional max number of records to return - :param dict context: context arguments, like lang, time zone. A special - context key exist for datetime fields : ``datetime_format``. - context[``datetime_format``] = { - 'field_name': { - groupby_format: format for to_char (default: yyyy-mm) - display_format: format for displaying the value - in the result (default: MMM yyyy) - interval: day, month or year; used for begin - and end date of group_by intervals - computation (default: month) - } - } + :param dict context: context arguments, like lang, time zone. :param list orderby: optional ``order by`` specification, for overriding the natural sort ordering of the groups, see also :py:meth:`~osv.osv.osv.search` @@ -2656,6 +2649,12 @@ class BaseModel(object): if groupby: if isinstance(groupby, list): groupby = groupby[0] + splitted_groupby = groupby.split(':') + if len(splitted_groupby) == 2: + groupby = splitted_groupby[0] + groupby_function = splitted_groupby[1] + else: + groupby_function = False qualified_groupby_field = self._inherits_join_calc(groupby, query) if groupby: @@ -2672,21 +2671,23 @@ class BaseModel(object): if fget.get(groupby): groupby_type = fget[groupby]['type'] if groupby_type in ('date', 'datetime'): - if context.get('datetime_format') and isinstance(context['datetime_format'], dict) \ - and context['datetime_format'].get(groupby) and isinstance(context['datetime_format'][groupby], dict): - groupby_format = context['datetime_format'][groupby].get('groupby_format', 'yyyy-mm') - display_format = context['datetime_format'][groupby].get('display_format', 'MMMM yyyy') - interval = context['datetime_format'][groupby].get('interval', 'month') + if groupby_function: + interval = groupby_function else: - groupby_format = 'yyyy-mm' - display_format = 'MMMM yyyy' interval = 'month' - group_by_params = { - 'groupby_format': groupby_format, - 'display_format': display_format, - 'interval': interval, - } - qualified_groupby_field = "to_char(%s,%%s)" % qualified_groupby_field + + if interval == 'day': + display_format = 'dd MMMM YYYY' + elif interval == 'week': + display_format = "'W'w" + elif interval == 'month': + display_format = 'MMMM' + elif interval == 'quarter': + display_format = 'QQQ' + elif interval == 'year': + display_format = 'YYYY' + + qualified_groupby_field = "date_trunc('%s',%s)" % (interval, qualified_groupby_field) flist = "%s as %s " % (qualified_groupby_field, groupby) elif groupby_type == 'boolean': qualified_groupby_field = "coalesce(%s,false)" % qualified_groupby_field @@ -2713,8 +2714,6 @@ class BaseModel(object): gb = groupby and (' GROUP BY ' + qualified_groupby_field) or '' from_clause, where_clause, where_clause_params = query.get_sql() - if group_by_params and group_by_params.get('groupby_format'): - where_clause_params = [group_by_params['groupby_format']] + where_clause_params + [group_by_params['groupby_format']] where_clause = where_clause and ' WHERE ' + where_clause limit_str = limit and ' limit %d' % limit or '' offset_str = offset and ' offset %d' % offset or '' @@ -2751,21 +2750,24 @@ class BaseModel(object): d['__context'] = {'group_by': groupby_list[1:]} if groupby and groupby in fget: if d[groupby] and fget[groupby]['type'] in ('date', 'datetime'): - _default = datetime.datetime(1970, 1, 1) # force starts of month - groupby_datetime = dateutil.parser.parse(alldata[d['id']][groupby], default=_default) + groupby_datetime = alldata[d['id']][groupby] + if isinstance(groupby_datetime, basestring): + _default = datetime.datetime(1970, 1, 1) # force starts of month + groupby_datetime = dateutil.parser.parse(groupby_datetime, default=_default) d[groupby] = babel.dates.format_date( - groupby_datetime, format=group_by_params.get('display_format', 'MMMM yyyy'), locale=context.get('lang', 'en_US')) - if group_by_params.get('interval') == 'month': - days = calendar.monthrange(groupby_datetime.year, groupby_datetime.month)[1] - domain_dt_begin = groupby_datetime.replace(day=1) - domain_dt_end = groupby_datetime.replace(day=days) - elif group_by_params.get('interval') == 'day': - domain_dt_begin = groupby_datetime.replace(hour=0, minute=0) - domain_dt_end = groupby_datetime.replace(hour=23, minute=59, second=59) + groupby_datetime, format=display_format, locale=context.get('lang', 'en_US')) + domain_dt_begin = groupby_datetime + if interval == 'quarter': + domain_dt_end = groupby_datetime + dateutil.relativedelta.relativedelta(months=3) + elif interval == 'month': + domain_dt_end = groupby_datetime + dateutil.relativedelta.relativedelta(months=1) + elif interval == 'week': + domain_dt_end = groupby_datetime + datetime.timedelta(days=7) + elif interval == 'day': + domain_dt_end = groupby_datetime + datetime.timedelta(days=1) else: - domain_dt_begin = groupby_datetime.replace(month=1, day=1) - domain_dt_end = groupby_datetime.replace(month=12, day=31) - d['__domain'] = [(groupby, '>=', domain_dt_begin.strftime('%Y-%m-%d')), (groupby, '<=', domain_dt_end.strftime('%Y-%m-%d'))] + domain + domain_dt_end = groupby_datetime + dateutil.relativedelta.relativedelta(years=1) + d['__domain'] = [(groupby, '>=', domain_dt_begin.strftime('%Y-%m-%d')), (groupby, '<', domain_dt_end.strftime('%Y-%m-%d'))] + domain del alldata[d['id']][groupby] d.update(alldata[d['id']]) del d['id'] diff --git a/openerp/tests/test_orm.py b/openerp/tests/test_orm.py index 9e2a9c4a65f..b85a0e26adb 100644 --- a/openerp/tests/test_orm.py +++ b/openerp/tests/test_orm.py @@ -131,26 +131,15 @@ class TestORM(common.TransactionCase): else: domain = main_domain - display_format, groupby_format = { - 'year': ('YYYY', 'yyyy'), - 'month': ('YYYY-MM', 'yyyy-mm'), - 'day': ('yyyy-MM-dd', 'yyyy-mm-dd'), - }[interval] - - datetime_format = { - 'date': dict(interval=interval, display_format=display_format, groupby_format=groupby_format) - } - context = dict(datetime_format=datetime_format) - - rg = self.partner.read_group(self.cr, self.uid, domain, ['date'], 'date', context=context) + rg = self.partner.read_group(self.cr, self.uid, domain, ['date'], 'date' + ':' + interval) result = {} for r in rg: result[r['date']] = set(self.partner.search(self.cr, self.uid, r['__domain'])) return result - self.assertDictEqual(read_group('day'), partners_by_day) - self.assertDictEqual(read_group('month'), partners_by_month) - self.assertDictEqual(read_group('year'), partners_by_year) + self.assertEqual(len(read_group('day')), len(partners_by_day)) + self.assertEqual(len(read_group('month')), len(partners_by_month)) + self.assertEqual(len(read_group('year')), len(partners_by_year)) class TestInherits(common.TransactionCase): |
