From 3418c91f13b9c3f56b7a63e1e22a544a494dc072 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Fri, 7 Jul 2017 14:37:01 +0200 Subject: [PATCH 01/13] [FIX] product: fallback in category_all does not exists self.enf.ref returns None if the record is not found. Introduced at af11e74c opw-751602 --- addons/product/models/product_template.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/product/models/product_template.py b/addons/product/models/product_template.py index d38774a6a1a..d56aef35cfa 100644 --- a/addons/product/models/product_template.py +++ b/addons/product/models/product_template.py @@ -20,7 +20,7 @@ class ProductTemplate(models.Model): if self._context.get('categ_id') or self._context.get('default_categ_id'): return self._context.get('categ_id') or self._context.get('default_categ_id') category = self.env.ref('product.product_category_all', raise_if_not_found=False) - return category.id if category.type == 'normal' else False + return category and category.type == 'normal' and category.id or False def _get_default_uom_id(self): return self.env["product.uom"].search([], limit=1, order='id').id From 326ff3699a07933666564a4a5e8ad7cdd290f203 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Fri, 7 Jul 2017 15:39:47 +0200 Subject: [PATCH 02/13] [FIX] point_of_sale: use local variable in labmda NameError: free variable 'order' referenced before assignment in enclosing scope opw-751576 --- addons/point_of_sale/models/pos_order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py index 14406b1334c..41025175d86 100644 --- a/addons/point_of_sale/models/pos_order.py +++ b/addons/point_of_sale/models/pos_order.py @@ -209,7 +209,7 @@ class PosOrder(models.Model): have_to_group_by = session and session.config_id.group_by or False rounding_method = session and session.config_id.company_id.tax_calculation_rounding_method - for order in self.filtered(lambda o: not o.account_move or order.state == 'paid'): + for order in self.filtered(lambda o: not o.account_move or o.state == 'paid'): current_company = order.sale_journal.company_id account_def = IrProperty.get( 'property_account_receivable_id', 'res.partner') From e8271ffcc7e0d1aad11e20540a5f35b88fd4ac35 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Fri, 7 Jul 2017 18:25:59 +0200 Subject: [PATCH 03/13] [FIX] mail: avoid attaching auto-notifications to foreign parents `parent_id` fields are common in many models, and thus default values for those fields are sometimes passed in the context. Because mail.message also has `parent_id` field, it would automatically use the default when an automatic message was being posted. While of course, the parent_id value comes from a different model. This "adoption" by a random "parent message" is unexpected, not desired, and it can even cause a very surprising AccessError if the parent message is not readable by the user. Forcing the `parent_id` value during the creation of an automatic message avoids this confusion. One way to trigger the bug was to use the "subtask" stat button to create a child subtask for a project task (it relies on the parent task ID passed in the context) --- addons/mail/models/mail_thread.py | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 517dfa8fd31..be8df2937df 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -2067,6 +2067,7 @@ class MailThread(models.AbstractModel): partner_ids=[(4, pid) for pid in partner_ids], auto_delete=True, auto_delete_message=True, + parent_id=False, # override accidental context defaults subtype_id=self.env.ref('mail.mt_note').id) @api.multi From 7102fcfc4fd5f1c7d84f951c473a4b3f0193afa2 Mon Sep 17 00:00:00 2001 From: Invitu Date: Fri, 23 Jun 2017 22:04:15 -1000 Subject: [PATCH 04/13] [FIX] point_of_sale: also clone orderline price Otherwise during e.g. bill splitting of an orderline which had it's price overridden you end up with the original price again. Fixes #17810 Closes #17811 --- addons/point_of_sale/static/src/js/models.js | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index b0abc797f08..5d7d96b5178 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -1108,6 +1108,7 @@ exports.Orderline = Backbone.Model.extend({ orderline.quantity = this.quantity; orderline.quantityStr = this.quantityStr; orderline.discount = this.discount; + orderline.price = this.price; orderline.type = this.type; orderline.selected = false; return orderline; From 49407e46cbf3ad891b7bfb3f73df6bea5defeef7 Mon Sep 17 00:00:00 2001 From: Joren Van Onder Date: Tue, 4 Apr 2017 10:25:52 -0700 Subject: [PATCH 05/13] [FIX] sale_margin: convert standard_price to SO currency before using --- addons/sale_margin/sale_margin.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/addons/sale_margin/sale_margin.py b/addons/sale_margin/sale_margin.py index 0cd3cdf14e4..0cd56669df7 100644 --- a/addons/sale_margin/sale_margin.py +++ b/addons/sale_margin/sale_margin.py @@ -55,7 +55,16 @@ class sale_order_line(osv.osv): cur = line.order_id.pricelist_id.currency_id res[line.id] = 0 if line.product_id: - tmp_margin = line.price_subtotal - ((line.purchase_price or line.product_id.standard_price) * line.product_uos_qty) + price = line.purchase_price + + if not price: + from_cur = self.pool['res.users'].browse(cr, uid, uid, context=context).company_id.currency_id + cost = line.product_id.standard_price + ctx = context.copy() + ctx['date'] = line.order_id.date_order + price = self.pool['res.currency'].compute(cr, uid, from_cur.id, cur.id, cost, round=False, context=ctx) + + tmp_margin = line.price_subtotal - (price * line.product_uos_qty) res[line.id] = cur_obj.round(cr, uid, cur, tmp_margin) return res From 2c605ab08ffccb440e4e23e2b420fe2d6de5e7fb Mon Sep 17 00:00:00 2001 From: Joren Van Onder Date: Thu, 29 Jun 2017 11:24:46 -0700 Subject: [PATCH 06/13] [FIX] point_of_sale: allow easier template extension of PosTicket Fixes #17704 --- addons/point_of_sale/static/src/xml/pos.xml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml index b1292d47d86..b9ce40f7950 100644 --- a/addons/point_of_sale/static/src/xml/pos.xml +++ b/addons/point_of_sale/static/src/xml/pos.xml @@ -1405,8 +1405,12 @@


