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: