From 6b7ccc16b7883367ef4810a823ba66b85e725b06 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Mon, 28 Oct 2013 14:50:50 +0100 Subject: [PATCH 01/77] [FIX] mail: mail_message: avoid crash when checking access rules against invalid ids bzr revid: chs@openerp.com-20131028135050-4hqx129ouy7z5b03 --- addons/mail/mail_message.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 3719dbc1c63..de8e4c68fda 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -212,7 +212,7 @@ class mail_message(osv.Model): _defaults = { 'type': 'email', - 'date': fields.datetime.now(), + 'date': fields.datetime.now, 'author_id': lambda self, cr, uid, ctx=None: self._get_default_author(cr, uid, ctx), 'body': '', 'email_from': lambda self, cr, uid, ctx=None: self._get_default_from(cr, uid, ctx), @@ -698,8 +698,9 @@ class mail_message(osv.Model): """ model_record_ids = {} for id in msg_ids: - if msg_val[id]['model'] and msg_val[id]['res_id']: - model_record_ids.setdefault(msg_val[id]['model'], dict()).setdefault(msg_val[id]['res_id'], set()).add(msg_val[id]['res_id']) + vals = msg_val.get(id, {}) + if vals.get('model') and vals.get('res_id'): + model_record_ids.setdefault(vals['model'], set()).add(vals['res_id']) return model_record_ids if uid == SUPERUSER_ID: @@ -711,7 +712,7 @@ class mail_message(osv.Model): partner_id = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=None).partner_id.id # Read mail_message.ids to have their values - message_values = dict.fromkeys(ids) + message_values = dict.fromkeys(ids, {}) cr.execute('SELECT DISTINCT id, model, res_id, author_id, parent_id FROM "%s" WHERE id = ANY (%%s)' % self._table, (ids,)) for id, rmod, rid, author_id, parent_id in cr.fetchall(): message_values[id] = {'model': rmod, 'res_id': rid, 'author_id': author_id, 'parent_id': parent_id} @@ -745,10 +746,10 @@ class mail_message(osv.Model): ], context=context) notified_ids = [notification.message_id.id for notification in not_obj.browse(cr, SUPERUSER_ID, not_ids, context=context)] elif operation == 'create': - for doc_model, doc_dict in model_record_ids.items(): + for doc_model, doc_ids in model_record_ids.items(): fol_ids = fol_obj.search(cr, SUPERUSER_ID, [ ('res_model', '=', doc_model), - ('res_id', 'in', list(doc_dict.keys())), + ('res_id', 'in', list(doc_ids)), ('partner_id', '=', partner_id), ], context=context) fol_mids = [follower.res_id for follower in fol_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context)] @@ -759,9 +760,9 @@ class mail_message(osv.Model): other_ids = other_ids.difference(set(notified_ids)) model_record_ids = _generate_model_record_ids(message_values, other_ids) document_related_ids = [] - for model, doc_dict in model_record_ids.items(): + for model, doc_ids in model_record_ids.items(): model_obj = self.pool[model] - mids = model_obj.exists(cr, uid, doc_dict.keys()) + mids = model_obj.exists(cr, uid, list(doc_ids)) if hasattr(model_obj, 'check_mail_message_access'): model_obj.check_mail_message_access(cr, uid, mids, operation, context=context) else: From 12690a7cfec84d3314eaf2f2aedcfc1154b3c971 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Mon, 28 Oct 2013 15:57:12 +0100 Subject: [PATCH 02/77] [FIX] project_issue: correct issue escalation bzr revid: chs@openerp.com-20131028145712-a6egn04g1g2va5cs --- addons/project_issue/project_issue.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py index 351b55fdcfc..cf0f79e18a5 100644 --- a/addons/project_issue/project_issue.py +++ b/addons/project_issue/project_issue.py @@ -465,18 +465,20 @@ class project_issue(osv.Model): return stage_ids[0] return False - def case_escalate(self, cr, uid, ids, context=None): - cases = self.browse(cr, uid, ids) - for case in cases: + def case_escalate(self, cr, uid, ids, context=None): # FIXME rename this method to issue_escalate + for issue in self.browse(cr, uid, ids, context=context): data = {} - if case.project_id.project_escalation_id: - data['project_id'] = case.project_id.project_escalation_id.id - if case.project_id.project_escalation_id.user_id: - data['user_id'] = case.project_id.project_escalation_id.user_id.id - if case.task_id: - self.pool.get('project.task').write(cr, uid, [case.task_id.id], {'project_id': data['project_id'], 'user_id': False}) - else: + esc_proj = issue.project_id.project_escalation_id + if not esc_proj: raise osv.except_osv(_('Warning!'), _('You cannot escalate this issue.\nThe relevant Project has not configured the Escalation Project!')) + + data['project_id'] = esc_proj.id + if esc_proj.user_id: + data['user_id'] = esc_proj.user_id.id + issue.write(data) + + if issue.task_id: + issue.task_id.write({'project_id': esc_proj.id, 'user_id': False}) return True # ------------------------------------------------------- From 06a3255576922aac31f52b916fff9e8416a3bfce Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Mon, 28 Oct 2013 16:56:00 +0100 Subject: [PATCH 03/77] [IMP] res_partner: default search field can be based on display_name + have email matching by default This more closely matches the behavior of name_search, until name_search is actually available in search views. bzr revid: odo@openerp.com-20131028155600-1dwd35sjht2of63m --- openerp/addons/base/res/res_partner_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/addons/base/res/res_partner_view.xml b/openerp/addons/base/res/res_partner_view.xml index f02021313c0..943aedf49f7 100644 --- a/openerp/addons/base/res/res_partner_view.xml +++ b/openerp/addons/base/res/res_partner_view.xml @@ -329,7 +329,7 @@ + filter_domain="['|','|',('display_name','ilike',self),('ref','=',self),('email,'ilike',self)]"/> From 5db5d655d6f2abf2220bad5db09ecf5f02c7dee0 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Mon, 28 Oct 2013 16:56:39 +0100 Subject: [PATCH 04/77] [IMP] res.users: default search field should match emails too bzr revid: odo@openerp.com-20131028155639-it1q12xt5iul1oac --- openerp/addons/base/res/res_users_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/addons/base/res/res_users_view.xml b/openerp/addons/base/res/res_users_view.xml index 770cb45149b..a5f988428e9 100644 --- a/openerp/addons/base/res/res_users_view.xml +++ b/openerp/addons/base/res/res_users_view.xml @@ -196,7 +196,7 @@ res.users - + From d1d35b3f573a2f0407abed51b1d8f2b689b745d7 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Mon, 28 Oct 2013 17:01:00 +0100 Subject: [PATCH 05/77] [FIX] mail.thread: message_redirect_action should not crash when the message has been deleted bzr revid: odo@openerp.com-20131028160100-yhebao3adbzz00cn --- addons/mail/mail_thread.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 9692b94f159..9ed63ae14fa 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -577,7 +577,8 @@ class mail_thread(osv.AbstractModel): return action if msg_id and not (model and res_id): msg = self.pool.get('mail.message').browse(cr, uid, msg_id, context=context) - model, res_id = msg.model, msg.res_id + if msg.exists(): + model, res_id = msg.model, msg.res_id # if model + res_id found: try to redirect to the document or fallback on the Inbox if model and res_id: From abe6df638d3fa79e62ff50f16435b6ad35c6a370 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Tue, 29 Oct 2013 09:53:56 +0100 Subject: [PATCH 06/77] [FIX] Reverted modification of behavior in 3858 and replaced it with a fix that solves the core problem (the fact that the function redirect_with_hash() didn't produced the expected effect in safari). To solve that problem, the method was simply modified to use the same trick already used in IE that has the same problem than safari. bzr revid: nicolas.vanhoren@openerp.com-20131029085356-hb2sk4g7j3xh4zar --- addons/web/controllers/main.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 9584c53ca5b..9df5355b9c1 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -91,13 +91,16 @@ db_list = http.db_list db_monodb = http.db_monodb def redirect_with_hash(url, code=303): + redirect_code = "" % url if request.httprequest.user_agent.browser == 'msie': try: version = float(request.httprequest.user_agent.version) if version < 10: - return "" % url + return redirect_code except Exception: pass + elif request.httprequest.user_agent.browser == 'safari': + return redirect_code return werkzeug.utils.redirect(url, code) def module_topological_sort(modules): @@ -529,14 +532,12 @@ class Home(http.Controller): def index(self, s_action=None, db=None, debug=False, **kw): debug = debug != False - try: - lst = http.db_list() - except openerp.exceptions.AccessDenied: - lst = [] - + lst = http.db_list(True) if db not in lst: db = None guessed_db = http.db_monodb(request.httprequest) + if guessed_db is None and len(lst) > 0: + guessed_db = lst[0] def redirect(db): query = dict(urlparse.parse_qsl(request.httprequest.query_string, keep_blank_values=True)) @@ -544,11 +545,8 @@ class Home(http.Controller): redirect = request.httprequest.path + '?' + urllib.urlencode(query) return redirect_with_hash(redirect) - if guessed_db is None and db is None and lst: - return redirect(lst[0]) - - if guessed_db is None and lst: - guessed_db = lst[0] + if db is None and guessed_db is not None: + return redirect(guessed_db) if db is not None and db != guessed_db: request.session.logout() From 866148efa4543a63db43d428642bcfcd9b375e7a Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Tue, 29 Oct 2013 10:01:50 +0100 Subject: [PATCH 07/77] [FIX] Corrected the redirect_with_hash() method that produced an incorrect url in IE and safari bzr revid: nicolas.vanhoren@openerp.com-20131029090150-u397wkzdo9an9n0w --- addons/web/controllers/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 9df5355b9c1..04570b68ccf 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -91,7 +91,7 @@ db_list = http.db_list db_monodb = http.db_monodb def redirect_with_hash(url, code=303): - redirect_code = "" % url + redirect_code = "" % url if request.httprequest.user_agent.browser == 'msie': try: version = float(request.httprequest.user_agent.version) From be9bb538bc9343e069ccecc5266eda2b07bed037 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Tue, 29 Oct 2013 20:28:38 +0100 Subject: [PATCH 08/77] [FIX] crm.phonecall: correct view to call correct on_change method bzr revid: chs@openerp.com-20131029192838-6c6z22enbcgotqma --- addons/crm/crm_phonecall_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/crm/crm_phonecall_view.xml b/addons/crm/crm_phonecall_view.xml index 585286f5456..a027a910520 100644 --- a/addons/crm/crm_phonecall_view.xml +++ b/addons/crm/crm_phonecall_view.xml @@ -120,7 +120,7 @@ + on_change="on_change_partner_id(partner_id)"/> From c384955cfaa0f7e6b98236aeb27f4e058e88d369 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 30 Oct 2013 11:23:13 +0100 Subject: [PATCH 09/77] [FIX] osv.fields: don't raise an error for searching on dummy fields because it's their main reason to be bzr revid: qdp-launchpad@openerp.com-20131030102313-64gb1n98rzdg5mx1 --- openerp/osv/fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index 6622128f234..57a68338193 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -1373,7 +1373,7 @@ class dummy(function): def __init__(self, *arg, **args): self.arg = arg self._relations = [] - super(dummy, self).__init__(self._fnct_read, arg, self._fnct_write, fnct_inv_arg=arg, fnct_search=None, **args) + super(dummy, self).__init__(self._fnct_read, arg, self._fnct_write, fnct_inv_arg=arg, fnct_search=self._fnct_search, **args) # --------------------------------------------------------- # Serialized fields From 30b6eea12d8df70bde2e9a396946e1a712bd6974 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Wed, 30 Oct 2013 12:13:03 +0100 Subject: [PATCH 10/77] [FIX] l10n_multilang: remove force_write attribute in process_translations When processing a translation, the module used to replace the original term by the translated value for accounts (only object with force_write=True). This lead to only having the translated version for every user, independent of user's language. On new chart of accounts, will have different account names according to the user preference. Keep argument force_write in API for stability reason (will be removed in trunk) bzr revid: mat@openerp.com-20131030111303-ziusplk330oj9wf4 --- addons/l10n_multilang/l10n_multilang.py | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/addons/l10n_multilang/l10n_multilang.py b/addons/l10n_multilang/l10n_multilang.py index 9596b292ff3..a44c9f82fe4 100644 --- a/addons/l10n_multilang/l10n_multilang.py +++ b/addons/l10n_multilang/l10n_multilang.py @@ -65,20 +65,15 @@ class wizard_multi_charts_accounts(osv.osv_memory): for j in range(len(in_ids)): in_id = in_ids[j] if value[in_id]: - if not force_write: - #copy Translation from Source to Destination object - xlat_obj.create(cr, uid, { - 'name': out_obj._name + ',' + in_field, - 'type': 'model', - 'res_id': out_ids[j], - 'lang': lang, - 'src': src[in_id], - 'value': value[in_id], + #copy Translation from Source to Destination object + xlat_obj.create(cr, uid, { + 'name': out_obj._name + ',' + in_field, + 'type': 'model', + 'res_id': out_ids[j], + 'lang': lang, + 'src': src[in_id], + 'value': value[in_id], }) - else: - #replace the value in the destination object only if it's the user lang - if context.get('lang') == lang: - self.pool.get(out_obj._name).write(cr, uid, out_ids[j], {in_field: value[in_id]}) else: _logger.info('Language: %s. Translation from template: there is no translation available for %s!' %(lang, src[in_id]))#out_obj._name)) return True From 621b9f54c83b26e1e550bc21905510dfa0037d83 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Wed, 30 Oct 2013 15:54:32 +0100 Subject: [PATCH 11/77] [FIX] stock: use eventual serial number attribute into account while doing product reservation bzr revid: mat@openerp.com-20131030145432-2sij3p1dae8ghzuz --- addons/stock/stock.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index ca6733e5cf0..fb595d76cc1 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -401,15 +401,17 @@ class stock_location(osv.osv): uom_rounding = self.pool.get('product.product').browse(cr, uid, product_id, context=context).uom_id.rounding if context.get('uom'): uom_rounding = uom_obj.browse(cr, uid, context.get('uom'), context=context).rounding + prodlot_id = context.get('prodlot_id', False) locations_ids = self.search(cr, uid, [('location_id', 'child_of', ids)]) if locations_ids: # Fetch only the locations in which this product has ever been processed (in or out) cr.execute("""SELECT l.id FROM stock_location l WHERE l.id in %s AND EXISTS (SELECT 1 FROM stock_move m WHERE m.product_id = %s + AND (NOT BOOL(%s) OR m.prodlot_id=%s) AND ((state = 'done' AND m.location_dest_id = l.id) OR (state in ('done','assigned') AND m.location_id = l.id))) - """, (tuple(locations_ids), product_id,)) + """, (tuple(locations_ids), product_id, prodlot_id, prodlot_id or None)) locations_ids = [i for (i,) in cr.fetchall()] for id in locations_ids: if lock: @@ -421,6 +423,7 @@ class stock_location(osv.osv): cr.execute("SAVEPOINT stock_location_product_reserve") cr.execute("""SELECT id FROM stock_move WHERE product_id=%s AND + (NOT BOOL(%s) OR prodlot_id=%s) AND ( (location_dest_id=%s AND location_id<>%s AND @@ -430,7 +433,7 @@ class stock_location(osv.osv): location_dest_id<>%s AND state in ('done', 'assigned')) ) - FOR UPDATE of stock_move NOWAIT""", (product_id, id, id, id, id), log_exceptions=False) + FOR UPDATE of stock_move NOWAIT""", (product_id, prodlot_id, prodlot_id or None, id, id, id, id), log_exceptions=False) except Exception: # Here it's likely that the FOR UPDATE NOWAIT failed to get the LOCK, # so we ROLLBACK to the SAVEPOINT to restore the transaction to its earlier @@ -446,20 +449,22 @@ class stock_location(osv.osv): WHERE location_dest_id=%s AND location_id<>%s AND product_id=%s AND + (NOT BOOL(%s) OR prodlot_id=%s) AND state='done' GROUP BY product_uom """, - (id, id, product_id)) + (id, id, product_id, prodlot_id, prodlot_id or None)) results = cr.dictfetchall() cr.execute("""SELECT product_uom,-sum(product_qty) AS product_qty FROM stock_move WHERE location_id=%s AND location_dest_id<>%s AND product_id=%s AND + (NOT BOOL(%s) OR prodlot_id=%s) AND state in ('done', 'assigned') GROUP BY product_uom """, - (id, id, product_id)) + (id, id, product_id, prodlot_id, prodlot_id or None)) results += cr.dictfetchall() total = 0.0 results2 = 0.0 @@ -2176,8 +2181,12 @@ class stock_move(osv.osv): pickings[move.picking_id.id] = 1 continue if move.state in ('confirmed', 'waiting'): + ctx = context.copy() + ctx.update({'uom': move.product_uom.id}) + if move.prodlot_id: + ctx.update({'prodlot_id': move.prodlot_id.id}) # Important: we must pass lock=True to _product_reserve() to avoid race conditions and double reservations - res = self.pool.get('stock.location')._product_reserve(cr, uid, [move.location_id.id], move.product_id.id, move.product_qty, {'uom': move.product_uom.id}, lock=True) + res = self.pool.get('stock.location')._product_reserve(cr, uid, [move.location_id.id], move.product_id.id, move.product_qty, context=ctx, lock=True) if res: #_product_available_test depends on the next status for correct functioning #the test does not work correctly if the same product occurs multiple times From 53c15261979cc7d406264970168933ee0c55ac8a Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Wed, 30 Oct 2013 16:26:28 +0100 Subject: [PATCH 12/77] [FIX]crm: crm_lead_to_opportunity wizard, the wizard was not choosing duplicated leads/opps which was having probability null in database bzr revid: dle@openerp.com-20131030152628-tn12sxhbqbdqh3m4 --- addons/crm/wizard/crm_lead_to_opportunity.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/crm/wizard/crm_lead_to_opportunity.py b/addons/crm/wizard/crm_lead_to_opportunity.py index 48097944ec4..f239ad739c1 100644 --- a/addons/crm/wizard/crm_lead_to_opportunity.py +++ b/addons/crm/wizard/crm_lead_to_opportunity.py @@ -59,11 +59,11 @@ class crm_lead2opportunity_partner(osv.osv_memory): if partner_id: # Search for opportunities that have the same partner and that arent done or cancelled - ids = lead_obj.search(cr, uid, [('partner_id', '=', partner_id), ('probability', '<', '100')]) + ids = lead_obj.search(cr, uid, [('partner_id', '=', partner_id), '|', ('probability', '=', False), ('probability', '<', '100')]) for id in ids: tomerge.add(id) if email: - ids = lead_obj.search(cr, uid, [('email_from', '=ilike', email[0]), ('probability', '<', '100')]) + ids = lead_obj.search(cr, uid, [('email_from', '=ilike', email[0]), '|', ('probability', '=', False), ('probability', '<', '100')]) for id in ids: tomerge.add(id) From 01c06b08dbc4cd86b3857a40e93e53f34ef2da76 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 30 Oct 2013 17:49:25 +0100 Subject: [PATCH 13/77] [FIX] account_payment: the amount_residual field is not searchable so it cannot be used in domains bzr revid: qdp-launchpad@openerp.com-20131030164925-c66d7jfx0x3546kt --- addons/account_payment/account_payment_view.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/account_payment/account_payment_view.xml b/addons/account_payment/account_payment_view.xml index 982de455063..f66f02a6d12 100644 --- a/addons/account_payment/account_payment_view.xml +++ b/addons/account_payment/account_payment_view.xml @@ -93,7 +93,7 @@ - +