diff --git a/addons/account_tax_cash_basis/models/account_partial_reconcile.py b/addons/account_tax_cash_basis/models/account_partial_reconcile.py
index b2999f421bd..703eba5801c 100644
--- a/addons/account_tax_cash_basis/models/account_partial_reconcile.py
+++ b/addons/account_tax_cash_basis/models/account_partial_reconcile.py
@@ -21,8 +21,9 @@ class AccountPartialReconcileCashBasis(models.Model):
#TOCHECK: normal and cash basis taxes shoudn't be mixed together (on the same invoice line for example) as it will
#create reporting issues. Not sure of the behavior to implement in that case, though.
# amount to write is the current cash_basis amount minus the one before the reconciliation
+ currency_id = line.currency_id or line.company_id.currency_id
matched_percentage = value_before_reconciliation[move.id]
- amount = line.currency_id.round((line.credit_cash_basis - line.debit_cash_basis) - (line.credit - line.debit) * matched_percentage)
+ amount = currency_id.round((line.credit_cash_basis - line.debit_cash_basis) - (line.credit - line.debit) * matched_percentage)
if not line.tax_exigible:
if line.tax_line_id and line.tax_line_id.use_cash_basis:
# group by line account
@@ -42,16 +43,16 @@ class AccountPartialReconcileCashBasis(models.Model):
for tax in line.tax_ids:
line_to_create.append((0, 0, {
'name': '/',
- 'debit': line.currency_id.round(line.debit_cash_basis - line.debit * matched_percentage),
- 'credit': line.currency_id.round(line.credit_cash_basis - line.credit * matched_percentage),
+ 'debit': currency_id.round(line.debit_cash_basis - line.debit * matched_percentage),
+ 'credit': currency_id.round(line.credit_cash_basis - line.credit * matched_percentage),
'account_id': line.account_id.id,
'tax_ids': [(6, 0, [tax.id])],
'tax_exigible': True,
}))
line_to_create.append((0, 0, {
'name': '/',
- 'credit': line.currency_id.round(line.debit_cash_basis - line.debit * matched_percentage),
- 'debit': line.currency_id.round(line.credit_cash_basis - line.credit * matched_percentage),
+ 'credit': currency_id.round(line.debit_cash_basis - line.debit * matched_percentage),
+ 'debit': currency_id.round(line.credit_cash_basis - line.credit * matched_percentage),
'account_id': line.account_id.id,
'tax_exigible': True,
}))
diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py
index 716175a5fd8..2718e47dd2a 100644
--- a/addons/auth_signup/controllers/main.py
+++ b/addons/auth_signup/controllers/main.py
@@ -63,8 +63,7 @@ class AuthSignupHome(Home):
qcontext['error'] = _("Could not reset your password")
_logger.exception('error when resetting password')
except Exception, e:
- qcontext['error'] = e.message
-
+ qcontext['error'] = e.message or e.name
return request.render('auth_signup.reset_password', qcontext)
diff --git a/addons/barcodes/static/src/js/barcode_events.js b/addons/barcodes/static/src/js/barcode_events.js
index fca30916106..3c5cb289232 100644
--- a/addons/barcodes/static/src/js/barcode_events.js
+++ b/addons/barcodes/static/src/js/barcode_events.js
@@ -4,6 +4,16 @@ odoo.define('barcodes.BarcodeEvents', function(require) {
var core = require('web.core');
var mixins = core.mixins;
+
+// For IE >= 9, use this, new CustomEvent(), instead of new Event()
+function CustomEvent ( event, params ) {
+ params = params || { bubbles: false, cancelable: false, detail: undefined };
+ var evt = document.createEvent( 'CustomEvent' );
+ evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
+ return evt;
+ }
+CustomEvent.prototype = window.Event.prototype;
+
var BarcodeEvents = core.Class.extend(mixins.PropertiesMixin, {
timeout: null,
key_pressed: {},
@@ -63,10 +73,16 @@ var BarcodeEvents = core.Class.extend(mixins.PropertiesMixin, {
// bug for the longest time that causes keyCode and
// charCode to not be set for events created this way:
// https://bugs.webkit.org/show_bug.cgi?id=16735
- new_event = new Event("keypress", {
+ var params = {
'bubbles': old_event.bubbles,
'cancelable': old_event.cancelable,
- });
+ };
+ try {
+ new_event = new Event("keypress", params);
+ } catch(error) {
+ // For IE >= 9, use new CustomEvent(), instead of new Event()
+ new_event = new CustomEvent("keypress", params);
+ }
new_event.viewArg = old_event.viewArg;
new_event.ctrl = old_event.ctrl;
diff --git a/addons/crm/data/crm_lead_demo.xml b/addons/crm/data/crm_lead_demo.xml
index e5281090e28..a4b40a6d984 100644
--- a/addons/crm/data/crm_lead_demo.xml
+++ b/addons/crm/data/crm_lead_demo.xml
@@ -669,7 +669,7 @@ Andrew
]]>
Birmingham
B46 3AG
- 81 Academy Avenue
+ Cannon Hill Park
2
diff --git a/addons/l10n_si/__manifest__.py b/addons/l10n_si/__manifest__.py
index bb79727cdf1..1a06c04cdfd 100644
--- a/addons/l10n_si/__manifest__.py
+++ b/addons/l10n_si/__manifest__.py
@@ -5,6 +5,7 @@
{
"name": "Slovenian - Accounting",
+ "versiom": "1.1",
"author": "Mentis d.o.o.",
"website": "http://www.mentis.si",
'category': 'Localization',
diff --git a/addons/l10n_si/data/account.account.template.csv b/addons/l10n_si/data/account.account.template.csv
index 92cbf7ee3b3..40b08e97e60 100644
--- a/addons/l10n_si/data/account.account.template.csv
+++ b/addons/l10n_si/data/account.account.template.csv
@@ -96,14 +96,14 @@ code,id,user_type_id/id,name,reconcile,chart_template_id/id
155000,gd_acc_155000,account.data_account_type_current_assets,"DRUGE KRATKOROČNE TERJATVE, POVEZANE S FINANČNIMI PRIHODKI",False,gd_chart
159000,gd_acc_159000,account.data_account_type_current_assets,"OSLABITEV VREDNOSTI KRATKOROČNIH TERJATEV, POVEZANIH S FINANČNIMI PRIHODKI",False,gd_chart
160001,gd_acc_160001,account.data_account_type_current_assets,"KRATKOROČNE TERJATVE ZA NEODBITNI DDV",False,gd_chart
-160002,gd_acc_160002,account.data_account_type_current_assets,"KRATKOROČNE TERJATVE ZA ODBITNI DDV 8,5%",False,gd_chart
-160003,gd_acc_160003,account.data_account_type_current_assets,"KRATKOROČNE TERJATVE ZA ODBITNI DDV 20%",False,gd_chart
-160004,gd_acc_160004,account.data_account_type_current_assets,"KRATKOROČNE TERJATVE ZA ODBITNI DDV 8,5% V EU",False,gd_chart
-160005,gd_acc_160005,account.data_account_type_current_assets,"KRATKOROČNE TERJATVE ZA ODBITNI DDV 20% V EU",False,gd_chart
-160006,gd_acc_160006,account.data_account_type_current_assets,"KRATKOROČNE TERJATVE ZA ODBITNI DDV 8,5% IZVEN EU",False,gd_chart
-160007,gd_acc_160007,account.data_account_type_current_assets,"KRATKOROČNE TERJATVE ZA ODBITNI DDV 20% IZVEN EU",False,gd_chart
-160008,gd_acc_160008,account.data_account_type_current_assets,"KRATKOROČNE TERJATVE ZA ODBITNI DDV 8,5% UVOZ",False,gd_chart
-160009,gd_acc_160009,account.data_account_type_current_assets,"KRATKOROČNE TERJATVE ZA ODBITNI DDV 20% UVOZ",False,gd_chart
+160002,gd_acc_160002,account.data_account_type_current_assets,"KRATKOROČNE TERJATVE ZA ODBITNI DDV 9,5%",False,gd_chart
+160003,gd_acc_160003,account.data_account_type_current_assets,"KRATKOROČNE TERJATVE ZA ODBITNI DDV 22%",False,gd_chart
+160004,gd_acc_160004,account.data_account_type_current_assets,"KRATKOROČNE TERJATVE ZA ODBITNI DDV 9,5% V EU",False,gd_chart
+160005,gd_acc_160005,account.data_account_type_current_assets,"KRATKOROČNE TERJATVE ZA ODBITNI DDV 22% V EU",False,gd_chart
+160006,gd_acc_160006,account.data_account_type_current_assets,"KRATKOROČNE TERJATVE ZA ODBITNI DDV 9,5% IZVEN EU",False,gd_chart
+160007,gd_acc_160007,account.data_account_type_current_assets,"KRATKOROČNE TERJATVE ZA ODBITNI DDV 22% IZVEN EU",False,gd_chart
+160008,gd_acc_160008,account.data_account_type_current_assets,"KRATKOROČNE TERJATVE ZA ODBITNI DDV 9,5% UVOZ",False,gd_chart
+160009,gd_acc_160009,account.data_account_type_current_assets,"KRATKOROČNE TERJATVE ZA ODBITNI DDV 22% UVOZ",False,gd_chart
161000,gd_acc_161000,account.data_account_type_current_assets,"KRATKOROČNE TERJATVE ZA DAVEK OD DOHODKOV PRAVNIH OSEB, VKLJUČNO Z DAVKOM, PLAČANIM V TUJINI",False,gd_chart
162000,gd_acc_162000,account.data_account_type_current_assets,"DRUGE KRATKOROČNE TERJATVE DO DRŽAVNIH IN DRUGIH INŠTITUCIJ",False,gd_chart
165000,gd_acc_165000,account.data_account_type_current_assets,"OSTALE KRATKOROČNE TERJATVE",False,gd_chart
@@ -152,12 +152,12 @@ code,id,user_type_id/id,name,reconcile,chart_template_id/id
255000,gd_acc_255000,account.data_account_type_current_liabilities,"KRATKOROČNE OBVEZNOSTI ZA DRUGE PREJEMKE IZ DELOVNEGA RAZMERJA",False,gd_chart
256000,gd_acc_256000,account.data_account_type_current_liabilities,"KRATKOROČNE OBVEZNOSTI ZA PRISPEVKE IZ DRUGIH PREJEMKOV IZ DELOVNEGA RAZMERJA, KI SE NE OBRAČUNAVAJO SKUPAJ S PLAČAMI",False,gd_chart
257000,gd_acc_257000,account.data_account_type_current_liabilities,"KRATKOROČNE OBVEZNOSTI ZA DAVEK IZ DRUGIH PREJEMKOV IZ DELOVNEGA RAZMERJA, KI SE NE OBRAČUNAVAJO SKUPAJ S PLAČAMI",False,gd_chart
-260001,gd_acc_260001,account.data_account_type_current_liabilities,"OBVEZNOSTI ZA ZARAČUNANI DDV 8,5%",False,gd_chart
-260002,gd_acc_260002,account.data_account_type_current_liabilities,"OBVEZNOSTI ZA ZARAČUNANI DDV 20%",False,gd_chart
-260003,gd_acc_260003,account.data_account_type_current_liabilities,"OBVEZNOSTI ZA ZARAČUNANI DDV 8,5% V EU",False,gd_chart
-260004,gd_acc_260004,account.data_account_type_current_liabilities,"OBVEZNOSTI ZA ZARAČUNANI DDV 20% V EU",False,gd_chart
-260005,gd_acc_260005,account.data_account_type_current_liabilities,"OBVEZNOSTI ZA ZARAČUNANI DDV 8,5% IZVEN EU",False,gd_chart
-260006,gd_acc_260006,account.data_account_type_current_liabilities,"OBVEZNOSTI ZA ZARAČUNANI DDV 20% IZVEN EU",False,gd_chart
+260001,gd_acc_260001,account.data_account_type_current_liabilities,"OBVEZNOSTI ZA ZARAČUNANI DDV 9,5%",False,gd_chart
+260002,gd_acc_260002,account.data_account_type_current_liabilities,"OBVEZNOSTI ZA ZARAČUNANI DDV 22%",False,gd_chart
+260003,gd_acc_260003,account.data_account_type_current_liabilities,"OBVEZNOSTI ZA ZARAČUNANI DDV 9,5% V EU",False,gd_chart
+260004,gd_acc_260004,account.data_account_type_current_liabilities,"OBVEZNOSTI ZA ZARAČUNANI DDV 22% V EU",False,gd_chart
+260005,gd_acc_260005,account.data_account_type_current_liabilities,"OBVEZNOSTI ZA ZARAČUNANI DDV 9,5% IZVEN EU",False,gd_chart
+260006,gd_acc_260006,account.data_account_type_current_liabilities,"OBVEZNOSTI ZA ZARAČUNANI DDV 22% IZVEN EU",False,gd_chart
261000,gd_acc_261000,account.data_account_type_current_liabilities,"OBVEZNOSTI ZA DDV, CARINO IN DRUGE DAJATVE OD UVOŽENEGA BLAGA",False,gd_chart
262000,gd_acc_262000,account.data_account_type_current_liabilities,"OBVEZNOSTI ZA PRISPEVKE IZPLAČEVALCA",False,gd_chart
263000,gd_acc_263000,account.data_account_type_current_liabilities,"OBVEZNOSTI ZA DAVEK OD IZPLAČANIH PLAČ",False,gd_chart
diff --git a/addons/report/i18n/report.pot b/addons/report/i18n/report.pot
index 8b66e8b4728..d35bf683eed 100644
--- a/addons/report/i18n/report.pot
+++ b/addons/report/i18n/report.pot
@@ -507,6 +507,12 @@ msgid "Unable to find Wkhtmltopdf on this \n"
"wkhtmltopdf.org"
msgstr ""
+#. module: report
+#: code:addons/report/models/report.py:164
+#, python-format
+msgid "Unable to find Wkhtmltopdf on this system. The PDF can not be created."
+msgstr ""
+
#. module: report
#: model:ir.ui.view,arch_db:report.external_layout_footer
msgid "Website:"
@@ -542,17 +548,14 @@ msgid "base.config.settings"
msgstr ""
#. module: report
-#: model:ir.model,name:report.model_ir_actions_report_xml
-msgid "ir.actions.report.xml"
+#. openerp-web
+#: code:addons/report/static/src/js/qwebactionmanager.js:96
+#, python-format
+msgid "Your installation of Wkhtmltopdf seems to be broken. The \n"
+"report will be shown in html.
wkhtmltopdf.org"
msgstr ""
#. module: report
#: model:ir.model,name:report.model_ir_qweb_field_barcode
msgid "ir.qweb.field.barcode"
msgstr ""
-
-#. module: report
-#: model:ir.model,name:report.model_report_abstract_report
-msgid "report.abstract_report"
-msgstr ""
-
diff --git a/addons/report/models/report.py b/addons/report/models/report.py
index 2eed9824bf2..6f01e3d26f2 100644
--- a/addons/report/models/report.py
+++ b/addons/report/models/report.py
@@ -59,16 +59,21 @@ except (OSError, IOError):
else:
_logger.info('Will use the Wkhtmltopdf binary at %s' % _get_wkhtmltopdf_bin())
out, err = process.communicate()
- version = re.search('([0-9.]+)', out or "0").group(0)
- if LooseVersion(version) < LooseVersion('0.12.0'):
- _logger.info('Upgrade Wkhtmltopdf to (at least) 0.12.0')
- wkhtmltopdf_state = 'upgrade'
- else:
- wkhtmltopdf_state = 'ok'
+ match = re.search('([0-9.]+)', out)
+ if match:
+ version = match.group(0)
+ if LooseVersion(version) < LooseVersion('0.12.0'):
+ _logger.info('Upgrade Wkhtmltopdf to (at least) 0.12.0')
+ wkhtmltopdf_state = 'upgrade'
+ else:
+ wkhtmltopdf_state = 'ok'
- if config['workers'] == 1:
- _logger.info('You need to start Odoo with at least two workers to print a pdf version of the reports.')
- wkhtmltopdf_state = 'workers'
+ if config['workers'] == 1:
+ _logger.info('You need to start Odoo with at least two workers to print a pdf version of the reports.')
+ wkhtmltopdf_state = 'workers'
+ else:
+ _logger.info('Wkhtmltopdf seems to be broken.')
+ wkhtmltopdf_state = 'broken'
class Report(models.Model):
@@ -141,6 +146,14 @@ class Report(models.Model):
def get_pdf(self, docids, report_name, html=None, data=None):
"""This method generates and returns pdf version of a report.
"""
+
+ if self._check_wkhtmltopdf() == 'install':
+ # wkhtmltopdf is not installed
+ # the call should be catched before (cf /report/check_wkhtmltopdf) but
+ # if get_pdf is called manually (email template), the check could be
+ # bypassed
+ raise UserError(_("Unable to find Wkhtmltopdf on this system. The PDF can not be created."))
+
# As the assets are generated during the same transaction as the rendering of the
# templates calling them, there is a scenario where the assets are unreachable: when
# you make a request to read the assets while the transaction creating them is not done.
diff --git a/addons/report/static/src/js/qwebactionmanager.js b/addons/report/static/src/js/qwebactionmanager.js
index f67357e926a..4bd7b8c89ea 100644
--- a/addons/report/static/src/js/qwebactionmanager.js
+++ b/addons/report/static/src/js/qwebactionmanager.js
@@ -18,6 +18,7 @@ var WKHTMLTOPDF_MESSAGES = {
'install': _lt('Unable to find Wkhtmltopdf on this \nsystem. The report will be shown in html.
\nwkhtmltopdf.org'),
'workers': _lt('You need to start OpenERP with at least two \nworkers to print a pdf version of the reports.'),
'upgrade': _lt('You should upgrade your version of\nWkhtmltopdf to at least 0.12.0 in order to get a correct display of headers and footers as well as\nsupport for table-breaking between pages.
wkhtmltopdf.org'),
+ 'broken': _lt('Your installation of Wkhtmltopdf seems to be broken. The report will be shown in html.
wkhtmltopdf.org')
};
var trigger_download = function (session, response, c, action, options) {
diff --git a/addons/stock/models/stock_quant.py b/addons/stock/models/stock_quant.py
index 4b41e10361b..b5512c6d6e0 100644
--- a/addons/stock/models/stock_quant.py
+++ b/addons/stock/models/stock_quant.py
@@ -697,7 +697,6 @@ class QuantPackage(models.Model):
# TDE FIXME: why superuser ?
package.mapped('quant_ids').sudo().write({'package_id': package.parent_id.id})
package.mapped('children_ids').write({'parent_id': package.parent_id.id})
- self.unlink()
return self.env['ir.actions.act_window'].for_xml_id('stock', 'action_package_view')
@api.multi
diff --git a/addons/stock/models/stock_warehouse.py b/addons/stock/models/stock_warehouse.py
index 189618a7755..aa386c6b8b7 100644
--- a/addons/stock/models/stock_warehouse.py
+++ b/addons/stock/models/stock_warehouse.py
@@ -791,7 +791,7 @@ class Orderpoint(models.Model):
('qty_multiple_check', 'CHECK( qty_multiple >= 0 )', 'Qty Multiple must be greater than or equal to zero.'),
]
- @api.constrains('product_id', 'product_uom')
+ @api.constrains('product_id')
def _check_product_uom(self):
''' Check if the UoM has the same category as the product standard UoM '''
if any(orderpoint.product_id.uom_id.category_id != orderpoint.product_uom.category_id for orderpoint in self):
diff --git a/addons/stock/report/report_deliveryslip.xml b/addons/stock/report/report_deliveryslip.xml
index 579b38b3995..5511e1de8f5 100644
--- a/addons/stock/report/report_deliveryslip.xml
+++ b/addons/stock/report/report_deliveryslip.xml
@@ -12,7 +12,7 @@
Customer Address:
diff --git a/addons/web_editor/static/src/js/backend.js b/addons/web_editor/static/src/js/backend.js
index 8d05a92260c..9c6f1df5e8c 100644
--- a/addons/web_editor/static/src/js/backend.js
+++ b/addons/web_editor/static/src/js/backend.js
@@ -340,7 +340,7 @@ var FieldTextHtml = widget.extend({
$("body").toggleClass("o_form_FieldTextHtml_fullscreen");
var full = $("body").hasClass("o_form_FieldTextHtml_fullscreen");
self.$iframe.parents().toggleClass('o_form_fullscreen_ancestor', full);
- self.resize();
+ $(window).trigger("resize"); // induce a resize() call and let other backend elements know (the navbar extra items management relies on this)
});
this.$body.on('click', '[data-action="cancel"]', function (event) {
diff --git a/doc/cla/corporate/VanRoey.md b/doc/cla/corporate/VanRoey.md
index 956d6bb43a4..0e3122e27f4 100644
--- a/doc/cla/corporate/VanRoey.md
+++ b/doc/cla/corporate/VanRoey.md
@@ -13,6 +13,4 @@ Yenthe Van Ginneken yenthe.vanginneken@vanroey.be https://github.com/Yenthe666
List of contributors:
Yenthe Van Ginneken yenthe.vanginneken@vanroey.be https://github.com/Yenthe666
-Maarten Wijnants maarten.wijnants@vanroey.be https://github.com/weilant
Vincent Adriaensen vincent.adriaensen@vanroey.be https://github.com/vincentadriaensen
-Pieter Paulussen pieter.paulussen@vanroey.be https://github.com/PieterPaulussen
diff --git a/doc/cla/corporate/goopen.md b/doc/cla/corporate/goopen.md
index 91f5cded22a..5d562fed621 100644
--- a/doc/cla/corporate/goopen.md
+++ b/doc/cla/corporate/goopen.md
@@ -12,4 +12,5 @@ Aleš Ferlan alefer89@protonmail.com
List of contributors:
+Aleš Ferlan alefer89@gmail.com https://github.com/Alko89
Aleš Ferlan alefer89@protonmail.com
diff --git a/doc/cla/individual/Sergio2409.md b/doc/cla/individual/Sergio2409.md
new file mode 100644
index 00000000000..dd118d31abf
--- /dev/null
+++ b/doc/cla/individual/Sergio2409.md
@@ -0,0 +1,11 @@
+Cuba, 2016-10-24
+
+I hereby agree to the terms of the Odoo Individual Contributor License
+Agreement v1.0.
+
+I declare that I am authorized and able to make this agreement and sign this
+declaration.
+
+Signed,
+
+Sergio Valdés sergiov@merchise.org https://github.com/Sergio2409
diff --git a/odoo/addons/base/ir/ir_ui_view.py b/odoo/addons/base/ir/ir_ui_view.py
index fa7ca55c200..893eccd8d01 100644
--- a/odoo/addons/base/ir/ir_ui_view.py
+++ b/odoo/addons/base/ir/ir_ui_view.py
@@ -271,7 +271,7 @@ actual arch.
self.raise_view_error(message, self.id)
return True
- @api.constrains('arch', 'arch_base')
+ @api.constrains('arch_db')
def _check_xml(self):
# Sanity checks: the view should not break anything upon rendering!
# Any exception raised below will cause a transaction rollback.
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 5dbfbdf4f46..84b77d5852d 100644
--- a/odoo/addons/test_new_api/tests/test_new_fields.py
+++ b/odoo/addons/test_new_api/tests/test_new_fields.py
@@ -130,6 +130,26 @@ class TestFields(common.TransactionCase):
})
check_stored(discussion3)
+ def test_11_computed_access(self):
+ """ test computed fields with access right errors """
+ User = self.env['res.users']
+ user1 = User.create({'name': 'Aaaah', 'login': 'a'})
+ user2 = User.create({'name': 'Boooh', 'login': 'b'})
+ user3 = User.create({'name': 'Crrrr', 'login': 'c'})
+ # add a rule to not give access to user2
+ self.env['ir.rule'].create({
+ 'model_id': self.env['ir.model'].search([('model', '=', 'res.users')]).id,
+ 'domain_force': "[('id', '!=', %d)]" % user2.id,
+ })
+ # group users as a recordset, and read them as user demo
+ users = (user1 + user2 + user3).sudo(self.env.ref('base.user_demo'))
+ user1, user2, user3 = users
+ # regression test: a bug invalidated the field's value from cache
+ user1.company_type
+ with self.assertRaises(AccessError):
+ user2.company_type
+ user3.company_type
+
def test_12_recursive(self):
""" test recursively dependent fields """
Category = self.env['test_new_api.category']
diff --git a/odoo/fields.py b/odoo/fields.py
index 8971c239ac9..72e82249d54 100644
--- a/odoo/fields.py
+++ b/odoo/fields.py
@@ -922,15 +922,15 @@ class Field(object):
for field in fields:
for record in records:
record._cache[field] = field.convert_to_cache(False, record, validate=False)
- with records.env.protecting(fields, records):
- if isinstance(self.compute, basestring):
- getattr(records, self.compute)()
- else:
- self.compute(records)
+ if isinstance(self.compute, basestring):
+ getattr(records, self.compute)()
+ else:
+ self.compute(records)
def compute_value(self, records):
""" Invoke the compute method on ``records``; the results are in cache. """
- with records.env.do_in_draft():
+ fields = records._field_computed[self]
+ with records.env.do_in_draft(), records.env.protecting(fields, records):
try:
self._compute_value(records)
except (AccessError, MissingError):
diff --git a/odoo/models.py b/odoo/models.py
index c8287c3f9f9..3ac08b0f4bd 100644
--- a/odoo/models.py
+++ b/odoo/models.py
@@ -664,8 +664,11 @@ class BaseModel(object):
cls = type(self)
methods = []
for attr, func in getmembers(cls, is_constraint):
- if not all(name in cls._fields for name in func._constrains):
- _logger.warning("@constrains%r parameters must be field names", func._constrains)
+ for name in func._constrains:
+ if name not in cls._fields:
+ _logger.warning("method %s.%s: @constrains parameter %r is not a field name", cls._name, attr, name)
+ if not cls._fields[name].store:
+ _logger.warning("method %s.%s: @constrains parameter %r is not stored", cls._name, attr, name)
methods.append(func)
# optimization: memoize result on cls, it will not be recomputed