[MERGE]:for read_group method in orm for group_by

bzr revid: nch@tinyerp.com-20100119084644-wxj2l6o2m3fd9hg1
This commit is contained in:
nch@tinyerp.com
2010-01-19 14:16:44 +05:30
+129 -25
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
@@ -212,7 +212,7 @@ class browse_record(object):
# create browse records for 'remote' objects
for data in datas:
if len(str(data['id']).split('-')) > 1:
data['id'] = int(str(data['id']).split('-')[0])
data['id'] = int(str(data['id']).split('-')[0])
for n, f in ffields:
if f._type in ('many2one', 'one2one'):
if data[n]:
@@ -348,6 +348,112 @@ class orm_template(object):
CONCURRENCY_CHECK_FIELD = '__last_update'
def read_group(self, cr, user, ids, fields, groupby, context=None):
context = context or {}
if not ids:return
if fields[groupby]['type'] not in ('many2one','date','datetime'):
raise Exception(_("Type Not supported for Group By: %s :Only many2one,date and datetime are supported ") %(fields[groupby]['type'],))
qu1 = ' where id in (' + ','.join([str(id) for id in ids]) + ')'
qu2 = ''
# construct a clause for the rules :
d1, d2, d3 = self.pool.get('ir.rule').domain_get(cr, user, self._name)
if d1:
qu1 = qu1 and qu1+' and '+d1 or ' where '+d1
qu2 += d2
float_int_fields = list(field_name for field_name,values in fields.items() if values['type'] in ('float','integer'))
sum = {}
cr.execute('select '+groupby+' from ' + self._table +qu1+' group by '+groupby+qu2)
parent_res = cr.fetchall()
try:
parent_res = [(m[0],m[1]) for m in parent_res if m[0]]
except:
parent_res = [(m[0],) for m in parent_res if m[0]]
groupby_ids = map(lambda x:x[0],parent_res)
groupby_name = {}
child_ids_dict = {}
if fields[groupby]['type'] == 'many2one':
groupby_name = dict(self.pool.get(fields[groupby]['relation']).name_get(cr,user,groupby_ids,context))
chqu1 =' where id in (' + ','.join([str(id) for id in ids]) + ') and '
# get child ids
for parent_id in groupby_ids:
cr.execute('select id from '+self._table+chqu1 +groupby+" = '%s'"%(parent_id,))
child_ids = cr.fetchall()
for val in child_ids:
if parent_id not in child_ids_dict:
child_ids_dict[parent_id] = [val[0]]
else:
child_ids_dict[parent_id].append(val[0])
#create [{},{}] for parent ids i.e for group by field
result = []
if fields[groupby]['type'] in ('date','datetime'):
curr_date = datetime.date.today()
yesterday = (curr_date - datetime.timedelta(days=1)).strftime('%Y-%m-%d')
lastweek = (curr_date + datetime.timedelta(weeks=-1)).strftime('%Y-%m-%d')
date_result = {'Today':{'group_child':[]},'Yesterday':{'group_child':[]},
'LastWeek':{'group_child':[]},'Old':{'group_child':[]}}
for x in parent_res:
db_date = x[0][:10]
if db_date == curr_date.strftime('%Y-%m-%d'):
date_format = 'Today'
elif db_date == yesterday:
date_format = 'Yesterday'
elif (db_date < yesterday) and (db_date >= lastweek):
date_format = 'LastWeek'
else:
date_format = 'Old'
date_result[date_format].update({'id':None,groupby:date_format})
date_result[date_format]['group_child'] += child_ids_dict[x[0]]
float_int_sum = self.read(cr, user, child_ids_dict[x[0]], float_int_fields, context)
for value in float_int_sum:
for field,val in value.items():
if field == 'id':continue
if field not in sum:
sum[field] = 0.0
sum[field] += val
for k,v in sum.items():
date_result[date_format][k] = v
sum = {}
for key,val in date_result.items():
if len(date_result[key]) == 1:
del date_result[key]
continue
for field in fields.keys():
if field not in val:
val[field] = False
if key in ('Today','Yesterday') and len(result):
result.insert(0,val)
else:
result.insert(-1,val)
return result
else:
for x in parent_res:
parent_val_dict = {'id':str(x[0])+':Gpby',groupby:(x[0],groupby_name[x[0]]),'group_child':child_ids_dict[x[0]]}
float_int_sum = self.read(cr, user, child_ids_dict[x[0]], float_int_fields, context)
for value in float_int_sum:
for field,val in value.items():
if field == 'id':continue
if field not in sum:
sum[field] = 0.0
sum[field] += val
for k,v in sum.items():
parent_val_dict[k] = v
sum = {}
for field in fields.keys():
if field not in parent_val_dict:
parent_val_dict[field] = False
result.append(parent_val_dict)
return result
def _field_create(self, cr, context={}):
cr.execute("SELECT id FROM ir_model WHERE model=%s", (self._name,))
if not cr.rowcount:
@@ -392,7 +498,7 @@ class orm_template(object):
#setting value to let the problem NOT occur next time
else:
vals['select_level'] = cols[k]['select_level']
if k not in cols:
cr.execute('select nextval(%s)', ('ir_model_fields_id_seq',))
id = cr.fetchone()[0]
@@ -473,7 +579,7 @@ class orm_template(object):
elif field_type == 'boolean':
return False
return ''
def selection_field(in_field):
col_obj = self.pool.get(in_field.keys()[0])
if f[i] in col_obj._columns.keys():
@@ -481,8 +587,8 @@ class orm_template(object):
elif f[i] in col_obj._inherits.keys():
selection_field(col_obj._inherits)
else:
return False
return False
lines = []
data = map(lambda x: '', range(len(fields)))
@@ -509,7 +615,7 @@ class orm_template(object):
else:
r = r[f[i]]
# To display external name of selection field when its exported
if not context.get('import_comp',False):# Allow external name only if its not import compatible
if not context.get('import_comp',False):# Allow external name only if its not import compatible
cols = False
if f[i] in self._columns.keys():
cols = self._columns[f[i]]
@@ -1138,7 +1244,7 @@ class orm_template(object):
# running -> done = signal_next (role Z)
# running -> cancel = signal_cancel (role Z)
# As we don't know the object state, in this scenario,
# As we don't know the object state, in this scenario,
# the button "signal_cancel" will be always shown as there is no restriction to cancel in draft
# the button "signal_next" will be show if the user has any of the roles (X Y or Z)
# The verification will be made later in workflow process...
@@ -1214,23 +1320,23 @@ class orm_template(object):
return arch
def __get_default_search_view(self, cr, uid, context={}):
def encode(s):
if isinstance(s, unicode):
return s.encode('utf8')
return s
view = self.fields_view_get(cr, uid, False, 'form', context)
root = etree.fromstring(encode(view['arch']))
res = etree.XML("<search string='%s'></search>" % root.get("string", ""))
node = etree.Element("group")
res.append(node)
fields = root.xpath("//field[@select=1]")
for field in fields:
node.append(field)
return etree.tostring(res, encoding="utf-8").replace('\t', '')
#
@@ -1354,7 +1460,7 @@ class orm_template(object):
if not sql_res:
break
ok = sql_res[5]
view_id = ok or sql_res[3]
model = False
@@ -1380,7 +1486,7 @@ class orm_template(object):
result['name'] = sql_res[1]
result['field_parent'] = sql_res[2] or False
else:
# otherwise, build some kind of default view
if view_type == 'form':
res = self.fields_get(cr, user, context=context)
@@ -1392,7 +1498,7 @@ class orm_template(object):
if res[x]['type'] == 'text':
xml += "<newline/>"
xml += "</form>"
elif view_type == 'tree':
_rec_name = self._rec_name
if _rec_name not in self._columns:
@@ -1400,13 +1506,13 @@ class orm_template(object):
xml = '<?xml version="1.0" encoding="utf-8"?>' \
'<tree string="%s"><field name="%s"/></tree>' \
% (self._description, self._rec_name)
elif view_type == 'calendar':
xml = self.__get_default_calendar_view()
elif view_type == 'search':
xml = self.__get_default_search_view(cr, user, context)
else:
xml = '<?xml version="1.0"?>' # what happens here, graph case?
raise except_orm(_('Invalid Architecture!'),_("There is no view of type '%s' defined for the structure!") % view_type)
@@ -1956,7 +2062,7 @@ class orm(orm_template):
cr.execute('ALTER TABLE "%s" RENAME "%s" TO "%s"' % ( self._table,f.oldname, k))
res = res_old
res[0]['attname'] = k
if not res:
if not isinstance(f, fields.function) or f.store:
@@ -2045,7 +2151,7 @@ class orm(orm_template):
field_size = (65535 * f.digits[0]) + f.digits[0] + f.digits[1]
if field_size != f_pg_size:
field_size_change = True
if f_pg_type != f_obj_type or field_size_change:
if f_pg_type != f_obj_type:
logger.notifyChannel('orm', netsvc.LOG_INFO, "column '%s' in table '%s' changed type to %s." % (k, self._table, c[1]))
@@ -2403,7 +2509,7 @@ class orm(orm_template):
return 'length("%s") as "%s"' % (f, f)
return '"%s"' % (f,)
fields_pre2 = map(convert_field, fields_pre)
order_by = self._parent_order or self._order
order_by = self._parent_order or self._order
for i in range(0, len(ids), cr.IN_MAX):
sub_ids = ids[i:i+cr.IN_MAX]
if d1:
@@ -2415,7 +2521,7 @@ class orm(orm_template):
_('You try to bypass an access rule while reading (Document type: %s).') % self._description)
else:
cr.execute('SELECT %s FROM \"%s\" WHERE id = ANY (%%s) ORDER BY %s' %
(','.join(fields_pre2 + ['id']), self._table,
(','.join(fields_pre2 + ['id']), self._table,
order_by), (sub_ids,))
res.extend(cr.dictfetchall())
else:
@@ -3194,8 +3300,6 @@ class orm(orm_template):
','.join(tables) +qu1 + limit_str + offset_str, qu2)
res = cr.fetchall()
return res[0][0]
# execute the "main" query to fetch the ids we were searching for
cr.execute('select %s.id from ' % self._table + ','.join(tables) +qu1+' order by '+order_by+limit_str+offset_str, qu2)
res = cr.fetchall()
return [x[0] for x in res]