diff --git a/addons/calendar/controllers/bus.py b/addons/calendar/controllers/bus.py index 90203db4463..4ed07ebba9e 100644 --- a/addons/calendar/controllers/bus.py +++ b/addons/calendar/controllers/bus.py @@ -10,5 +10,6 @@ class CalendarBusController(BusController): # -------------------------- def _poll(self, dbname, channels, last, options): if request.session.uid: + channels = list(channels) channels.append((request.db, 'calendar.alarm', request.env.user.partner_id.id)) return super(CalendarBusController, self)._poll(dbname, channels, last, options) diff --git a/addons/google_account/models/google_service.py b/addons/google_account/models/google_service.py index 07fa2d12cf5..cd046ec95a7 100644 --- a/addons/google_account/models/google_service.py +++ b/addons/google_account/models/google_service.py @@ -139,7 +139,11 @@ class GoogleService(models.TransientModel): if error.code == 400: # invalid grant with registry(request.session.db).cursor() as cur: self.env(cur)['res.users'].browse(self.env.uid).write({'google_%s_rtoken' % service: False}) - error_key = json.loads(error.read()).get("error", "nc") + try: + error_file = error.read() + error_key = json.loads(error_file).get("error", "nc") + except: + error_key = error _logger.exception("Bad google request : %s !", error_key) error_msg = _("Something went wrong during your token generation. Maybe your Authorization Code is invalid or already expired [%s]") % error_key raise self.env['res.config.settings'].get_config_warning(error_msg) diff --git a/addons/product/views/product_views.xml b/addons/product/views/product_views.xml index b5389153168..78de88c74da 100644 --- a/addons/product/views/product_views.xml +++ b/addons/product/views/product_views.xml @@ -112,7 +112,7 @@ - + diff --git a/addons/product_extended/models/product.py b/addons/product_extended/models/product.py index 11a7bdc07ef..f0f886b66d4 100644 --- a/addons/product_extended/models/product.py +++ b/addons/product_extended/models/product.py @@ -35,7 +35,6 @@ class ProductProduct(models.Model): def _calc_price(self, bom): price = 0.0 - workcenter_cost = 0.0 result, result2 = bom.explode(self, 1) for sbom, sbom_data in result2: if not sbom.attribute_value_ids: @@ -44,9 +43,8 @@ class ProductProduct(models.Model): if bom.routing_id: total_cost = 0.0 for order in bom.routing_id.operation_ids: - total_cost += (order.time_cycle_manual/60) * order.workcenter_id.costs_hour - workcenter_cost = total_cost / len(bom.routing_id.operation_ids) - price += bom.product_uom_id._compute_price(workcenter_cost, bom.product_id.uom_id) + total_cost += (order.time_cycle/60) * order.workcenter_id.costs_hour + price += bom.product_uom_id._compute_price(total_cost, bom.product_id.uom_id) # Convert on product UoM quantities if price > 0: price = bom.product_uom_id._compute_price(price / bom.product_qty, self.uom_id) diff --git a/addons/web_editor/static/src/js/snippets.editor.js b/addons/web_editor/static/src/js/snippets.editor.js index 42f2103f95f..e5d184117f4 100644 --- a/addons/web_editor/static/src/js/snippets.editor.js +++ b/addons/web_editor/static/src/js/snippets.editor.js @@ -1118,7 +1118,7 @@ data.Editor = Class.extend({ }).bind(this)); // Activate the overlay - $style_button.toggleClass("hidden", $ul.children(":not(.divider):not(.hidden)").length === 0); + $style_button.toggleClass("hidden", $ul.children(":not(.o_main_header):not(.divider):not(.hidden)").length === 0); this.$overlay.toggleClass("oe_active", !!focus); function _do_action_focus(style, $dest) { diff --git a/addons/web_editor/static/src/js/snippets.options.js b/addons/web_editor/static/src/js/snippets.options.js index 4d533cadd00..1444f404ff6 100644 --- a/addons/web_editor/static/src/js/snippets.options.js +++ b/addons/web_editor/static/src/js/snippets.options.js @@ -576,15 +576,18 @@ odoo.define('web_editor.snippets.options', function (require) { registry.background = SnippetOption.extend({ start: function () { var res = this._super.apply(this, arguments); - this.$target.off(".background-option") - .on("background-color-event.background-option", (function (e, type) { - e.stopPropagation(); - if (e.currentTarget !== e.target) return; - this.$el.find("li:first > a").trigger(type); - }).bind(this)); + this.bind_bg_events(); return res; }, + bind_bg_events: function () { + this.$target.off(".background-option") + .on("background-color-event.background-option", (function (e, type) { + e.stopPropagation(); + if (e.currentTarget !== e.target) return; + this.$el.find("li:first > a").trigger(type); + }).bind(this)); + }, background: function (type, value, $li) { if (value && value.length) { this.$target.css("background-image", "url(" + value + ")"); diff --git a/addons/web_tour/static/src/less/tip.less b/addons/web_tour/static/src/less/tip.less index 8f994e64ee7..b2679e886c8 100644 --- a/addons/web_tour/static/src/less/tip.less +++ b/addons/web_tour/static/src/less/tip.less @@ -238,3 +238,9 @@ } } } + +@media print { + .o_tooltip { + display: none; + } +} diff --git a/addons/website/static/src/js/website.snippets.editor.js b/addons/website/static/src/js/website.snippets.editor.js index 1e62ed557f7..339c7437afe 100644 --- a/addons/website/static/src/js/website.snippets.editor.js +++ b/addons/website/static/src/js/website.snippets.editor.js @@ -228,6 +228,9 @@ options.registry.carousel = options.registry.slider.extend({ s_option.$target = self.$target.find(".item.active"); s_option.set_active(); s_option.$target.trigger("snippet-option-change", [s_option]); + if (opt_name === 'background') { + s_option.bind_bg_events(); + } }); }); this.$target.trigger('slid.bs.carousel'); diff --git a/addons/website_forum/controllers/main.py b/addons/website_forum/controllers/main.py index ca536bc28bd..fb21827b0fe 100644 --- a/addons/website_forum/controllers/main.py +++ b/addons/website_forum/controllers/main.py @@ -152,7 +152,7 @@ class WebsiteForum(http.Controller): question_ids = Post.search(domain, limit=self._post_per_page, offset=pager['offset'], order=sorting) - values = self._prepare_forum_values(forum=forum, searches=post) + values = self._prepare_forum_values(forum=forum, searches=post, header={'ask_hide': not forum.active}) values.update({ 'main_object': tag or forum, 'question_ids': question_ids, diff --git a/addons/website_portal_sale/controllers/main.py b/addons/website_portal_sale/controllers/main.py index 0fe93347abf..00d2e8377ac 100644 --- a/addons/website_portal_sale/controllers/main.py +++ b/addons/website_portal_sale/controllers/main.py @@ -150,9 +150,12 @@ class website_account(website_account): order.check_access_rule('read') except AccessError: return request.render("website.403") - order_invoice_lines = {il.product_id.id: il.invoice_id for il in order.invoice_ids.mapped('invoice_line_ids')} + + order_sudo = order.sudo() + order_invoice_lines = {il.product_id.id: il.invoice_id for il in order_sudo.invoice_ids.mapped('invoice_line_ids')} + return request.render("website_portal_sale.orders_followup", { - 'order': order.sudo(), + 'order': order_sudo, 'order_invoice_lines': order_invoice_lines, }) diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index c175ee6cd4f..122499bca3d 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -235,7 +235,9 @@ class WebsiteSale(http.Controller): ProductAttribute = request.env['product.attribute'] if products: - attributes = ProductAttribute.search([('attribute_line_ids.product_tmpl_id', 'in', products.ids)]) + # get all products without limit + selected_products = Product.search(domain, limit=False) + attributes = ProductAttribute.search([('attribute_line_ids.product_tmpl_id', 'in', selected_products.ids)]) else: attributes = ProductAttribute.browse(attributes_ids) diff --git a/odoo/service/model.py b/odoo/service/model.py index 8ad94fd4f56..fb81676db0c 100644 --- a/odoo/service/model.py +++ b/odoo/service/model.py @@ -57,10 +57,15 @@ def check(f): elif isinstance(kwargs, dict): if 'context' in kwargs: ctx = kwargs['context'] - elif 'kwargs' in kwargs: + elif 'kwargs' in kwargs and kwargs['kwargs'].get('context'): # http entry points such as call_kw() ctx = kwargs['kwargs'].get('context') - + else: + try: + from odoo.http import request + ctx = request.env.context + except Exception: + pass uid = 1 if args and isinstance(args[0], (long, int)): @@ -74,29 +79,6 @@ def check(f): # queries (as in IntegrityError) will invalidate the current one. cr = False - if hasattr(src, '__call__'): - # callable. We need to find the right parameters to call - # the orm._sql_message(self, cr, uid, ids, context) function, - # or we skip.. - # our signature is f(registry, dbname [,uid, obj, method, args]) - try: - if args and len(args) > 1: - # TODO self doesn't exist, but was already wrong before (it was not a registry but just the object_service. - obj = self.get(args[1]) - if len(args) > 3 and isinstance(args[3], (long, int, list)): - ids = args[3] - else: - ids = [] - cr = odoo.sql_db.db_connect(dbname).cursor() - return src(obj, cr, uid, ids, context=(ctx or {})) - except Exception: - pass - finally: - if cr: cr.close() - - return False # so that the original SQL error will - # be returned, it is the best we have. - try: cr = odoo.sql_db.db_connect(dbname).cursor() res = translate(cr, name=False, source_type=ttype, diff --git a/odoo/tools/misc.py b/odoo/tools/misc.py index 36061213003..c54af653a00 100644 --- a/odoo/tools/misc.py +++ b/odoo/tools/misc.py @@ -196,7 +196,16 @@ def file_open(name, mode="r", subdir='addons', pathinfo=False): def _fileopen(path, mode, basedir, pathinfo, basename=None): - name = os.path.normpath(os.path.join(basedir, path)) + name = os.path.normpath(os.path.normcase(os.path.join(basedir, path))) + + import odoo.modules as addons + paths = addons.module.ad_paths + [config['root_path']] + for addons_path in paths: + addons_path = os.path.normpath(os.path.normcase(addons_path)) + os.sep + if name.startswith(addons_path): + break + else: + raise ValueError("Unknown path: %s" % name) if basename is None: basename = name