From 449214a51dc7f54892043951fac1c3a0cd88f171 Mon Sep 17 00:00:00 2001
From: Jean-Paul Smets <jp@nexedi.com>
Date: Wed, 23 Feb 2005 10:26:59 +0000
Subject: [PATCH] Massive update to remove target values in simulation

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@2539 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 product/ERP5/DeliverySolver/Copy.py           |   2 +-
 product/ERP5/DeliverySolver/Distribute.py     |  11 +-
 .../Document/AccountingTransactionLine.py     |  20 +-
 product/ERP5/Document/Amount.py               |  32 ----
 product/ERP5/Document/ContainerLine.py        |   6 +-
 product/ERP5/Document/Delivery.py             |  97 ++++------
 product/ERP5/Document/DeliveryCell.py         |  34 +---
 product/ERP5/Document/DeliveryLine.py         |  71 +------
 product/ERP5/Document/DeliveryRule.py         |   6 -
 product/ERP5/Document/Domain.py               |  23 ++-
 product/ERP5/Document/Invoice.py              |  36 ++--
 product/ERP5/Document/InvoicingRule.py        |  18 +-
 product/ERP5/Document/Movement.py             | 173 +++++++++++++++---
 product/ERP5/Document/OrderLine.py            |  17 +-
 product/ERP5/Document/OrderRule.py            |  23 ++-
 product/ERP5/Document/PaymentRule.py          |  20 +-
 product/ERP5/Document/PredicateGroup.py       |   9 +-
 product/ERP5/Document/SimulationMovement.py   |  15 ++
 product/ERP5/Document/TransformationRule.py   |  28 +--
 product/ERP5/ERP5Defaults.py                  |   2 +-
 .../ERP5/Extensions/InitializeAcquisition.py  |   4 +-
 product/ERP5/MovementGroup.py                 |  44 ++---
 product/ERP5/PropertySheet/Amount.py          |  25 ---
 product/ERP5/PropertySheet/Arrow.py           | 166 -----------------
 product/ERP5/PropertySheet/Inventory.py       |  11 --
 product/ERP5/PropertySheet/Predicate.py       |  10 +-
 product/ERP5/TargetSolver/CopyToTarget.py     |   6 +-
 product/ERP5/Tool/SimulationTool.py           | 119 +++++-------
 product/ERP5/tests/testInvoice.py             |  29 ++-
 29 files changed, 444 insertions(+), 613 deletions(-)

diff --git a/product/ERP5/DeliverySolver/Copy.py b/product/ERP5/DeliverySolver/Copy.py
index 471d8926cb..bf7ddb66bb 100755
--- a/product/ERP5/DeliverySolver/Copy.py
+++ b/product/ERP5/DeliverySolver/Copy.py
@@ -45,6 +45,6 @@ class Copy(DeliverySolver):
     """
       Solve a delivery
     """
-    movement.setQuantity(movement.getTargetQuantity())
+    movement.setQuantity(movement.getSimulationQuantity())
 
 registerDeliverySolver(Copy)
diff --git a/product/ERP5/DeliverySolver/Distribute.py b/product/ERP5/DeliverySolver/Distribute.py
index aba8c31b73..4571a87bee 100755
--- a/product/ERP5/DeliverySolver/Distribute.py
+++ b/product/ERP5/DeliverySolver/Distribute.py
@@ -40,12 +40,12 @@ class Distribute(DeliverySolver):
       Solve a delivery by reducing / increasing each simulation movement
       it relates to
     """
+    delivery_line_simulation_quantity = float(movement.getSimulationQuantity())
     delivery_line_quantity = float(movement.getQuantity())
-    delivery_line_target_quantity = float(movement.getTargetQuantity())
-    if delivery_line_quantity != delivery_line_target_quantity:
-      if delivery_line_quantity != 0 :
-      # XXXXXXXXXXXXXXXXXXXXXXXXX something special should be done if delivery_line_quantity == 0 !
-        distribute_ratio = delivery_line_target_quantity  / delivery_line_quantity
+    if delivery_line_simulation_quantity != delivery_line_quantity:
+      if delivery_line_simulation_quantity != 0 :
+      # XXXXXXXXXXXXXXXXXXXXXXXXX something special should be done if delivery_line_simulation_quantity == 0 !
+        distribute_ratio = delivery_line_quantity  / delivery_line_simulation_quantity
         for s in movement.getDeliveryRelatedValueList():
           # Reduce quantity
           s.setQuantity(s.getQuantity() * distribute_ratio)
@@ -64,7 +64,6 @@ class Distribute(DeliverySolver):
           s.setStartDate(movement.getStartDate())
           s.setStopDate(movement.getStopDate())
           s.diverge() # Make sure everyone knows this simulation movement is inconsistent
-    movement.setQuantity(movement.getTargetQuantity())
     # No need to touch date since it should be defined at the upper level.
 
 registerDeliverySolver(Distribute)
diff --git a/product/ERP5/Document/AccountingTransactionLine.py b/product/ERP5/Document/AccountingTransactionLine.py
index 18321f5103..4887fa62fa 100755
--- a/product/ERP5/Document/AccountingTransactionLine.py
+++ b/product/ERP5/Document/AccountingTransactionLine.py
@@ -28,6 +28,7 @@
 
 from Globals import InitializeClass, PersistentMapping
 from AccessControl import ClassSecurityInfo
+from Acquisition import aq_base, aq_inner, aq_acquire, aq_chain
 
 from Products.CMFCore.WorkflowCore import WorkflowAction
 from Products.ERP5Type import Permissions, PropertySheet, Constraint, Interface
@@ -201,10 +202,13 @@ Une ligne tarifaire."""
   security.declarePrivate('_setSource')
   def _setSource(self, value):
     self._setCategoryMembership('source', value, base=0)
-    if self.getPortalType() not in self.getPortalBalanceTransactionLineTypeList():
-      source = self.restrictedTraverse(value)
+    if self.getPortalType() not in self.getPortalBalanceTransactionLineTypeList() and value not in (None, ''):
+      source = self.getPortalObject().portal_categories.resolveCategory(value)
       destination = self.getDestination()
-      mirror_list = source.getDestinationList()
+      if source is not None:
+        mirror_list = source.getDestinationList()
+      else:
+        mirror_list = []      
       #LOG('_setSource', 0, 'value = %s, mirror_list = %s, destination = %s' % (str(value), str(mirror_list), str(destination)))
       if len(mirror_list) > 0 and destination not in mirror_list:
         self._setCategoryMembership('destination', mirror_list[0], base=0)
@@ -219,11 +223,15 @@ Une ligne tarifaire."""
 
   security.declarePrivate('_setDestination')
   def _setDestination(self, value):
-    if self.getPortalType() not in self.getPortalBalanceTransactionLineTypeList():
+    if self.getPortalType() not in self.getPortalBalanceTransactionLineTypeList() and value not in (None, ''):
       self._setCategoryMembership('destination', value, base=0)
-      destination = self.restrictedTraverse(value)
+      destination = self.getPortalObject().portal_categories.resolveCategory(value)
       source = self.getSource()
-      mirror_list = destination.getDestinationList()
+      if destination is not None:
+        #LOG('_setSource', 0, 'destination %s' % destination)
+        mirror_list = destination.getDestinationList()
+      else:
+        mirror_list = []      
       #LOG('_setDestination', 0, 'value = %s, mirror_list = %s, source = %s' % (str(value), str(mirror_list), str(source)))
       if len(mirror_list) > 0 and source not in mirror_list:
         self._setCategoryMembership('source', mirror_list[0], base=0)
diff --git a/product/ERP5/Document/Amount.py b/product/ERP5/Document/Amount.py
index 6cf48ff591..d306f0f576 100755
--- a/product/ERP5/Document/Amount.py
+++ b/product/ERP5/Document/Amount.py
@@ -206,38 +206,6 @@ class Amount(Base, Variated):
     except:
       LOG("ERP5 WARNING:", 100, 'could not set converted quantity for %s' % self.getRelativeUrl())
 
-  security.declareProtected(Permissions.AccessContentsInformation, 'getConvertedTargetQuantity')
-  def getConvertedTargetQuantity(self):
-    """
-      Converts target_quantity to default unit
-    """
-    #if 1:
-    try:
-    #if 1:
-      resource = self.getResourceValue()
-      resource_quantity_unit = resource.getDefaultQuantityUnit()
-      quantity_unit = self.getQuantityUnit()
-      quantity = self.getTargetQuantity()
-      converted_quantity = resource.convertQuantity(quantity, quantity_unit, resource_quantity_unit)
-    #else:
-    except:
-    #else:
-      LOG("ERP5 WARNING:", 100, 'could not convert target_quantity for %s' % self.getRelativeUrl())
-      converted_quantity = None
-    return converted_quantity
-
-  security.declareProtected(Permissions.ModifyPortalContent, 'setConvertedTargetQuantity')
-  def setConvertedTargetQuantity(self, value):
-    try:
-    #if 1:
-      resource = self.getResourceValue()
-      resource_quantity_unit = resource.getDefaultQuantityUnit()
-      quantity_unit = self.getQuantityUnit()
-      quantity = resource.convertQuantity(value, resource_quantity_unit, quantity_unit)
-      self.setTargetQuantity(quantity)
-    except:
-      LOG("ERP5 WARNING:", 100, 'could not set converted quantity for %s' % self.getRelativeUrl())
-
   security.declareProtected(Permissions.AccessContentsInformation, 'getNetQuantity')
   def getNetQuantity(self):
     """
diff --git a/product/ERP5/Document/ContainerLine.py b/product/ERP5/Document/ContainerLine.py
index b849b20593..c4c9a7c3cd 100755
--- a/product/ERP5/Document/ContainerLine.py
+++ b/product/ERP5/Document/ContainerLine.py
@@ -164,8 +164,8 @@ Une ligne tarifaire."""
       # Never divergent
       return 0
 
-    security.declareProtected(Permissions.AccessContentsInformation, 'getTargetTotalQuantity')
-    def getTargetTotalQuantity(self):
+    security.declareProtected(Permissions.AccessContentsInformation, 'getTotalQuantity')
+    def getTotalQuantity(self):
       """
         Returns the quantity if no cell or the total quantity if cells
       """
@@ -174,4 +174,4 @@ Une ligne tarifaire."""
       else:
         # Use MySQL
         aggregate = self.ContainerLine_zGetTotal()[0]
-        return aggregate.target_total_quantity
+        return aggregate.total_quantity
diff --git a/product/ERP5/Document/Delivery.py b/product/ERP5/Document/Delivery.py
index 8b16adddb1..30fc7dcd0f 100755
--- a/product/ERP5/Document/Delivery.py
+++ b/product/ERP5/Document/Delivery.py
@@ -373,18 +373,12 @@ class Delivery(XMLObject):
               for date_group in path_group.group_list :
 
                 invoice = invoice_module.newContent(portal_type = invoice_type,
-                              target_start_date = date_group.start_date,
-                              target_stop_date = date_group.stop_date,
                               start_date = date_group.start_date,
                               stop_date = date_group.stop_date,
                               source = path_group.source,
                               destination = path_group.destination,
                               source_section = path_group.source_section,
                               destination_section = path_group.destination_section,
-                              target_source = path_group.source,
-                              target_destination = path_group.destination,
-                              target_source_section = path_group.source_section,
-                              target_destination_section = path_group.destination_section,
                               causality_value = self,
                               title = self.getTitle(),
                               description = 'Invoice related to the Delivery %s' % self.getTitle())
@@ -396,7 +390,8 @@ class Delivery(XMLObject):
 
                   LOG('buildInvoiceList resource_group.group_list',0,resource_group.group_list)
                   # Create a new Sale Invoice Transaction Line for each resource
