diff --git a/addons/product/pricelist.py b/addons/product/pricelist.py index 49b518a8078..5881099a13c 100644 --- a/addons/product/pricelist.py +++ b/addons/product/pricelist.py @@ -247,19 +247,27 @@ class product_pricelist(osv.osv): results = {} for product, qty, partner in products_by_qty_by_partner: - uom_price_already_computed = False results[product.id] = 0.0 - price = False rule_id = False + price = False + + # Final unit price is computed according to `qty` in the `qty_uom_id` UoM. + # An intermediary unit price may be computed according to a different UoM, in + # which case the price_uom_id contains that UoM. + # The final price will be converted to match `qty_uom_id`. + qty_uom_id = context.get('uom') or product.uom_id.id + price_uom_id = product.uom_id.id + qty_in_product_uom = qty + if qty_uom_id != product.uom_id.id: + try: + qty_in_product_uom = product_uom_obj._compute_qty( + cr, uid, context['uom'], qty, product.uom_id.id or product.uos_id.id) + except except_orm: + # Ignored - incompatible UoM in context, use default product UoM + pass + for rule in items: - if 'uom' in context and product.uom_id and context['uom'] != product.uom_id.id: - try: - qty_in_product_uom = product_uom_obj._compute_qty(cr, uid, context['uom'], qty, product.uom_id.id, dict(context.items() + [('raise-exception', False)])) - except except_orm: - qty_in_product_uom = qty - else: - qty_in_product_uom = qty - if rule.min_quantity and qty_in_product_uom 3 tonnes + spam_id = self.product_product.copy(cr, uid, self.usb_adapter_id, + { 'name': '1 tonne of spam', + 'uom_id': self.tonne_id, + 'uos_id': self.tonne_id, + 'uom_po_id': self.tonne_id, + 'list_price': tonne_price, + }) + pricelist_version_id = self.ir_model_data.xmlid_to_res_id(cr, uid, 'product.ver0') + self.registry('product.pricelist.item').create(cr, uid, + { 'price_version_id': pricelist_version_id, + 'sequence': 10, + 'name': '3+ tonnes: -10 EUR discount/t', + 'base': 1, # based on public price + 'min_quantity': 3, # min = 3 tonnes + 'price_surcharge': -10, # -10 EUR / tonne + 'product_id': spam_id, + }) + pricelist_id = self.public_pricelist_id + + def test_unit_price(qty, uom, expected_unit_price): + unit_price = self.registry('product.pricelist').price_get(cr, uid, [pricelist_id], + spam_id, qty, + context={'uom': uom})[pricelist_id] + self.assertAlmostEqual(unit_price, expected_unit_price, msg='Computed unit price is wrong') + + # Test prices - they are *per unit*, the quantity is only here to match the pricelist rules! + test_unit_price(2, kg, tonne_price / 1000.0) + test_unit_price(2000, kg, tonne_price / 1000.0) + test_unit_price(3500, kg, (tonne_price - 10) / 1000.0) + test_unit_price(2, tonne, tonne_price) + test_unit_price(3, tonne, tonne_price - 10)