diff --git a/addons/sale/models/account_move_line.py b/addons/sale/models/account_move_line.py index 6315c6591da..5c983ac1414 100644 --- a/addons/sale/models/account_move_line.py +++ b/addons/sale/models/account_move_line.py @@ -118,8 +118,6 @@ class AccountMoveLine(models.Model): # create the sale lines in batch new_sale_lines = self.env['sale.order.line'].create(sale_line_values_to_create) - for sol in new_sale_lines: - sol._onchange_discount() # build result map by replacing index with newly created record of sale.order.line result = {} diff --git a/addons/sale/models/sale_order_line.py b/addons/sale/models/sale_order_line.py index f0e93e3bb5e..7c1e64ed496 100644 --- a/addons/sale/models/sale_order_line.py +++ b/addons/sale/models/sale_order_line.py @@ -238,7 +238,9 @@ class SaleOrderLine(models.Model): price_reduce_taxinc = fields.Monetary(compute='_compute_price_reduce_taxinc', string='Price Reduce Tax inc', store=True) price_reduce_taxexcl = fields.Monetary(compute='_compute_price_reduce_taxexcl', string='Price Reduce Tax excl', store=True) - discount = fields.Float(string='Discount (%)', digits='Discount', default=0.0) + discount = fields.Float( + string='Discount (%)', digits='Discount', + compute='_compute_discount', store=True, readonly=False) product_id = fields.Many2one( 'product.product', string='Product', domain="[('sale_ok', '=', True), '|', ('company_id', '=', False), ('company_id', '=', company_id)]", @@ -781,39 +783,49 @@ class SaleOrderLine(models.Model): 'tax_id', 'analytic_tag_ids' ] - @api.onchange('product_id', 'price_unit', 'product_uom', 'product_uom_qty', 'tax_id') - def _onchange_discount(self): - if not (self.product_id and self.product_uom and - self.order_id.partner_id and self.order_id.pricelist_id and - self.order_id.pricelist_id.discount_policy == 'without_discount' and - self.env.user.has_group('product.group_discount_per_so_line')): - return + @api.depends('product_id', 'price_unit', 'product_uom', 'product_uom_qty', 'tax_id') + def _compute_discount(self): + for line in self: + if not (line.product_id and line.product_uom and + line.order_id.partner_id and line.order_id.pricelist_id and + line.order_id.pricelist_id.discount_policy == 'without_discount' and + self.env.user.has_group('product.group_discount_per_so_line')): + continue - self.discount = 0.0 - product = self.product_id.with_context( - lang=self.order_id.partner_id.lang, - partner=self.order_id.partner_id, - quantity=self.product_uom_qty, - date=self.order_id.date_order, - pricelist=self.order_id.pricelist_id.id, - uom=self.product_uom.id, - fiscal_position=self.env.context.get('fiscal_position') - ) + line.discount = 0.0 + product = line.product_id.with_context( + lang=line.order_id.partner_id.lang, + partner=line.order_id.partner_id, + quantity=line.product_uom_qty, + date=line.order_id.date_order, + pricelist=line.order_id.pricelist_id.id, + uom=line.product_uom.id, + fiscal_position=self.env.context.get('fiscal_position')) - product_context = dict(self.env.context, partner_id=self.order_id.partner_id.id, date=self.order_id.date_order, uom=self.product_uom.id) + product_context = dict( + self.env.context, + partner_id=line.order_id.partner_id.id, + date=line.order_id.date_order, + uom=line.product_uom.id) - price, rule_id = self.order_id.pricelist_id.with_context(product_context).get_product_price_rule(self.product_id, self.product_uom_qty or 1.0, self.order_id.partner_id) - new_list_price, currency = self.with_context(product_context)._get_real_price_currency(product, rule_id, self.product_uom_qty, self.product_uom, self.order_id.pricelist_id.id) + price, rule_id = line.order_id.pricelist_id.with_context(product_context).get_product_price_rule( + line.product_id, + line.product_uom_qty or 1.0, + line.order_id.partner_id) + new_list_price, currency = line.with_context(product_context)._get_real_price_currency( + product, rule_id, line.product_uom_qty, + line.product_uom, line.order_id.pricelist_id.id) - if new_list_price != 0: - if self.order_id.pricelist_id.currency_id != currency: - # we need new_list_price in the same currency as price, which is in the SO's pricelist's currency - new_list_price = currency._convert( - new_list_price, self.order_id.pricelist_id.currency_id, - self.order_id.company_id or self.env.company, self.order_id.date_order or fields.Date.today()) - discount = (new_list_price - price) / new_list_price * 100 - if (discount > 0 and new_list_price > 0) or (discount < 0 and new_list_price < 0): - self.discount = discount + if new_list_price != 0: + if line.order_id.pricelist_id.currency_id != currency: + # we need new_list_price in the same currency as price, which is in the SO's pricelist's currency + new_list_price = currency._convert( + new_list_price, line.order_id.pricelist_id.currency_id, + line.order_id.company_id or self.env.company, + line.order_id.date_order or fields.Date.today()) + discount = (new_list_price - price) / new_list_price * 100 + if (discount > 0 and new_list_price > 0) or (discount < 0 and new_list_price < 0): + line.discount = discount def _is_delivery(self): self.ensure_one() diff --git a/addons/sale/tests/test_onchange.py b/addons/sale/tests/test_onchange.py index 95e3a2997d6..6a894ca6d03 100644 --- a/addons/sale/tests/test_onchange.py +++ b/addons/sale/tests/test_onchange.py @@ -156,12 +156,9 @@ class TestOnchangeProductId(TransactionCase): 'product_id': computer_case.id, }) - # force compute uom and prices - order_line._onchange_discount() self.assertEqual(order_line.price_subtotal, 90, "Christmas discount pricelist rule not applied") self.assertEqual(order_line.discount, 10, "Christmas discount not equalt to 10%") order_line.product_uom = new_uom - order_line._onchange_discount() self.assertEqual(order_line.price_subtotal, 900, "Christmas discount pricelist rule not applied") self.assertEqual(order_line.discount, 10, "Christmas discount not equalt to 10%") @@ -211,7 +208,6 @@ class TestOnchangeProductId(TransactionCase): 'product_id': computer_case.id, }) - order_line._onchange_discount() self.assertEqual(order_line.price_subtotal, 81, "Second pricelist rule not applied") self.assertEqual(order_line.discount, 19, "Second discount not applied") diff --git a/addons/sale/tests/test_sale_order.py b/addons/sale/tests/test_sale_order.py index e260359d351..36493593930 100644 --- a/addons/sale/tests/test_sale_order.py +++ b/addons/sale/tests/test_sale_order.py @@ -281,10 +281,6 @@ class TestSaleOrder(TestSaleCommon): self.sol_serv_order.write({'tax_id': [(4, tax_exclude.id)]}) self.sol_product_deliver.write({'tax_id': [(4, tax_exclude.id)]}) - # Trigger onchange to reset discount, unit price, subtotal, ... - for line in self.sale_order.order_line: - line._onchange_discount() - for line in self.sale_order.order_line: if line.tax_id.price_include: price = line.price_unit * line.product_uom_qty - line.price_tax @@ -461,9 +457,6 @@ class TestSaleOrder(TestSaleCommon): }) ] }) - for line in sales_order.order_line: - # Create values autofill does not compute discount. - line._onchange_discount() so_line_1 = sales_order.order_line[0] so_line_2 = sales_order.order_line[1] @@ -492,8 +485,6 @@ class TestSaleOrder(TestSaleCommon): }) ] }) - for line in sales_order.order_line: - line._onchange_discount() so_line_1 = sales_order.order_line[0] so_line_2 = sales_order.order_line[1] diff --git a/addons/sale/tests/test_sale_pricelist.py b/addons/sale/tests/test_sale_pricelist.py index a7dc070cec4..bd3588c380c 100644 --- a/addons/sale/tests/test_sale_pricelist.py +++ b/addons/sale/tests/test_sale_pricelist.py @@ -119,9 +119,6 @@ class TestSaleOrder(TestSaleCommon): """ Test SO with the pricelist and check unit price appeared on its lines """ # Change the pricelist self.sale_order.write({'pricelist_id': self.pricelist_discount_incl.id}) - # Trigger onchange to reset discount, unit price, subtotal, ... - for line in self.sale_order.order_line: - line._onchange_discount() # Check that pricelist of the SO has been applied on the sale order lines or not for line in self.sale_order.order_line: if line.product_id == self.company_data['product_order_no']: @@ -142,9 +139,6 @@ class TestSaleOrder(TestSaleCommon): # Change the pricelist self.sale_order.write({'pricelist_id': self.pricelist_discount_excl.id}) - # Trigger onchange to reset discount, unit price, subtotal, ... - for line in self.sale_order.order_line: - line._onchange_discount() # Check pricelist of the SO apply or not on order lines where pricelist contains formula that add 15% on the cost price for line in self.sale_order.order_line: diff --git a/addons/sale_management/models/sale_order.py b/addons/sale_management/models/sale_order.py index 5086e31ec52..49bfa8d2f35 100644 --- a/addons/sale_management/models/sale_order.py +++ b/addons/sale_management/models/sale_order.py @@ -239,7 +239,7 @@ class SaleOrderOption(models.Model): # To compute the discount a so line is created in cache values = self._get_values_to_add_to_order() new_sol = self.env['sale.order.line'].new(values) - new_sol._onchange_discount() + new_sol._compute_discount() self.discount = new_sol.discount if self.order_id.pricelist_id and self.order_id.partner_id: self.price_unit = new_sol._get_display_price(product) diff --git a/addons/sale_product_matrix/models/sale_order.py b/addons/sale_product_matrix/models/sale_order.py index 4b11fd966ba..7f6ab29955f 100644 --- a/addons/sale_product_matrix/models/sale_order.py +++ b/addons/sale_product_matrix/models/sale_order.py @@ -115,14 +115,9 @@ class SaleOrder(models.Model): product_uom_qty=qty, product_no_variant_attribute_value_ids=no_variant_attribute_values.ids) )) - if product_ids: - if new_lines: - # Add new SO lines - self.update(dict(order_line=new_lines)) - - # Recompute prices for new/modified lines - for line in self.order_line.filtered(lambda line: line.product_id.id in product_ids): - line._onchange_discount() + if product_ids and new_lines: + # Add new SO lines + self.update(dict(order_line=new_lines)) def _get_matrix(self, product_template): """Return the matrix of the given product, updated with current SOLines quantities. diff --git a/addons/website_sale/models/sale_order.py b/addons/website_sale/models/sale_order.py index 431817cec7e..7977fa164e9 100644 --- a/addons/website_sale/models/sale_order.py +++ b/addons/website_sale/models/sale_order.py @@ -116,7 +116,7 @@ class SaleOrder(models.Model): discount = 0 if order.pricelist_id.discount_policy == 'without_discount': - # This part is pretty much a copy-paste of the method '_onchange_discount' of + # This part is pretty much a copy-paste of the method '_compute_discount' of # 'sale.order.line'. price, rule_id = order.pricelist_id.with_context(product_context).get_product_price_rule(product, qty or 1.0, order.partner_id) pu, currency = request.env['sale.order.line'].with_context(product_context)._get_real_price_currency(product, rule_id, qty, product.uom_id, order.pricelist_id.id)