diff --git a/addons/base_calendar/base_calendar.py b/addons/base_calendar/base_calendar.py index 11bd22e6134..facb598427b 100644 --- a/addons/base_calendar/base_calendar.py +++ b/addons/base_calendar/base_calendar.py @@ -398,10 +398,13 @@ property or property parameter."), """ res = None def ics_datetime(idate, short=False): - if short: - return date.fromtimestamp(time.mktime(time.strptime(idate, '%Y-%m-%d'))) + if idate: + if short: + return date.fromtimestamp(time.mktime(time.strptime(idate, '%Y-%m-%d'))) + else: + return datetime.strptime(idate, '%Y-%m-%d %H:%M:%S') else: - return datetime.strptime(idate, '%Y-%m-%d %H:%M:%S') + return False try: # FIXME: why isn't this in CalDAV? import vobject @@ -482,35 +485,37 @@ property or property parameter."), sign = att.sent_by_uid and att.sent_by_uid.signature or '' sign = '
'.join(sign and sign.split('\n') or []) res_obj = att.ref - sub = res_obj.name - att_infos = [] - other_invitaion_ids = self.search(cr, uid, [('ref', '=', res_obj._name + ',' + str(res_obj.id))]) - for att2 in self.browse(cr, uid, other_invitaion_ids): - att_infos.append(((att2.user_id and att2.user_id.name) or \ - (att2.partner_id and att2.partner_id.name) or \ - att2.email) + ' - Status: ' + att2.state.title()) - body_vals = {'name': res_obj.name, - 'start_date': res_obj.date, - 'end_date': res_obj.date_deadline or False, - 'description': res_obj.description or '-', - 'location': res_obj.location or '-', - 'attendees': '
'.join(att_infos), - 'user': res_obj.user_id and res_obj.user_id.name or 'OpenERP User', - 'sign': sign, - 'company': company - } - body = html_invitation % body_vals - if mail_to and email_from: - attach = self.get_ics_file(cr, uid, res_obj, context=context) - tools.email_send( - email_from, - mail_to, - sub, - body, - attach=attach and [('invitation.ics', attach)] or None, - subtype='html', - reply_to=email_from - ) + if res_obj: + att_infos = [] + sub = res_obj.name + other_invitation_ids = self.search(cr, uid, [('ref', '=', res_obj._name + ',' + str(res_obj.id))]) + + for att2 in self.browse(cr, uid, other_invitation_ids): + att_infos.append(((att2.user_id and att2.user_id.name) or \ + (att2.partner_id and att2.partner_id.name) or \ + att2.email) + ' - Status: ' + att2.state.title()) + body_vals = {'name': res_obj.name, + 'start_date': res_obj.date, + 'end_date': res_obj.date_deadline or False, + 'description': res_obj.description or '-', + 'location': res_obj.location or '-', + 'attendees': '
'.join(att_infos), + 'user': res_obj.user_id and res_obj.user_id.name or 'OpenERP User', + 'sign': sign, + 'company': company + } + body = html_invitation % body_vals + if mail_to and email_from: + attach = self.get_ics_file(cr, uid, res_obj, context=context) + tools.email_send( + email_from, + mail_to, + sub, + body, + attach=attach and [('invitation.ics', attach)] or None, + subtype='html', + reply_to=email_from + ) return True def onchange_user_id(self, cr, uid, ids, user_id, *args, **argv): diff --git a/addons/base_calendar/wizard/base_calendar_invite_attendee.py b/addons/base_calendar/wizard/base_calendar_invite_attendee.py index f60139c0600..98369962ab7 100644 --- a/addons/base_calendar/wizard/base_calendar_invite_attendee.py +++ b/addons/base_calendar/wizard/base_calendar_invite_attendee.py @@ -128,8 +128,9 @@ send an Email to Invited Person') att = att_obj.browse(cr, uid, context_id) att_val.update({ 'parent_ids': [(4, att.id)], - 'ref': att.ref._name + ',' +str(att.ref.id) + 'ref': att.ref and (att.ref._name + ',' +str(att.ref.id)) or False }) + attendees.append(att_obj.create(cr, uid, att_val)) if model_field: for attendee in attendees: diff --git a/addons/crm/report/report_businessopp.py b/addons/crm/report/report_businessopp.py index 7cadb41359a..07751622abe 100644 --- a/addons/crm/report/report_businessopp.py +++ b/addons/crm/report/report_businessopp.py @@ -83,12 +83,12 @@ class report_custom(report_int): if benefit < minbenef: minbenef = benefit - tuple = (proba * 100, benefit) + tuple_benefit = (proba * 100, benefit) responsible_data.setdefault(userid, []) - responsible_data[userid].append(tuple) + responsible_data[userid].append(tuple_benefit) - tuple = (proba * 100, cost, benefit) - data.append(tuple) + tuple_benefit = (proba * 100, cost, benefit) + data.append(tuple_benefit) responsible_names[userid] = (row['name'] or '/').replace('/','//') diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py index 4915ac7fc01..5ad90bf25d6 100644 --- a/addons/mrp/mrp.py +++ b/addons/mrp/mrp.py @@ -19,8 +19,8 @@ # ############################################################################## -import itertools -import operator +from itertools import groupby +from operator import itemgetter from datetime import datetime from osv import osv, fields from tools.translate import _ @@ -355,13 +355,16 @@ class many2many_domain(fields.many2many): def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None): if not context: context = {} - res = {} + move_obj = obj.pool.get('stock.move') - for prod in obj.browse(cr, user, ids, context=context): - cr.execute("SELECT move_id from mrp_production_move_ids where production_id=%s" % (prod.id)) - m_ids = map(lambda x: x[0], cr.fetchall()) - final = move_obj.search(cr, user, self._domain + [('id', 'in', tuple(m_ids))]) - res[prod.id] = final + res = {}.fromkeys(ids, []) + valid_move_ids = move_obj.search(cr, user, self._domain) # move ids relative to domain argument + cr.execute("SELECT production_id, move_id from mrp_production_move_ids where production_id in %s and move_id in %s", + [tuple(ids), tuple(valid_move_ids)]) + related_move_map = cr.fetchall() + related_move_dict = dict((k, list(set([v[1] for v in itr]))) for k, itr in groupby(related_move_map, itemgetter(0))) + res.update(related_move_dict) + return res class one2many_domain(fields.one2many): @@ -377,8 +380,7 @@ class one2many_domain(fields.one2many): res = {}.fromkeys(ids, []) key = operator.itemgetter(0) move_ids = move_obj.search(cr, user, self._domain+[('production_id', 'in', tuple(ids))], context=context) - related_move_map = [(o.production_id.id, o.id) for o in move_obj.browse(cr, user, move_ids, context=context)] - related_move_dict = dict((k, [v[1] for v in itr]) for k, itr in itertools.groupby(related_move_map, key)) + related_move_dict = dict([(o.production_id.id, [o.id]) for o in move_obj.browse(cr, user, move_ids, context=context)]) res.update(related_move_dict) return res diff --git a/addons/project/project.py b/addons/project/project.py index 0b9584655a8..6959a19fd03 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -22,12 +22,14 @@ from lxml import etree import time from datetime import datetime, date +from operator import itemgetter +from itertools import groupby +from tools.misc import flatten from tools.translate import _ from osv import fields, osv from tools import email_send as email -from operator import itemgetter class project_task_type(osv.osv): _name = 'project.task.type' @@ -77,20 +79,6 @@ class project(osv.osv): pricelist_id = pricelist.get('property_product_pricelist', False) and pricelist.get('property_product_pricelist')[0] or False return {'value':{'contact_id': addr['contact'], 'pricelist_id': pricelist_id}} - def get_all_child_projects(self, cr, uid, ids, context=None): - # Calculate child project for Given project id => For progress rate + planned time + Time spent - cr.execute('''SELECT prpc.id AS id from account_analytic_account AS p - JOIN account_analytic_account AS c ON p.id = c.parent_id - JOIN project_project AS prp ON prp.analytic_account_id = p.id - JOIN project_project AS prpc ON prpc.analytic_account_id = c.id - WHERE prp.id IN %s''',(tuple(ids),)) - - child_ids = cr.fetchall() - if child_ids: - child_ids = [x[0] for x in child_ids] - child_ids = self.get_all_child_projects(cr, uid, child_ids) - return ids + child_ids - def _get_user_and_default_uom_ids(self, cr, uid): users_obj = self.pool.get('res.users') model_data_obj = self.pool.get('ir.model.data') @@ -102,17 +90,33 @@ class project(osv.osv): return user_uom, default_uom def _progress_rate(self, cr, uid, ids, names, arg, context=None): + def _get_all_child_projects(ids): + """Recursively get child project ids""" + child_ids = flatten([project_hierarchy.get(idn, []) for idn in ids]) + if child_ids: + child_ids = _get_all_child_projects(child_ids) + return ids + child_ids + # END _get_all_child_projects + res = {}.fromkeys(ids, 0.0) progress = {} if not ids: return res - par_child_projects={} + par_child_projects = {} all_projects = list(ids) + # get project hierarchy: + cr.execute('''SELECT prp.id AS pr_parent_id, prpc.id AS pr_child_id + FROM account_analytic_account AS p + JOIN account_analytic_account AS c ON p.id = c.parent_id + JOIN project_project AS prp ON prp.analytic_account_id = p.id + JOIN project_project AS prpc ON prpc.analytic_account_id = c.id''') + + project_hierarchy = dict((k, list(set([v[1] for v in itr]))) for k, itr in groupby(cr.fetchall(), itemgetter(0))) + for id in ids: - child_projects = self.get_all_child_projects(cr, uid, [id], context) - child_projects = [x for x in child_projects] + child_projects = _get_all_child_projects([id]) par_child_projects[id] = child_projects all_projects.extend(child_projects) @@ -128,6 +132,7 @@ class project(osv.osv): project_id''',(tuple(all_projects),)) progress = dict(map(lambda x: (x[0], (x[1], x[2], x[3])), cr.fetchall())) + user_uom, def_uom = self._get_user_and_default_uom_ids(cr, uid) for project in self.browse(cr, uid, par_child_projects.keys(), context=context): s = [0.0, 0.0, 0.0] tocompute = par_child_projects[project.id] @@ -137,7 +142,6 @@ class project(osv.osv): s[i] += progress.get(p, (0.0, 0.0, 0.0))[i] uom_obj = self.pool.get('product.uom') - user_uom, def_uom = self._get_user_and_default_uom_ids(cr, uid) if user_uom != def_uom: s[0] = uom_obj._compute_qty(cr, uid, user_uom, s[0], def_uom) s[1] = uom_obj._compute_qty(cr, uid, user_uom, s[1], def_uom) @@ -426,7 +430,7 @@ class task(osv.osv): 'parent_ids': fields.many2many('project.task', 'project_task_parent_rel', 'task_id', 'parent_id', 'Parent Tasks'), 'child_ids': fields.many2many('project.task', 'project_task_parent_rel', 'parent_id', 'task_id', 'Delegated Tasks'), 'notes': fields.text('Notes'), - 'planned_hours': fields.float('Planned Hours', required=True, help='Estimated time to do the task, usually set by the project manager when the task is in draft state.'), + 'planned_hours': fields.float('Planned Hours', help='Estimated time to do the task, usually set by the project manager when the task is in draft state.'), 'effective_hours': fields.function(_hours_get, method=True, string='Hours Spent', multi='hours', store=True, help="Computed using the sum of the task work done."), 'remaining_hours': fields.float('Remaining Hours', digits=(16,2), help="Total remaining time, can be re-estimated periodically by the assignee of the task."), 'total_hours': fields.function(_hours_get, method=True, string='Total Hours', multi='hours', store=True, help="Computed as: Time Spent + Remaining Time."), @@ -466,7 +470,7 @@ class task(osv.osv): cr.execute('SELECT DISTINCT task_id '\ 'FROM project_task_parent_rel '\ 'WHERE parent_id IN %s', (tuple(ids),)) - child_ids = map(itemgetter(0), cr.fetchall()) + child_ids = map(lambda x: x[0], cr.fetchall()) c_ids = child_ids if (list(set(parent_ids).intersection(set(c_ids)))) or (obj_task.id in c_ids): return False