[FIX] product: pricelist, uom and price_surcharge
authorMartin Trigaux <mat@odoo.com>
Thu, 23 Oct 2014 15:14:19 +0000 (17:14 +0200)
committerMartin Trigaux <mat@odoo.com>
Fri, 24 Oct 2014 15:21:42 +0000 (17:21 +0200)
The price_surcharge attribute must be computed based on the reference unit of measure (divided by the factor).
This is to make sure than 12 units and 1 dozen have the same price after pricelist computation (opw 599727).

Added test checking the correctness of pricelist computation based on unit of measures.

addons/product/pricelist.py
addons/product/tests/__init__.py
addons/product/tests/test_pricelist.py [new file with mode: 0644]

index d4ed256..0dd6b45 100644 (file)
@@ -297,7 +297,12 @@ class product_pricelist(osv.osv):
                             price = price * (1.0+(res['price_discount'] or 0.0))
                             if res['price_round']:
                                 price = tools.float_round(price, precision_rounding=res['price_round'])
-                            price += (res['price_surcharge'] or 0.0)
+                            if context.get('uom'):
+                                # compute price_surcharge based on reference uom
+                                factor = product_uom_obj.browse(cr, uid, context.get('uom'), context=context).factor
+                            else:
+                                factor = 1.0
+                            price += (res['price_surcharge'] or 0.0) / factor
                             if res['price_min_margin']:
                                 price = max(price, price_limit+res['price_min_margin'])
                             if res['price_max_margin']:
index 850189a..4a1ce43 100644 (file)
@@ -1,5 +1,6 @@
-from . import test_uom
+from . import test_uom, test_pricelist
 
 fast_suite = [
        test_uom,
+       test_pricelist
 ]
diff --git a/addons/product/tests/test_pricelist.py b/addons/product/tests/test_pricelist.py
new file mode 100644 (file)
index 0000000..dd9130e
--- /dev/null
@@ -0,0 +1,70 @@
+from openerp.tests.common import TransactionCase
+
+class TestPricelist(TransactionCase):
+    """Tests for unit of measure conversion"""
+
+    def setUp(self):
+        super(TestPricelist, self).setUp()
+        cr, uid, context = self.cr, self.uid, {}
+        self.ir_model_data = self.registry('ir.model.data')
+        self.product_product = self.registry('product.product')
+        self.product_pricelist = self.registry('product.pricelist')
+        self.uom = self.registry('product.uom')
+
+        self.usb_adapter_id = self.ir_model_data.get_object_reference(cr, uid, 'product', 'product_product_48')[1]
+        self.datacard_id = self.ir_model_data.get_object_reference(cr, uid, 'product', 'product_template_46')[1]
+        self.unit_id = self.ir_model_data.get_object_reference(cr, uid, 'product', 'product_uom_unit')[1]
+        self.dozen_id = self.ir_model_data.get_object_reference(cr, uid, 'product', 'product_uom_dozen')[1]
+
+        self.public_pricelist_id = self.ir_model_data.get_object_reference(cr, uid, 'product', 'list0')[1]
+        self.sale_pricelist_id = self.product_pricelist.create(cr, uid, {
+            'name': 'Sale pricelist',
+            'type': 'sale',
+            'version_id': [(0, 0, {
+                'name': 'v1.0',
+                'items_id': [(0, 0, {
+                    'name': 'Discount 10%',
+                    'base': 1, # based on public price
+                    'price_discount': -0.1,
+                    'product_id': self.usb_adapter_id
+                }), (0, 0, {
+                    'name': 'Discount -0.5',
+                    'base': 1, # based on public price
+                    'price_surcharge': -0.5,
+                    'product_id': self.datacard_id
+                })]
+            })]
+        }, context=context)
+
+    def test_10_discount(self):
+        # Make sure the price using a pricelist is the same than without after
+        # applying the computation manually
+        cr, uid, context = self.cr, self.uid, {}
+
+        public_context = dict(context, pricelist=self.public_pricelist_id)
+        pricelist_context = dict(context, pricelist=self.sale_pricelist_id)
+
+        usb_adapter_without_pricelist = self.product_product.browse(cr, uid, self.usb_adapter_id, context=public_context)
+        usb_adapter_with_pricelist = self.product_product.browse(cr, uid, self.usb_adapter_id, context=pricelist_context)
+        self.assertEqual(usb_adapter_with_pricelist.price, usb_adapter_without_pricelist.price*0.9)
+
+        datacard_without_pricelist = self.product_product.browse(cr, uid, self.datacard_id, context=public_context)
+        datacard_with_pricelist = self.product_product.browse(cr, uid, self.datacard_id, context=pricelist_context)
+        self.assertEqual(datacard_with_pricelist.price, datacard_without_pricelist.price-0.5)
+
+        # Make sure that changing the unit of measure does not break the unit
+        # price (after converting)
+        unit_context = dict(context,
+            pricelist=self.sale_pricelist_id,
+            uom=self.unit_id)
+        dozen_context = dict(context,
+            pricelist=self.sale_pricelist_id,
+            uom=self.dozen_id)
+
+        usb_adapter_unit = self.product_product.browse(cr, uid, self.usb_adapter_id, context=unit_context)
+        usb_adapter_dozen = self.product_product.browse(cr, uid, self.usb_adapter_id, context=dozen_context)
+        self.assertAlmostEqual(usb_adapter_unit.price*12, usb_adapter_dozen.price)
+
+        datacard_unit = self.product_product.browse(cr, uid, self.datacard_id, context=unit_context)
+        datacard_dozen = self.product_product.browse(cr, uid, self.datacard_id, context=dozen_context)
+        self.assertAlmostEqual(datacard_unit.price*12, datacard_dozen.price)