-                  invoice_line = invoice.newContent(portal_type=invoice_line_type
+                  invoice_line = invoice.newContent(
+                        portal_type=invoice_line_type
                       , resource=resource_group.resource)
 
 #                  line_variation_category_list = []
@@ -421,15 +416,15 @@ class Delivery(XMLObject):
 
                   #XXX for now, we quickly need this working, without the need of variant_group
                   object_to_update = invoice_line
-                  # compute target_quantity, quantity and price for invoice_cell or invoice_line and
+                  # compute quantity and price for invoice_cell or invoice_line and
                   # build relation between simulation_movement and invoice_cell or invoice_line
                   if object_to_update is not None :
-                    target_quantity = 0
+                    quantity = 0
                     total_price = 0
                     for movement in resource_group.movement_list :
-                      target_quantity += movement.getConvertedTargetQuantity()
+                      quantity += movement.getConvertedQuantity()
                       try :
-                        total_price += movement.getNetConvertedTargetQuantity() * movement.getPrice() # XXX WARNING - ADD PRICED QUANTITY
+                        total_price += movement.getNetConvertedQuantity() * movement.getPrice() # XXX WARNING - ADD PRICED QUANTITY
                       except :
                         total_price = None
                       # What do we really need to update in the simulation movement ?
@@ -437,17 +432,16 @@ class Delivery(XMLObject):
                         movement._setDeliveryValue(object_to_update)
                         reindexable_movement_list.append(movement)
 
-                    if target_quantity <> 0 and total_price is not None:
-                      average_price = total_price/target_quantity
+                    if quantity <> 0 and total_price is not None:
+                      average_price = total_price/quantity
                     else :
                       average_price = 0
 
-                    LOG('buildInvoiceList edit', 0, repr(( object_to_update, target_quantity, average_price, )))
-                    object_to_update.edit(target_quantity = target_quantity,
-                                          quantity = target_quantity,
+                    LOG('buildInvoiceList edit', 0, repr(( object_to_update, quantity, average_price, )))
+                    object_to_update.edit(quantity = quantity,
                                           price = average_price)
 
-                  # update target_quantity, quantity and price for each invoice_cell
+                  # update quantity and price for each invoice_cell
                   #XXX for variant_group in resource_group.group_list :
                   if 0 :
                     LOG('Variant_group examin',0,str(variant_group.category_list))
@@ -476,15 +470,15 @@ class Delivery(XMLObject):
                           object_to_update = invoice_cell
                           break
 
-                    # compute target_quantity, quantity and price for invoice_cell or invoice_line and
+                    # compute quantity and price for invoice_cell or invoice_line and
                     # build relation between simulation_movement and invoice_cell or invoice_line
                     if object_to_update is not None :
-                      cell_target_quantity = 0
+                      cell_quantity = 0
                       cell_total_price = 0
                       for movement in variant_group.movement_list :
-                        cell_target_quantity += movement.getConvertedTargetQuantity()
+                        cell_quantity += movement.getConvertedQuantity()
                         try :
-                          cell_total_price += movement.getNetConvertedTargetQuantity() * movement.getPrice() # XXX WARNING - ADD PRICED QUANTITY
+                          cell_total_price += movement.getNetConvertedQuantity() * movement.getPrice() # XXX WARNING - ADD PRICED QUANTITY
                         except :
                           cell_total_price = None
                         # What do we really need to update in the simulation movement ?
@@ -492,15 +486,15 @@ class Delivery(XMLObject):
                           movement._setDeliveryValue(object_to_update)
                           reindexable_movement_list.append(movement)
 
-                      if cell_target_quantity <> 0 and cell_total_price is not None:
-                        average_price = cell_total_price/cell_target_quantity
+                      if cell_quantity <> 0 and cell_total_price is not None:
+                        average_price = cell_total_price/cell_quantity
                       else :
                         average_price = 0
 
-                      LOG('buildInvoiceList edit', 0, repr(( object_to_update, cell_target_quantity, average_price, )))
-                      object_to_update.edit(target_quantity = cell_target_quantity,
-                                            quantity = cell_target_quantity,
+                      LOG('buildInvoiceList edit', 0, repr(( object_to_update, cell_quantity, average_price, )))
+                      object_to_update.edit(quantity = cell_quantity,
                                             price = average_price)
+                                            
       # we now reindex the movements we modified
       for movement in reindexable_movement_list :
         movement.immediateReindexObject()
@@ -527,13 +521,6 @@ class Delivery(XMLObject):
       result = self.z_total_price(delivery_uid = self.getUid())
       return result[0][0]
 
-    security.declareProtected(Permissions.AccessContentsInformation, 'getTargetTotalPrice')
-    def getTargetTotalPrice(self):
-      """
-      """
-      result = self.z_total_price(delivery_uid = self.getUid())
-      return result[0][1]
-
 #     security.declareProtected(Permissions.AccessContentsInformation, 'getTotalPrice')
 #     def getTotalPrice(self, context=None, REQUEST=None, **kw):
 #       """
@@ -581,14 +568,6 @@ class Delivery(XMLObject):
       aggregate = self.Delivery_zGetTotal(uid=self.getUid())[0]
       return aggregate.total_quantity
 
-    security.declareProtected(Permissions.AccessContentsInformation, 'getTargetTotalQuantity')
-    def getTargetTotalQuantity(self):
-      """
-        Returns the quantity if no cell or the total quantity if cells
-      """
-      aggregate = self.Delivery_zGetTotal()[0]
-      return aggregate.target_total_quantity
-
     security.declareProtected(Permissions.AccessContentsInformation, 'getDeliveryUid')
     def getDeliveryUid(self):
       return self.getUid()
@@ -694,8 +673,8 @@ class Delivery(XMLObject):
         LOG('Delivery.isSimulated m.isSimulated',0,m.isSimulated())
         if not m.isSimulated():
           LOG('Delivery.isSimulated m.getQuantity',0,m.getQuantity())
-          LOG('Delivery.isSimulated m.getTargetQuantity',0,m.getTargetQuantity())
-          if m.getQuantity() != 0.0 or m.getTargetQuantity() != 0:
+          LOG('Delivery.isSimulated m.getSimulationQuantity',0,m.getSimulationQuantity())
+          if m.getQuantity() != 0.0 or m.getSimulationQuantity() != 0:
             return 0
           # else Do we need to create a simulation movement ? XXX probably not
       return 1
@@ -718,9 +697,9 @@ class Delivery(XMLObject):
         Source is divergent if simulated and target values differ
         or if multiple sources are defined
       """
-      if self.getSource() != self.getTargetSource() \
+      if self.getSource() != self.getSimulationSource() \
           or len(self.getSourceList()) > 1 \
-          or len(self.getTargetSourceList()) > 1:
+          or len(self.getSimulationSourceList()) > 1:
         return 1
       return 0
 
@@ -732,12 +711,12 @@ class Delivery(XMLObject):
       """
       LOG('Delivery.isDestinationDivergent, self.getPath()',0,self.getPath())
       LOG('Delivery.isDestinationDivergent, self.getDestination()',0,self.getDestination())
-      LOG('Delivery.isDestinationDivergent, self.getTargetDestination()',0,self.getTargetDestination())
+      LOG('Delivery.isDestinationDivergent, self.getSimulationDestination()',0,self.getSimulationDestination())
       LOG('Delivery.isDestinationDivergent, self.getDestinationList()',0,self.getDestinationList())
-      LOG('Delivery.isDestinationDivergent, self.getTargetDestinationList()',0,self.getTargetDestinationList())
-      if self.getDestination() != self.getTargetDestination() \
+      LOG('Delivery.isDestinationDivergent, self.getSimulationDestinationList()',0,self.getSimulationDestinationList())
+      if self.getDestination() != self.getSimulationDestination() \
           or len(self.getDestinationList()) > 1 \
-          or len(self.getTargetDestinationList()) > 1:
+          or len(self.getSimulationDestinationList()) > 1:
         return 1
       return 0
 
@@ -746,9 +725,9 @@ class Delivery(XMLObject):
       """
         Same as isSourceDivergent for source_section
       """
-      if self.getSourceSection() != self.getTargetSourceSection() \
+      if self.getSourceSection() != self.getSimulationSourceSection() \
           or len(self.getSourceSectionList()) > 1 \
-          or len(self.getTargetSourceSectionList()) > 1:
+          or len(self.getSimulationSourceSectionList()) > 1:
         return 1
       return 0
 
@@ -757,9 +736,9 @@ class Delivery(XMLObject):
       """
         Same as isDestinationDivergent for source_section
       """
-      if self.getDestinationSection() != self.getTargetDestinationSection() \
+      if self.getDestinationSection() != self.getSimulationDestinationSection() \
           or len(self.getDestinationSectionList()) > 1 \
-          or len(self.getTargetDestinationSectionList()) > 1:
+          or len(self.getSimulationDestinationSectionList()) > 1:
         return 1
       return 0
 
@@ -768,16 +747,16 @@ class Delivery(XMLObject):
       """
       """
       LOG("isDivergent getStartDate", 0, repr(self.getStartDate()))
-      LOG("isDivergent getTargetStartDate", 0, repr(self.getTargetStartDate()))
+      LOG("isDivergent getSimulationStartDate", 0, repr(self.getSimulationStartDate()))
       LOG("isDivergent getStopDate", 0, repr(self.getStopDate()))
-      LOG("isDivergent getTargetStopDate", 0, repr(self.getTargetStopDate()))
+      LOG("isDivergent getSimulationStopDate", 0, repr(self.getSimulationStopDate()))
       from DateTime import DateTime
-      if self.getStartDate() is None or self.getTargetStartDate() is None \
-               or self.getStopDate() is None or self.getTargetStopDate() is None:
+      if self.getStartDate() is None or self.getSimulationStartDate() is None \
+               or self.getStopDate() is None or self.getSimulationStopDate() is None:
         return 1
       # This is uggly but required due to python2.2/2.3 Zope 2.6/2.7 inconsistency in _millis calculation
-      if self.getStartDate().Date() != self.getTargetStartDate().Date()  or \
-         self.getStopDate().Date() != self.getTargetStopDate().Date():
+      if self.getStartDate().Date() != self.getSimulationStartDate().Date()  or \
+         self.getStopDate().Date() != self.getSimulationStopDate().Date():
 #         LOG("isDivergent getStartDate", 0, repr(self.getStartDate()))
 #         LOG("isDivergent getTargetStartDate", 0, repr(self.getTargetStartDate()))
 #         LOG("isDivergent getStopDate", 0, repr(self.getStopDate()))
diff --git a/product/ERP5/Document/DeliveryCell.py b/product/ERP5/Document/DeliveryCell.py
index e858866e65..fe16b76910 100755
--- a/product/ERP5/Document/DeliveryCell.py
+++ b/product/ERP5/Document/DeliveryCell.py
@@ -240,21 +240,6 @@ Une ligne tarifaire."""
         return self.getTargetQuantity() # We have acquisition here which me should mimic
         # return None
 
-    security.declareProtected( Permissions.AccessContentsInformation, 'getTargetQuantity' )
-    def getTargetQuantity(self):
-      """
-        Returns the target quantity if defined on the cell
-        or acquire it
-      """
-      # Call a script on the context
-      if 'target_quantity' in self.getMappedValuePropertyList([]):
-        if getattr(aq_base(self), 'target_quantity', None) is not None:
-          return getattr(self, 'target_quantity')
-        else:
-          return self.aq_parent.getProperty('target_quantity')
-      else:
-        return None
-
     def _setItemIdList(self, value):
       """
         Computes total_quantity of all given items and stores this total_quantity
@@ -353,34 +338,19 @@ Une ligne tarifaire."""
       return self.getParent().getRootDeliveryValue()
 
     # Simulation Consistency Check
-    def getRelatedQuantity(self):
+    def getSimulationQuantity(self):
       """
           Computes the quantities in the simulation
       """
       if isinstance(self, OrderLine):
         result = self.OrderLine_zGetRelatedQuantity(uid=self.getUid())
-        if len(result) > 0:
-          return result[0].target_quantity
-        return None
-      else:
-        result = self.DeliveryLine_zGetRelatedQuantity(uid=self.getUid())
         if len(result) > 0:
           return result[0].quantity
         return None
-
-    def getRelatedTargetQuantity(self):
-      """
-          Computes the target quantities in the simulation
-      """
-      if isinstance(self, OrderLine):
-        result = self.OrderLine_zGetRelatedQuantity(uid=self.getUid())
-        if len(result) > 0:
-          return result[0].target_quantity
-        return None
       else:
         result = self.DeliveryLine_zGetRelatedQuantity(uid=self.getUid())
         if len(result) > 0:
-          return result[0].target_quantity
+          return result[0].quantity
         return None
 
     security.declareProtected( Permissions.ModifyPortalContent, 'notifyAfterUpdateRelatedContent' )
diff --git a/product/ERP5/Document/DeliveryLine.py b/product/ERP5/Document/DeliveryLine.py
index b455239b4c..3916af785c 100755
--- a/product/ERP5/Document/DeliveryLine.py
+++ b/product/ERP5/Document/DeliveryLine.py
@@ -209,23 +209,13 @@ Une ligne tarifaire."""
 
     def _getTotalPrice(self, context):
       if not self.hasCellContent():
-        price = self.getPrice(context=context)
-        if price is None: price = 0.0 # Quick and dirty fix XXX
-        return self.getQuantity() * price
-      else:
-        # Use MySQL
-        aggregate = self.DeliveryLine_zGetTotal()[0]
-        return aggregate.total_price
-
-    def _getTargetTotalPrice(self, context):
-      if not self.hasCellContent():
-        target_quantity = self.getTargetQuantity() or 0.0
+        quantity = self.getQuantity() or 0.0
         price = self.getPrice(context=context) or 0.0
-        return target_quantity * price
+        return quantity * price
       else:
         # Use MySQL
         aggregate = self.DeliveryLine_zGetTotal()[0]
-        return aggregate.target_total_price
+        return aggregate.total_price
 
     security.declareProtected(Permissions.AccessContentsInformation, 'getTotalQuantity')
     def getTotalQuantity(self):
@@ -239,18 +229,6 @@ Une ligne tarifaire."""
         aggregate = self.DeliveryLine_zGetTotal()[0]
         return aggregate.total_quantity
 
-    security.declareProtected(Permissions.AccessContentsInformation, 'getTargetTotalQuantity')
-    def getTargetTotalQuantity(self):
-      """
-        Returns the quantity if no cell or the total quantity if cells
-      """
-      if not self.hasCellContent():
-        return self.getTargetQuantity()
-      else:
-        # Use MySQL
-        aggregate = self.DeliveryLine_zGetTotal()[0]
-        return aggregate.target_total_quantity
-
     # Cell Related
     security.declareProtected( Permissions.ModifyPortalContent, 'newCellContent' )
     def newCellContent(self, id, **kw):
@@ -320,7 +298,7 @@ Une ligne tarifaire."""
           #LOG('new cell',0,str(k))
           c = self.newCell(*k, **kwd)
           c.edit( domain_base_category_list = self.getVariationBaseCategoryList(),
-                  mapped_value_property_list = ('target_quantity', 'quantity', 'price',),
+                  mapped_value_property_list = ('quantity', 'price',),
                   #predicate_operator = 'SUPERSET_OF',
                   membership_criterion_category = filter(lambda k_item: k_item is not None, k),
                   variation_category_list = filter(lambda k_item: k_item is not None, k),
@@ -468,7 +446,7 @@ Une ligne tarifaire."""
 
 
     security.declarePrivate('_checkConsistency')
-    def _checkConsistency(self, fixit=0, mapped_value_property_list = ('target_quantity', 'quantity', 'price')):
+    def _checkConsistency(self, fixit=0, mapped_value_property_list = ('quantity', 'price')):
       """
         Check the constitency of transformation elements
       """
@@ -507,18 +485,10 @@ Une ligne tarifaire."""
       """
           Computes the quantities in the simulation
       """
-      result = self.DeliveryLine_zGetRelatedQuantity(uid=self.getUid())
-      if len(result) > 0:
-        return result[0].quantity
-      return None
-
-    def getSimulationTargetQuantity(self):
-      """
-          Computes the target quantities in the simulation
-      """
-      result = self.DeliveryLine_zGetRelatedQuantity(uid=self.getUid())
-      if len(result) > 0:
-        return result[0].target_quantity
+      if not self.hasCellContent():
+        result = self.DeliveryLine_zGetRelatedQuantity(uid=self.getUid())
+        if len(result) > 0:
+          return result[0].quantity
       return None
 
     def getSimulationSourceList(self):
@@ -556,26 +526,3 @@ Une ligne tarifaire."""
       """
       return self.getParent().getRootDeliveryValue()
 
-    # Simulation Consistency Check
-    def getRelatedQuantity(self):
-      """
-          Computes the quantities in the simulation
-      """
-      if not self.hasCellContent():
-        result = self.DeliveryLine_zGetRelatedQuantity(uid=self.getUid())
-        if len(result) > 0:
-          return result[0].quantity
-      return None
-
-    def getRelatedTargetQuantity(self):
-      """
-          Computes the target quantities in the simulation
-      """
-      if not self.hasCellContent():
-        result = self.DeliveryLine_zGetRelatedQuantity(uid=self.getUid())
-        if len(result) > 0:
-          return result[0].target_quantity
-      return None
-
-      
-      
diff --git a/product/ERP5/Document/DeliveryRule.py b/product/ERP5/Document/DeliveryRule.py
index 15ca32cad3..9d0111ccc4 100755
--- a/product/ERP5/Document/DeliveryRule.py
+++ b/product/ERP5/Document/DeliveryRule.py
@@ -183,11 +183,8 @@ An ERP5 Rule..."""
                           delivery_value = c,
                           order_value = c,
                           quantity = c.getQuantity(),
-                          target_quantity = c.getTargetQuantity(),
                           start_date = c.getStartDate(),
                           stop_date = c.getStopDate(),
-                          target_start_date = c.getTargetStartDate(),
-                          target_stop_date = c.getTargetStopDate(),
                           deliverable = 1
                       )
                       # We must create both order and delivery link in this case
@@ -203,11 +200,8 @@ An ERP5 Rule..."""
                         delivery_value = delivery_line_object,
                         order_value = delivery_line_object,
                         quantity = delivery_line_object.getQuantity(),
-                        target_quantity = delivery_line_object.getTargetQuantity(),
                         start_date = delivery_line_object.getStartDate(),
                         stop_date = delivery_line_object.getStopDate(),
-                        target_start_date = delivery_line_object.getTargetStartDate(),
-                        target_stop_date = delivery_line_object.getTargetStopDate(),
                         deliverable = 1
                     )
                     # Source, Destination, Quantity, Date, etc. are
diff --git a/product/ERP5/Document/Domain.py b/product/ERP5/Document/Domain.py
index 958051c542..25eaaf2db1 100755
--- a/product/ERP5/Document/Domain.py
+++ b/product/ERP5/Document/Domain.py
@@ -37,7 +37,28 @@ class Domain(PredicateGroup):
   """
     An abstract class subclassed by reports and mapped values
 
-    Implements subdomain traversal methods
+    Structure is:
+       - base domain (like base category)
+       - sub domain (like category)
+       
+    Allows to define ranges:
+       - price between X and Y
+       - portal_type in (a, b, c)
+       - price between X and Y and region in (a, b, c)
+       
+    Reports:
+       - listbox allows to produce reports
+         - output to html, pdf or ooffice
+         - definition through the web (ie. which field in which column, which statistics)
+         - definition of selection (to list)
+         - ability for use to "save" favourite report (user reports)
+         - library of favourite reports (global reports)
+       - matrixbox allows to produce reports       
+         - output to html, pdf or ooffice
+         - definition through the web (ie. which base_category or base_domain in which axis)
+         - definition of selection (to map to matrix)
+         - ability for use to "save" favourite report (user reports)
+         - library of favourite reports (global reports)
   """
   meta_type = 'ERP5 Domain'
   portal_type = 'Domain'
diff --git a/product/ERP5/Document/Invoice.py b/product/ERP5/Document/Invoice.py
index 7a47dc1988..41e67b7063 100755
--- a/product/ERP5/Document/Invoice.py
+++ b/product/ERP5/Document/Invoice.py
@@ -106,7 +106,7 @@ class Invoice(AccountingTransaction):
         for rule in o.objectValues():
           invoice_transaction_rule_list.append(rule)
           simulation_line_list += rule.objectValues()
-      LOG('buildInvoiceTransactionList simulation_line_list',0,simulation_line_list)
+      #LOG('buildInvoiceTransactionList simulation_line_list',0,simulation_line_list)
       from Products.ERP5.MovementGroup import CategoryMovementGroup
       class_list = [CategoryMovementGroup, ]
       root_group = self.portal_simulation.collectMovement(simulation_line_list,class_list=class_list)
@@ -144,9 +144,14 @@ class Invoice(AccountingTransaction):
             
           # add sum of movements to invoice
           #LOG('buildInvoiceTransactionList group_id',0,group_id)          
+          #LOG('buildInvoiceTransactionList reference_movement',0,str(reference_movement.getRelativeUrl()))
+          #LOG('buildInvoiceTransactionList reference_movement',0,str(reference_movement.showDict()))
+          #LOG('buildInvoiceTransactionList reference_movement',0,str(reference_movement.getSource()))
+          #LOG('buildInvoiceTransactionList reference_movement',0,str(reference_movement.getDestination()))
           sale_invoice_transaction_line_item = getattr(self, group_id, None)          
           if sale_invoice_transaction_line_item is None :
-            sale_invoice_transaction_line_item = self.newContent(portal_type = self._transaction_line_portal_type
+            sale_invoice_transaction_line_item = self.newContent(
+                portal_type = self._transaction_line_portal_type
               , id = group_id
               , source = reference_movement.getSource()
               , destination = reference_movement.getDestination()
@@ -156,11 +161,13 @@ class Invoice(AccountingTransaction):
               sale_invoice_transaction_line_item._setDestinationSection(reference_movement.getDestinationSection())
             if self.getSourceSection() != reference_movement.getSourceSection():
               sale_invoice_transaction_line_item._setSourceSection(reference_movement.getSourceSection())
+            #LOG('buildInvoiceTransactionList sale_invoice_transaction_line',0,str(sale_invoice_transaction_line_item.showDict())) 
           else :
             sale_invoice_transaction_line_item.edit(
                 source = reference_movement.getSource()
               , destination = reference_movement.getDestination()
               , quantity = quantity
+              , force_update = 1
             )
             if self.getDestinationSection() != reference_movement.getDestinationSection():
               sale_invoice_transaction_line_item._setDestinationSection(reference_movement.getDestinationSection())
@@ -200,7 +207,7 @@ class Invoice(AccountingTransaction):
         for rule in o.objectValues():
           payment_transaction_rule_list.append(rule)
           simulation_line_list += rule.objectValues()
-      LOG('buildPaymentTransactionList simulation_line_list',0,simulation_line_list)
+      #LOG('buildPaymentTransactionList simulation_line_list',0,simulation_line_list)
 
       # create payment transaction
       accounting_module = self.accounting
@@ -208,17 +215,15 @@ class Invoice(AccountingTransaction):
       payment_id = str(accounting_module.generateNewId())
       payment_transaction = accounting_module.newContent(portal_type = payment_type
           , id = payment_id
-          , source = self.getSource()
           , reference = self.getReference()
           , resource = self.getResource()
           , start_date = self.getStartDate()
           , source_payment = self.getSourcePayment()
           , source_section = self.getSourceSection()
-          , destination = self.getDestination()
           , destination_payment = self.getDestinationPayment()
           , destination_section = self.getDestinationSection()
           )
-      LOG('buildPaymentTransactionList payment_transaction', 0, repr(( payment_transaction )))
+      #LOG('buildPaymentTransactionList payment_transaction', 0, repr(( payment_transaction.showDict() )))
 
       # fill quantity in lines
       for movement in simulation_line_list :
@@ -228,16 +233,25 @@ class Invoice(AccountingTransaction):
 
           payment_transaction_line = getattr(payment_transaction, movement_id, None)
           if payment_transaction_line is None :
-            payment_transaction.newContent(portal_type = 'Accounting Transaction Line'
+            payment_transaction.newContent(
+                portal_type = 'Accounting Transaction Line'
               , id = movement_id
-              , quantity = quantity
             )
+            previous_quantity = 0.0
           else :
             previous_quantity = payment_transaction_line.getQuantity()
-            if previous_quantity is not None:
-              quantity = quantity + previous_quantity
-            payment_transaction_line.setQuantity(quantity)
+          if previous_quantity is not None:
+            quantity = quantity + previous_quantity
+          payment_transaction_line.edit(
+              quantity = quantity
+            , source = movement.getSource()
+            , destination = movement.getDestination()
+            , force_update = 1
+            )
 
+          #LOG('buildPaymentTransactionList movement', 0, repr(( movement.showDict() )))              
+          #LOG('buildPaymentTransactionList payment_transaction_line', 0, repr(( payment_transaction_line.showDict() )))              
+              
           # What do we really need to update in the simulation movement ?
           if movement.getPortalType() == 'Simulation Movement' :
             movement._setDeliveryValue(payment_transaction_line)
diff --git a/product/ERP5/Document/InvoicingRule.py b/product/ERP5/Document/InvoicingRule.py
index 69356fc29a..870b462720 100755
--- a/product/ERP5/Document/InvoicingRule.py
+++ b/product/ERP5/Document/InvoicingRule.py
@@ -85,9 +85,7 @@ class InvoicingRule(Rule):
       my_context_movement = applied_rule.getParent()
       LOG('InvoicingRule.expand, my_context_movement.getPhysicalPath()',0,my_context_movement.getPhysicalPath())
       LOG('InvoicingRule.expand, my_context_movement.getSource()',0,my_context_movement.getSource())
-      LOG('InvoicingRule.expand, my_context_movement.getTargetSource()',0,my_context_movement.getTargetSource())
       LOG('InvoicingRule.expand, my_context_movement.showDict()',0,my_context_movement.showDict())
-      LOG('InvoicingRule.expand, my_context_movement.getSource',0,my_context_movement.getSource())
       if my_context_movement.getSource() is not None:
         # We should only expand movements if they have a source
         # otherwise, it creates infinite recursion
@@ -106,16 +104,16 @@ class InvoicingRule(Rule):
         resource = my_context_movement.getResource()
         invoice_line._edit(
                 price = my_context_movement.getPrice(),
-                target_quantity = my_context_movement.getTargetQuantity(),
-                target_efficiency = my_context_movement.getTargetEfficiency(),
+                quantity = my_context_movement.getQuantity(),
+                efficiency = my_context_movement.getEfficiency(),
                 resource = resource,
-                target_start_date = my_context_movement.getTargetStartDate(),
-                target_stop_date = my_context_movement.getTargetStartDate(),
-                target_source = my_context_movement.getTargetDestination(),
-                target_source_section = my_context_movement.getTargetSourceSection(),
+                start_date = my_context_movement.getStartDate(),
+                stop_date = my_context_movement.getStartDate(),
+                source = my_context_movement.getDestination(),
+                source_section = my_context_movement.getSourceSection(),
                 quantity_unit = my_context_movement.getQuantityUnit(),
-                target_destination = my_context_movement.getTargetDestination(),
-                target_destination_section = my_context_movement.getTargetDestinationSection(),
+                destination = my_context_movement.getDestination(),
+                destination_section = my_context_movement.getDestinationSection(),
                 deliverable = 1   # We do need to collect invoice lines to build invoices
             )
         #  transformation_source.setVariationCategoryList(
diff --git a/product/ERP5/Document/Movement.py b/product/ERP5/Document/Movement.py
index bd5e4e9021..76100b3d1e 100755
--- a/product/ERP5/Document/Movement.py
+++ b/product/ERP5/Document/Movement.py
@@ -269,14 +269,6 @@ a service in a public administration)."""
     else:
       return None
 
-  def _getTargetTotalPrice(self, context):
-    price = self.getPrice(context=context)
-    quantity = self.getTargetQuantity()
-    if type(price) in (type(1.0), type(1)) and type(quantity) in (type(1.0), type(1)):
-      return quantity * price
-    else:
-      return None
-
   security.declareProtected(Permissions.AccessContentsInformation, 'getPrice')
   def getPrice(self, context=None, REQUEST=None, **kw):
     """
@@ -295,12 +287,6 @@ a service in a public administration)."""
     """
     return self._getTotalPrice(self.asContext(context=context, REQUEST=REQUEST, **kw))
 
-  security.declareProtected(Permissions.AccessContentsInformation, 'getTargetTotalPrice')
-  def getTargetTotalPrice(self, context=None, REQUEST=None, **kw):
-    """
-    """
-    return self._getTargetTotalPrice(self.asContext(context=context, REQUEST=REQUEST, **kw))
-
   security.declareProtected(Permissions.AccessContentsInformation, 'getTotalQuantity')
   def getTotalQuantity(self):
     """
@@ -308,13 +294,6 @@ a service in a public administration)."""
     """
     return self.getQuantity()
 
-  security.declareProtected(Permissions.AccessContentsInformation, 'getTargetTotalQuantity')
-  def getTargetTotalQuantity(self):
-    """
-      Returns the quantity if no cell or the total quantity if cells
-    """
-    return self.getTargetQuantity()
-
   # Industrial price API
   security.declareProtected(Permissions.AccessContentsInformation, 'getIndustrialPrice')
   def getIndustrialPrice(self):
@@ -418,3 +397,155 @@ a service in a public administration)."""
   security.declareProtected(Permissions.View, 'isSimulated')
   def isSimulated(self):
     return len(self.getDeliveryRelatedValueList()) > 0 or len(self.getOrderRelatedValueList()) > 0
+
+  # New Causality API          
+  security.declareProtected(Permissions.AccessContentsInformation, 'getOrderQuantity')
+  def getOrderQuantity(self):
+    """
+      Returns the quantity of related order(s)
+    """
+    return self.getQuantity()
+    
+  security.declareProtected(Permissions.AccessContentsInformation, 'getDeliveryQuantity')
+  def getDeliveryQuantity(self):
+    """
+      Returns the quantity of related delivery(s)
+    """
+    return self.getQuantity()    
+    
+  security.declareProtected(Permissions.AccessContentsInformation, 'getSimulationQuantity')
+  def getSimulationQuantity(self):
+    """
+      Returns the sum of quantities in related simulation movements
+    """
+    return self.getQuantity()    
+    
+  security.declareProtected(Permissions.AccessContentsInformation, 'getOrderStartDateList')
+  def getOrderStartDateList(self):
+    """
+      Returns the start date of related order(s)
+    """
+    return [self.getStartDate()]
+    
+  security.declareProtected(Permissions.AccessContentsInformation, 'getDeliveryStartDateList')
+  def getDeliveryStartDateList(self):
+    """
+      Returns the start date of related delivery(s)
+    """
+    return [self.getStartDate()]
+    
+  security.declareProtected(Permissions.AccessContentsInformation, 'getSimulationStartDateList')
+  def getSimulationStartDateList(self):
+    """
+      Returns the of start date related simulation movements
+    """
+    return [self.getStartDate()]
+  
+  security.declareProtected(Permissions.AccessContentsInformation, 'getOrderStopDateList')
+  def getOrderStopDateList(self):
+    """
+      Returns the stop date of related order(s)
+    """
+    return [self.getStopDate()]
+    
+  security.declareProtected(Permissions.AccessContentsInformation, 'getDeliveryStopDateList')
+  def getDeliveryStopDateList(self):
+    """
+      Returns the stop date of related delivery(s)
+    """
+    return [self.getStopDate()]
+    
+  security.declareProtected(Permissions.AccessContentsInformation, 'getSimulationStopDateList')
+  def getSimulationStopDateList(self):
+    """
+      Returns the of stop date related simulation movements
+    """
+    return [self.getStopDate()]
+  
+  security.declareProtected(Permissions.AccessContentsInformation, 'getOrderSourceList')
+  def getOrderSourceList(self):
+    """
+      Returns the source of related orders
+    """
+    return self.getSourceList()    
+    
+  security.declareProtected(Permissions.AccessContentsInformation, 'getDeliverySourceList')
+  def getDeliverySourceList(self):
+    """
+      Returns the source of related deliveries
+    """
+    return self.getSourceList()    
+    
+  security.declareProtected(Permissions.AccessContentsInformation, 'getSimulationSourceList')
+  def getSimulationSourceList(self):
+    """
+      Returns the source of related simulation movements
+    """
+    return self.getSourceList()    
+    
+  security.declareProtected(Permissions.AccessContentsInformation, 'getOrderDestinationList')
+  def getOrderDestinationList(self):
+    """
+      Returns the destination of related orders
+    """
+    return self.getDestinationList()    
+    
+  security.declareProtected(Permissions.AccessContentsInformation, 'getDeliveryDestinationList')
+  def getDeliveryDestinationList(self):
+    """
+      Returns the destination of related deliveries
+    """
+    return self.getDestinationList()    
+    
+  security.declareProtected(Permissions.AccessContentsInformation, 'getSimulationDestinationList')
+  def getSimulationDestinationList(self):
+    """
+      Returns the destination of related simulation movements
+    """
+    return self.getDestinationList()    
+    
+  security.declareProtected(Permissions.AccessContentsInformation, 'getOrderSourceSectionList')
+  def getOrderSourceSectionList(self):
+    """
+      Returns the source_section of related orders
+    """
+    return self.getSourceSectionList()    
+    
+  security.declareProtected(Permissions.AccessContentsInformation, 'getDeliverySourceSectionList')
+  def getDeliverySourceSectionList(self):
+    """
+      Returns the source_section of related deliveries
+    """
+    return self.getSourceSectionList()    
+    
+  security.declareProtected(Permissions.AccessContentsInformation, 'getSimulationSourceSectionList')
+  def getSimulationSourceSectionList(self):
+    """
+      Returns the source_section of related simulation movements
+    """
+    return self.getSourceSectionList()    
+    
+  security.declareProtected(Permissions.AccessContentsInformation, 'getOrderDestinationSectionList')
+  def getOrderDestinationSectionList(self):
+    """
+      Returns the destination_section of related orders
+    """
+    return self.getDestinationSectionList()    
+    
+  security.declareProtected(Permissions.AccessContentsInformation, 'getDeliveryDestinationSectionList')
+  def getDeliveryDestinationSectionList(self):
+    """
+      Returns the destination_section of related deliveries
+    """
+    return self.getDestinationSectionList()    
+    
+  security.declareProtected(Permissions.AccessContentsInformation, 'getSimulationDestinationSectionList')
+  def getSimulationDestinationSectionList(self):
+    """
+      Returns the destination_section of related simulation movements
+    """
+    return self.getDestinationSectionList()    
+    
+    
+    
+    
\ No newline at end of file
diff --git a/product/ERP5/Document/OrderLine.py b/product/ERP5/Document/OrderLine.py
index 497dba9b03..df3dda9185 100755
--- a/product/ERP5/Document/OrderLine.py
+++ b/product/ERP5/Document/OrderLine.py
@@ -151,7 +151,7 @@ Une ligne tarifaire."""
           c = self.newCell(*k, **kwd)
           #LOG('OrderLine _setVariationCategoryList', 0, 'k = %s, c = %s, self.getVariationBaseCategoryList() = %s' % (repr(k), repr(c), repr(self.getVariationBaseCategoryList())))
           c.edit( domain_base_category_list = self.getVariationBaseCategoryList(),
-                  mapped_value_property_list = ('target_quantity', 'price',),
+                  mapped_value_property_list = ('quantity', 'price',),
                   predicate_operator = 'SUPERSET_OF',
                   predicate_value = filter(lambda k_item: k_item is not None, k),
                   variation_category_list = filter(lambda k_item: k_item is not None, k),
@@ -168,7 +168,7 @@ Une ligne tarifaire."""
             self._delObject(k)
 
     security.declarePrivate('_checkConsistency')
-    def _checkConsistency(self, fixit=0, mapped_value_property_list = ('target_quantity', 'price')):
+    def _checkConsistency(self, fixit=0, mapped_value_property_list = ('quantity', 'price')):
       """
         Check the constitency of transformation elements
       """
@@ -211,20 +211,11 @@ Une ligne tarifaire."""
         self.aq_parent.activate()._createOrderRule()
 
     # Simulation Consistency Check
-    def getRelatedQuantity(self):
-      """
-          Computes the quantities in the simulation
-      """
-      result = self.OrderLine_zGetRelatedQuantity(uid=self.getUid())
-      if len(result) > 0:
-        return result[0].quantity
-      return None
-
-    def getRelatedTargetQuantity(self):
+    def getSimulationQuantity(self):
       """
           Computes the target quantities in the simulation
       """
       result = self.OrderLine_zGetRelatedQuantity(uid=self.getUid())
       if len(result) > 0:
-        return result[0].target_quantity
+        return result[0].quantity
       return None
diff --git a/product/ERP5/Document/OrderRule.py b/product/ERP5/Document/OrderRule.py
index 8f5da5331e..cf7d4509dc 100755
--- a/product/ERP5/Document/OrderRule.py
+++ b/product/ERP5/Document/OrderRule.py
@@ -146,7 +146,7 @@ An ERP5 Rule..."""
           # eventually delete movement which do not exist anylonger
           existing_uid_list = []
           for movement in applied_rule.contentValues(filter={'portal_type':applied_rule.getPortalMovementTypeList()}):
-            #LOG('Movement', 0, str(movement))
+            LOG('Movement', 0, str(movement))
             order_value = movement.getOrderValue(portal_type=applied_rule.getPortalOrderMovementTypeList())
             if order_value is None:
               movement.flushActivity(invoke=0)
@@ -156,7 +156,7 @@ An ERP5 Rule..."""
                 existing_uid_list += [order_value.getUid()]
               elif order_value.hasCellContent():
                 # Do not keep head of cells
-                #LOG('INFO', 0, 'Order Rule Deleting Simulatino Movement %s' % movement.getRelativeUrl())
+                LOG('INFO', 0, 'Order Rule Deleting Simulatino Movement %s' % movement.getRelativeUrl())
                 order_value.flushActivity(invoke=0)
                 applied_rule._delObject(movement.getId())  # XXXX Make sur this is not deleted if already in delivery
               else:
@@ -164,16 +164,22 @@ An ERP5 Rule..."""
 
           # Copy each movement (line or cell) from the order
           for order_line_object in my_order.contentValues(filter={'portal_type':applied_rule.getPortalMovementTypeList()}):
+            LOG('OrderRule.expand, examining:',0,order_line_object.getPhysicalPath())
             try:
               if order_line_object.hasCellContent():
                 for c in order_line_object.getCellValueList():
-                  #LOG('Cell  in', 0, '%s %s' % (c.getUid(), existing_uid_list))
+                  LOG('Cell  in', 0, '%s %s' % (c.getUid(), existing_uid_list))
                   if c.getUid() not in existing_uid_list:
                     new_id = order_line_object.getId() + '_' + c.getId()
-                    #LOG('Create Cell', 0, str(new_id))
+                    LOG('Create Cell', 0, str(new_id))
                     new_line = applied_rule.newContent(type_name=delivery_line_type,
                         id=new_id,
                         order_value = c,
+                        quantity = c.getQuantity(),
+                        source = c.getSource(),
+                        destination = c.getDestination(),
+                        source_section = c.getSourceSection(),
+                        destination_section = c.getDestinationSection(),
                         deliverable = 1
                     )
                     LOG('OrderRule.expand, object created:',0,new_line.getPhysicalPath())
@@ -182,16 +188,21 @@ An ERP5 Rule..."""
               else:
                 if order_line_object.getUid() not in existing_uid_list:
                   new_id = order_line_object.getId()
-                  #LOG('Line', 0, str(new_id))
+                  LOG('Line', 0, str(new_id))
                   new_line = applied_rule.newContent(type_name=delivery_line_type,
                       container=applied_rule,
                       id=new_id,
                       order_value = order_line_object,
+                      quantity = order_line_object.getQuantity(),
+                      source = order_line_object.getSource(),
+                      destination = order_line_object.getDestination(),
+                      source_section = order_line_object.getSourceSection(),
+                      destination_section = order_line_object.getDestinationSection(),
                       deliverable = 1
                   )
                   LOG('OrderRule.expand, object created:',0,new_line.getPhysicalPath())
                   new_line.immediateReindexObject()
-                  #LOG('After Create Cell', 0, str(new_id))
+                  LOG('After Create Cell', 0, str(new_id))
                   # Source, Destination, Quantity, Date, etc. are
                   # acquired from the order and need not to be copied.
             except AttributeError:
diff --git a/product/ERP5/Document/PaymentRule.py b/product/ERP5/Document/PaymentRule.py
index 6439d40190..6a91a7141d 100755
--- a/product/ERP5/Document/PaymentRule.py
+++ b/product/ERP5/Document/PaymentRule.py
@@ -69,7 +69,7 @@ class PaymentRule(Rule):
       if 'receivable' in movement.getId() :
         parent = movement.getParent()
         if parent.getPortalType()=='Applied Rule' and parent.getSpecialiseId()=='default_invoice_transaction_rule':
-          LOG('PaymentRule.test :', 0, repr(( 'applies with', movement, parent )))
+          #LOG('PaymentRule.test :', 0, repr(( 'applies with', movement, parent )))
           return 1
       return 0
 
@@ -103,9 +103,21 @@ class PaymentRule(Rule):
                 type_name = payment_line_type,
                 id = receivable_id)
 
-        bank_movement.setQuantity(my_parent_movement.getQuantity())
-        receivable_movement.setQuantity(0 - my_parent_movement.getQuantity())
-
+        bank_movement.edit(
+          quantity = my_parent_movement.getQuantity(),
+          source = 'account/banques_etablissements_financiers', # XXX Not Generic
+          destination = 'account/banques_etablissements_financiers', # XXX Not Generic
+          source_section = my_parent_movement.getSourceSection(),
+          destination_section = my_parent_movement.getDestinationSection(),
+        )          
+        receivable_movement.edit(
+          quantity = - my_parent_movement.getQuantity(),
+          source = 'account/creance_client', # XXX Not Generic
+          destination = 'account/dette_fournisseur', # XXX Not Generic
+          source_section = my_parent_movement.getSourceSection(),
+          destination_section = my_parent_movement.getDestinationSection(),
+        )
+        
       Rule.expand(self, applied_rule, **kw)
 
 
diff --git a/product/ERP5/Document/PredicateGroup.py b/product/ERP5/Document/PredicateGroup.py
index 773100fe8b..b6570d03d2 100755
--- a/product/ERP5/Document/PredicateGroup.py
+++ b/product/ERP5/Document/PredicateGroup.py
@@ -226,6 +226,7 @@ identify a bank account."""
     membership_criterion_category_list = []
     membership_criterion_base_category_list = []
     multimembership_criterion_base_category_list = []
+    test_method_id_list = []
     criterion_property_list = []
     for c in category_list:
       bc = c.split('/')[0]
@@ -243,12 +244,14 @@ identify a bank account."""
                       predicate_value.getMembershipCriterionBaseCategoryList())
           multimembership_criterion_base_category_list.extend(
                       predicate_value.getMultimembershipCriterionBaseCategoryList())
+          test_method_id_list += list(predicate_value.getTestMethodIdList() or [])
           for p in predicate_value.getCriterionList():
             self.setCriterion(p.property, identity=p.identity, min=p.min, max=p.max)
     self.setCriterionPropertyList(criterion_property_list)
-    self.setMembershipCriterionCategoryList(membership_criterion_category_list)
-    self.setMembershipCriterionBaseCategoryList(membership_criterion_base_category_list)
-    self.setMultimembershipCriterionBaseCategoryList(multimembership_criterion_base_category_list)
+    self._setMembershipCriterionCategoryList(membership_criterion_category_list)
+    self._setMembershipCriterionBaseCategoryList(membership_criterion_base_category_list)
+    self._setMultimembershipCriterionBaseCategoryList(multimembership_criterion_base_category_list)
+    self._setTestMethodIdList(test_method_id_list)    
     self.reindexObject()
 
   # Predicate handling
diff --git a/product/ERP5/Document/SimulationMovement.py b/product/ERP5/Document/SimulationMovement.py
index 7dc9a042e1..bfc83e7046 100755
--- a/product/ERP5/Document/SimulationMovement.py
+++ b/product/ERP5/Document/SimulationMovement.py
@@ -435,3 +435,18 @@ a service in a public administration)."""
     return 0
 
   getDeliverable = isDeliverable
+
+  # Simulation Dates - acquire target dates 
+  security.declareProtected(Permissions.AccessContentsInformation, 'getOrderStartDate')
+  def getOrderStartDate(self):
+    order_value = self.getOrderValue()
+    if order_value is not None:
+      return order_value.getStartDate()
+  
+  security.declareProtected(Permissions.AccessContentsInformation, 'getOrderStopDate')
+  def getOrderStopDate(self):
+    order_value = self.getOrderValue()
+    if order_value is not None:
+      return order_value.getStopDate()
+  
+  
\ No newline at end of file
diff --git a/product/ERP5/Document/TransformationRule.py b/product/ERP5/Document/TransformationRule.py
index a93d4d47d6..84169757b7 100755
--- a/product/ERP5/Document/TransformationRule.py
+++ b/product/ERP5/Document/TransformationRule.py
@@ -232,15 +232,15 @@ An ERP5 Rule..."""
 
       produced_resource = applied_rule[new_id]
       produced_resource._edit(
-        target_start_date = my_context_movement.getTargetStartDate(),
-        target_stop_date = my_context_movement.getTargetStartDate(),
+        start_date = my_context_movement.getStartDate(),
+        stop_date = my_context_movement.getStartDate(),
         resource = my_context_movement.getResource(),
-        target_quantity = my_context_movement.getTargetQuantity() + lost_quantity,
-        target_source_list = (),
-        target_source_section_list = (),
+        quantity = my_context_movement.getQuantity() + lost_quantity,
+        source_list = (),
+        source_section_list = (),
         quantity_unit = my_context_movement.getQuantityUnit(),
-        target_destination_section = production_section,
-        target_destination = production_node,
+        destination_section = production_section,
+        destination = production_node,
         deliverable = 1
       )
       # Mising quantity unit conversion for my_quantity !!!! XXXX
@@ -270,15 +270,15 @@ An ERP5 Rule..."""
         if amount_line['quantity'] != 0.0:
           # Only create line if it is not 0.0
           transformed_resource._edit(
-            target_start_date = my_context_movement.getTargetStartDate(),
-            target_stop_date = my_context_movement.getTargetStartDate(),
-            target_quantity = amount_line['quantity'] * my_quantity,
-            target_efficiency = amount_line['efficiency'],
+            start_date = my_context_movement.getStartDate(),
+            stop_date = my_context_movement.getStartDate(),
+            quantity = amount_line['quantity'] * my_quantity,
+            efficiency = amount_line['efficiency'],
             resource_value = amount_line['resource'],
             quantity_unit = amount_line['quantity_unit'],
-            target_source = production_node,
-            target_source_section = production_section,
-            target_destination_list = (),
+            source = production_node,
+            source_section = production_section,
+            destination_list = (),
             deliverable = 1
           )
           LOG('TransformationRule.expand transformed_resource.getPhysicalPath()',0,transformed_resource.getPhysicalPath())
diff --git a/product/ERP5/ERP5Defaults.py b/product/ERP5/ERP5Defaults.py
index 61d4b0e6dc..9cf2b69ab0 100755
--- a/product/ERP5/ERP5Defaults.py
+++ b/product/ERP5/ERP5Defaults.py
@@ -140,7 +140,7 @@ portal_balance_transaction_line_type_list = ('Balance Transaction Line',)
 ## Inventory States
 
 portal_current_inventory_state_list = ('delivered', 'started', 'stopped', 'invoiced') # invoiced is Coramy specific and should be removed
-portal_target_inventory_state_list = ('ready', 'delivered', 'started', 'stopped', 'invoiced') # if simulation_state in target_list, target_quantity should be considered instead of quantity for stock indexing
+portal_target_inventory_state_list = ('ready', 'delivered', 'started', 'stopped', 'invoiced') # if simulation_state in target_list, target_quantity should be considered instead of quantity for stock indexing XXX why do we need two inventory_state_list ?
 portal_draft_order_state_list =  ('cancelled', 'draft', 'auto_planned' )
 portal_planned_order_state_list =  ('planned', 'ordered', )
 portal_reserved_inventory_state_list = ('confirmed', 'getting_ready', 'ready')
diff --git a/product/ERP5/Extensions/InitializeAcquisition.py b/product/ERP5/Extensions/InitializeAcquisition.py
index 70c4632b1a..19c443f887 100755
--- a/product/ERP5/Extensions/InitializeAcquisition.py
+++ b/product/ERP5/Extensions/InitializeAcquisition.py
@@ -9,9 +9,7 @@ def setBaseAcquisition(self):
   #   we should not use causality here because of production reports
   #   for which source or destination can be None (ie. different from Production Order)
   for bc in ('source', 'destination',
-             'target_source', 'target_destination',
-             'source_section', 'destination_section',
-             'target_source_section', 'target_destination_section',):
+             'source_section', 'destination_section',):
     if not hasattr(pc, bc):
       addBaseCategory(pc, bc)
     pc[bc].setAcquisitionBaseCategoryList(('delivery', 'order', 'parent', ))
diff --git a/product/ERP5/MovementGroup.py b/product/ERP5/MovementGroup.py
index 7df00e525f..609f0f9042 100755
--- a/product/ERP5/MovementGroup.py
+++ b/product/ERP5/MovementGroup.py
@@ -48,11 +48,11 @@ class RootMovementGroup:
       This sets an appropriate nested class.
     """
 
-    LOG('RootGroup.setNestedClass, class_list:',0,class_list)
+    #LOG('RootGroup.setNestedClass, class_list:',0,class_list)
     for i in range(len(class_list)):
-      LOG('RootGroup.setNestedClass, class_list[i]:',0,class_list[i])
+      #LOG('RootGroup.setNestedClass, class_list[i]:',0,class_list[i])
       #LOG('RootGroup.setNestedClass, class_list[i].getId():',0,class_list[i].getId())
-      LOG('RootGroup.setNestedClass, self.__class__:',0,self.__class__)
+      #LOG('RootGroup.setNestedClass, self.__class__:',0,self.__class__)
       if class_list[i] == self.__class__:
         break
     else:
@@ -71,7 +71,7 @@ class RootMovementGroup:
 
   def appendGroup(self, movement,class_list=None):
     if self.nested_class is not None:
-      LOG('RootGroup.appendGroup, class_list',0,class_list)
+      #LOG('RootGroup.appendGroup, class_list',0,class_list)
       nested_instance = self.nested_class(movement=movement,class_list=class_list)
       self.group_list.append(nested_instance)
 
@@ -84,7 +84,7 @@ class RootMovementGroup:
         movement_in_group = 1
         break
     if movement_in_group == 0 :
-      LOG('RootGroup.append, class_list',0,class_list)
+      #LOG('RootGroup.append, class_list',0,class_list)
       self.appendGroup(movement,class_list=class_list)
 
 allow_class(RootMovementGroup)
@@ -93,7 +93,7 @@ class OrderMovementGroup(RootMovementGroup):
 
 
   def __init__(self,movement,**kw):
-    LOG('OrderMovementGroup.__init__, kw:',0,kw)
+    #LOG('OrderMovementGroup.__init__, kw:',0,kw)
     RootMovementGroup.__init__(self,movement,**kw)
     if hasattr(movement, 'getRootAppliedRule'):
       # This is a simulation movement
@@ -146,32 +146,20 @@ class PathMovementGroup(RootMovementGroup):
   def __init__(self,movement,**kw):
     RootMovementGroup.__init__(self,movement,**kw)
     self.source = movement.getSource()
-    LOG('PathGroup.__init__ source',0,self.source)
+    #LOG('PathGroup.__init__ source',0,self.source)
     self.destination = movement.getDestination()
-    LOG('PathGroup.__init__ destination',0,self.destination)
+    #LOG('PathGroup.__init__ destination',0,self.destination)
     self.source_section = movement.getSourceSection()
-    LOG('PathGroup.__init__ source_section',0,self.source_section)
+    #LOG('PathGroup.__init__ source_section',0,self.source_section)
     self.destination_section = movement.getDestinationSection()
-    LOG('PathGroup.__init__ destination_section',0,self.destination_section)
-    self.target_source = movement.getTargetSource()
-    LOG('PathGroup.__init__ target_source',0,self.target_source)
-    self.target_destination = movement.getTargetDestination()
-    LOG('PathGroup.__init__ target_destination',0,self.target_destination)
-    self.target_source_section = movement.getTargetSourceSection()
-    LOG('PathGroup.__init__ target_source_section',0,self.target_source_section)
-    self.target_destination_section = movement.getTargetDestinationSection()
-    LOG('PathGroup.__init__ target_destination_section',0,self.target_destination_section)
+    #LOG('PathGroup.__init__ destination_section',0,self.destination_section)
 
 
   def test(self,movement):
     if movement.getSource() == self.source and \
       movement.getDestination() == self.destination and \
       movement.getSourceSection() == self.source_section and \
-      movement.getDestinationSection() == self.destination_section and \
-      movement.getTargetSource() == self.target_source and \
-      movement.getTargetDestination() == self.target_destination and \
-      movement.getTargetSourceSection() == self.target_source_section and \
-      movement.getTargetDestinationSection() == self.target_destination_section :
+      movement.getDestinationSection() == self.destination_section  :
 
       return 1
     else :
@@ -183,8 +171,6 @@ class DateMovementGroup(RootMovementGroup):
 
   def __init__(self,movement,**kw):
     RootMovementGroup.__init__(self,movement,**kw)
-    self.target_start_date = movement.getTargetStartDate()
-    self.target_stop_date = movement.getTargetStopDate()
     self.start_date = movement.getStartDate()
     self.stop_date = movement.getStopDate()
 
@@ -236,7 +222,7 @@ class BaseVariantMovementGroup(RootMovementGroup):
     RootMovementGroup.__init__(self,movement,**kw)
     self.base_category_list = movement.getVariationBaseCategoryList()
     if self.base_category_list is None:
-      LOG('BaseVariantGroup __init__', 0, 'movement = %s, movement.showDict() = %s' % (repr(movement), repr(movement.showDict())))
+      #LOG('BaseVariantGroup __init__', 0, 'movement = %s, movement.showDict() = %s' % (repr(movement), repr(movement.showDict())))
       self.base_category_list = []
 
   def test(self,movement):
@@ -245,7 +231,7 @@ class BaseVariantMovementGroup(RootMovementGroup):
     #LOG('BaseVariantGroup', 0, 'self.base_category_list = %s, movement = %s, movement.getVariationBaseCategoryList() = %s' % (repr(self.base_category_list), repr(movement), repr(movement.getVariationBaseCategoryList())))
     movement_base_category_list = movement.getVariationBaseCategoryList()
     if movement_base_category_list is None:
-      LOG('BaseVariantGroup test', 0, 'movement = %s, movement.showDict() = %s' % (repr(movement), repr(movement.showDict())))
+      #LOG('BaseVariantGroup test', 0, 'movement = %s, movement.showDict() = %s' % (repr(movement), repr(movement.showDict())))
       movement_base_category_list = []
     if len(self.base_category_list) == len(movement_base_category_list):
       for category in movement_base_category_list:
@@ -263,7 +249,7 @@ class VariantMovementGroup(RootMovementGroup):
     RootMovementGroup.__init__(self,movement,**kw)
     self.category_list = movement.getVariationCategoryList()
     if self.category_list is None:
-      LOG('VariantGroup __init__', 0, 'movement = %s, movement.showDict() = %s' % (repr(movement), repr(movement.showDict())))
+      #LOG('VariantGroup __init__', 0, 'movement = %s, movement.showDict() = %s' % (repr(movement), repr(movement.showDict())))
       self.category_list = []
 
   def test(self,movement):
@@ -271,7 +257,7 @@ class VariantMovementGroup(RootMovementGroup):
     categories_identity = 0
     movement_category_list = movement.getVariationCategoryList()
     if movement_category_list is None:
-      LOG('VariantGroup test', 0, 'movement = %s, movement.showDict() = %s' % (repr(movement), repr(movement.showDict())))
+      #LOG('VariantGroup test', 0, 'movement = %s, movement.showDict() = %s' % (repr(movement), repr(movement.showDict())))
       movement_category_list = []
     if len(self.category_list) == len(movement_category_list):
       for category in movement_category_list:
diff --git a/product/ERP5/PropertySheet/Amount.py b/product/ERP5/PropertySheet/Amount.py
index 4e01d6e902..9c09f6ec0d 100755
--- a/product/ERP5/PropertySheet/Amount.py
+++ b/product/ERP5/PropertySheet/Amount.py
@@ -90,7 +90,6 @@ class Amount:
       'acquisition_mask_value'        : 1,
       'acquisition_accessor_id'       : 'getQuantity',
       'acquisition_depends'           : None,
-      'alt_accessor_id'               : ('getTargetQuantity', ),
       'mode'        : 'w' },
     { 'id'          : 'efficiency',
       'description' : """The efficiency.""",
@@ -102,34 +101,10 @@ class Amount:
       'acquisition_mask_value'        : 1,
       'acquisition_accessor_id'       : 'getEfficiency',
       'acquisition_depends'           : None,
-      'alt_accessor_id'               : ('getTargetEfficiency', ),
       #'get_adapter_id'                :
       #'set_adapater_id'               :
       #'has_adapater_id'               :
       'mode'        : 'w' },
-    # Planning
-    { 'id'          : 'target_quantity',
-      'description' : """The target quantity of resource.""",
-      'type'        : 'float',
-      'default'     : 0.0,
-      'acquisition_base_category'     : ('order',),
-      'acquisition_portal_type'       : Expression('python: portal.getPortalAcquisitionMovementTypeList() + portal.getPortalOrderTypeList()'),
-      'acquisition_copy_value'        : 0,
-      'acquisition_mask_value'        : 1,
-      'acquisition_accessor_id'       : 'getTargetQuantity',
-      'acquisition_depends'           : None,
-      'mode'        : 'w' },
-    { 'id'          : 'target_efficiency',
-      'description' : """The target efficiency.""",
-      'type'        : 'float',
-      'default'     : 1.0,
-      'acquisition_base_category'     : ('order',),
-      'acquisition_portal_type'       : Expression('python: portal.getPortalAcquisitionMovementTypeList() + portal.getPortalOrderTypeList()'),
-      'acquisition_copy_value'        : 0,
-      'acquisition_mask_value'        : 1,
-      'acquisition_accessor_id'       : 'getTargetEfficiency',
-      'acquisition_depends'           : None,
-      'mode'        : 'w' },
     # Profit and loss
     { 'id'          : 'profit_quantity',
       'description' : 'A quantity which represents generation of resource from nowhere',
diff --git a/product/ERP5/PropertySheet/Arrow.py b/product/ERP5/PropertySheet/Arrow.py
index efb9e6f6ea..56c611c126 100755
--- a/product/ERP5/PropertySheet/Arrow.py
+++ b/product/ERP5/PropertySheet/Arrow.py
@@ -135,108 +135,6 @@ class Arrow:
             'acquisition_accessor_id'       : 'getTitle',
             'acquisition_depends'           : None,
             'mode'        : 'r' },
-        # Target Source reference
-        {   'id'          : 'target_source_title',
-            'description' : 'The title of the target source of this movement',
-            'type'        : 'string',
-            'acquisition_base_category'     : ('target_source',),
-            'acquisition_portal_type'       : Expression('python: portal.getPortalNodeTypeList()'),
-            'acquisition_copy_value'        : 0,
-            'acquisition_accessor_id'       : 'getTitle',
-            'acquisition_depends'           : None,
-            'alt_accessor_id'               : ('_categoryGetTargetSourceTitle', '_categoryGetSourceTitle'),
-            'mode'        : 'w' },
-        {   'id'          : 'target_source_id',
-            'description' : 'The id of the target source of this movement',
-            'type'        : 'string',
-            'acquisition_base_category'     : ('target_source',),
-            'acquisition_portal_type'       : Expression('python: portal.getPortalNodeTypeList()'),
-            'acquisition_copy_value'        : 0,
-            'acquisition_accessor_id'       : 'getId',
-            'acquisition_depends'           : None,
-            'alt_accessor_id'               : ('_categoryGetTargetSourceId', '_categoryGetSourceId' ),
-            'mode'        : 'w' },
-        {   'id'          : 'target_source_relative_url',
-            'description' : 'The relative url of the target destination of this movement',
-            'type'        : 'string',
-            'acquisition_base_category'     : ('target_source',),
-            'acquisition_portal_type'       : Expression('python: portal.getPortalNodeTypeList()'),
-            'acquisition_copy_value'        : 0,
-            'acquisition_accessor_id'       : 'getRelativeUrl',
-            'acquisition_depends'           : None,
-            'alt_accessor_id'               : ('_categoryGetTargetSourceRelativeUrl', '_categoryGetSourceRelativeUrl' ),
-            'mode'        : 'w' },
-        {   'id'          : 'target_source_person_title',
-            'description' : 'The title of the target source person of this movement',
-            'type'        : 'string',
-            'acquisition_base_category'     : ('target_source',),
-            'acquisition_portal_type'       : ('Person'),
-            'acquisition_copy_value'        : 0,
-            'acquisition_accessor_id'       : 'getTitle',
-            'acquisition_depends'           : None,
-            'alt_accessor_id'               : ('getSourcePersonTitle',  ),
-            'mode'        : 'r' },
-        {   'id'          : 'target_source_organisation_title',
-            'description' : 'The title of the target source organisation of this movement',
-            'type'        : 'string',
-            'acquisition_base_category'     : ('target_source',),
-            'acquisition_portal_type'       : ('Organisation'),
-            'acquisition_copy_value'        : 0,
-            'acquisition_accessor_id'       : 'getTitle',
-            'acquisition_depends'           : None,
-            'alt_accessor_id'               : ('getSourceOrganisationTitle',  ),
-            'mode'        : 'r' },
-        # Destination reference
-        {   'id'          : 'target_destination_title',
-            'description' : 'The title of the target destination of this movement',
-            'type'        : 'string',
-            'acquisition_base_category'     : ('target_destination',),
-            'acquisition_portal_type'       : Expression('python: portal.getPortalNodeTypeList()'),
-            'acquisition_copy_value'        : 0,
-            'acquisition_accessor_id'       : 'getTitle',
-            'acquisition_depends'           : None,
-            'alt_accessor_id'               : ('_categoryGetTargetDestinationTitle', '_categoryGetDestinationTitle' ),
-            'mode'        : 'w' },
-        {   'id'          : 'target_destination_id',
-            'description' : 'The id of the target destination of this movement',
-            'type'        : 'string',
-            'acquisition_base_category'     : ('target_destination',),
-            'acquisition_portal_type'       : Expression('python: portal.getPortalNodeTypeList()'),
-            'acquisition_copy_value'        : 0,
-            'acquisition_accessor_id'       : 'getId',
-            'acquisition_depends'           : None,
-            'alt_accessor_id'               : ('_categoryGetTargetDestinationId', '_categoryGetDestinationId' ),
-            'mode'        : 'w' },
-        {   'id'          : 'target_destination_relative_url',
-            'description' : 'The relative url of the target destination of this movement',
-            'type'        : 'string',
-            'acquisition_base_category'     : ('target_destination',),
-            'acquisition_portal_type'       : Expression('python: portal.getPortalNodeTypeList()'),
-            'acquisition_copy_value'        : 0,
-            'acquisition_accessor_id'       : 'getRelativeUrl',
-            'acquisition_depends'           : None,
-            'alt_accessor_id'               : ('_categoryGetTargetDestinationRelativeUrl', '_categoryGetDestinationRelativeUrl' ),
-            'mode'        : 'w' },
-        {   'id'          : 'target_destination_person_title',
-            'description' : 'The title of the target destination person of this movement',
-            'type'        : 'string',
-            'acquisition_base_category'     : ('target_destination',),
-            'acquisition_portal_type'       : ('Person'),
-            'acquisition_copy_value'        : 0,
-            'acquisition_accessor_id'       : 'getTitle',
-            'acquisition_depends'           : None,
-            'alt_accessor_id'               : ('getDestinationPersonTitle',  ),
-            'mode'        : 'r' },
-        {   'id'          : 'target_destination_organisation_title',
-            'description' : 'The title of the target destination organisation of this movement',
-            'type'        : 'string',
-            'acquisition_base_category'     : ('target_destination',),
-            'acquisition_portal_type'       : ('Organisation'),
-            'acquisition_copy_value'        : 0,
-            'acquisition_accessor_id'       : 'getTitle',
-            'acquisition_depends'           : None,
-            'alt_accessor_id'               : ('getDestinationOrganisationTitle',  ),
-            'mode'        : 'r' },
         # Source decision reference
         {   'id'          : 'source_decision_title',
             'description' : 'The title of the source decision of this movement',
@@ -361,68 +259,6 @@ class Arrow:
             'acquisition_depends'           : None,
             'alt_accessor_id'               : ('_categoryGetDestinationSectionRelativeUrl', ),
             'mode'        : 'w' },
-        # Source section reference
-        {   'id'          : 'target_source_section_title',
-            'description' : 'The title of the target source section of this movement',
-            'type'        : 'string',
-            'acquisition_base_category'     : ('target_source_section',),
-            'acquisition_portal_type'       : Expression('python: portal.getPortalNodeTypeList()'),
-            'acquisition_copy_value'        : 0,
-            'acquisition_accessor_id'       : 'getTitle',
-            'acquisition_depends'           : None,
-            'alt_accessor_id'               : ('_categoryGetTargetSourceSectionTitle', '_categoryGetSourceSectionTitle' ),
-            'mode'        : 'w' },
-        {   'id'          : 'target_source_section_id',
-            'description' : 'The id of the target source section of this movement',
-            'type'        : 'string',
-            'acquisition_base_category'     : ('target_source_section',),
-            'acquisition_portal_type'       : Expression('python: portal.getPortalNodeTypeList()'),
-            'acquisition_copy_value'        : 0,
-            'acquisition_accessor_id'       : 'getId',
-            'acquisition_depends'           : None,
-            'alt_accessor_id'               : ('_categoryGetTargetSourceSectionId', '_categoryGetSourceSectionId' ),
-            'mode'        : 'w' },
-        {   'id'          : 'target_source_section_relative_url',
-            'description' : 'The relative url of the target source section of this movement',
-            'type'        : 'string',
-            'acquisition_base_category'     : ('target_source_section',),
-            'acquisition_portal_type'       : Expression('python: portal.getPortalNodeTypeList()'),
-            'acquisition_copy_value'        : 0,
-            'acquisition_accessor_id'       : 'getRelativeUrl',
-            'acquisition_depends'           : None,
-            'alt_accessor_id'               : ('_categoryGetTargetSourceSectionRelativeUrl', '_categoryGetSourceSectionRelativeUrl' ),
-            'mode'        : 'w' },
-        # Destination section reference
-        {   'id'          : 'target_destination_section_title',
-            'description' : 'The title of the target destination section of this movement',
-            'type'        : 'string',
-            'acquisition_base_category'     : ('target_destination_section',),
-            'acquisition_portal_type'       : Expression('python: portal.getPortalNodeTypeList()'),
-            'acquisition_copy_value'        : 0,
-            'acquisition_accessor_id'       : 'getTitle',
-            'acquisition_depends'           : None,
-            'alt_accessor_id'               : ('_categoryGetTargetDestinationSectionTitle', '_categoryGetDestinationSectionTitle' ),
-            'mode'        : 'w' },
-        {   'id'          : 'target_destination_section_id',
-            'description' : 'The id of the target destination section of this movement',
-            'type'        : 'string',
-            'acquisition_base_category'     : ('target_destination_section',),
-            'acquisition_portal_type'       : Expression('python: portal.getPortalNodeTypeList()'),
-            'acquisition_copy_value'        : 0,
-            'acquisition_accessor_id'       : 'getId',
-            'acquisition_depends'           : None,
-            'alt_accessor_id'               : ('_categoryGetTargetDestinationSectionId', '_categoryGetDestinationSectionId'),
-            'mode'        : 'w' },
-        {   'id'          : 'target_destination_section_relative_url',
-            'description' : 'The relative url of the target destination section of this movement',
-            'type'        : 'string',
-            'acquisition_base_category'     : ('target_destination_section',),
-            'acquisition_portal_type'       : Expression('python: portal.getPortalNodeTypeList()'),
-            'acquisition_copy_value'        : 0,
-            'acquisition_accessor_id'       : 'getRelativeUrl',
-            'acquisition_depends'           : None,
-            'alt_accessor_id'               : ('_categoryGetTargetDestinationSectionRelativeUrl', '_categoryGetDestinationSectionRelativeUrl' ),
-            'mode'        : 'w' },
         # Source administration reference
         {   'id'          : 'source_administration_title',
             'description' : 'The title of the source administration of this movement',
@@ -711,9 +547,7 @@ class Arrow:
    )
 
     _categories = ( 'source', 'destination',
-                    'target_source', 'target_destination',
                     'source_section', 'destination_section',
-                    'target_source_section', 'target_destination_section',
                     'source_decision', 'destination_decision',
                     'source_administration', 'destination_administration',
                     'source_payment', 'destination_payment',
diff --git a/product/ERP5/PropertySheet/Inventory.py b/product/ERP5/PropertySheet/Inventory.py
index bf82df01ce..1457e7a357 100755
--- a/product/ERP5/PropertySheet/Inventory.py
+++ b/product/ERP5/PropertySheet/Inventory.py
@@ -50,23 +50,12 @@ class Inventory:
       'acquisition_mask_value'        : 1,
       'acquisition_accessor_id'       : 'getInventory',
       'acquisition_depends'           : None,
-      'alt_accessor_id'               : ('getTargetInventory', ),
       'mode'        : 'w' },
     { 'id'          : 'inventory_efficiency',
       'description' : """The efficiency of the inventory. 1.0 is perfect.""",
       'type'        : 'float',
       'default'     : None,
       'mode'        : 'w' },
-    { 'id'          : 'target_inventory',
-      'description' : """The quantity of items in stock after inventory.""",
-      'type'        : 'float',
-      'default'     : None,
-      'mode'        : 'w' },
-    { 'id'          : 'target_inventory_efficiency',
-      'description' : """The efficiency of the inventory. 1.0 is perfect.""",
-      'type'        : 'float',
-      'default'     : None,
-      'mode'        : 'w' },
   )
 
   _categories = ()
diff --git a/product/ERP5/PropertySheet/Predicate.py b/product/ERP5/PropertySheet/Predicate.py
index 804f5e23a8..6a2153d37d 100755
--- a/product/ERP5/PropertySheet/Predicate.py
+++ b/product/ERP5/PropertySheet/Predicate.py
@@ -65,12 +65,12 @@ class Predicate:
             'mode'        : 'w' },                                    
         {   'id'          : 'test_method_id',
             'description' : 'A python method to implement additional tests',
-            'type'        : 'string',
-            'mode'        : 'w' },                
-        {   'id'          : 'parameter_string',
-            'description' : 'A string defining default values for parameters (python syntax)',
-            'type'        : 'string',
+            'type'        : 'lines', # Only a list of method ids is feasable for lines
             'mode'        : 'w' },                
+        #{   'id'          : 'parameter_string', # XXX Not feasable for AND
+        #    'description' : 'A string defining default values for parameters (python syntax)',
+        #    'type'        : 'string',
+        #    'mode'        : 'w' },                
         # Compatibility with legacy implementation       
 #        {   'id'          : 'predicate_property',
 #            'description' : 'The properties to use for the predicate',
diff --git a/product/ERP5/TargetSolver/CopyToTarget.py b/product/ERP5/TargetSolver/CopyToTarget.py
index eaa865a0b8..111730eb2b 100755
--- a/product/ERP5/TargetSolver/CopyToTarget.py
+++ b/product/ERP5/TargetSolver/CopyToTarget.py
@@ -44,10 +44,10 @@ class CopyToTarget(TargetSolver):
       Adopt values as new target
     """
     # Reduce quantity
-    movement.setTargetQuantity(new_target.target_quantity)
+    movement.setQuantity(new_target.target_quantity)
     # Change dates
-    movement.setTargetStartDate(new_target.target_start_date)
-    movement.setTargetStopDate(new_target.target_stop_date)
+    movement.setStartDate(new_target.target_start_date)
+    movement.setStopDate(new_target.target_stop_date)
 
   def close(self):
     """
diff --git a/product/ERP5/Tool/SimulationTool.py b/product/ERP5/Tool/SimulationTool.py
index c2ccdf782c..b6944b7108 100755
--- a/product/ERP5/Tool/SimulationTool.py
+++ b/product/ERP5/Tool/SimulationTool.py
@@ -286,18 +286,12 @@ class SimulationTool (BaseTool):
                   self.portal_types.constructContent(type_name = delivery_type,
                                                       container = delivery_module,
                                                       id = new_delivery_id,
-                                                      target_start_date = date_group.start_date,
-                                                      target_stop_date = date_group.stop_date,
                                                       start_date = date_group.start_date,
                                                       stop_date = date_group.stop_date,
                                                       source = path_group.source,
                                                       destination = path_group.destination,
                                                       source_section = path_group.source_section,
                                                       destination_section = path_group.destination_section,
-                                                      target_source = path_group.source,
-                                                      target_destination = path_group.destination,
-                                                      target_source_section = path_group.source_section,
-                                                      target_destination_section = path_group.destination_section,
                                                       description = of_description,
                                                       title = new_delivery_id
                                                     )
@@ -335,7 +329,7 @@ class SimulationTool (BaseTool):
 
                   # IMPORTANT : delivery cells are automatically created during setVariationCategoryList
 
-                  # update target_quantity for each delivery_cell
+                  # update quantity for each delivery_cell
                   for variant_group in resource_group.group_list :
                     #LOG('Variant_group examin',0,str(variant_group.category_list))
                     object_to_update = None
@@ -364,16 +358,15 @@ class SimulationTool (BaseTool):
                           object_to_update = delivery_cell
                           break
 
-                    # compute target_quantity, quantity and price for delivery_cell or delivery_line and
+                    # compute quantity and price for delivery_cell or delivery_line and
                     # build relation between simulation_movement and delivery_cell or delivery_line
                     if object_to_update is not None :
-                      cell_target_quantity = 0
+                      cell_quantity = 0
                       for movement in variant_group.movement_list :
-                        cell_target_quantity += movement.getConvertedTargetQuantity()
+                        cell_quantity += movement.getConvertedQuantity()
                       # We do not create a relation or modifu anything
                       # since planification of this movement will create new applied rule
-                      object_to_update.edit(target_quantity = cell_target_quantity,
-                                            quantity = cell_target_quantity,
+                      object_to_update.edit(quantity = cell_quantity,
                                             force_update = 1)
 
       return order_list
@@ -448,27 +441,27 @@ class SimulationTool (BaseTool):
         else:
           # if path is internal ???
           # JPS NEW
-          if path_group.target_source is None or path_group.target_destination is None:
+          if path_group.source is None or path_group.destination is None:
             # Production Path
-            LOG("Builder",0, "Strange Path %s " % path_group.target_source)
-            LOG("Builder",0, "Strange Path %s " % path_group.target_destination)
+            LOG("Builder",0, "Strange Path %s " % path_group.source)
+            LOG("Builder",0, "Strange Path %s " % path_group.destination)
           LOG("Builder path_group in pathGroupProcessing",0, path_group.__dict__)
 
           
-          if path_group.target_source is None or path_group.target_destination is None:
+          if path_group.source is None or path_group.destination is None:
             pass
             #delivery_module = self.rapport_fabrication
             #delivery_type = 'Production Report'
             #delivery_line_type = 'Production Report Line'
             #delivery_cell_type = 'Production Report Cell'
-          elif path_group.target_destination.find('site/Stock_PF') >= 0 and \
-              path_group.target_source.find('site/Piquage') >= 0:
+          elif path_group.destination.find('site/Stock_PF') >= 0 and \
+              path_group.source.find('site/Piquage') >= 0:
             delivery_module = self.livraison_fabrication
             delivery_type = 'Production Packing List'
             delivery_line_type = delivery_type + ' Line'
             delivery_cell_type = 'Delivery Cell'
-          elif path_group.target_source.find('site/Stock_MP') >= 0 and \
-              path_group.target_destination.find('site/Piquage') >= 0:
+          elif path_group.source.find('site/Stock_MP') >= 0 and \
+              path_group.destination.find('site/Piquage') >= 0:
             delivery_module = self.livraison_fabrication
             delivery_type = 'Production Packing List'
             delivery_line_type = delivery_type + ' Line'
@@ -518,8 +511,6 @@ class SimulationTool (BaseTool):
               new_delivery_id = str(delivery_module.generateNewId())
               accounting_transaction = delivery_module.newContent(portal_type = delivery_type,
                                                 id = new_delivery_id,
-                                                target_start_date = date_group.start_date,
-                                                target_stop_date = date_group.stop_date,
                                                 start_date = date_group.start_date,
                                                 stop_date = date_group.stop_date,
                                                 source_section = source_section,
@@ -544,18 +535,12 @@ class SimulationTool (BaseTool):
           new_delivery_id = str(delivery_module.generateNewId())
           delivery = delivery_module.newContent(type_name = delivery_type,
                                     id = new_delivery_id,
-                                    target_start_date = date_group.start_date,
-                                    target_stop_date = date_group.stop_date,
                                     start_date = date_group.start_date,
                                     stop_date = date_group.stop_date,
                                     source = path_group.source,
                                     destination = path_group.destination,
                                     source_section = path_group.source_section,
                                     destination_section = path_group.destination_section,
-                                    target_source = path_group.source,
-                                    target_destination = path_group.destination,
-                                    target_source_section = path_group.source_section,
-                                    target_destination_section = path_group.destination_section
                                     )
           if order is not None :
             delivery.edit(title = order.getTitle(),
@@ -628,7 +613,7 @@ class SimulationTool (BaseTool):
 
           # IMPORTANT : delivery cells are automatically created during setVariationCategoryList
 
-          # update target_quantity for each delivery_cell
+          # update quantity for each delivery_cell
           for variant_group in resource_group.group_list:
             #LOG('Variant_group examin?,0,str(variant_group.category_list))
             object_to_update = None
@@ -656,17 +641,17 @@ class SimulationTool (BaseTool):
                   object_to_update = delivery_cell
                   break
 
-            # compute target_quantity, quantity and price for delivery_cell or delivery_line and
+            # compute quantity, quantity and price for delivery_cell or delivery_line and
             # build relation between simulation_movement and delivery_cell or delivery_line
             if object_to_update is not None :
-              cell_target_quantity = 0
+              cell_quantity = 0
               cell_total_price = 0
               for movement in variant_group.movement_list :
                 LOG('SimulationTool, movement.getPhysicalPath',0,movement.getPhysicalPath())
                 LOG('SimulationTool, movement.showDict',0,movement.showDict())
-                cell_target_quantity += movement.getNetConvertedTargetQuantity()
+                cell_quantity += movement.getNetConvertedQuantity()
                 try:
-                  cell_total_price += movement.getNetConvertedTargetQuantity()*movement.getPrice() # XXX WARNING - ADD PRICED QUANTITY
+                  cell_total_price += movement.getNetConvertedQuantity()*movement.getPrice() # XXX WARNING - ADD PRICED QUANTITY
                 except:
                   cell_total_price = None
 
@@ -674,34 +659,26 @@ class SimulationTool (BaseTool):
                   # update every simulation_movement
                   # we set delivery_value and target dates and quantity
                   movement._setDeliveryValue(object_to_update)
-                  movement._setTargetQuantity(movement.getTargetQuantity())
-                  movement._setQuantity(movement.getTargetQuantity())
-                  movement._setEfficiency(movement.getTargetEfficiency())
-                  movement._setTargetStartDate(movement.getTargetStartDate())
-                  movement._setTargetStopDate(movement.getTargetStopDate())
-                  movement._setStartDate(movement.getTargetStartDate())
-                  movement._setStopDate(movement.getTargetStopDate())
-                  movement._setSource(movement.getTargetSource())
-                  movement._setDestination(movement.getTargetDestination())
-                  movement._setTargetSource(movement.getTargetSource())
-                  movement._setTargetDestination(movement.getTargetDestination())
-                  movement._setSourceSection(movement.getTargetSourceSection())
-                  movement._setDestinationSection(movement.getTargetDestinationSection())
-                  movement._setTargetSourceSection(movement.getTargetSourceSection())
-                  movement._setTargetDestinationSection(movement.getTargetDestinationSection())
+                  movement._setQuantity(movement.getQuantity())
+                  movement._setEfficiency(movement.getEfficiency())
+                  movement._setStartDate(movement.getStartDate())
+                  movement._setStopDate(movement.getStopDate())
+                  movement._setSource(movement.getSource())
+                  movement._setDestination(movement.getDestination())
+                  movement._setSourceSection(movement.getSourceSection())
+                  movement._setDestinationSection(movement.getDestinationSection())
 
                   # We will reindex later
                   reindexable_movement_list.append(movement)
 
-              if cell_target_quantity <> 0 and cell_total_price is not None:
-                average_price = cell_total_price/cell_target_quantity
+              if cell_quantity <> 0 and cell_total_price is not None:
+                average_price = cell_total_price/cell_quantity
               else :
                 average_price = 0
               #LOG('object mis à jour',0,str(object_to_update.getRelativeUrl()))
-              object_to_update._edit(target_quantity = cell_target_quantity,
-                                    quantity = cell_target_quantity,
-                                    price = average_price,
-                                    force_update = 1,
+              object_to_update._edit(quantity = cell_quantity,
+                                     price = average_price,
+                                     force_update = 1,
                                     )
 
 
@@ -795,8 +772,8 @@ class SimulationTool (BaseTool):
       # Get nodes and dat
       source_node = movement.getSourceValue()
       destination_node = movement.getDestinationValue()
-      start_date = movement.getTargetStartDate()
-      stop_date = movement.getTargetStopDate()
+      start_date = movement.getStartDate()
+      stop_date = movement.getStopDate()
       # Return result
       return self.isNodeInsideCapacity(source_node, start_date, additional_movement=movement, sign=1) and self.isNodeInsideCapacity(destination_node, stop_date, additional_movement=movement, sign=-1)
 
@@ -1029,21 +1006,21 @@ class SimulationTool (BaseTool):
               asset_price = m.getIndustrialPrice()
               if asset_price is None: asset_price = current_asset_price  # Use current price if no price defined
             result.append((m.getRelativeUrl(), m.getStartDate(), m.getSource(), m.getSourceSection(), m.getDestination(), m.getDestinationSection(),
-                          m.getTargetQuantity(), 'Production or Inventory', 'Price: %s' % asset_price
+                          m.getQuantity(), 'Production or Inventory', 'Price: %s' % asset_price
                         ))
           elif m.getDestinationValue() is None:
             # This is a consumption movement or an inventory movement
             current_inventory += inventory_quantity # Update inventory
             asset_price = current_asset_price
             result.append((m.getRelativeUrl(),m.getStartDate(), m.getSource(), m.getSourceSection(), m.getDestination(), m.getDestinationSection(),
-                          m.getTargetQuantity(), 'Consumption or Inventory', 'Price: %s' % asset_price
+                          m.getQuantity(), 'Consumption or Inventory', 'Price: %s' % asset_price
                         ))
           elif m.getSourceValue().isAcquiredMemberOf(node_category) and m.getDestinationValue().isAcquiredMemberOf(node_category):
             # This is an internal movement
             current_inventory += inventory_quantity # Update inventory
             asset_price = current_asset_price
             result.append((m.getRelativeUrl(),m.getStartDate(), m.getSource(), m.getSourceSection(), m.getDestination(), m.getDestinationSection(),
-                          m.getTargetQuantity(), 'Internal', 'Price: %s' % asset_price
+                          m.getQuantity(), 'Internal', 'Price: %s' % asset_price
                         ))
           elif m.getSourceValue().isAcquiredMemberOf(node_category) and quantity < 0:
             # This is a physically inbound movement - try to use commercial price
@@ -1052,14 +1029,14 @@ class SimulationTool (BaseTool):
               current_inventory += inventory_quantity # Update inventory
               asset_price = current_asset_price
               result.append((m.getRelativeUrl(),m.getStartDate(), m.getSource(), m.getSourceSection(), m.getDestination(), m.getDestinationSection(),
-                            m.getTargetQuantity(), 'Error', 'Price: %s' % asset_price
+                            m.getQuantity(), 'Error', 'Price: %s' % asset_price
                           ))
             elif m.getDestinationSectionValue() is None:
               # No meaning
               current_inventory += inventory_quantity # Update inventory
               asset_price = current_asset_price
               result.append((m.getRelativeUrl(),m.getStartDate(), m.getSource(), m.getSourceSection(), m.getDestination(), m.getDestinationSection(),
-                            m.getTargetQuantity(), 'Error', 'Price: %s' % asset_price
+                            m.getQuantity(), 'Error', 'Price: %s' % asset_price
                           ))
             elif m.getDestinationSectionValue().isAcquiredMemberOf(section_category):
               current_inventory += inventory_quantity # Update inventory
@@ -1068,19 +1045,19 @@ class SimulationTool (BaseTool):
                 asset_price = m.getIndustrialPrice()
                 if asset_price is None: asset_price = current_asset_price  # Use current price if no price defined
                 result.append((m.getRelativeUrl(),m.getStartDate(), m.getSource(), m.getSourceSection(), m.getDestination(), m.getDestinationSection(),
-                              m.getTargetQuantity(), 'Production', 'Price: %s' % asset_price
+                              m.getQuantity(), 'Production', 'Price: %s' % asset_price
                             ))
               else:
                 # Inbound from same section
                 asset_price = current_asset_price
                 result.append((m.getRelativeUrl(),m.getStartDate(), m.getSource(), m.getSourceSection(), m.getDestination(), m.getDestinationSection(),
-                              m.getTargetQuantity(), 'Inbound same section', 'Price: %s' % asset_price
+                              m.getQuantity(), 'Inbound same section', 'Price: %s' % asset_price
                             ))
             else:
               current_inventory += inventory_quantity # Update inventory
               asset_price = m.getPrice()
               result.append((m.getRelativeUrl(),m.getStartDate(), m.getSource(), m.getSourceSection(), m.getDestination(), m.getDestinationSection(),
-                            m.getTargetQuantity(), 'Inbound different section', 'Price: %s' % asset_price
+                            m.getQuantity(), 'Inbound different section', 'Price: %s' % asset_price
                           ))
           elif m.getDestinationValue().isAcquiredMemberOf(node_category) and quantity > 0:
             # This is a physically inbound movement - try to use commercial price
@@ -1089,14 +1066,14 @@ class SimulationTool (BaseTool):
               current_inventory += inventory_quantity # Update inventory
               asset_price = current_asset_price
               result.append((m.getRelativeUrl(),m.getStartDate(), m.getSource(), m.getSourceSection(), m.getDestination(), m.getDestinationSection(),
-                            m.getTargetQuantity(), 'Error', 'Price: %s' % asset_price
+                            m.getQuantity(), 'Error', 'Price: %s' % asset_price
                           ))
             elif m.getDestinationSectionValue() is None:
               # No meaning
               current_inventory += inventory_quantity # Update inventory
               asset_price = current_asset_price
               result.append((m.getRelativeUrl(),m.getStartDate(), m.getSource(), m.getSourceSection(), m.getDestination(), m.getDestinationSection(),
-                            m.getTargetQuantity(), 'Error', 'Price: %s' % asset_price
+                            m.getQuantity(), 'Error', 'Price: %s' % asset_price
                           ))
             elif m.getSourceSectionValue().isAcquiredMemberOf(section_category):
               current_inventory += inventory_quantity # Update inventory
@@ -1105,26 +1082,26 @@ class SimulationTool (BaseTool):
                 asset_price = m.getIndustrialPrice()
                 if asset_price is None: asset_price = current_asset_price  # Use current price if no price defined
                 result.append((m.getRelativeUrl(),m.getStartDate(), m.getSource(), m.getSourceSection(), m.getDestination(), m.getDestinationSection(),
-                              m.getTargetQuantity(), 'Production', 'Price: %s' % asset_price
+                              m.getQuantity(), 'Production', 'Price: %s' % asset_price
                             ))
               else:
                 # Inbound from same section
                 asset_price = current_asset_price
                 result.append((m.getRelativeUrl(),m.getStartDate(), m.getSource(), m.getSourceSection(), m.getDestination(), m.getDestinationSection(),
-                            m.getTargetQuantity(), 'Inbound same section', 'Price: %s' % asset_price
+                            m.getQuantity(), 'Inbound same section', 'Price: %s' % asset_price
                           ))
             else:
               current_inventory += inventory_quantity # Update inventory
               asset_price = m.getPrice()
               result.append((m.getRelativeUrl(),m.getStartDate(), m.getSource(), m.getSourceSection(), m.getDestination(), m.getDestinationSection(),
-                            m.getTargetQuantity(), 'Inbound different section', 'Price: %s' % asset_price
+                            m.getQuantity(), 'Inbound different section', 'Price: %s' % asset_price
                           ))
           else:
             # Outbound movement
             current_inventory += inventory_quantity # Update inventory
             asset_price = current_asset_price
             result.append((m.getRelativeUrl(),m.getStartDate(), m.getSource(), m.getSourceSection(), m.getDestination(), m.getDestinationSection(),
-                            m.getTargetQuantity(), 'Outbound', 'Price: %s' % asset_price
+                            m.getQuantity(), 'Outbound', 'Price: %s' % asset_price
                           ))
 
           # Update asset_price
@@ -1335,7 +1312,7 @@ class SimulationTool (BaseTool):
                 if object_to_update is not None:
                   cell_price = object_to_update.getPrice() or 0.0
                   cell_quantity = object_to_update.getQuantity() or 0.0
-                  cell_target_quantity = object_to_update.getNetConvertedTargetQuantity() or 0.0
+                  cell_target_quantity = object_to_update.getNetConvertedTargetQuantity() or 0.0 # XXX What to do ?
                   cell_total_price = cell_target_quantity * cell_price
                   cell_category_list = list(object_to_update.getCategoryList())
 
diff --git a/product/ERP5/tests/testInvoice.py b/product/ERP5/tests/testInvoice.py
index 1d608d7275..0fff5e48bb 100755
--- a/product/ERP5/tests/testInvoice.py
+++ b/product/ERP5/tests/testInvoice.py
@@ -82,9 +82,12 @@ class Test(ERP5TypeTestCase):
   account1 = 'prestation_service'
   account2 = 'creance_client'
   account3 = 'tva_collectee_196'
-  quantity1 = 3
-  price1 = 72
-  total_price1 = 216
+  account1_mirror = 'fourniture_service' # Not used
+  account2_mirror = 'dette_client'       # Not used
+  account3_mirror = 'tva_collectee_196'  # Not used
+  quantity1 = 3.0
+  price1 = 72.0
+  total_price1 = 216.0
 
   def getTitle(self):
     return "Invoices"
@@ -284,7 +287,7 @@ class Test(ERP5TypeTestCase):
     line1 = order.newContent(portal_type='Sale Order Line',id='1')
     product = sequence.get('product')
     line1.setResourceValue(product)
-    line1.setTargetQuantity(self.quantity1)
+    line1.setQuantity(self.quantity1)
     line1.setPrice(self.price1)
     sequence.edit(order=order)
     self.assertEquals(line1.getTotalPrice(),self.total_price1)
@@ -321,7 +324,7 @@ class Test(ERP5TypeTestCase):
     rule_line = rule_line_list[0]
     sequence.edit(order_rule_line=rule_line)
     order_line = order_line_list[0]
-    self.assertEquals(rule_line.getTargetQuantity(),self.quantity1)
+    self.assertEquals(rule_line.getQuantity(),self.quantity1)
     self.assertEquals(rule_line.getPrice(),self.price1)
     self.assertEquals(rule_line.getOrderValue(),order_line)
     self.assertEquals(rule_line.getStartDate(),order_line.getStartDate())
@@ -342,7 +345,7 @@ class Test(ERP5TypeTestCase):
     rule_line = rule_line_list[0]
     sequence.edit(invoicing_rule_line=rule_line)
     product = sequence.get('product')
-    self.assertEquals(rule_line.getTargetQuantity(),self.quantity1)
+    self.assertEquals(rule_line.getQuantity(),self.quantity1)
     self.assertEquals(rule_line.getPrice(),self.price1)
     self.assertEquals(rule_line.getPortalType(),'Simulation Movement')
     self.assertEquals(rule_line.getResourceValue(), product)
@@ -442,7 +445,7 @@ class Test(ERP5TypeTestCase):
     invoice = sequence.get('invoice')
 
     # It should be in a script inside the workflow
-    invoice.buildInvoiceTransactionList()
+    invoice.buildInvoiceTransactionList()    
 
   def stepBuildPaymentTransactionList(self, sequence=None, sequence_list=None, **kw) :
     invoice = sequence.get('invoice')
@@ -521,6 +524,7 @@ class Test(ERP5TypeTestCase):
         self.assertEquals(transaction_line.getQuantity(), 3 * 72 * 0.5)
         sequence.edit(invoice_transaction_line_receivable=transaction_line)
       elif transaction_line.getId() == 'collected_vat' :
+        simulation_movement = transaction_line.getDeliveryRelatedValueList()[0].getObject()
         self.assertEquals(transaction_line.getSourceValue(), self.getAccountModule()['tva_collectee_196']) # this is defined in SaleInvoiceTransaction_init in ERP5 skins.
       else :
         raise self.failureException
@@ -538,6 +542,7 @@ class Test(ERP5TypeTestCase):
 
     invoice_transaction_line_receivable = sequence.get('invoice_transaction_line_receivable')
     for transaction_line in payment_transaction_line_list :
+      
       if transaction_line.getId() == 'receivable' :
         self.assertEquals(transaction_line.getSourceValue(), self.getAccountModule()['creance_client'])
         self.assertEquals(transaction_line.getQuantity(), 0 - invoice_transaction_line_receivable.getQuantity())
@@ -548,8 +553,14 @@ class Test(ERP5TypeTestCase):
         self.assertEquals(transaction_line.getSourceValue(), self.getAccountModule()['dette_fournisseur']) # this is defined in SaleInvoiceTransaction_init in ERP5 skins.
       else :
         raise self.failureException
-
-
+      
+      # Make sure payment and simulation are consistent
+      for simulation_movement in transaction_line.getDeliveryRelatedValueList():
+        self.assertEquals(simulation_movement.getSource(), transaction_line.getSource())            
+        self.assertEquals(simulation_movement.getDestination(), transaction_line.getDestination())            
+        self.assertEquals(simulation_movement.getSourceSection(), transaction_line.getSourceSection())            
+        self.assertEquals(simulation_movement.getDestinationSection(), transaction_line.getDestinationSection())            
+                
   def testInvoice(self, quiet=0,run=1):
     """
     We will play many sequences
-- 
2.30.9