From 4e6db76abab979d25c51875ba16edb324655d476 Mon Sep 17 00:00:00 2001 From: Victor Feyens Date: Thu, 23 Feb 2023 13:21:34 +0000 Subject: [PATCH] [IMP] product,sale: extract computation of price before discount So that we can in the future harmonize more easily the discount computation between sale, point_of_sale, e-commerce, ... closes odoo/odoo#123849 Signed-off-by: Victor Feyens (vfe) --- .../product/models/product_pricelist_item.py | 39 +++++++++++++-- addons/sale/models/sale_order_line.py | 47 +++++-------------- 2 files changed, 47 insertions(+), 39 deletions(-) diff --git a/addons/product/models/product_pricelist_item.py b/addons/product/models/product_pricelist_item.py index 571f44c957e..38f223af4dc 100644 --- a/addons/product/models/product_pricelist_item.py +++ b/addons/product/models/product_pricelist_item.py @@ -403,19 +403,19 @@ class PricelistItem(models.Model): return price - def _compute_base_price(self, product, quantity, uom, date, target_currency): + def _compute_base_price(self, product, quantity, uom, date, currency): """ Compute the base price for a given rule :param product: recordset of product (product.product/product.template) :param float qty: quantity of products requested (in given uom) :param uom: unit of measure (uom.uom record) :param datetime date: date to use for price computation and currency conversions - :param target_currency: pricelist currency + :param currency: currency in which the returned price must be expressed :returns: base price, expressed in provided pricelist currency :rtype: float """ - target_currency.ensure_one() + currency.ensure_one() rule_base = self.base or 'list_price' if rule_base == 'pricelist' and self.base_pricelist_id: @@ -430,7 +430,36 @@ class PricelistItem(models.Model): src_currency = product.currency_id price = product._price_compute(rule_base, uom=uom, date=date)[product.id] - if src_currency != target_currency: - price = src_currency._convert(price, target_currency, self.env.company, date, round=False) + if src_currency != currency: + price = src_currency._convert(price, currency, self.env.company, date, round=False) return price + + def _compute_price_before_discount(self, *args, **kwargs): + """Compute the base price of the lowest pricelist rule whose pricelist discount_policy + is set to show the discount to the customer. + + :param product: recordset of product (product.product/product.template) + :param float qty: quantity of products requested (in given uom) + :param uom: unit of measure (uom.uom record) + :param datetime date: date to use for price computation and currency conversions + :param currency: currency in which the returned price must be expressed + + :returns: base price, expressed in provided pricelist currency + :rtype: float + """ + pricelist_rule = self + if pricelist_rule and pricelist_rule.pricelist_id.discount_policy == 'without_discount': + pricelist_item = pricelist_rule + # Find the lowest pricelist rule whose pricelist is configured to show the discount + # to the customer. + while ( + pricelist_item.base == 'pricelist' + and pricelist_item.base_pricelist_id.discount_policy == 'without_discount' + ): + rule_id = pricelist_item.base_pricelist_id._get_product_rule(*args, **kwargs) + pricelist_item = self.env['product.pricelist.item'].browse(rule_id) + + pricelist_rule = pricelist_item + + return pricelist_rule._compute_base_price(*args, **kwargs) diff --git a/addons/sale/models/sale_order_line.py b/addons/sale/models/sale_order_line.py index 558c7e3e9ac..7769978de8c 100644 --- a/addons/sale/models/sale_order_line.py +++ b/addons/sale/models/sale_order_line.py @@ -476,14 +476,13 @@ class SaleOrderLine(models.Model): self.ensure_one() self.product_id.ensure_one() - pricelist_rule = self.pricelist_item_id - order_date = self.order_id.date_order or fields.Date.today() - product = self.product_id.with_context(**self._get_product_price_context()) - quantity = self.product_uom_qty or 1.0 - uom = self.product_uom or self.product_id.uom_id - - price = pricelist_rule._compute_price( - product, quantity, uom, order_date, currency=self.currency_id) + price = self.pricelist_item_id._compute_price( + product=self.product_id.with_context(**self._get_product_price_context()), + quantity=self.product_uom_qty or 1.0, + uom=self.product_uom, + date=self.order_id.date_order, + currency=self.currency_id, + ) return price @@ -507,34 +506,14 @@ class SaleOrderLine(models.Model): self.ensure_one() self.product_id.ensure_one() - pricelist_rule = self.pricelist_item_id - order_date = self.order_id.date_order or fields.Date.today() - product = self.product_id.with_context(**self._get_product_price_context()) - quantity = self.product_uom_qty or 1.0 - uom = self.product_uom - - if pricelist_rule: - pricelist_item = pricelist_rule - if pricelist_item.pricelist_id.discount_policy == 'without_discount': - # Find the lowest pricelist rule whose pricelist is configured - # to show the discount to the customer. - while pricelist_item.base == 'pricelist' and pricelist_item.base_pricelist_id.discount_policy == 'without_discount': - rule_id = pricelist_item.base_pricelist_id._get_product_rule( - product, quantity, currency=self.currency_id, uom=uom, date=order_date) - pricelist_item = self.env['product.pricelist.item'].browse(rule_id) - - pricelist_rule = pricelist_item - - price = pricelist_rule._compute_base_price( - product, - quantity, - uom, - order_date, - target_currency=self.currency_id, + return self.pricelist_item_id._compute_price_before_discount( + product=self.product_id.with_context(**self._get_product_price_context()), + quantity=self.product_uom_qty or 1.0, + uom=self.product_uom, + date=self.order_id.date_order, + currency=self.currency_id, ) - return price - @api.depends('product_id', 'product_uom', 'product_uom_qty') def _compute_discount(self): for line in self: