diff --git a/addons/account_payment/account_move_line.py b/addons/account_payment/account_move_line.py index 266876db95f..c0d670d72e9 100644 --- a/addons/account_payment/account_move_line.py +++ b/addons/account_payment/account_move_line.py @@ -51,7 +51,7 @@ class account_move_line(osv.osv): if bank.state in bank_type: line2bank[line.id] = bank.id break - if line.id not in line2bank and line.partner_id.bank_ids: + if not line2bank.get(line.id) and line.partner_id.bank_ids: line2bank[line.id] = line.partner_id.bank_ids[0].id else: raise osv.except_osv(_('Error!'), _('There is no partner defined on the entry line.')) diff --git a/addons/base_action_rule/__openerp__.py b/addons/base_action_rule/__openerp__.py index 5dd4b057514..d1bed2f1a27 100644 --- a/addons/base_action_rule/__openerp__.py +++ b/addons/base_action_rule/__openerp__.py @@ -37,9 +37,9 @@ trigger an automatic reminder email. 'website': 'http://www.openerp.com', 'depends': ['base', 'resource', 'mail'], 'data': [ + 'base_action_rule_data.xml', 'base_action_rule_view.xml', 'security/ir.model.access.csv', - 'base_action_rule_data.xml' ], 'demo': [], 'installable': True, diff --git a/addons/base_action_rule/base_action_rule.py b/addons/base_action_rule/base_action_rule.py index 5189bcbc7df..e74e7193b62 100644 --- a/addons/base_action_rule/base_action_rule.py +++ b/addons/base_action_rule/base_action_rule.py @@ -227,10 +227,20 @@ class base_action_rule(osv.osv): updated = True return updated + def _update_cron(self, cr, uid, context=None): + try: + cron = self.pool['ir.model.data'].get_object( + cr, uid, 'base_action_rule', 'ir_cron_crm_action', context=context) + except ValueError: + return False + + return cron.toggle(model=self._name, domain=[('kind', '=', 'on_time')]) + def create(self, cr, uid, vals, context=None): res_id = super(base_action_rule, self).create(cr, uid, vals, context=context) if self._register_hook(cr, [res_id]): openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname) + self._update_cron(cr, uid, context=context) return res_id def write(self, cr, uid, ids, vals, context=None): @@ -239,8 +249,14 @@ class base_action_rule(osv.osv): super(base_action_rule, self).write(cr, uid, ids, vals, context=context) if self._register_hook(cr, ids): openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname) + self._update_cron(cr, uid, context=context) return True + def unlink(self, cr, uid, ids, context=None): + res = super(base_action_rule, self).unlink(cr, uid, ids, context=context) + self._update_cron(cr, uid, context=context) + return res + def onchange_model_id(self, cr, uid, ids, model_id, context=None): data = {'model': False, 'filter_pre_id': False, 'filter_id': False} if model_id: diff --git a/addons/base_action_rule/base_action_rule_data.xml b/addons/base_action_rule/base_action_rule_data.xml index d4b12f5d4a3..78988554e86 100644 --- a/addons/base_action_rule/base_action_rule_data.xml +++ b/addons/base_action_rule/base_action_rule_data.xml @@ -11,6 +11,7 @@ + diff --git a/addons/calendar/__openerp__.py b/addons/calendar/__openerp__.py index 0cae2b6faf9..a7e947b916e 100644 --- a/addons/calendar/__openerp__.py +++ b/addons/calendar/__openerp__.py @@ -40,6 +40,7 @@ If you need to manage your meetings, you should install the CRM module. 'website': 'http://www.openerp.com', 'demo': ['calendar_demo.xml'], 'data': [ + 'calendar_cron.xml', 'security/ir.model.access.csv', 'security/calendar_security.xml', 'calendar_view.xml', diff --git a/addons/calendar/calendar.py b/addons/calendar/calendar.py index 3e51407339b..f25e530e679 100644 --- a/addons/calendar/calendar.py +++ b/addons/calendar/calendar.py @@ -415,11 +415,12 @@ class calendar_alarm_manager(osv.AbstractModel): return res def get_next_mail(self, cr, uid, context=None): - cron = self.pool.get('ir.cron').search(cr, uid, [('model', 'ilike', self._name)], context=context) - if cron and len(cron) == 1: - cron = self.pool.get('ir.cron').browse(cr, uid, cron[0], context=context) - else: - _logger.exception("Cron for " + self._name + " can not be identified !") + try: + cron = self.pool['ir.model.data'].get_object( + cr, uid, 'calendar', 'ir_cron_scheduler_alarm', context=context) + except ValueError: + _logger.error("Cron for " + self._name + " can not be identified !") + return False if cron.interval_type == "weeks": cron_interval = cron.interval_number * 7 * 24 * 60 * 60 @@ -431,9 +432,12 @@ class calendar_alarm_manager(osv.AbstractModel): cron_interval = cron.interval_number * 60 elif cron.interval_type == "seconds": cron_interval = cron.interval_number + else: + cron_interval = False if not cron_interval: - _logger.exception("Cron delay can not be computed !") + _logger.error("Cron delay can not be computed !") + return False all_events = self.get_next_potential_limit_alarm(cr, uid, cron_interval, notif=False, context=context) @@ -558,6 +562,35 @@ class calendar_alarm(osv.Model): 'interval': 'hours', } + def _update_cron(self, cr, uid, context=None): + try: + cron = self.pool['ir.model.data'].get_object( + cr, uid, 'calendar', 'ir_cron_scheduler_alarm', context=context) + except ValueError: + return False + return cron.toggle(model=self._name, domain=[('type', '=', 'email')]) + + def create(self, cr, uid, values, context=None): + res = super(calendar_alarm, self).create(cr, uid, values, context=context) + + self._update_cron(cr, uid, context=context) + + return res + + def write(self, cr, uid, ids, values, context=None): + res = super(calendar_alarm, self).write(cr, uid, ids, values, context=context) + + self._update_cron(cr, uid, context=context) + + return res + + def unlink(self, cr, uid, ids, context=None): + res = super(calendar_alarm, self).unlink(cr, uid, ids, context=context) + + self._update_cron(cr, uid, context=context) + + return res + class ir_values(osv.Model): _inherit = 'ir.values' diff --git a/addons/calendar/calendar_cron.xml b/addons/calendar/calendar_cron.xml new file mode 100644 index 00000000000..313a0211fa4 --- /dev/null +++ b/addons/calendar/calendar_cron.xml @@ -0,0 +1,18 @@ + + + + + + Run Event Reminder + + + 30 + minutes + -1 + + + + + + + \ No newline at end of file diff --git a/addons/calendar/calendar_data.xml b/addons/calendar/calendar_data.xml index 68d7aa449e4..e13edaf6312 100644 --- a/addons/calendar/calendar_data.xml +++ b/addons/calendar/calendar_data.xml @@ -71,22 +71,7 @@ days email - - - - - Run Event Reminder - - - 30 - minutes - -1 - - - - - - + Customer Meeting diff --git a/addons/crm_partner_assign/crm_portal_view.xml b/addons/crm_partner_assign/crm_portal_view.xml index 1ad0659d217..36a4f324ebf 100644 --- a/addons/crm_partner_assign/crm_portal_view.xml +++ b/addons/crm_partner_assign/crm_portal_view.xml @@ -114,7 +114,7 @@ diff --git a/addons/document/static/src/js/document.js b/addons/document/static/src/js/document.js index e4bce2da76e..5b353d5b0dd 100644 --- a/addons/document/static/src/js/document.js +++ b/addons/document/static/src/js/document.js @@ -3,8 +3,10 @@ openerp.document = function (instance) { instance.web.Sidebar.include({ init : function(){ this._super.apply(this, arguments); - this.sections.splice(1, 0, { 'name' : 'files', 'label' : _t('Attachment(s)'), }); - this.items['files'] = []; + if (this.getParent().view_type == "form"){ + this.sections.splice(1, 0, { 'name' : 'files', 'label' : _t('Attachment(s)'), }); + this.items['files'] = []; + } }, on_attachments_loaded: function(attachments) { //to display number in name if more then one attachment which has same name. diff --git a/addons/fetchmail/__openerp__.py b/addons/fetchmail/__openerp__.py index 84a26d5ec40..082d53df5e9 100644 --- a/addons/fetchmail/__openerp__.py +++ b/addons/fetchmail/__openerp__.py @@ -56,8 +56,8 @@ For more specific needs, you may also assign custom-defined actions """, 'website': 'http://www.openerp.com', 'data': [ - 'fetchmail_view.xml', 'fetchmail_data.xml', + 'fetchmail_view.xml', 'security/ir.model.access.csv', 'fetchmail_installer_view.xml' ], diff --git a/addons/fetchmail/fetchmail.py b/addons/fetchmail/fetchmail.py index 565996bf961..37a0f165435 100644 --- a/addons/fetchmail/fetchmail.py +++ b/addons/fetchmail/fetchmail.py @@ -251,27 +251,33 @@ openerp_mailgate: "|/path/to/openerp-mailgate.py --host=localhost -u %(uid)d -p server.write({'date': time.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)}) return True - def cron_update(self, cr, uid, context=None): - if context is None: - context = {} - if not context.get('fetchmail_cron_running'): - # Enabled/Disable cron based on the number of 'done' server of type pop or imap - ids = self.search(cr, uid, [('state','=','done'),('type','in',['pop','imap'])]) - try: - cron_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'fetchmail', 'ir_cron_mail_gateway_action')[1] - self.pool.get('ir.cron').write(cr, 1, [cron_id], {'active': bool(ids)}) - except ValueError: - # Nevermind if default cron cannot be found - pass + def _update_cron(self, cr, uid, context=None): + if context and context.get('fetchmail_cron_running'): + return + + try: + cron = self.pool['ir.model.data'].get_object( + cr, uid, 'fetchmail', 'ir_cron_mail_gateway_action', context=context) + except ValueError: + # Nevermind if default cron cannot be found + return + + # Enabled/Disable cron based on the number of 'done' server of type pop or imap + cron.toggle(model=self._name, domain=[('state','=','done'), ('type','in',['pop','imap'])]) def create(self, cr, uid, values, context=None): res = super(fetchmail_server, self).create(cr, uid, values, context=context) - self.cron_update(cr, uid, context=context) + self._update_cron(cr, uid, context=context) return res def write(self, cr, uid, ids, values, context=None): res = super(fetchmail_server, self).write(cr, uid, ids, values, context=context) - self.cron_update(cr, uid, context=context) + self._update_cron(cr, uid, context=context) + return res + + def unlink(self, cr, uid, ids, context=None): + res = super(fetchmail_server, self).unlink(cr, uid, ids, context=context) + self._update_cron(cr, uid, context=context) return res class mail_mail(osv.osv): diff --git a/addons/payment_paypal/controllers/main.py b/addons/payment_paypal/controllers/main.py index e07fa3d738f..94c8171da14 100644 --- a/addons/payment_paypal/controllers/main.py +++ b/addons/payment_paypal/controllers/main.py @@ -24,7 +24,7 @@ class PaypalController(http.Controller): """ Extract the return URL from the data coming from paypal. """ return_url = post.pop('return_url', '') if not return_url: - custom = json.loads(post.pop('custom', '{}')) + custom = json.loads(post.pop('custom', False) or '{}') return_url = custom.get('return_url', '/') return return_url diff --git a/addons/sale/sale.py b/addons/sale/sale.py index b3f2cc68910..25f3995a207 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -597,22 +597,8 @@ class sale_order(osv.osv): def action_button_confirm(self, cr, uid, ids, context=None): assert len(ids) == 1, 'This option should only be used for a single id at a time.' self.signal_order_confirm(cr, uid, ids) - - # redisplay the record as a sales order - view_ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'sale', 'view_order_form') - view_id = view_ref and view_ref[1] or False, - return { - 'type': 'ir.actions.act_window', - 'name': _('Sales Order'), - 'res_model': 'sale.order', - 'res_id': ids[0], - 'view_type': 'form', - 'view_mode': 'form', - 'view_id': view_id, - 'target': 'current', - 'nodestroy': True, - } - + return True + def action_wait(self, cr, uid, ids, context=None): context = context or {} for o in self.browse(cr, uid, ids): diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 53addf97e56..f8f2d758b9a 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -405,15 +405,36 @@ instance.web.ActionManager = instance.web.Widget.extend({ } var widget = executor.widget(); if (executor.action.target === 'new') { + var pre_dialog = this.dialog; + if (pre_dialog){ + // prevent previous dialog to consider itself closed, + // right now, as we're opening a new one (prevents + // reload of original form view) + pre_dialog.off('closing', null, pre_dialog.on_close); + } if (this.dialog_widget && !this.dialog_widget.isDestroyed()) { this.dialog_widget.destroy(); } + // explicitly passing a closing action to dialog_stop() prevents + // it from reloading the original form view this.dialog_stop(executor.action); this.dialog = new instance.web.Dialog(this, { title: executor.action.name, dialogClass: executor.klass, }); - this.dialog.on("closing", null, options.on_close); + + // chain on_close triggers with previous dialog, if any + this.dialog.on_close = function(){ + options.on_close.apply(null, arguments); + if (pre_dialog && pre_dialog.on_close){ + // no parameter passed to on_close as this will + // only be called when the last dialog is truly + // closing, and *should* trigger a reload of the + // underlying form view (see comments above) + pre_dialog.on_close(); + } + }; + this.dialog.on("closing", null, this.dialog.on_close); if (widget instanceof instance.web.ViewManager) { _.extend(widget.flags, { $buttons: this.dialog.$buttons, @@ -426,6 +447,9 @@ instance.web.ActionManager = instance.web.Widget.extend({ this.dialog.open(); return initialized; } else { + // explicitly passing a closing action to dialog_stop() prevents + // it from reloading the original form view - we're opening a + // completely new action anyway this.dialog_stop(executor.action); this.inner_action = executor.action; this.inner_widget = widget; diff --git a/openerp/addons/base/ir/ir_cron.py b/openerp/addons/base/ir/ir_cron.py index 8f85beb820c..029c2471f49 100644 --- a/openerp/addons/base/ir/ir_cron.py +++ b/openerp/addons/base/ir/ir_cron.py @@ -294,4 +294,20 @@ class ir_cron(osv.osv): res = super(ir_cron, self).unlink(cr, uid, ids, context=context) return res + def try_write(self, cr, uid, ids, values, context=None): + try: + with cr.savepoint(): + cr.execute("""SELECT id FROM "%s" WHERE id IN %%s FOR UPDATE NOWAIT""" % self._table, + (tuple(ids),), log_exceptions=False) + except psycopg2.OperationalError: + pass + else: + return super(ir_cron, self).write(cr, uid, ids, values, context=context) + return False + + def toggle(self, cr, uid, ids, model, domain, context=None): + active = bool(self.pool[model].search_count(cr, uid, domain, context=context)) + + return self.try_write(cr, uid, ids, {'active': active}, context=context) + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: