From 1f6bf21445aeb40e63bc35965eb50d74bb3fe18d Mon Sep 17 00:00:00 2001
From: Julien Muchembled <jm@nexedi.com>
Date: Thu, 30 Dec 2010 19:31:15 +0000
Subject: [PATCH] MovementGroup.getAveragePrice: avoid useless calculations
 when all prices are equal

What could happen otherwise:

  >>> a = 0.4 * 6 * 5; a
  12.000000000000002
  >>> b = 1.6 * 3; b
  4.8000000000000007
  >>> c = 0.05; c
  0.050000000000000003
  >>> (a * c + b * c) / (a + b)
  0.049999999999999989

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@41891 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 product/ERP5/MovementGroup.py | 44 +++++++++++++++++++++--------------
 1 file changed, 26 insertions(+), 18 deletions(-)

diff --git a/product/ERP5/MovementGroup.py b/product/ERP5/MovementGroup.py
index 33c52423af..ec535a29c2 100644
--- a/product/ERP5/MovementGroup.py
+++ b/product/ERP5/MovementGroup.py
@@ -401,10 +401,11 @@ class FakeMovement:
     """
       Return average price
     """
-    total_quantity = self.getAddQuantity()
-    if total_quantity != 0:
-      return (self.getAddPrice() / total_quantity)
-    return 0.0
+    price_dict = self._getPriceDict()
+    if len(price_dict) == 1:
+      return price_dict.keys()[0]
+    return sum(price * quantity for price, quantity in price_dict.items()) / \
+           float(sum(price_dict.values()))
 
   def getAddQuantity(self):
     """
@@ -412,28 +413,35 @@ class FakeMovement:
     """
     total_quantity = 0
     for movement in self.getMovementList():
-      if getattr(movement, 'getMappedProperty', None) is not None:
-        quantity = movement.getMappedProperty('quantity')
-      else:
+      getMappedProperty = getattr(movement, 'getMappedProperty', None)
+      if getMappedProperty is None:
         quantity = movement.getQuantity()
-      if quantity != None:
+      else:
+        quantity = getMappedProperty('quantity')
+      if quantity:
         total_quantity += quantity
     return total_quantity
 
+  def _getPriceDict(self):
+    price_dict = {}
+    for movement in self.getMovementList():
+      getMappedProperty = getattr(movement, 'getMappedProperty', None)
+      if getMappedProperty is None:
+        quantity = movement.getQuantity()
+      else:
+        quantity = getMappedProperty('quantity')
+      if quantity:
+        price = movement.getPrice() or 0
+        quantity += price_dict.setdefault(price, 0)
+        price_dict[price] = quantity
+    return price_dict
+
   def getAddPrice(self):
     """
       Return total price
     """
-    total_price = 0
-    for movement in self.getMovementList():
-      if getattr(movement, 'getMappedProperty', None) is not None:
-        quantity = movement.getMappedProperty('quantity')
-      else:
-        quantity = movement.getQuantity()
-      price = movement.getPrice()
-      if (quantity is not None) and (price is not None):
-        total_price += (quantity * price)
-    return total_price
+    price_dict = self._getPriceDict()
+    return sum(price * quantity for price, quantity in price_dict.items())
 
   def recursiveReindexObject(self):
     """
-- 
2.30.9