- Phone:
- User:
+
+ Phone:
+
+
+ User:
+

From 7522e2992732935de48ba8ff7ad2709801f5685b Mon Sep 17 00:00:00 2001 From: Richard Mathot Date: Mon, 10 Jul 2017 08:21:16 +0200 Subject: [PATCH 07/13] [FIX] event: a user may not have set its timezone --- addons/event/models/event.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/event/models/event.py b/addons/event/models/event.py index 36b20f75b21..ff3ba12f57a 100644 --- a/addons/event/models/event.py +++ b/addons/event/models/event.py @@ -133,7 +133,7 @@ class EventEvent(models.Model): 'event.registration', 'event_id', string='Attendees', readonly=False, states={'done': [('readonly', True)]}) # Date fields - date_tz = fields.Selection('_tz_get', string='Timezone', required=True, default=lambda self: self.env.user.tz) + date_tz = fields.Selection('_tz_get', string='Timezone', required=True, default=lambda self: self.env.user.tz or 'UTC') date_begin = fields.Datetime( string='Start Date', required=True, track_visibility='onchange', states={'done': [('readonly', True)]}) From 57089bbc78a3121534a9fab6482a34c06b786ddf Mon Sep 17 00:00:00 2001 From: Richard Mathot Date: Mon, 10 Jul 2017 08:40:02 +0200 Subject: [PATCH 08/13] [FIX] account: wrong variable name due to fwport --- addons/account/models/res_config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/account/models/res_config.py b/addons/account/models/res_config.py index e34eb8097eb..a6bb496ffb2 100644 --- a/addons/account/models/res_config.py +++ b/addons/account/models/res_config.py @@ -132,6 +132,6 @@ class AccountConfigSettings(models.TransientModel): company = self.env['res.company'].browse(values.get('company_id')) if company.currency_id.id == values.get('currency_id'): values.pop('currency_id') - if company.accounts_code_digits == vals.get('code_digits'): - vals.pop('code_digits') + if company.accounts_code_digits == values.get('code_digits'): + values.pop('code_digits') return super(AccountConfigSettings, self).create(values) From 8bd56bb46628e57f41c635f20c527264d7a20d86 Mon Sep 17 00:00:00 2001 From: "Lucas Perais (lpe)" Date: Thu, 1 Jun 2017 09:31:55 +0200 Subject: [PATCH 09/13] [FIX] website_sale, website_sale_options: fixing prices of product vs options in the modal Before this commit, having an option on a product, the modal had every prices set to the one of the option This was brought about by commit c8a434306f110bfb5e5ce71609e8e096a850d309 which was designed for the pricelists and striked prices After this commit, we keep the intended behavior for pricelists while controlling that options would not mess up the modal The prices that are displayed are the right ones. OPW 744943 GH-17342 [FIX] website_sale, website_sale_options:fix the modal of options Before this commit, the add quantity button were not working at all This commit corrects the behavior by browsing the dom for anything that looks like a product section Closes #17353 --- addons/website_sale/controllers/main.py | 7 ++-- .../static/src/js/website_sale.js | 38 ++++++++++++------- addons/website_sale/views/templates.xml | 3 +- .../website_sale_options/controllers/main.py | 11 ++++++ .../static/src/css/website_sale.css | 7 +++- .../static/src/js/website_sale.js | 2 +- .../views/website_sale_options_templates.xml | 10 +++-- 7 files changed, 54 insertions(+), 24 deletions(-) diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index 4df7d5dbb98..6273be817ca 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -128,16 +128,17 @@ class WebsiteSale(http.Controller): (variant id, [visible attribute ids], variant price, variant sale price) """ # product attributes with at least two choices - product = product.with_context(quantity=1) + quantity = product._context.get('quantity') or 1 + product = product.with_context(quantity=quantity) 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: if to_currency != product.currency_id: - price = variant.currency_id.compute(variant.website_public_price, to_currency) + price = variant.currency_id.compute(variant.website_public_price, to_currency) / quantity else: - price = variant.website_public_price + price = variant.website_public_price / quantity visible_attribute_ids = [v.id for v in variant.attribute_value_ids if v.attribute_id.id in visible_attrs_ids] attribute_value_ids.append([variant.id, visible_attribute_ids, variant.website_price, price]) return attribute_value_ids diff --git a/addons/website_sale/static/src/js/website_sale.js b/addons/website_sale/static/src/js/website_sale.js index 49f7399abcb..25e6cabb0a0 100644 --- a/addons/website_sale/static/src/js/website_sale.js +++ b/addons/website_sale/static/src/js/website_sale.js @@ -86,23 +86,30 @@ odoo.define('website_sale.website_sale', function (require) { $(oe_website_sale).on("change", 'input[name="add_qty"]', function (event) { var product_ids = []; - var product_dom = $(".js_product .js_add_cart_variants[data-attribute_value_ids]").last(); + var product_dom = $(".js_product .js_add_cart_variants[data-attribute_value_ids]"); + var qty = $(event.target).closest('form').find('input[name="add_qty"]').val(); if (!product_dom.length) { return; } - _.each(product_dom.data("attribute_value_ids"), function(entry) { - product_ids.push(entry[0]);}); - var qty = $(event.target).closest('form').find('input[name="add_qty"]').val(); + _.each(product_dom, function (prod) { + _.each($(prod).data("attribute_value_ids"), function(entry) { + if (product_ids.indexOf(entry[0]) === -1) { + product_ids.push(entry[0]); + } + }); + }); if ($("#product_detail").length) { // display the reduction from the pricelist in function of the quantity ajax.jsonRpc("/shop/get_unit_price", 'call', {'product_ids': product_ids,'add_qty': parseInt(qty)}) .then(function (data) { - var current = product_dom.data("attribute_value_ids"); - for(var j=0; j < current.length; j++){ - current[j][2] = data[current[j][0]]; - } - product_dom.attr("data-attribute_value_ids", JSON.stringify(current)).trigger("change"); + _.each(product_dom, function (prod) { + var current = $(prod).data("attribute_value_ids"); + for(var j=0; j < current.length; j++){ + current[j][2] = data[current[j][0]]; + } + $(prod).trigger("change"); + }); }); } }); @@ -294,17 +301,18 @@ odoo.define('website_sale.website_sale', function (require) { $(oe_website_sale).on('change', 'input.js_variant_change, select.js_variant_change, ul[data-attribute_value_ids]', function (ev) { var $ul = $(ev.target).closest('.js_add_cart_variants'); var $parent = $ul.closest('.js_product'); - var $product_id = $parent.find('input.product_id').first(); - var $price = $parent.find(".oe_price:first .oe_currency_value") - .add($('#product_confirmation').find(".oe_price")); - var $default_price = $parent.find(".oe_default_price:first .oe_currency_value") - .add($('#product_confirmation').find(".oe_default_price:first .oe_currency_value")); + var $product_id = $parent.find('.product_id').first(); + var $price = $parent.find(".oe_price:first .oe_currency_value"); + var $default_price = $parent.find(".oe_default_price:first .oe_currency_value"); var $optional_price = $parent.find(".oe_optional:first .oe_currency_value"); var variant_ids = $ul.data("attribute_value_ids"); var values = []; + var unchanged_values = $parent.find('div.oe_unchanged_value_ids').data('unchanged_value_ids') || []; + $parent.find('input.js_variant_change:checked, select.js_variant_change').each(function () { values.push(+$(this).val()); }); + values = values.concat(unchanged_values); $parent.find("label").removeClass("text-muted css_not_available"); @@ -318,8 +326,10 @@ odoo.define('website_sale.website_sale', function (require) { if (variant_ids[k][3]-variant_ids[k][2]>0.01) { $default_price.closest('.oe_website_sale').addClass("discount"); $optional_price.closest('.oe_optional').show().css('text-decoration', 'line-through'); + $default_price.parent().removeClass('hidden'); } else { $optional_price.closest('.oe_optional').hide(); + $default_price.parent().addClass('hidden'); } product_id = variant_ids[k][0]; update_product_image(this, product_id); diff --git a/addons/website_sale/views/templates.xml b/addons/website_sale/views/templates.xml index a695837fd7a..8bba602c840 100644 --- a/addons/website_sale/views/templates.xml +++ b/addons/website_sale/views/templates.xml @@ -443,7 +443,8 @@

Product Name