diff --git a/addons/account/data/mail_template_data.xml b/addons/account/data/mail_template_data.xml index 55518c79549..25d54c81c85 100644 --- a/addons/account/data/mail_template_data.xml +++ b/addons/account/data/mail_template_data.xml @@ -71,7 +71,7 @@ from ${object.company_id.name}.
% set record = ctx.get('record') -% set company = record and record.company_id or user.company_id +% set company = record and record.company_id or ctx.get('company') diff --git a/addons/account_check_printing/models/account_payment.py b/addons/account_check_printing/models/account_payment.py index c610ff3ee84..3409ef51a66 100644 --- a/addons/account_check_printing/models/account_payment.py +++ b/addons/account_check_printing/models/account_payment.py @@ -9,7 +9,7 @@ class AccountRegisterPayments(models.TransientModel): _inherit = "account.register.payments" check_amount_in_words = fields.Char(string="Amount in Words") - check_manual_sequencing = fields.Boolean(related='journal_id.check_manual_sequencing') + check_manual_sequencing = fields.Boolean(related='journal_id.check_manual_sequencing', readonly=1) # Note: a check_number == 0 means that it will be attributed when the check is printed check_number = fields.Integer(string="Check Number", readonly=True, copy=False, default=0, help="Number of the check corresponding to this payment. If your pre-printed check are not already numbered, " @@ -32,7 +32,6 @@ class AccountRegisterPayments(models.TransientModel): res = super(AccountRegisterPayments, self)._prepare_payment_vals(invoices) if self.payment_method_id == self.env.ref('account_check_printing.account_payment_method_check'): res.update({ - 'check_amount_in_words': self.currency_id.amount_to_text(res['amount']) if self.multi else self.check_amount_in_words, 'check_manual_sequencing': self.check_manual_sequencing, }) return res diff --git a/addons/hr_holidays/models/hr_holidays.py b/addons/hr_holidays/models/hr_holidays.py index c7b0609efe0..907d5f8c36b 100644 --- a/addons/hr_holidays/models/hr_holidays.py +++ b/addons/hr_holidays/models/hr_holidays.py @@ -253,7 +253,7 @@ class Holidays(models.Model): if nholidays: raise ValidationError(_('You can not have 2 leaves that overlaps on same day!')) - @api.constrains('state', 'number_of_days_temp') + @api.constrains('state', 'number_of_days_temp', 'holiday_status_id') def _check_holidays(self): for holiday in self: if holiday.holiday_type != 'employee' or holiday.type != 'remove' or not holiday.employee_id or holiday.holiday_status_id.limit: diff --git a/addons/l10n_mx/data/account_tag_data.xml b/addons/l10n_mx/data/account_tag_data.xml index 5160151c821..244c9b65ff3 100644 --- a/addons/l10n_mx/data/account_tag_data.xml +++ b/addons/l10n_mx/data/account_tag_data.xml @@ -5399,7 +5399,7 @@ 802.02 Contra cuenta CUFIN4accounts - D + A 803.01 CUFIN de ejercicios anteriores diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py index 661d4f755a4..ac747d90d91 100644 --- a/addons/mrp/models/mrp_production.py +++ b/addons/mrp/models/mrp_production.py @@ -389,7 +389,7 @@ class MrpProduction(models.Model): source_location = routing.location_id else: source_location = self.location_src_id - original_quantity = self.product_qty - self.qty_produced + original_quantity = (self.product_qty - self.qty_produced) or 1.0 data = { 'sequence': bom_line.sequence, 'name': self.name, diff --git a/addons/purchase/data/mail_template_data.xml b/addons/purchase/data/mail_template_data.xml index 74ef46f2846..aa2f852a9ac 100644 --- a/addons/purchase/data/mail_template_data.xml +++ b/addons/purchase/data/mail_template_data.xml @@ -86,6 +86,7 @@ from ${object.company_id.name}. + % set company = record and record.company_id or ctx.get('company')
@@ -101,7 +102,7 @@ from ${object.company_id.name}.
- ${user.company_id.name} + ${company.name}
@@ -127,16 +128,16 @@ from ${object.company_id.name}. diff --git a/addons/purchase/i18n/purchase.pot b/addons/purchase/i18n/purchase.pot index da81a3b66eb..605455c3be7 100644 --- a/addons/purchase/i18n/purchase.pot +++ b/addons/purchase/i18n/purchase.pot @@ -130,6 +130,7 @@ msgstr "" #: model:mail.template,body_html:purchase.mail_template_data_notification_email_purchase_order msgid "\n" " \n" +" % set company = record and record.company_id or or ctx.get('company')\n" " \n" "
- ${user.company_id.name}
- ${user.company_id.phone or ''} + ${company.name}
+ ${company.phone or ''}
- % if user.company_id.email: - ${user.company_id.email}
+ % if company.email: + ${company.email}
% endif - % if user.company_id.website: - - ${user.company_id.website} + % if company.website: + + ${company.website} % endif
\n" " \n" @@ -145,7 +146,7 @@ msgid "\n" " \n" " \n" " \n" " \n" "
\n" -" \"${user.company_id.name}\"\n" +" \"${company.name}\"\n" "
\n" @@ -171,16 +172,16 @@ msgid "\n" " \n" " \n" " \n" " \n" diff --git a/addons/sale/data/mail_template_data.xml b/addons/sale/data/mail_template_data.xml index 473da40a96c..1a584b765f5 100644 --- a/addons/sale/data/mail_template_data.xml +++ b/addons/sale/data/mail_template_data.xml @@ -70,7 +70,7 @@ from ${object.company_id.name}. % set record = ctx.get('record') - % set company = record and record.company_id or user.company_id + % set company = record and record.company_id or ctx.get('company')
\n" -" ${user.company_id.name}
\n" -" ${user.company_id.phone or ''}\n" +" ${company.name}
\n" +" ${company.phone or ''}\n" "
\n" -" % if user.company_id.email:\n" -" ${user.company_id.email}
\n" +" % if company.email:\n" +" ${company.email}
\n" " % endif\n" -" % if user.company_id.website:\n" -" \n" -" ${user.company_id.website}\n" +" % if company.website:\n" +" \n" +" ${company.website}\n" " \n" " % endif\n" "
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 91d178bc69c..03f73d8f947 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -28,6 +28,7 @@ import werkzeug.wsgi from collections import OrderedDict from werkzeug.urls import url_decode, iri_to_uri from xml.etree import ElementTree +import unicodedata import odoo @@ -1110,20 +1111,27 @@ class Binary(http.Controller): """ args = [] for ufile in files: + + filename = ufile.filename + if request.httprequest.user_agent.browser == 'safari': + # Safari sends NFD UTF-8 (where é is composed by 'e' and [accent]) + # we need to send it the same stuff, otherwise it'll fail + filename = unicodedata.normalize('NFD', ufile.filename).encode('UTF-8') + try: attachment = Model.create({ - 'name': ufile.filename, + 'name': filename, 'datas': base64.encodestring(ufile.read()), - 'datas_fname': ufile.filename, + 'datas_fname': filename, 'res_model': model, 'res_id': int(id) }) except Exception: - args = args.append({'error': _("Something horrible happened")}) + args.append({'error': _("Something horrible happened")}) _logger.exception("Fail to upload attachment %s" % ufile.filename) else: args.append({ - 'filename': ufile.filename, + 'filename': filename, 'mimetype': ufile.content_type, 'id': attachment.id }) diff --git a/addons/web_editor/static/src/js/editor/rte.summernote.js b/addons/web_editor/static/src/js/editor/rte.summernote.js index 9a2d04eeca5..15c1ef5655d 100644 --- a/addons/web_editor/static/src/js/editor/rte.summernote.js +++ b/addons/web_editor/static/src/js/editor/rte.summernote.js @@ -663,7 +663,15 @@ function summernote_mousedown(event) { } // restore range if range lost after clicking on non-editable area - r = range.create(); + try { + r = range.create(); + } catch (e) { + // If this code is running inside an iframe-editor and that the range + // is outside of this iframe, this will fail as the iframe does not have + // the permission to check the outside content this way. In that case, + // we simply ignore the exception as it is as if there was no range. + return; + } var editables = $(".o_editable[contenteditable], .note-editable[contenteditable]"); var r_editable = editables.has((r||{}).sc); if (!r_editable.closest('.note-editor').is($editable) && !r_editable.filter('.o_editable').is(editables)) { diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index ffc4452e790..21158500e00 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -2,7 +2,7 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. import json import logging -from werkzeug.exceptions import Forbidden +from werkzeug.exceptions import Forbidden, NotFound from odoo import http, tools, _ from odoo.http import request @@ -217,6 +217,11 @@ class WebsiteSale(http.Controller): else: ppg = PPG + if category: + category = request.env['product.public.category'].search([('id', '=', int(category))], limit=1) + if not category: + raise NotFound() + attrib_list = request.httprequest.args.getlist('attrib') attrib_values = [[int(x) for x in v.split("-")] for v in attrib_list if v] attributes_ids = {v[0] for v in attrib_values} @@ -233,9 +238,6 @@ class WebsiteSale(http.Controller): url = "/shop" if search: post["search"] = search - if category: - category = request.env['product.public.category'].browse(int(category)) - url = "/shop/category/%s" % slug(category) if attrib_list: post['attrib'] = attrib_list @@ -244,6 +246,7 @@ class WebsiteSale(http.Controller): parent_category_ids = [] if category: + url = "/shop/category/%s" % slug(category) parent_category_ids = [category.id] current_category = category while current_category.parent_id: diff --git a/odoo/addons/base/ir/ir_ui_view.py b/odoo/addons/base/ir/ir_ui_view.py index 328f3aca56a..6a49f15e90a 100644 --- a/odoo/addons/base/ir/ir_ui_view.py +++ b/odoo/addons/base/ir/ir_ui_view.py @@ -1309,7 +1309,7 @@ actual arch. query = """SELECT max(v.id) FROM ir_ui_view v LEFT JOIN ir_model_data md ON (md.model = 'ir.ui.view' AND md.res_id = v.id) - WHERE md.module NOT IN (SELECT name FROM ir_module_module) + WHERE md.module IN (SELECT name FROM ir_module_module) IS NOT TRUE AND v.model = %s AND v.active = true GROUP BY coalesce(v.inherit_id, v.id)"""