From d1e7ad9be6f01644567df0fb8d0e68e6c40aff5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 6 Aug 2013 17:10:18 +0200 Subject: [PATCH 1/5] [IMP] tools: added a regex for bounce email addresses bzr revid: tde@openerp.com-20130806151018-0uom07dbr8b7ycb3 --- openerp/tools/mail.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openerp/tools/mail.py b/openerp/tools/mail.py index 5970ce47040..36a4c1610c4 100644 --- a/openerp/tools/mail.py +++ b/openerp/tools/mail.py @@ -297,6 +297,11 @@ command_re = re.compile("^Set-([a-z]+) *: *(.+)$", re.I + re.UNICODE) # group(1) = the record ID ; group(2) = the model (if any) ; group(3) = the domain reference_re = re.compile("<.*-open(?:object|erp)-(\\d+)(?:-([\w.]+))?.*@(.*)>", re.UNICODE) +# Bounce regex +# Typical form of bounce is bounce-128-crm.lead-34@domain +# group(1) = the mail ID; group(2) = the model (if any); group(3) = the record ID +bounce_re = re.compile("[\w]+-(\d+)-?([\w.]+)?-?(\d+)?", re.UNICODE) + def generate_tracking_message_id(res_id): """Returns a string that can be used in the Message-ID RFC822 header field From aca5e7606209cd3382c07f1a4aeedce3960650a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 10 Sep 2013 12:45:00 +0200 Subject: [PATCH 2/5] [IMP] orm: first draft of improvign group_by on date field, allowing to tune the grain, format and interval when grouping on a date field. Default behavior is the old one, grouping on month. bzr revid: tde@openerp.com-20130910104500-sfjosqkmpfxa2jxk --- openerp/osv/orm.py | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 51b0c2b56b9..f081e11b9e2 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -2641,11 +2641,26 @@ class BaseModel(object): fget = self.fields_get(cr, uid, fields) flist = '' group_count = group_by = groupby + group_by_params = {} if groupby: if fget.get(groupby): groupby_type = fget[groupby]['type'] if groupby_type in ('date', 'datetime'): - qualified_groupby_field = "to_char(%s,'yyyy-mm')" % qualified_groupby_field + 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') + 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 flist = "%s as %s " % (qualified_groupby_field, groupby) elif groupby_type == 'boolean': qualified_groupby_field = "coalesce(%s,false)" % qualified_groupby_field @@ -2672,6 +2687,8 @@ 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 '' @@ -2708,14 +2725,17 @@ 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'): - dt = datetime.datetime.strptime(alldata[d['id']][groupby][:7], '%Y-%m') - days = calendar.monthrange(dt.year, dt.month)[1] - - date_value = datetime.datetime.strptime(d[groupby][:10], '%Y-%m-%d') + groupby_datetime = datetime.datetime.strptime(alldata[d['id']][groupby], '%Y-%m-%d') d[groupby] = babel.dates.format_date( - date_value, format='MMMM yyyy', locale=context.get('lang', 'en_US')) - d['__domain'] = [(groupby, '>=', alldata[d['id']][groupby] and datetime.datetime.strptime(alldata[d['id']][groupby][:7] + '-01', '%Y-%m-%d').strftime('%Y-%m-%d') or False),\ - (groupby, '<=', alldata[d['id']][groupby] and datetime.datetime.strptime(alldata[d['id']][groupby][:7] + '-' + str(days), '%Y-%m-%d').strftime('%Y-%m-%d') or False)] + domain + groupby_datetime, format=group_by_params.get('display_format', 'MMMM yyyy'), locale=context.get('lang', 'en_US')) + if 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) + else: + 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) + d['__domain'] = [(group_by, '>=', domain_dt_begin.strftime('%Y-%m-%d')), (group_by, '<=', domain_dt_end.strftime('%Y-%m-%d'))] + domain del alldata[d['id']][groupby] d.update(alldata[d['id']]) del d['id'] From defa3adbe898bfb10f497ae5c6cae7981bfa63c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 16 Sep 2013 12:30:47 +0200 Subject: [PATCH 3/5] [DOC] read_group: added comments for the new formatting option bzr revid: tde@openerp.com-20130916103047-lpbf7czflyvgtonu --- doc/changelog.rst | 2 ++ openerp/osv/orm.py | 13 ++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/doc/changelog.rst b/doc/changelog.rst index eadfe81b5e8..46f84364c76 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -6,6 +6,8 @@ Changelog `trunk` ------- +- Added support of custom group_by format and display format when using group_by + on a datetime field, using datetime_format context key - Improved ``html_email_clean`` in tools: better quote and signature finding, added shortening. - Cleaned and slightly refactored ``ir.actions.server``. The ``loop``, ``sms`` diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index f081e11b9e2..25ed8bdf861 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -2601,7 +2601,18 @@ class BaseModel(object): :param list groupby: fields by which the records will be grouped :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 + :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 list orderby: optional ``order by`` specification, for overriding the natural sort ordering of the groups, see also :py:meth:`~osv.osv.osv.search` From 63988959a7750b03096e95a6cd36ce731fbdb445 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 16 Sep 2013 13:47:22 +0200 Subject: [PATCH 4/5] [IMP] read_group: added forgottent year computation bzr revid: tde@openerp.com-20130916114722-4742fhn4ilhf133e --- openerp/osv/orm.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 25ed8bdf861..764279bc45e 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -2739,13 +2739,16 @@ class BaseModel(object): groupby_datetime = datetime.datetime.strptime(alldata[d['id']][groupby], '%Y-%m-%d') 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') == 'day': - domain_dt_begin = groupby_datetime.replace(hour=0, minute=0) - domain_dt_end = groupby_datetime.replace(hour=23, minute=59, second=59) - else: + 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) + else: + domain_dt_begin = groupby_datetime.replace(month=1, day=1) + domain_dt_end = groupby_datetime.replace(month=12, day=31) d['__domain'] = [(group_by, '>=', domain_dt_begin.strftime('%Y-%m-%d')), (group_by, '<=', domain_dt_end.strftime('%Y-%m-%d'))] + domain del alldata[d['id']][groupby] d.update(alldata[d['id']]) From 54c014c4eab26feddfd0ccbc053a50fc810cb3f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 17 Sep 2013 12:04:47 +0200 Subject: [PATCH 5/5] [IMP] read_group: group_by -> groupby (same variable, but was used in previous implementation, so I keep it) bzr revid: tde@openerp.com-20130917100447-u0qhdsw14wdngxwc --- openerp/osv/orm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 764279bc45e..2fd31a8b80d 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -2749,7 +2749,7 @@ class BaseModel(object): else: domain_dt_begin = groupby_datetime.replace(month=1, day=1) domain_dt_end = groupby_datetime.replace(month=12, day=31) - d['__domain'] = [(group_by, '>=', domain_dt_begin.strftime('%Y-%m-%d')), (group_by, '<=', domain_dt_end.strftime('%Y-%m-%d'))] + domain + 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']