diff --git a/product/ERP5/TargetSolver/CopyToTarget.py b/product/ERP5/TargetSolver/CopyToTarget.py
index a7cd0e5953d1b254d5d91a75521479b5f4108f5f..1f1e5af11f68d1a283845cad62d30015e868379d 100644
--- a/product/ERP5/TargetSolver/CopyToTarget.py
+++ b/product/ERP5/TargetSolver/CopyToTarget.py
@@ -28,7 +28,6 @@
 ##############################################################################
 
 from TargetSolver import TargetSolver
-from zLOG import LOG
 
 class CopyToTarget(TargetSolver):
   """
@@ -36,9 +35,9 @@ class CopyToTarget(TargetSolver):
   only acceptable for root movements. The meaning of
   this solver of other movements is far from certain.
   """
-  def solve(self, movement):
+  def _generateValueDeltaDict(self, movement):
     """
-      Adopt values as new target
+    Get interesting value
     """
     # Get interesting value
     old_quantity = movement.getQuantity()
@@ -58,33 +57,57 @@ class CopyToTarget(TargetSolver):
       start_date_delta = new_start_date - old_start_date
     if new_stop_date is not None and old_stop_date is not None:
       stop_date_delta = new_stop_date - old_stop_date
+    return {
+      'quantity_ratio': quantity_ratio,
+      'start_date_delta': start_date_delta,
+      'stop_date_delta': stop_date_delta,
+    }
+
+  def solve(self, movement):
+    """
+    Adopt values as new target
+    """
+    value_dict = self._generateValueDeltaDict(movement)
     # Modify recursively simulation movement
-    self._recursivelySolve(movement, quantity_ratio=quantity_ratio,
-                           start_date_delta=start_date_delta, 
-                           stop_date_delta=stop_date_delta)
+    self._recursivelySolve(movement, **value_dict)
 
-  def _recursivelySolve(self, movement, quantity_ratio=1, start_date_delta=0,
-                        stop_date_delta=0):
+  def _generateValueDict(self, movement, quantity_ratio=1, 
+                         start_date_delta=0, stop_date_delta=0,
+                         **value_delta_dict):
     """
-    Update value of the current simulation movement, and update his parent
-    movement.
+    Generate values to save on movement.
     """
+    value_dict = {}
     # Modify quantity, start_date, stop_date
     start_date = movement.getStartDate()
     if start_date is not None:
-      start_date = start_date + start_date_delta
+      value_dict['start_date'] = start_date + start_date_delta
     stop_date = movement.getStopDate()
     if stop_date is not None:
-      stop_date = stop_date + stop_date_delta
-    movement.edit(
-      quantity=movement.getQuantity() * quantity_ratio,
-      start_date=start_date,
-      stop_date=stop_date
-    )
+      value_dict['stop_date'] = stop_date + stop_date_delta
+    value_dict['quantity'] = movement.getQuantity() * quantity_ratio
+    return value_dict
+
+  def _getParentParameters(self, movement, 
+                           **value_delta_dict):
+    """
+    Get parent movement, and its value delta dict.
+    """
     applied_rule = movement.getParent()
     parent_movement = applied_rule.getParent()
-    if parent_movement.getPortalType() == "Simulation Movement":
+    if parent_movement.getPortalType() != "Simulation Movement":
+      parent_movement = None
+    return parent_movement, value_delta_dict
+
+  def _recursivelySolve(self, movement, **value_delta_dict):
+    """
+    Update value of the current simulation movement, and update his parent
+    movement.
+    """
+    value_dict = self._generateValueDict(movement, **value_delta_dict)
+    movement.edit(**value_dict)
+    parent_movement, parent_value_delta_dict = \
+                self._getParentParameters(movement, **value_delta_dict)
+    if parent_movement is not None:
       # Modify the parent movement
-      self._recursivelySolve(parent_movement, quantity_ratio=quantity_ratio,
-                             start_date_delta=start_date_delta, 
-                             stop_date_delta=stop_date_delta)
+      self._recursivelySolve(parent_movement, **parent_value_delta_dict)
diff --git a/product/ERP5/TargetSolver/TransformationSourcingCopyToTarget.py b/product/ERP5/TargetSolver/TransformationSourcingCopyToTarget.py
new file mode 100644
index 0000000000000000000000000000000000000000..811727e5e492bbb288da002b3324b004ba16ec64
--- /dev/null
+++ b/product/ERP5/TargetSolver/TransformationSourcingCopyToTarget.py
@@ -0,0 +1,69 @@
+##############################################################################
+#
+# Copyright (c) 2006 Nexedi SARL and Contributors. All Rights Reserved.
+#                    Romain Courteaud <romain@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+from CopyToTarget import CopyToTarget
+
+class TransformationSourcingCopyToTarget(CopyToTarget):
+  """
+  Copy values simulation movement as target, and
+    recursively solve the sourcing tree.
+  """
+  def _generateValueDeltaDict(self, movement):
+    """
+    Get interesting value
+    """
+    value_dict = CopyToTarget._generateValueDict(self, movement)
+    value_dict.update({
+      'aggregate_list': movement.getDeliveryValue().getAggregateList(),
+    })
+    return value_dict
+
+  def _generateValueDict(self, movement, aggregate_list=None,
+                         **value_delta_dict):
+    """
+    Generate values to save on movement.
+    """
+    value_dict = CopyToTarget._generateValueDict(self, movement,
+                                                 **value_delta_dict)
+    # Modify aggregate_list
+    if aggregate_list is not None:
+      value_dict['aggregate_list'] = aggregate_list
+    return value_dict
+
+  def _getParentParameters(self, movement, 
+                           **value_delta_dict):
+    """
+    Get parent movement, and its value delta dict.
+    """
+    applied_rule = movement.getParent()
+    rule = applied_rule.getSpecialiseValue()
+    if rule.getPortalType() != "Transformation Sourcing Rule":
+      value_delta_dict.pop('aggregate_list', None)
+    return CopyToTarget._getParentParameters(self, movement, 
+                                             **value_delta_dict)
+