diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py
index 771ed8f2bd6..b669bdfc3ba 100644
--- a/addons/website_sale/controllers/main.py
+++ b/addons/website_sale/controllers/main.py
@@ -500,7 +500,7 @@ class WebsiteSale(http.Controller):
def _checkout_form_save(self, mode, checkout, all_values):
Partner = request.env['res.partner']
if mode[0] == 'new':
- partner_id = Partner.sudo().create(checkout)
+ partner_id = Partner.sudo().create(checkout).id
elif mode[0] == 'edit':
partner_id = int(all_values.get('partner_id', 0))
if partner_id:
diff --git a/addons/website_sale/models/product.py b/addons/website_sale/models/product.py
index d3e1c6b893a..5d372588088 100644
--- a/addons/website_sale/models/product.py
+++ b/addons/website_sale/models/product.py
@@ -190,7 +190,9 @@ class Product(models.Model):
def _website_price(self):
qty = self._context.get('quantity', 1.0)
partner = self.env.user.partner_id
- pricelist = self.env['website'].get_current_website().get_current_pricelist()
+ current_website = self.env['website'].get_current_website()
+ pricelist = current_website.get_current_pricelist()
+ company_id = current_website.company_id
context = dict(self._context, pricelist=pricelist.id, partner=partner)
self2 = self.with_context(context) if self._context != context else self
@@ -198,7 +200,7 @@ class Product(models.Model):
ret = self.env.user.has_group('sale.group_show_price_subtotal') and 'total_excluded' or 'total_included'
for p, p2 in zip(self, self2):
- taxes = partner.property_account_position_id.map_tax(p.taxes_id)
+ taxes = partner.property_account_position_id.map_tax(p.taxes_id.filtered(lambda x: x.company_id == company_id))
p.website_price = taxes.compute_all(p2.price, pricelist.currency_id, quantity=qty, product=p2, partner=partner)[ret]
p.website_public_price = taxes.compute_all(p2.lst_price, quantity=qty, product=p2, partner=partner)[ret]
diff --git a/addons/website_sale/models/sale_order.py b/addons/website_sale/models/sale_order.py
index 880c3a62171..3cbeccdc513 100644
--- a/addons/website_sale/models/sale_order.py
+++ b/addons/website_sale/models/sale_order.py
@@ -459,7 +459,7 @@ class Website(models.Model):
else:
request.session['sale_order_id'] = None
- return None
+ return self.env['sale.order']
return sale_order
diff --git a/addons/website_sale_digital/controllers/main.py b/addons/website_sale_digital/controllers/main.py
index b633596a0bf..7977b44bac8 100644
--- a/addons/website_sale_digital/controllers/main.py
+++ b/addons/website_sale_digital/controllers/main.py
@@ -101,6 +101,6 @@ class WebsiteSaleDigital(website_account):
return request.not_found()
elif attachment["datas"]:
data = StringIO(base64.standard_b64decode(attachment["datas"]))
- return http.send_file(data, filename=attachment['name'], as_attachment=True)
+ return http.send_file(data, filename=attachment['name'].encode('utf-8'), as_attachment=True)
else:
return request.not_found()
diff --git a/doc/cla/corporate/vauxoo.md b/doc/cla/corporate/vauxoo.md
index 036e1a63620..096c835ef55 100644
--- a/doc/cla/corporate/vauxoo.md
+++ b/doc/cla/corporate/vauxoo.md
@@ -36,4 +36,5 @@ Luis González lgonzalez@vauxoo.com https://github.com/luisg123v
Oriana Maita oriana@vauxoo.com https://github.com/maitaoriana
Gabriela Mogollon gmogollon@vauxoo.com https://github.com/GavyMG
Jesus Zapata jesus@vauxoo.com https://github.com/JesusZapata
-Germana Oliveira germana@vauxoo.com https://github.com/goliveirab
\ No newline at end of file
+Germana Oliveira germana@vauxoo.com https://github.com/goliveirab
+Mariano Fernandez mariano@vauxoo.com https://github.com/Batuto
diff --git a/doc/cla/individual/NothingCtrl.md b/doc/cla/individual/NothingCtrl.md
new file mode 100644
index 00000000000..bf58b0034d3
--- /dev/null
+++ b/doc/cla/individual/NothingCtrl.md
@@ -0,0 +1,9 @@
+Vietnam, 2017-08-15
+
+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,
+
+Duong Bao Thang nothingctrl@gmail.com https://github.com/NothingCtrl
diff --git a/doc/cla/individual/repodevs.md b/doc/cla/individual/repodevs.md
new file mode 100644
index 00000000000..06f8ec2f166
--- /dev/null
+++ b/doc/cla/individual/repodevs.md
@@ -0,0 +1,10 @@
+Indonesia, 2017-08-12
+
+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,
+Edi Santoso repodevs@gmail.com https://github.com/repodevs
diff --git a/doc/reference/cmdline.rst b/doc/reference/cmdline.rst
index c92a8b034a9..b8881e9a935 100644
--- a/doc/reference/cmdline.rst
+++ b/doc/reference/cmdline.rst
@@ -159,7 +159,11 @@ database
- ``%h`` is replaced by the whole hostname the request is made on.
- ``%d`` is replaced by the subdomain the request is made on, with the
exception of ``www`` (so domain ``odoo.com`` and ``www.odoo.com`` both
- match the database ``odoo``)
+ match the database ``odoo``).
+
+ These operations are case sensitive. Add option ``(?i)`` to match all
+ databases (so domain ``odoo.com`` using ``(?i)%d`` matches the database
+ ``Odoo``).
.. option:: --db-template
diff --git a/doc/reference/views.rst b/doc/reference/views.rst
index 386989b75c6..5d760b611be 100644
--- a/doc/reference/views.rst
+++ b/doc/reference/views.rst
@@ -840,17 +840,13 @@ attributes:
Possible children of the view element are:
``field``
- declares fields to aggregate or to use in kanban *logic*. If the field is
- simply displayed in the kanban view, it does not need to be pre-declared.
+ declares fields to use in kanban *logic*. If the field is simply displayed in
+ the kanban view, it does not need to be pre-declared.
Possible attributes are:
``name`` (required)
the name of the field to fetch
- ``sum``, ``avg``, ``min``, ``max``, ``count``
- displays the corresponding aggregation at the top of a kanban column, the
- field's value is the label of the aggregation (a string). Only one
- aggregate operation per field is supported.
``templates``
defines a list of :ref:`reference/qweb` templates. Cards definition may be
diff --git a/odoo/addons/base/ir/ir_model.py b/odoo/addons/base/ir/ir_model.py
index f3d65226877..411395b300b 100644
--- a/odoo/addons/base/ir/ir_model.py
+++ b/odoo/addons/base/ir/ir_model.py
@@ -512,7 +512,8 @@ class IrModelFields(models.Model):
if field.state == 'manual' and field.ttype == 'many2many':
rel_name = field.relation_table or model._fields[field.name].relation
tables_to_drop.add(rel_name)
- model._pop_field(field.name)
+ if field.state == 'manual':
+ model._pop_field(field.name)
if tables_to_drop:
# drop the relation tables that are not used by other fields
diff --git a/odoo/addons/base/ir/ir_qweb/ir_qweb.py b/odoo/addons/base/ir/ir_qweb/ir_qweb.py
index ddb1c64d73d..a3e63df6bea 100644
--- a/odoo/addons/base/ir/ir_qweb/ir_qweb.py
+++ b/odoo/addons/base/ir/ir_qweb/ir_qweb.py
@@ -62,7 +62,7 @@ class IrQWeb(models.AbstractModel, QWeb):
# assume cache will be invalidated by third party on write to ir.ui.view
def _get_template_cache_keys(self):
""" Return the list of context keys to use for caching ``_get_template``. """
- return ['lang', 'inherit_branding', 'editable', 'translatable', 'edit_translations']
+ return ['lang', 'inherit_branding', 'editable', 'translatable', 'edit_translations', 'website_id']
# apply ormcache_context decorator unless in dev mode...
@tools.conditional(
@@ -186,14 +186,14 @@ class IrQWeb(models.AbstractModel, QWeb):
# in non-xml-debug mode we want assets to be cached forever, and the admin can force a cache clear
# by restarting the server after updating the source code (or using the "Clear server cache" in debug tools)
'xml' not in tools.config['dev_mode'],
- tools.ormcache('xmlid', 'options.get("lang", "en_US")', 'css', 'js', 'debug', 'async'),
+ tools.ormcache_context('xmlid', 'options.get("lang", "en_US")', 'css', 'js', 'debug', 'async', keys=("website_id",)),
)
def _get_asset(self, xmlid, options, css=True, js=True, debug=False, async=False, values=None):
files, remains = self._get_asset_content(xmlid, options)
asset = AssetsBundle(xmlid, files, remains, env=self.env)
return asset.to_html(css=css, js=js, debug=debug, async=async, url_for=(values or {}).get('url_for', lambda url: url))
- @tools.ormcache('xmlid', 'options.get("lang", "en_US")')
+ @tools.ormcache_context('xmlid', 'options.get("lang", "en_US")', keys=("website_id",))
def _get_asset_content(self, xmlid, options):
options = dict(options,
inherit_branding=False, inherit_branding_auto=False,
diff --git a/odoo/addons/base/ir/ir_ui_view.py b/odoo/addons/base/ir/ir_ui_view.py
index 407a3385950..7f8578c2b7b 100644
--- a/odoo/addons/base/ir/ir_ui_view.py
+++ b/odoo/addons/base/ir/ir_ui_view.py
@@ -429,6 +429,15 @@ actual arch.
#------------------------------------------------------
# Inheritance mecanism
#------------------------------------------------------
+ @api.model
+ def _get_inheriting_views_arch_domain(self, view_id, model):
+ return [
+ ['inherit_id', '=', view_id],
+ ['model', '=', model],
+ ['mode', '=', 'extension'],
+ ['active', '=', True],
+ ]
+
@api.model
def get_inheriting_views_arch(self, view_id, model):
"""Retrieves the architecture of views that inherit from the given view, from the sets of
@@ -444,13 +453,8 @@ actual arch.
:return: [(view_arch,view_id), ...]
"""
user_groups = self.env.user.groups_id
+ conditions = self._get_inheriting_views_arch_domain(view_id, model)
- conditions = [
- ['inherit_id', '=', view_id],
- ['model', '=', model],
- ['mode', '=', 'extension'],
- ['active', '=', True],
- ]
if self.pool._init and not self._context.get('load_all_views'):
# Module init currently in progress, only consider views from
# modules whose code is already loaded
@@ -917,7 +921,7 @@ actual arch.
def _read_template_keys(self):
""" Return the list of context keys to use for caching ``_read_template``. """
- return ['lang', 'inherit_branding', 'editable', 'translatable', 'edit_translations']
+ return ['lang', 'inherit_branding', 'editable', 'translatable', 'edit_translations', 'website_id']
# apply ormcache_context decorator unless in dev mode...
@api.model
diff --git a/odoo/addons/base/res/res_config.py b/odoo/addons/base/res/res_config.py
index 73eb71580f1..f1bb5ffff74 100644
--- a/odoo/addons/base/res/res_config.py
+++ b/odoo/addons/base/res/res_config.py
@@ -522,7 +522,10 @@ class ResConfigSettings(models.TransientModel, ResConfigModuleInstallationMixin)
IrValues = self.env['ir.values'].sudo()
for name, model, field in classified['default']:
if isinstance(self[name], models.BaseModel):
- value = self[name].ids
+ if self._fields[name].type == 'many2one':
+ value = self[name].id
+ else:
+ value = self[name].ids
else:
value = self[name]
IrValues.set_default(model, field, value)
diff --git a/odoo/api.py b/odoo/api.py
index 1adbd08f6e5..413a6b8a2a5 100644
--- a/odoo/api.py
+++ b/odoo/api.py
@@ -155,6 +155,14 @@ def constrains(*args):
``@constrains`` only supports simple field names, dotted names
(fields of relational fields e.g. ``partner_id.customer``) are not
supported and will be ignored
+
+ ``@constrains`` will be triggered only if the declared fields in the
+ decorated method are included in the ``create`` or ``write`` call.
+ It implies that fields not present in a view will not trigger a call
+ during a record creation. A override of ``create`` is necessary to make
+ sure a constraint will always be triggered (e.g. to test the absence of
+ value).
+
"""
return attrsetter('_constrains', args)
diff --git a/odoo/models.py b/odoo/models.py
index d6417b0b7cd..e6862d70e15 100644
--- a/odoo/models.py
+++ b/odoo/models.py
@@ -781,7 +781,7 @@ class BaseModel(object):
# avoid broken transaction) and keep going
cr.execute('ROLLBACK TO SAVEPOINT model_load_save')
except Exception as e:
- message = (_('Unknown error during import:') + ' %s: %s' % (type(e), unicode(e)))
+ message = (_('Unknown error during import:') + ' %s: %s' % (type(e), unicode(e.message or e.name)))
moreinfo = _('Resolve other errors first')
messages.append(dict(info, type='error', message=message, moreinfo=moreinfo))
# Failed for some reason, perhaps due to invalid data supplied,