1).ids
+ visible_attrs_ids = product.attribute_line_ids.filtered(lambda l: len(l.value_ids) > 1).mapped('attribute_id').ids
to_currency = request.website.get_current_pricelist().currency_id
attribute_value_ids = []
for variant in product.product_variant_ids:
diff --git a/addons/website_sale/models/product.py b/addons/website_sale/models/product.py
index c436350c809..17516246a2b 100644
--- a/addons/website_sale/models/product.py
+++ b/addons/website_sale/models/product.py
@@ -2,6 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, tools, _
import odoo.addons.decimal_precision as dp
+from odoo.tools.translate import html_translate
class ProductStyle(models.Model):
@@ -108,7 +109,7 @@ class ProductTemplate(models.Model):
domain=lambda self: ['&', ('model', '=', self._name), ('message_type', '=', 'comment')],
string='Website Comments',
)
- website_description = fields.Html('Description for the website', sanitize_attributes=False, translate=True)
+ website_description = fields.Html('Description for the website', sanitize_attributes=False, translate=html_translate)
alternative_product_ids = fields.Many2many('product.template', 'product_alternative_rel', 'src_id', 'dest_id',
string='Alternative Products', help='Suggest more expensive alternatives to '
'your customers (upsell strategy). Those products show up on the product page.')
diff --git a/odoo/addons/base/ir/ir_http.py b/odoo/addons/base/ir/ir_http.py
index c63bd2f7226..6bca1edee58 100644
--- a/odoo/addons/base/ir/ir_http.py
+++ b/odoo/addons/base/ir/ir_http.py
@@ -324,7 +324,7 @@ class IrHttp(models.AbstractModel):
# cache
etag = hasattr(request, 'httprequest') and request.httprequest.headers.get('If-None-Match')
- retag = hashlib.md5(last_update).hexdigest()
+ retag = '"%s"' % hashlib.md5(last_update).hexdigest()
status = status or (304 if etag == retag else 200)
headers.append(('ETag', retag))
headers.append(('Cache-Control', 'max-age=%s' % (STATIC_CACHE if unique else 0)))
diff --git a/odoo/addons/base/res/res_partner_view.xml b/odoo/addons/base/res/res_partner_view.xml
index f5d1e819ded..92d4c41db55 100644
--- a/odoo/addons/base/res/res_partner_view.xml
+++ b/odoo/addons/base/res/res_partner_view.xml
@@ -140,6 +140,7 @@
+
diff --git a/odoo/addons/test_new_api/models.py b/odoo/addons/test_new_api/models.py
index 513fe06ca8c..5fc58ea976a 100644
--- a/odoo/addons/test_new_api/models.py
+++ b/odoo/addons/test_new_api/models.py
@@ -13,6 +13,7 @@ class Category(models.Model):
name = fields.Char(required=True)
color = fields.Integer('Color Index')
parent = fields.Many2one('test_new_api.category')
+ root_categ = fields.Many2one(_name, compute='_compute_root_categ')
display_name = fields.Char(compute='_compute_display_name', inverse='_inverse_display_name')
dummy = fields.Char(store=False)
discussions = fields.Many2many('test_new_api.discussion', 'test_new_api_discussion_category',
@@ -26,6 +27,14 @@ class Category(models.Model):
else:
self.display_name = self.name
+ @api.depends('parent')
+ def _compute_root_categ(self):
+ for cat in self:
+ current = cat
+ while current.parent:
+ current = current.parent
+ cat.root_categ = current
+
@api.one
def _inverse_display_name(self):
names = self.display_name.split('/')
diff --git a/odoo/addons/test_new_api/tests/test_onchange.py b/odoo/addons/test_new_api/tests/test_onchange.py
index 16d122c712c..87fc8229b7c 100644
--- a/odoo/addons/test_new_api/tests/test_onchange.py
+++ b/odoo/addons/test_new_api/tests/test_onchange.py
@@ -75,6 +75,33 @@ class TestOnChange(common.TransactionCase):
result = self.Message.onchange(values, 'body', field_onchange)
self.assertNotIn('name', result['value'])
+ def test_onchange_many2one(self):
+ Category = self.env['test_new_api.category']
+
+ field_onchange = Category._onchange_spec()
+ self.assertEqual(field_onchange.get('parent'), '1')
+
+ root = Category.create(dict(name='root'))
+
+ values = {
+ 'name': 'test',
+ 'parent': root.id,
+ 'root_categ': False,
+ }
+
+ self.env.invalidate_all()
+ result = Category.onchange(values, 'parent', field_onchange).get('value', {})
+ self.assertIn('root_categ', result)
+ self.assertEqual(result['root_categ'], root.name_get()[0])
+
+ values.update(result)
+ values['parent'] = False
+
+ self.env.invalidate_all()
+ result = Category.onchange(values, 'parent', field_onchange).get('value', {})
+ self.assertIn('root_categ', result)
+ self.assertIs(result['root_categ'], False)
+
def test_onchange_one2many(self):
""" test the effect of onchange() on one2many fields """
BODY = "What a beautiful day!"
diff --git a/odoo/addons/test_new_api/views.xml b/odoo/addons/test_new_api/views.xml
index b8c0f5bfa8b..0b053635319 100644
--- a/odoo/addons/test_new_api/views.xml
+++ b/odoo/addons/test_new_api/views.xml
@@ -205,6 +205,7 @@
+
diff --git a/odoo/fields.py b/odoo/fields.py
index 4d3f43f0fa7..d6dfe499f28 100644
--- a/odoo/fields.py
+++ b/odoo/fields.py
@@ -1898,6 +1898,10 @@ class Many2one(_Relational):
def convert_to_display_name(self, value, record):
return ustr(value.display_name)
+ def convert_to_onchange(self, value, record, fnames=()):
+ if not value.id:
+ return False
+ return super(Many2one, self).convert_to_onchange(value, record, fnames)
class UnionUpdate(SpecialValue):
""" Placeholder for a value update; when this value is taken from the cache,
@@ -1923,10 +1927,10 @@ class _RelationalMulti(_Relational):
""" Update the cached value of ``self`` for ``records`` with ``value``. """
for record in records:
if self in record._cache:
- value = self.convert_to_cache(record[self.name] | value, record, validate=False)
+ val = self.convert_to_cache(record[self.name] | value, record, validate=False)
else:
- value = UnionUpdate(self, record, value)
- record._cache[self] = value
+ val = UnionUpdate(self, record, value)
+ record._cache[self] = val
def convert_to_cache(self, value, record, validate=True):
# cache format: tuple(ids)
diff --git a/odoo/modules/module.py b/odoo/modules/module.py
index 66cbae460f0..1ff0d2d0ed1 100644
--- a/odoo/modules/module.py
+++ b/odoo/modules/module.py
@@ -156,7 +156,7 @@ def get_module_path(module, downloaded=False, display_warning=True):
"""
initialize_sys_path()
for adp in ad_paths:
- if os.path.exists(opj(adp, module)) or os.path.exists(opj(adp, '%s.zip' % module)):
+ if os.path.exists(opj(adp, module, MANIFEST)) or os.path.exists(opj(adp, '%s.zip' % module)):
return opj(adp, module)
if downloaded:
diff --git a/odoo/tools/convert.py b/odoo/tools/convert.py
index 089210d6f99..3c3eba3bec6 100644
--- a/odoo/tools/convert.py
+++ b/odoo/tools/convert.py
@@ -746,7 +746,8 @@ form: module.record_id""" % (xml_id,)
record.append(Field(name, name='name'))
record.append(Field(full_tpl_id, name='key'))
record.append(Field("qweb", name='type'))
- record.append(Field(el.get('priority', "16"), name='priority'))
+ if 'priority' in el.attrib:
+ record.append(Field(el.get('priority'), name='priority'))
if 'inherit_id' in el.attrib:
record.append(Field(name='inherit_id', ref=el.get('inherit_id')))
if 'website_id' in el.attrib: