From b3baba4461632e853a90927f291ae753f8281d40 Mon Sep 17 00:00:00 2001
From: Yusei Tahara <yusei@nexedi.com>
Date: Tue, 5 Jan 2010 03:16:06 +0000
Subject: [PATCH] Add base_contribution parameter to getTotalPrice to find a
 specific amount.

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@31566 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 product/ERP5/Document/Delivery.py | 36 +++++++++++++++++++++--
 product/ERP5/Document/Order.py    | 47 +++++++++++++++++++++++++++++--
 2 files changed, 77 insertions(+), 6 deletions(-)

diff --git a/product/ERP5/Document/Delivery.py b/product/ERP5/Document/Delivery.py
index c3be99e900..d0b1c2c24c 100644
--- a/product/ERP5/Document/Delivery.py
+++ b/product/ERP5/Document/Delivery.py
@@ -113,7 +113,7 @@ class Delivery(XMLObject, ImmobilisationDelivery):
 
     security.declareProtected( Permissions.AccessContentsInformation,
                                'getTotalPrice')
-    def getTotalPrice(self, fast=0, src__=0, **kw):
+    def getTotalPrice(self, fast=0, src__=0, base_contribution=None, rounding=False, **kw):
       """ Returns the total price for this order
         if the `fast` argument is set to a true value, then it use
         SQLCatalog to compute the price, otherwise it sums the total
@@ -121,13 +121,43 @@ class Delivery(XMLObject, ImmobilisationDelivery):
 
         So if the order is not in the catalog, getTotalPrice(fast=1)
         will return 0, this is not a bug.
+
+        base_contribution must be a relative url of a category.
       """
       result = None
       if not fast:
         kw.setdefault( 'portal_type',
                        self.getPortalDeliveryMovementTypeList())
-        result = sum([ line.getTotalPrice(fast=0) for line in
-                       self.objectValues(**kw) ])
+        if base_contribution is None:
+          result = sum([ line.getTotalPrice(fast=0) for line in
+                         self.objectValues(**kw) ])
+        else:
+          # Find amounts from movements in the delivery.
+          if isinstance(base_contribution, (tuple, list)):
+            base_contribution_list = base_contribution
+          else:
+            base_contribution_list = (base_contribution,)
+          base_contribution_value_list = []
+          portal_categories = self.portal_categories
+          for relative_url in base_contribution_list:
+            base_contribution_value = portal_categories.getCategoryValue(relative_url)
+            if base_contribution_value is not None:
+              base_contribution_value_list.append(base_contribution_value)
+          if not base_contribution_value_list:
+            # We cannot find any amount so that the result is 0.
+            result = 0
+          else:
+            matched_movement_list = [
+                movement
+                for movement in self.getMovementList()
+                if set(movement.getBaseContributionValueList()).intersection(base_contribution_value_list)]
+            if rounding:
+              portal_roundings = self.portal_roundings
+              matched_movement_list = [
+                  portal_roundings.getRoundingProxy(movement)
+                  for movement in matched_movement_list]
+            result = sum([movement.getTotalPrice()
+                          for movement in matched_movement_list])
       else:
         kw['explanation_uid'] = self.getUid()
         kw.update(self.portal_catalog.buildSQLQuery(**kw))
diff --git a/product/ERP5/Document/Order.py b/product/ERP5/Document/Order.py
index f71ca4ba8c..ec2c6a8ded 100644
--- a/product/ERP5/Document/Order.py
+++ b/product/ERP5/Document/Order.py
@@ -71,9 +71,50 @@ class Order(Delivery):
     
     def getTotalPrice(self, **kw) :
       """Returns the total price for this Order. """
-      kw.setdefault('portal_type', self.getPortalOrderMovementTypeList())
-      return Delivery.getTotalPrice(self, **kw)
-      
+      rounding = kw.get('rounding')
+      if kw.get('base_contribution') is None:
+        kw.setdefault('portal_type', self.getPortalOrderMovementTypeList())
+        return Delivery.getTotalPrice(self, **kw)
+      else:
+        # Find amounts from the result of getAggregatedAmountList.
+        # Call getAggregatedAmountList and sum all the amounts which
+        # base_contribution category is matched with.
+        from Products.ERP5Type.Document import newTempTradeModelLine
+        from Products.ERP5.PropertySheet.TradeModelLine import TARGET_LEVEL_MOVEMENT
+        trade_condition = self.getSpecialiseValue()
+        if trade_condition is None:
+          # We cannot find any amount so that the result is 0.
+          return 0
+        base_contribution = kw.get('base_contribution')
+        if isinstance(base_contribution, (tuple, list)):
+          base_contribution_list = base_contribution
+        else:
+          base_contribution_list = (base_contribution,)
+        base_contribution_value_list = []
+        portal_categories = self.portal_categories
+        for relative_url in base_contribution_list:
+          base_contribution_value = portal_categories.getCategoryValue(relative_url)
+          if base_contribution_value is not None:
+            base_contribution_value_list.append(base_contribution_value)
+        if not base_contribution_value_list:
+          # We cannot find any amount so that the result is 0.
+          return 0
+        current_aggregated_amount_list = trade_condition.getAggregatedAmountList(self, rounding=rounding)
+        trade_model_line = newTempTradeModelLine(
+            self,
+            '_temp_%s' % (self.getId()))
+        # prevent invoking interaction workflows.
+        trade_model_line.portal_type = ''
+        trade_model_line.edit(target_level=TARGET_LEVEL_MOVEMENT, price=1,
+                              efficiency=1, quantity=None,
+                              base_application_value_list=base_contribution_value_list)
+        aggregated_amount_list = trade_model_line._getAggregatedAmountList(
+            self,
+            movement_list=self.getMovementList(),
+            current_aggregated_amount_list=current_aggregated_amount_list,
+            rounding=rounding)
+        return aggregated_amount_list.getTotalPrice()
+
     def getTotalQuantity(self, **kw) :
       """Returns the total quantity for this Order. """
       kw.setdefault('portal_type', self.getPortalOrderMovementTypeList())
-- 
2.30.9