From a941cd62bb025f36bdd445e7f6db49f2293223f0 Mon Sep 17 00:00:00 2001 From: vava-odoo Date: Fri, 22 Mar 2024 07:51:57 +0000 Subject: [PATCH] [FIX] delivery: fix price when variable is weight*volume Before this commit, when using a shipping method with the variable weight*volume for price computation, the price was growing with the square of the ordered quantities. This is because both volume and weight were multiplied by the quantity, before being multiplied with each other in the next step. This commit fixes the issue by introducing the variable weight*volume at the beginning of the computation. In order not to break anything in stable, the new variable is added as a kwarg to the useful methods. OPW-3802315 closes odoo/odoo#159007 X-original-commit: 0a8db0fa14bb63abd0b2a8f0234d86700b6c1e2e Signed-off-by: Vallaeys Valentin (vava) --- addons/delivery/models/delivery_carrier.py | 13 +++---- addons/delivery/tests/test_delivery_cost.py | 38 +++++++++++++++++++++ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/addons/delivery/models/delivery_carrier.py b/addons/delivery/models/delivery_carrier.py index 593ab9beb54..b8b6c29fddc 100644 --- a/addons/delivery/models/delivery_carrier.py +++ b/addons/delivery/models/delivery_carrier.py @@ -333,7 +333,7 @@ class DeliveryCarrier(models.Model): self.ensure_one() self = self.sudo() order = order.sudo() - total = weight = volume = quantity = 0 + total = weight = volume = quantity = wv = 0 total_delivery = 0.0 for line in order.order_line: if line.state == 'cancel': @@ -347,6 +347,7 @@ class DeliveryCarrier(models.Model): qty = line.product_uom._compute_quantity(line.product_uom_qty, line.product_id.uom_id) weight += (line.product_id.weight or 0.0) * qty volume += (line.product_id.volume or 0.0) * qty + wv += (line.product_id.weight or 0.0) * (line.product_id.volume or 0.0) * qty quantity += qty total = (order.amount_total or 0.0) - total_delivery @@ -356,23 +357,23 @@ class DeliveryCarrier(models.Model): # 2- saved weight to use on sale order # 3- total order line weight as fallback weight = self.env.context.get('order_weight') or order.shipping_weight or weight - return self._get_price_from_picking(total, weight, volume, quantity) + return self._get_price_from_picking(total, weight, volume, quantity, wv=wv) - def _get_price_dict(self, total, weight, volume, quantity): + def _get_price_dict(self, total, weight, volume, quantity, wv=0.): '''Hook allowing to retrieve dict to be used in _get_price_from_picking() function. Hook to be overridden when we need to add some field to product and use it in variable factor from price rules. ''' return { 'price': total, 'volume': volume, 'weight': weight, - 'wv': volume * weight, + 'wv': wv or volume * weight, 'quantity': quantity } - def _get_price_from_picking(self, total, weight, volume, quantity): + def _get_price_from_picking(self, total, weight, volume, quantity, wv=0.): price = 0.0 criteria_found = False - price_dict = self._get_price_dict(total, weight, volume, quantity) + price_dict = self._get_price_dict(total, weight, volume, quantity, wv=wv) if self.free_over and total >= self.amount: return 0 for line in self.price_rule_ids: diff --git a/addons/delivery/tests/test_delivery_cost.py b/addons/delivery/tests/test_delivery_cost.py index d64d92d635b..a5d2a7d4582 100644 --- a/addons/delivery/tests/test_delivery_cost.py +++ b/addons/delivery/tests/test_delivery_cost.py @@ -353,3 +353,41 @@ class TestDeliveryCost(common.TransactionCase): ('is_delivery', '=', True) ]) self.assertEqual(line.price_unit, self.normal_delivery.fixed_price) + + def test_price_with_weight_volume_variable(self): + """ Test that the price is correctly computed when the variable is weight*volume. """ + qty = 3 + list_price = 2 + volume = 2.5 + weight = 1.5 + sale_order = self.env['sale.order'].create({ + 'partner_id': self.partner_18.id, + 'order_line': [ + (0, 0, { + 'product_id': self.env['product.product'].create({ + 'name': 'wv', + 'weight': weight, + 'volume': volume, + }).id, + 'product_uom_qty': qty, + 'product_uom': self.product_uom_unit.id, + }), + ], + }) + delivery = self.env['delivery.carrier'].create({ + 'name': 'Delivery Charges', + 'delivery_type': 'base_on_rule', + 'product_id': self.product_delivery_normal.id, + 'price_rule_ids': [(0, 0, { + 'variable': 'price', + 'operator': '>=', + 'max_value': 0, + 'list_price': list_price, + 'variable_factor': 'wv', + })] + }) + self.assertEqual( + delivery._get_price_available(sale_order), + qty * list_price * weight * volume, + "The shipping price is not correctly computed with variable weight*volume.", + )