diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py
index e3d89f11fe6..275d1fdf80a 100644
--- a/addons/account/models/account_move.py
+++ b/addons/account/models/account_move.py
@@ -903,8 +903,8 @@ class AccountMoveLine(models.Model):
# Writeoff line in the account of self
first_line_dict = vals.copy()
first_line_dict['account_id'] = self[0].account_id.id
- if 'analytic_account_id' in vals:
- del vals['analytic_account_id']
+ if 'analytic_account_id' in first_line_dict:
+ del first_line_dict['analytic_account_id']
# Writeoff line in specified writeoff account
second_line_dict = vals.copy()
diff --git a/addons/account/views/partner_view.xml b/addons/account/views/partner_view.xml
index beda8f4797c..f4bb90a1236 100644
--- a/addons/account/views/partner_view.xml
+++ b/addons/account/views/partner_view.xml
@@ -39,12 +39,12 @@
-
+
diff --git a/addons/base_action_rule/models/base_action_rule.py b/addons/base_action_rule/models/base_action_rule.py
index 7eacdb4ed8b..9c0151fba53 100644
--- a/addons/base_action_rule/models/base_action_rule.py
+++ b/addons/base_action_rule/models/base_action_rule.py
@@ -124,7 +124,7 @@ class BaseActionRule(models.Model):
def _update_registry(self):
""" Update the registry after a modification on action rules. """
- if self.env.registry.ready:
+ if self.env.registry.ready and not self.env.context.get('import_file'):
# for the sake of simplicity, simply force the registry to reload
self._cr.commit()
self.env.reset()
diff --git a/addons/base_import/models/base_import.py b/addons/base_import/models/base_import.py
index 3f872edfc26..32dfcbd0cf9 100644
--- a/addons/base_import/models/base_import.py
+++ b/addons/base_import/models/base_import.py
@@ -649,7 +649,7 @@ class Import(models.TransientModel):
}]
_logger.info('importing %d rows...', len(data))
- import_result = self.env[self.res_model].load(import_fields, data)
+ import_result = self.env[self.res_model].with_context(import_file=True).load(import_fields, data)
_logger.info('done')
# If transaction aborted, RELEASE SAVEPOINT is going to raise
diff --git a/addons/crm/views/crm_lead_views.xml b/addons/crm/views/crm_lead_views.xml
index 6565ec972f5..b3e54885818 100644
--- a/addons/crm/views/crm_lead_views.xml
+++ b/addons/crm/views/crm_lead_views.xml
@@ -525,7 +525,7 @@
-
+
diff --git a/addons/mail/models/mail_template.py b/addons/mail/models/mail_template.py
index d87cad5fec7..9f870b86ac2 100644
--- a/addons/mail/models/mail_template.py
+++ b/addons/mail/models/mail_template.py
@@ -45,7 +45,7 @@ def format_tz(env, dt, tz=False, format=False):
format_time = langs.time_format or '%I-%M %p'
fdate = ts.strftime(format_date).decode('utf-8')
- ftime = ts.strftime(format_time)
+ ftime = ts.strftime(format_time).decode('utf-8')
return "%s %s%s" % (fdate, ftime, (' (%s)' % tz) if tz else '')
try:
diff --git a/addons/point_of_sale/security/point_of_sale_security.xml b/addons/point_of_sale/security/point_of_sale_security.xml
index 649d9df8e57..f29a37cfcfd 100644
--- a/addons/point_of_sale/security/point_of_sale_security.xml
+++ b/addons/point_of_sale/security/point_of_sale_security.xml
@@ -36,12 +36,6 @@
[(1, '=', 1)]
-
- Point Of Sale Cashbox Line POS User
-
-
- [('bank_statement_id.pos_session_id', '!=', False)]
-
Point Of Sale Cashbox Line Accountant
diff --git a/addons/sale_crm/static/src/js/tour.js b/addons/sale_crm/static/src/js/tour.js
index cd3fff9d04e..392c93c0804 100644
--- a/addons/sale_crm/static/src/js/tour.js
+++ b/addons/sale_crm/static/src/js/tour.js
@@ -14,7 +14,7 @@ var quotation_button_step_index = _.findIndex(tour.tours.sale_tour.steps, functi
tour.tours.sale_tour.steps.splice(quotation_button_step_index, 1, {
trigger: ".o_kanban_manage_button_section > a",
content: _t("Click here to see more options."),
- position: "bottom"
+ position: "right"
}, {
trigger: ".o_quotation_view_button",
content: _t("Let's have a look at the quotations of this sales team."),
diff --git a/addons/web/static/src/js/views/list_view.js b/addons/web/static/src/js/views/list_view.js
index 327edcbb052..f2e4f565a79 100644
--- a/addons/web/static/src/js/views/list_view.js
+++ b/addons/web/static/src/js/views/list_view.js
@@ -1705,7 +1705,6 @@ var Column = Class.extend({
id: id,
tag: tag
});
-
this.modifiers = attrs.modifiers ? JSON.parse(attrs.modifiers) : {};
delete attrs.modifiers;
_.extend(this, attrs);
@@ -1732,10 +1731,14 @@ var Column = Class.extend({
if (this.type !== 'integer' && this.type !== 'float' && this.type !== 'monetary') {
return {};
}
- var aggregation_func = this['group_operator'] || 'sum';
- if (!(aggregation_func in this)) {
+
+ var aggregation_func = (this.sum && 'sum') || (this.avg && 'avg') ||
+ (this.max && 'max') || (this.min && 'min') || this.group_operator;
+
+ if (!aggregation_func) {
return {};
}
+
var C = function (fn, label) {
this['function'] = fn;
this.label = label;
diff --git a/addons/website/static/src/js/website.snippets.animation.js b/addons/website/static/src/js/website.snippets.animation.js
index 02ebc717ad9..5d55a25bdb0 100644
--- a/addons/website/static/src/js/website.snippets.animation.js
+++ b/addons/website/static/src/js/website.snippets.animation.js
@@ -147,6 +147,20 @@ animation.registry.ul = animation.Class.extend({
},
});
+/**
+ * This is a fix for apple device (<= IPhone 4, IPad 2)
+ * Standard bootstrap requires data-toggle='collapse' element to be tags. Unfortunatly one snippet uses a
+ * tag instead. The fix forces an empty click handler on these div, which allows standard bootstrap to work.
+ *
+ * This should be removed in a future odoo snippets refactoring.
+ */
+animation.registry._fix_apple_collapse = animation.Class.extend({
+ selector: ".s_faq_collapse [data-toggle='collapse']",
+ start: function () {
+ this.$target.off("click._fix_apple_collapse").on("click._fix_apple_collapse", function () {});
+ },
+});
+
/* -------------------------------------------------------------------------
Gallery Animation
diff --git a/addons/website_livechat/__manifest__.py b/addons/website_livechat/__manifest__.py
index 6161d3f8673..9caf3260d36 100644
--- a/addons/website_livechat/__manifest__.py
+++ b/addons/website_livechat/__manifest__.py
@@ -12,6 +12,7 @@ It also will include the feedback tool for the livechat, and web pages to displa
""",
'depends': ['website', 'im_livechat'],
'installable': True,
+ 'auto_install': True,
'data': [
'views/website_livechat.xml',
'views/res_config.xml',
diff --git a/odoo/addons/base/res/res_partner.py b/odoo/addons/base/res/res_partner.py
index 76e49b2ee52..74751b86f7b 100644
--- a/odoo/addons/base/res/res_partner.py
+++ b/odoo/addons/base/res/res_partner.py
@@ -213,7 +213,7 @@ class Partner(models.Model, FormatAddress):
# technical field used for managing commercial fields
commercial_partner_id = fields.Many2one('res.partner', compute='_compute_commercial_partner',
- string='Commercial Entity', store=True)
+ string='Commercial Entity', store=True, index=True)
commercial_company_name = fields.Char('Company Name Entity', compute='_compute_commercial_company_name',
store=True)
company_name = fields.Char('Company Name')
diff --git a/odoo/addons/test_new_api/models.py b/odoo/addons/test_new_api/models.py
index 5fc58ea976a..0d2054e32e5 100644
--- a/odoo/addons/test_new_api/models.py
+++ b/odoo/addons/test_new_api/models.py
@@ -71,10 +71,17 @@ class Discussion(models.Model):
message_concat = fields.Text(string='Message concatenate')
important_messages = fields.One2many('test_new_api.message', 'discussion',
domain=[('important', '=', True)])
+ very_important_messages = fields.One2many(
+ 'test_new_api.message', 'discussion',
+ domain=lambda self: self._domain_very_important())
emails = fields.One2many('test_new_api.emailmessage', 'discussion')
important_emails = fields.One2many('test_new_api.emailmessage', 'discussion',
domain=[('important', '=', True)])
+ def _domain_very_important(self):
+ """Ensure computed O2M domains work as expected."""
+ return [("important", "=", True)]
+
@api.onchange('moderator')
def _onchange_moderator(self):
self.participants |= self.moderator
diff --git a/odoo/addons/test_new_api/tests/test_new_fields.py b/odoo/addons/test_new_api/tests/test_new_fields.py
index 9c4af5d3579..22cee09ca12 100644
--- a/odoo/addons/test_new_api/tests/test_new_fields.py
+++ b/odoo/addons/test_new_api/tests/test_new_fields.py
@@ -621,6 +621,12 @@ class TestFields(common.TransactionCase):
message.important = True
self.assertIn(message, discussion.important_messages)
+ # writing on very_important_messages should call its domain method
+ self.assertIn(message, discussion.very_important_messages)
+ discussion.write({'very_important_messages': [(5,)]})
+ self.assertFalse(discussion.very_important_messages)
+ self.assertFalse(message.exists())
+
class TestHtmlField(common.TransactionCase):
diff --git a/odoo/fields.py b/odoo/fields.py
index 610839ba517..ee732b5b62f 100644
--- a/odoo/fields.py
+++ b/odoo/fields.py
@@ -1099,6 +1099,8 @@ class Integer(Field):
'group_operator': 'sum',
}
+ _description_group_operator = property(attrgetter('group_operator'))
+
def convert_to_column(self, value, record):
return int(value or 0)
@@ -1160,6 +1162,7 @@ class Float(Field):
_related__digits = property(attrgetter('_digits'))
_description_digits = property(attrgetter('digits'))
+ _description_group_operator = property(attrgetter('group_operator'))
def convert_to_column(self, value, record):
result = float(value or 0.0)
@@ -1201,6 +1204,7 @@ class Monetary(Field):
_related_currency_field = property(attrgetter('currency_field'))
_description_currency_field = property(attrgetter('currency_field'))
+ _description_group_operator = property(attrgetter('group_operator'))
def _setup_regular_base(self, model):
super(Monetary, self)._setup_regular_base(model)
@@ -1283,7 +1287,7 @@ class _String(Field):
return self.translate(callback, value)
else:
return value
-
+
class Char(_String):
""" Basic string field, can be length-limited, usually displayed as a
diff --git a/odoo/tools/config.py b/odoo/tools/config.py
index 07af83e7e3e..5584002c520 100644
--- a/odoo/tools/config.py
+++ b/odoo/tools/config.py
@@ -443,7 +443,7 @@ class configmanager(object):
for x in self.options['addons_path'].split(','))
self.options['init'] = opt.init and dict.fromkeys(opt.init.split(','), 1) or {}
- self.options['demo'] = (self.options['init']
+ self.options['demo'] = (dict(self.options['init'])
if not self.options['without_demo'] else {})
self.options['update'] = opt.update and dict.fromkeys(opt.update.split(','), 1) or {}
self.options['translate_modules'] = opt.translate_modules and map(lambda m: m.strip(), opt.translate_modules.split(',')) or ['all']