diff --git a/product/ERP5/tests/testInvoice.py b/product/ERP5/tests/testInvoice.py
index a9bd755fff67abd97fc1a74e0d9f800aa6566a97..6d517ec49bac9e36afa579ad6879d161094e2c11 100644
--- a/product/ERP5/tests/testInvoice.py
+++ b/product/ERP5/tests/testInvoice.py
@@ -351,1015 +351,951 @@ class TestInvoiceMixin(TestPackingListMixin,
         self.assertEquals(movement.getStopDate(),
             parent_movement.getStopDate())
 
+  def modifyPackingListState(self, transition_name,
+                             sequence,packing_list=None):
+    """ calls the workflow for the packing list """
+    if packing_list is None:
+      packing_list = sequence.get('packing_list')
+    packing_list.portal_workflow.doActionFor(packing_list, transition_name)
 
+  def stepSetReadyPackingList(self, sequence=None, sequence_list=None, **kw):
+    """ set the Packing List as Ready. This must build the invoice. """
+    self.modifyPackingListState('set_ready_action', sequence=sequence)
+    packing_list = sequence.get('packing_list')
+    self.assertEquals(packing_list.getSimulationState(), 'ready')
 
-class TestInvoice(TestInvoiceMixin):
-  """Test methods for sale and purchase invoice.
-  Subclasses must defines portal types to use.
-  """
-  quiet = 1
-  def test_invoice_transaction_line_resource(self):
-    """
-    tests that simulation movements corresponding to accounting line have a
-    good resource in the simulation
-    """
-    resource = self.portal.getDefaultModule(
-        self.resource_portal_type).newContent(
-                    portal_type=self.resource_portal_type,
-                    title='Resource',
-                    product_line='apparel')
-    currency = self.portal.currency_module.newContent(
-                                portal_type='Currency',
-                                title='Currency',
-                                base_unit_quantity=0.01)
-    self.createInvoiceTransactionRule(currency)
+  def stepSetReadyNewPackingList(self, sequence=None,
+                                 sequence_list=None, **kw):
+    """ set the Packing List as Ready. This must build the invoice. """
+    packing_list = sequence.get('new_packing_list')
+    self.modifyPackingListState('set_ready_action', sequence=sequence,
+                                packing_list=packing_list)
+    self.assertEquals(packing_list.getSimulationState(), 'ready')
 
-    client = self.portal.organisation_module.newContent(
-                            portal_type='Organisation',
-                            title='Client',
-                            price_currency= currency.getRelativeUrl(),
-                            default_address_region=self.default_region)
-    vendor = self.portal.organisation_module.newContent(
-                            portal_type='Organisation',
-                            title='Vendor',
-                            price_currency= currency.getRelativeUrl(),
-                            default_address_region=self.default_region)
-    order = self.portal.getDefaultModule(self.order_portal_type).newContent(
-                              portal_type=self.order_portal_type,
-                              source_value=vendor,
-                              source_section_value=vendor,
-                              destination_value=client,
-                              destination_section_value=client,
-                              start_date=DateTime(2008, 1, 1),
-                              price_currency_value=currency,
-                              title='Order')
-    order_line = order.newContent(portal_type=self.order_line_portal_type,
-                                  resource_value=resource,
-                                  quantity=1,
-                                  price=2)
+  def stepStartPackingList(self, sequence=None, sequence_list=None, **kw):
+    self.modifyPackingListState('start_action', sequence=sequence)
+    packing_list = sequence.get('packing_list')
+    self.assertEquals(packing_list.getSimulationState(), 'started')
 
-    order.confirm()
-    transaction.commit()
-    self.tic()
+  def stepStartNewPackingList(self, sequence=None, sequence_list=None, **kw):
+    packing_list = sequence.get('new_packing_list')
+    self.modifyPackingListState('start_action', sequence=sequence,
+                                packing_list=packing_list)
+    self.assertEquals(packing_list.getSimulationState(), 'started')
 
-    related_applied_rule = order.getCausalityRelatedValue(
-                             portal_type='Applied Rule')
-    order_movement = related_applied_rule.contentValues()[0]
-    delivery_applied_rule = order_movement.contentValues()[0]
-    delivery_movement = delivery_applied_rule.contentValues()[0]
-    invoice_applied_rule = delivery_movement.contentValues()[0]
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    invoice_transaction_applied_rule = invoice_movement.contentValues()[0]
-    invoice_transaction_movement =\
-         invoice_transaction_applied_rule.contentValues()[0]
-    self.assertEquals(currency,
-          invoice_transaction_movement.getResourceValue())
-    self.assertEquals(currency,
-          delivery_movement.getPriceCurrencyValue())
+  def stepStopPackingList(self, sequence=None, sequence_list=None, **kw):
+    self.modifyPackingListState('stop_action', sequence=sequence)
+    packing_list = sequence.get('packing_list')
+    self.assertEquals(packing_list.getSimulationState(), 'stopped')
 
-    
-  def test_modify_planned_order_invoicing_rule(self):
-    """
-    tests that modifying a planned order affects movements from invoicing
-    rule
-    """
-    resource = self.portal.getDefaultModule(
-        self.resource_portal_type).newContent(
-                    portal_type=self.resource_portal_type,
-                    title='Resource',
-                    product_line='apparel')
-    currency = self.portal.currency_module.newContent(
-                                portal_type='Currency',
-                                title='Currency',
-                                base_unit_quantity=0.01)
+  def stepDeliverPackingList(self, sequence=None, sequence_list=None, **kw):
+    self.modifyPackingListState('deliver_action', sequence=sequence)
+    packing_list = sequence.get('packing_list')
+    self.assertEquals(packing_list.getSimulationState(), 'delivered')
 
-    client = self.portal.organisation_module.newContent(
-                            portal_type='Organisation',
-                            title='Client',
-                            price_currency= currency.getRelativeUrl())
-    vendor = self.portal.organisation_module.newContent(
-                            portal_type='Organisation',
-                            title='Vendor',
-                            price_currency= currency.getRelativeUrl())
-    order = self.portal.getDefaultModule(self.order_portal_type).newContent(
-                              portal_type=self.order_portal_type,
-                              source_value=vendor,
-                              source_section_value=vendor,
-                              destination_value=client,
-                              destination_section_value=client,
-                              start_date=DateTime(2008, 1, 1),
-                              price_currency_value=currency,
-                              title='Order')
-    order_line = order.newContent(portal_type=self.order_line_portal_type,
-                                  resource_value=resource,
-                                  quantity=1,
-                                  price=2)
+  def stepCancelPackingList(self, sequence=None, sequence_list=None, **kw):
+    self.modifyPackingListState('cancel_action', sequence=sequence)
+    packing_list = sequence.get('packing_list')
+    self.assertEquals(packing_list.getSimulationState(), 'cancelled')
 
-    other_entity = self.portal.organisation_module.newContent(
-                                    portal_type='Organisation',
-                                    title='Other Entity',
-                                    price_currency=currency.getRelativeUrl())
-    other_project = self.portal.project_module.newContent(
-                                    portal_type='Project',
-                                    title='Other Project')
-    order.plan()
-    transaction.commit()
-    self.tic()
-    self.assertEquals('planned', order.getSimulationState())
+  def modifyInvoiceState(self, transition_name,
+                             sequence,invoice=None):
+    """ calls the workflow for the invoice """
+    if invoice is None:
+      invoice = sequence.get('invoice')
+    invoice.portal_workflow.doActionFor(invoice, transition_name)
 
-    related_applied_rule = order.getCausalityRelatedValue(
-                             portal_type='Applied Rule')
-    delivery_movement = related_applied_rule.contentValues()[0]
-    invoice_applied_rule = delivery_movement.contentValues()[0]
-    invoice_movement = invoice_applied_rule.contentValues()[0]
+  def stepStartInvoice(self, sequence=None, sequence_list=None, **kw):
+    self.modifyInvoiceState('start_action', sequence=sequence)
+    invoice = sequence.get('invoice')
+    self.assertEquals(invoice.getSimulationState(), 'started')
 
-    order_line.setSourceValue(other_entity)
-    transaction.commit()
-    self.tic()
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    self.assertEquals(other_entity,
-                      invoice_movement.getSourceValue())
+  def stepStartNewInvoice(self, sequence=None, sequence_list=None, **kw):
+    invoice = sequence.get('new_invoice')
+    self.modifyInvoiceState('start_action', sequence=sequence,
+                                invoice=invoice)
+    self.assertEquals(invoice.getSimulationState(), 'started')
 
-    order_line.setDestinationValue(other_entity)
-    transaction.commit()
-    self.tic()
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    self.assertEquals(other_entity,
-                      invoice_movement.getDestinationValue())
+  def stepStopInvoice(self, sequence=None, sequence_list=None, **kw):
+    self.modifyInvoiceState('stop_action', sequence=sequence)
+    invoice = sequence.get('invoice')
+    self.assertEquals(invoice.getSimulationState(), 'stopped')
 
-    order_line.setSourceSectionValue(other_entity)
-    transaction.commit()
-    self.tic()
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    self.assertEquals(other_entity,
-                      invoice_movement.getSourceSectionValue())
+  def stepDeliverInvoice(self, sequence=None, sequence_list=None, **kw):
+    self.modifyInvoiceState('deliver_action', sequence=sequence)
+    invoice = sequence.get('invoice')
+    self.assertEquals(invoice.getSimulationState(), 'delivered')
 
-    # make sure destination_section != source_section, this might be needed by
-    # some rules
-    order_line.setSourceSectionValue(order_line.getDestinationSectionValue())
+  def stepCancelInvoice(self, sequence=None, sequence_list=None, **kw):
+    self.modifyInvoiceState('cancel_action', sequence=sequence)
+    invoice = sequence.get('invoice')
+    self.assertEquals(invoice.getSimulationState(), 'cancelled')
 
-    order_line.setDestinationSectionValue(other_entity)
-    transaction.commit()
-    self.tic()
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    self.assertEquals(other_entity,
-                 invoice_movement.getDestinationSectionValue())
 
-    order_line.setSourceAdministrationValue(other_entity)
-    transaction.commit()
-    self.tic()
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    self.assertEquals(other_entity,
-                 invoice_movement.getSourceAdministrationValue())
+  def stepSwitchPackingLists(self, sequence=None, sequence_list=None, **kw):
+    packing_list = sequence.get('packing_list')
+    new_packing_list = sequence.get('new_packing_list')
+    #invoice = new_packing_list.getDefaultCausalityRelatedValue(
+        #portal_type=self.invoice_portal_type)
+    sequence.edit(packing_list=new_packing_list,
+        new_packing_list=packing_list)#, invoice=invoice)
 
-    order_line.setDestinationAdministrationValue(other_entity)
-    transaction.commit()
-    self.tic()
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    self.assertEquals(other_entity,
-            invoice_movement.getDestinationAdministrationValue())
+  def stepSwitchInvoices(self, sequence=None, sequence_list=None, **kw):
+    invoice = sequence.get('invoice')
+    new_invoice = sequence.get('new_invoice')
+    sequence.edit(invoice=new_invoice, new_invoice=invoice)
 
-    order_line.setSourceDecisionValue(other_entity)
-    transaction.commit()
-    self.tic()
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    self.assertEquals(other_entity,
-                 invoice_movement.getSourceDecisionValue())
+  def stepCheckPackingListSimulation(self, sequence=None, sequence_list=None, **kw):
+    """ checks that simulation movements related to the packing list are OK """
+    packing_list = sequence.get('packing_list')
+    order = sequence.get('order')
+    order_root_applied_rule = order.getCausalityRelatedValueList(
+                                  portal_type = 'Applied Rule')[0]
+    # check simulation movements from this packing list
+    for movement in packing_list.getMovementList() :
+      simulation_movement_list = movement.getOrderRelatedValueList()
+      self.assertNotEquals(len(simulation_movement_list), 0)
+      total_quantity = 0
+      for simulation_movement in simulation_movement_list :
+        total_quantity += simulation_movement.getQuantity()
+        # check that those movements come from the same root applied
+        # rule than the order.
+        self.assertEquals( simulation_movement.getRootAppliedRule(),
+                           order_root_applied_rule)
+      self.assertEquals(total_quantity, movement.getQuantity())
 
-    order_line.setDestinationDecisionValue(other_entity)
-    transaction.commit()
-    self.tic()
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    self.assertEquals(other_entity,
-            invoice_movement.getDestinationDecisionValue())
-
-    order_line.setSourceProjectValue(other_project)
-    transaction.commit()
-    self.tic()
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    self.assertEquals(other_project,
-                 invoice_movement.getSourceProjectValue())
-
-    order_line.setDestinationProjectValue(other_project)
-    transaction.commit()
-    self.tic()
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    self.assertEquals(other_project,
-            invoice_movement.getDestinationProjectValue())
+  def stepCheckInvoiceBuilding(self, sequence=None, sequence_list=None, **kw):
+    """
+    checks that the invoice is built with the default_invoice_builder
+    """
+    packing_list = sequence.get('packing_list')
+    related_invoice_list = packing_list.getCausalityRelatedValueList(
+                     portal_type=self.invoice_portal_type)
 
-    order_line.setSourcePaymentValue(other_entity)
-    transaction.commit()
-    self.tic()
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    self.assertEquals(other_entity,
-                 invoice_movement.getSourcePaymentValue())
+    packing_list_building_state = 'started'
+    packing_list_state = packing_list.getSimulationState()
+    if packing_list_state != packing_list_building_state :
+      self.assertEquals(0, len(related_invoice_list))
+    else:
+      self.assertEquals(1, len(related_invoice_list))
 
-    order_line.setDestinationPaymentValue(other_entity)
-    transaction.commit()
-    self.tic()
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    self.assertEquals(other_entity,
-            invoice_movement.getDestinationPaymentValue())
+      invoice = related_invoice_list[0].getObject()
+      self.failUnless(invoice is not None)
+      # Invoices created by Delivery Builder are in confirmed state
+      self.assertEquals(invoice.getSimulationState(), 'confirmed')
 
-    order_line.setSourceFunctionValue(other_entity)
-    transaction.commit()
-    self.tic()
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    self.assertEquals(other_entity,
-                 invoice_movement.getSourceFunctionValue())
+      # Get the list of simulation movements of packing list ...
+      packing_list_simulation_movement_list = []
+      for packing_list_movement in packing_list.getMovementList():
+           packing_list_simulation_movement_list.extend(
+                packing_list_movement.getDeliveryRelatedValueList())
+      # ... invoice simulation movement are their childrens.
+      simulation_movement_list = []
+      for p_l_simulation_movement in packing_list_simulation_movement_list :
+        for applied_rule in p_l_simulation_movement.objectValues() :
+          simulation_movement_list.extend(applied_rule.objectValues())
 
-    order_line.setDestinationFunctionValue(other_entity)
-    transaction.commit()
-    self.tic()
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    self.assertEquals(other_entity,
-            invoice_movement.getDestinationFunctionValue())
+      # First, test if each Simulation Movement is related to an
+      # Invoice Movement
+      invoice_relative_url = invoice.getRelativeUrl()
+      for simulation_movement in simulation_movement_list:
+        invoice_movement_list = simulation_movement.getDeliveryValueList()
+        self.assertEquals(len(invoice_movement_list), 1)
+        invoice_movement = invoice_movement_list[0]
+        self.failUnless(invoice_movement is not None)
+        self.assert_(invoice_movement.getRelativeUrl().\
+                              startswith(invoice_relative_url))
 
-    self.assertNotEquals(123, order_line.getPrice())
-    order_line.setPrice(123)
-    transaction.commit()
-    self.tic()
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    self.assertEquals(123,
-            invoice_movement.getPrice())
+      # Then, test if each Invoice movement is equals to the sum of somes
+      # Simulation Movements
+      for invoice_movement in invoice.getMovementList(portal_type = [
+                          self.invoice_cell_portal_type,
+                          self.invoice_line_portal_type]) :
+        related_simulation_movement_list = invoice_movement.\
+                 getDeliveryRelatedValueList(portal_type='Simulation Movement')
+        quantity = 0
+        total_price = 0
+        invoice_movement_quantity = invoice_movement.getQuantity()
+        for related_simulation_movement in related_simulation_movement_list:
+          quantity += related_simulation_movement.getQuantity()
+          total_price += related_simulation_movement.getPrice() *\
+                         related_simulation_movement.getQuantity()
+          # Test resource
+          self.assertEquals(invoice_movement.getResource(), \
+                            related_simulation_movement.getResource())
+          # Test resource variation
+          self.assertEquals(invoice_movement.getVariationText(), \
+                            related_simulation_movement.getVariationText())
+          self.assertEquals(invoice_movement.getVariationCategoryList(), \
+                        related_simulation_movement.getVariationCategoryList())
+          # Test acquisition
+          self.checkAcquisition(invoice_movement,
+                                related_simulation_movement)
+          # Test delivery ratio
+          self.assertEquals(related_simulation_movement.getQuantity() /\
+                            invoice_movement_quantity, \
+                            related_simulation_movement.getDeliveryRatio())
 
-    self.assertNotEquals(456, order_line.getQuantity())
-    order_line.setQuantity(456)
-    transaction.commit()
-    self.tic()
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    self.assertEquals(456,
-            invoice_movement.getQuantity())
+        self.assertEquals(quantity, invoice_movement.getQuantity())
+        # Test price
+        self.assertEquals(total_price / quantity, invoice_movement.getPrice())
 
-    other_resource = self.portal.product_module.newContent(
-                                        portal_type='Product',
-                                        title='Other Resource')
-    order_line.setResourceValue(other_resource)
-    transaction.commit()
-    self.tic()
-    # after changing 'resource', related simulation movement will be
-    # replaced with another id, and we need to find the appropriate one
-    # here.
-    delivery_movement = related_applied_rule.contentValues()[0]
-    invoice_applied_rule = delivery_movement.contentValues()[0]
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    self.assertEquals(other_resource,
-            invoice_movement.getResourceValue())
+      sequence.edit(invoice = invoice)
 
-    order_line.setStartDate(DateTime(2001, 02, 03))
-    transaction.commit()
-    self.tic()
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    self.assertEquals(DateTime(2001, 02, 03),
-                 invoice_movement.getStartDate())
+      # Test causality
+      self.assertEquals(len(invoice.getCausalityValueList(
+                      portal_type = self.packing_list_portal_type)), 1)
+      self.assertEquals(invoice.getCausalityValue(), packing_list)
 
-    order_line.setStopDate(DateTime(2002, 03, 04))
-    transaction.commit()
-    self.tic()
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    self.assertEquals(DateTime(2002, 03, 04),
-                 invoice_movement.getStopDate())
+      # Finally, test getTotalQuantity and getTotalPrice on Invoice
+      self.assertEquals(packing_list.getTotalQuantity(),
+                        invoice.getTotalQuantity())
+      self.assertEquals(packing_list.getTotalPrice(),
+                        invoice.getTotalPrice())
 
-  def test_modify_planned_order_invoice_transaction_rule(self):
+  def stepCheckPaymentBuilding(self, sequence=None, sequence_list=None, **kw):
     """
-    tests that modifying a planned order affects movements from invoice
-    transaction rule
+    checks that the payment is built with the default_payment_builder
     """
-    resource = self.portal.getDefaultModule(
-        self.resource_portal_type).newContent(
-                    portal_type=self.resource_portal_type,
-                    title='Resource',
-                    product_line='apparel')
-    currency = self.portal.currency_module.newContent(
-                                portal_type='Currency',
-                                title='Currency',
-                                base_unit_quantity=0.01)
-    self.createInvoiceTransactionRule(currency)
-
-    client = self.portal.organisation_module.newContent(
-                            portal_type='Organisation',
-                            title='Client',
-                            default_address_region=self.default_region)
-    vendor = self.portal.organisation_module.newContent(
-                            portal_type='Organisation',
-                            title='Vendor',
-                            default_address_region=self.default_region)
-    order = self.portal.getDefaultModule(self.order_portal_type).newContent(
-                              portal_type=self.order_portal_type,
-                              source_value=vendor,
-                              source_section_value=vendor,
-                              destination_value=client,
-                              destination_section_value=client,
-                              start_date=DateTime(2008, 1, 1),
-                              price_currency_value=currency,
-                              title='Order')
-    order_line = order.newContent(portal_type=self.order_line_portal_type,
-                                  resource_value=resource,
-                                  quantity=1,
-                                  price=2)
-    other_entity = self.portal.organisation_module.newContent(
-                                      portal_type='Organisation',
-                                      title='Other Entity',
-                                      default_address_region=self.default_region)
-    other_project = self.portal.project_module.newContent(
-                                      portal_type='Project',
-                                      title='Other Project')
-    order.plan()
-    transaction.commit()
-    self.tic()
-    self.assertEquals('planned', order.getSimulationState())
-
-    related_applied_rule = order.getCausalityRelatedValue(
-                             portal_type='Applied Rule')
-    order_movement = related_applied_rule.contentValues()[0]
-    delivery_applied_rule = order_movement.contentValues()[0]
-    delivery_movement = delivery_applied_rule.contentValues()[0]
-    invoice_applied_rule = delivery_movement.contentValues()[0]
-    invoice_movement = invoice_applied_rule.contentValues()[0]
-    invoice_transaction_applied_rule = invoice_movement.contentValues()[0]
+    invoice = sequence.get('invoice')
+    related_payment_list = invoice.getCausalityRelatedValueList(
+      portal_type=self.payment_portal_type)
 
-    # utility function to return the simulation movement that should be used
-    # for "income" line
-    def getIncomeSimulationMovement(applied_rule):
-      for movement in applied_rule.contentValues():
-        if movement.getDestination() == 'account_module/purchase'\
-            and movement.getSource() == 'account_module/sale':
-          return movement
-      self.fail('Income movement not found')
+    invoice_building_state = 'started'
+    invoice_state = invoice.getSimulationState()
+    if invoice_state != invoice_building_state :
+      self.assertEquals(0, len(related_payment_list))
+    else:
+      self.assertEquals(1, len(related_payment_list))
 
-    self.assertEquals(3, len(invoice_transaction_applied_rule))
-    invoice_transaction_movement = getIncomeSimulationMovement(
-                                        invoice_transaction_applied_rule)
+      payment = related_payment_list[0].getObject()
+      self.failUnless(payment is not None)
+      # Payments created by Delivery Builder are in planned state
+      self.assertEquals(payment.getSimulationState(), 'planned')
 
-    order_line.setSourceSectionValue(other_entity)
-    transaction.commit()
-    self.tic()
-    self.assertEquals(other_entity,
-                      invoice_transaction_movement.getSourceSectionValue())
+      # Get the list of simulation movements of packing list ...
+      invoice_simulation_movement_list = []
+      for invoice_movement in invoice.getMovementList(
+        portal_type=self.portal.getPortalAccountingMovementTypeList()):
+        invoice_simulation_movement_list.extend(
+          invoice_movement.getDeliveryRelatedValueList())
+      # ... payment simulation movement are their childrens.
+      simulation_movement_list = []
+      for p_l_simulation_movement in invoice_simulation_movement_list :
+        for applied_rule in p_l_simulation_movement.objectValues() :
+          simulation_movement_list.extend(applied_rule.objectValues())
 
-    # make sure destination_section != source_section, this might be needed by
-    # some rules
-    order_line.setSourceSectionValue(order_line.getDestinationSectionValue())
+      # First, test if each Simulation Movement is related to an
+      # Payment Movement
+      payment_relative_url = payment.getRelativeUrl()
+      for simulation_movement in simulation_movement_list:
+        payment_movement_list = simulation_movement.getDeliveryValueList()
+        self.assertEquals(len(payment_movement_list), 1)
+        payment_movement = payment_movement_list[0]
+        self.failUnless(payment_movement is not None)
+        self.assert_(payment_movement.getRelativeUrl().\
+                              startswith(payment_relative_url))
 
-    order_line.setDestinationSectionValue(other_entity)
-    transaction.commit()
-    self.tic()
-    self.assertEquals(3, len(invoice_transaction_applied_rule))
-    invoice_transaction_movement = getIncomeSimulationMovement(
-                                        invoice_transaction_applied_rule)
-    self.assertEquals(other_entity,
-                 invoice_transaction_movement.getDestinationSectionValue())
+      # Then, test if each Payment movement is equals to the sum of somes
+      # Simulation Movements
+      for payment_movement in payment.getMovementList():
+        related_simulation_movement_list = payment_movement.\
+                 getDeliveryRelatedValueList(portal_type='Simulation Movement')
+        quantity = 0
+        total_price = 0
+        payment_movement_quantity = payment_movement.getQuantity()
+        for related_simulation_movement in related_simulation_movement_list:
+          quantity += related_simulation_movement.getQuantity()
+          total_price += related_simulation_movement.getPrice() *\
+                         related_simulation_movement.getQuantity()
+          # Test resource
+          self.assertEquals(payment_movement.getResource(), \
+                            related_simulation_movement.getResource())
+          # Test resource variation
+          self.assertEquals(payment_movement.getVariationText(), \
+                            related_simulation_movement.getVariationText())
+          self.assertEquals(payment_movement.getVariationCategoryList(), \
+                        related_simulation_movement.getVariationCategoryList())
+          # Test acquisition
+          self.checkAcquisition(payment_movement,
+                                related_simulation_movement)
+          # Test delivery ratio
+          self.assertEquals(related_simulation_movement.getQuantity() /\
+                            payment_movement_quantity, \
+                            related_simulation_movement.getDeliveryRatio())
 
-    order_line.setSourceAdministrationValue(other_entity)
-    transaction.commit()
-    self.tic()
-    self.assertEquals(3, len(invoice_transaction_applied_rule))
-    invoice_transaction_movement = getIncomeSimulationMovement(
-                                        invoice_transaction_applied_rule)
-    self.assertEquals(other_entity,
-                 invoice_transaction_movement.getSourceAdministrationValue())
+        self.assertEquals(quantity, payment_movement.getQuantity())
+        # Test price
+        self.assertEquals(total_price / quantity, payment_movement.getPrice())
 
-    order_line.setDestinationAdministrationValue(other_entity)
-    transaction.commit()
-    self.tic()
-    self.assertEquals(3, len(invoice_transaction_applied_rule))
-    invoice_transaction_movement = getIncomeSimulationMovement(
-                                        invoice_transaction_applied_rule)
-    self.assertEquals(other_entity,
-            invoice_transaction_movement.getDestinationAdministrationValue())
+      sequence.edit(payment = payment)
 
-    order_line.setSourceDecisionValue(other_entity)
-    transaction.commit()
-    self.tic()
-    self.assertEquals(3, len(invoice_transaction_applied_rule))
-    invoice_transaction_movement = getIncomeSimulationMovement(
-                                        invoice_transaction_applied_rule)
-    self.assertEquals(other_entity,
-                 invoice_transaction_movement.getSourceDecisionValue())
+      # Test causality
+      self.assertEquals(len(payment.getCausalityValueList(
+                      portal_type = self.invoice_portal_type)), 1)
+      self.assertEquals(payment.getCausalityValue(), invoice)
 
-    order_line.setDestinationDecisionValue(other_entity)
-    transaction.commit()
-    self.tic()
-    self.assertEquals(3, len(invoice_transaction_applied_rule))
-    invoice_transaction_movement = getIncomeSimulationMovement(
-                                        invoice_transaction_applied_rule)
-    self.assertEquals(other_entity,
-            invoice_transaction_movement.getDestinationDecisionValue())
+      # Finally, test getTotalQuantity and getTotalPrice on Payment
+      self.assertEquals(0, payment.getTotalQuantity())
+      self.assertEquals(0, payment.getTotalPrice())
 
-    order_line.setSourceProjectValue(other_project)
-    transaction.commit()
-    self.tic()
-    self.assertEquals(3, len(invoice_transaction_applied_rule))
-    invoice_transaction_movement = getIncomeSimulationMovement(
-                                        invoice_transaction_applied_rule)
-    self.assertEquals(other_project,
-                 invoice_transaction_movement.getSourceProjectValue())
+  def stepCheckInvoicesConsistency(self, sequence=None, sequence_list=None,
+      **kw):
+    """
+    Checks that all invoices are consistent:
+    - transaction lines match invoice lines
+    - no movement is divergent
+    """
+    invoice_list = self.getPortal()['accounting_module'].objectValues()
+    for invoice in invoice_list:
+      accounting_state_list = \
+          list(self.getPortal().getPortalCurrentInventoryStateList())
+      accounting_state_list.append('cancelled')
+      if invoice.getSimulationState() in accounting_state_list:
+        invoice_line_list = invoice.contentValues(
+            portal_type=self.invoice_line_portal_type)
+        invoice_transaction_line_list = invoice.contentValues(
+            portal_type=self.invoice_transaction_line_portal_type)
+        self.assertEquals(3, len(invoice_transaction_line_list))
+        expected_price = 0.0
+        for line in invoice_line_list:
+          expected_price += line.getTotalPrice()
+        for line_id, line_source, line_dest, line_ratio in \
+            self.transaction_line_definition_list:
+          for line in invoice.contentValues(
+              portal_type=self.invoice_transaction_line_portal_type):
+            if line.getSource() == 'account_module/%s' % line_source and \
+                line.getDestination() == 'account_module/%s' % line_dest:
+              break
+          else:
+            self.fail('No line found that matches %s' % line_id)
+          resource_precision = line.getResourceValue().getQuantityPrecision()
+          self.assertEquals(round(line.getQuantity(), resource_precision),
+              round(expected_price * line_ratio, resource_precision))
 
-    order_line.setDestinationProjectValue(other_project)
-    transaction.commit()
-    self.tic()
-    self.assertEquals(3, len(invoice_transaction_applied_rule))
-    invoice_transaction_movement = getIncomeSimulationMovement(
-                                        invoice_transaction_applied_rule)
-    self.assertEquals(other_project,
-            invoice_transaction_movement.getDestinationProjectValue())
+  def stepCheckInvoiceLineHasReferenceAndIntIndex(self, sequence=None, **kw):
+    """Check that the unique invoice line in the invoice has reference and int
+    index.
+    """
+    invoice = sequence.get('invoice')
+    invoice_line_list = invoice.contentValues(
+                            portal_type=self.invoice_line_portal_type)
+    self.assertEquals(1, len(invoice_line_list))
+    invoice_line = invoice_line_list[0]
+    self.assertEquals(1, invoice_line.getIntIndex())
+    self.assertEquals('1', invoice_line.getReference())
 
-    order_line.setSourceFunctionValue(other_entity)
-    transaction.commit()
-    self.tic()
-    self.assertEquals(3, len(invoice_transaction_applied_rule))
-    invoice_transaction_movement = getIncomeSimulationMovement(
-                                        invoice_transaction_applied_rule)
-    self.assertEquals(other_entity,
-                 invoice_transaction_movement.getSourceFunctionValue())
+  def stepCheckPackingListInvoice(
+                      self, sequence=None, sequence_list=None, **kw):
+    """ Checks if the delivery builder is working as expected,
+        coping the atributes from packing list to invoice."""
+    packing_list = sequence.get('packing_list')
+    related_invoice_list = packing_list.getCausalityRelatedValueList(
+                     portal_type=self.invoice_portal_type)
+    self.assertEquals(len(related_invoice_list), 1)
+    invoice = related_invoice_list[0]
+    self.assertEquals(packing_list.getSource(), invoice.getSource())
+    self.assertEquals(packing_list.getDestination(), invoice.getDestination())
+    self.assertEquals(packing_list.getDestinationSection(), \
+                                       invoice.getDestinationSection())
+    self.assertEquals(packing_list.getSourceSection(), \
+                                       invoice.getSourceSection())
+    self.assertEquals(packing_list.getDestinationDecision(), \
+                                       invoice.getDestinationDecision())
+    self.assertEquals(packing_list.getSourceDecision(), \
+                                       invoice.getSourceDecision())
+    self.assertEquals(packing_list.getDestinationAdministration(), \
+                                       invoice.getDestinationAdministration())
+    self.assertEquals(packing_list.getSourceAdministration(), \
+                                       invoice.getSourceAdministration())
+    self.assertEquals(packing_list.getDestinationProject(), \
+                                       invoice.getDestinationProject())
+    self.assertEquals(packing_list.getSourceProject(), \
+                                       invoice.getSourceProject())
+    self.assertEquals(packing_list.getPriceCurrency(), \
+                                       invoice.getPriceCurrency())
 
-    order_line.setDestinationFunctionValue(other_entity)
-    transaction.commit()
-    self.tic()
-    self.assertEquals(3, len(invoice_transaction_applied_rule))
-    invoice_transaction_movement = getIncomeSimulationMovement(
-                                        invoice_transaction_applied_rule)
-    self.assertEquals(other_entity,
-            invoice_transaction_movement.getDestinationFunctionValue())
 
-    order_line.setSourcePaymentValue(other_entity)
-    transaction.commit()
-    self.tic()
-    self.assertEquals(3, len(invoice_transaction_applied_rule))
-    invoice_transaction_movement = getIncomeSimulationMovement(
-                                        invoice_transaction_applied_rule)
-    self.assertEquals(other_entity,
-                 invoice_transaction_movement.getSourcePaymentValue())
 
-    order_line.setDestinationPaymentValue(other_entity)
-    transaction.commit()
-    self.tic()
-    self.assertEquals(3, len(invoice_transaction_applied_rule))
-    invoice_transaction_movement = getIncomeSimulationMovement(
-                                        invoice_transaction_applied_rule)
-    self.assertEquals(other_entity,
-            invoice_transaction_movement.getDestinationPaymentValue())
+  def stepCheckDeliveryRuleForDeferred(
+                      self, sequence=None, sequence_list=None, **kw):
+    """ Checks that a delivery rule has been created when we took 'split
+        and defer' decision on the divergeant Packing List. """
+    # TODO
 
-    order_line.setQuantity(1)
-    order_line.setPrice(123)
-    transaction.commit()
-    self.tic()
-    self.assertEquals(3, len(invoice_transaction_applied_rule))
-    invoice_transaction_movement = getIncomeSimulationMovement(
-                                        invoice_transaction_applied_rule)
-    self.assertEquals(123,
-            invoice_transaction_movement.getQuantity())
+  def stepCheckDeliveryRuleIsEmpty(
+                      self, sequence=None, sequence_list=None, **kw):
+    """ Checks that an empty delivery rule is created for the
+        convergeant Packing List"""
+    packing_list = sequence.get('packing_list')
+    self.failUnless(packing_list is not None)
+    simulation_tool = self.getSimulationTool()
+    # Check that there is an applied rule for our packing list
+    rule_list = [x for x in simulation_tool.objectValues()
+                          if x.getCausalityValue()==packing_list]
+    self.assertEquals(len(rule_list),1)
+    packing_list_rule = rule_list[0]
+    sequence.edit(packing_list_rule=packing_list_rule)
+    rule_line_list = packing_list_rule.objectValues()
+    packing_list_line_list = packing_list.objectValues()
+    self.assertEquals(len(packing_list_line_list),
+                      len(rule_line_list))
+    self.assertEquals(1, len(rule_line_list))
+    rule_line = rule_line_list[0]
+    packing_list_line = packing_list_line_list[0]
+    self.assertEquals(rule_line.getQuantity(), 10)
+    self.assertEquals(rule_line.getPrice(), 100)
+    self.assertEquals(rule_line.getDeliveryValue(),
+                      packing_list_line)
+    self.assertEquals(rule_line.getStartDate(),
+                      packing_list_line.getStartDate())
+    self.assertEquals(rule_line.getStopDate(),
+                      packing_list_line.getStopDate())
+    self.assertEquals(rule_line.getPortalType(),
+                      'Simulation Movement')
 
-    order_line.setQuantity(456)
-    order_line.setPrice(1)
-    transaction.commit()
-    self.tic()
-    self.assertEquals(3, len(invoice_transaction_applied_rule))
-    invoice_transaction_movement = getIncomeSimulationMovement(
-                                        invoice_transaction_applied_rule)
-    self.assertEquals(456,
-            invoice_transaction_movement.getQuantity())
-
-    order_line.setStartDate(DateTime(2001, 02, 03))
-    transaction.commit()
-    self.tic()
-    self.assertEquals(3, len(invoice_transaction_applied_rule))
-    invoice_transaction_movement = getIncomeSimulationMovement(
-                                        invoice_transaction_applied_rule)
-    self.assertEquals(DateTime(2001, 02, 03),
-                 invoice_transaction_movement.getStartDate())
-
-    order_line.setStopDate(DateTime(2002, 03, 04))
-    transaction.commit()
-    self.tic()
-    self.assertEquals(3, len(invoice_transaction_applied_rule))
-    invoice_transaction_movement = getIncomeSimulationMovement(
-                                        invoice_transaction_applied_rule)
-    self.assertEquals(DateTime(2002, 03, 04),
-                 invoice_transaction_movement.getStopDate())
-
-
-  def test_Invoice_viewAsODT(self):
-    resource = self.portal.getDefaultModule(
-        self.resource_portal_type).newContent(
-                    portal_type=self.resource_portal_type,
-                    title='Resource',)
-    client = self.portal.organisation_module.newContent(
-                              portal_type='Organisation', title='Client')
-    vendor = self.portal.organisation_module.newContent(
-                              portal_type='Organisation', title='Vendor')
-    invoice = self.portal.getDefaultModule(self.invoice_portal_type).newContent(
-                              portal_type=self.invoice_portal_type,
-                              start_date=DateTime(2008, 12, 31),
-                              title='Invoice',
-                              source_value=vendor,
-                              source_section_value=vendor,
-                              destination_value=client,
-                              destination_section_value=client)
-    line = invoice.newContent(portal_type=self.invoice_line_portal_type,
-                            resource_value=resource,
-                            quantity=10,
-                            price=3)
-    invoice.confirm()
-    transaction.commit()
-    self.tic()
-
-    odt = invoice.Invoice_viewAsODT()
-    from Products.ERP5OOo.tests.utils import Validator
-    odf_validator = Validator()
-    err_list = odf_validator.validate(odt)
-    if err_list:
-      self.fail(''.join(err_list))
-
-  def test_Invoice_viewAsODT_empty_image(self):
-    resource = self.portal.getDefaultModule(
-        self.resource_portal_type).newContent(
-                    portal_type=self.resource_portal_type,
-                    title='Resource',)
-    client = self.portal.organisation_module.newContent(
-                              portal_type='Organisation', title='Client')
-    client_logo = client.newContent(portal_type='Image',
-                                    id='default_image')
-    vendor = self.portal.organisation_module.newContent(
-                              portal_type='Organisation', title='Vendor')
-    vendor_logo = vendor.newContent(portal_type='Image',
-                                    id='default_image')
-    self.assertEquals(0, vendor_logo.getSize())
-    self.assertEquals(0, vendor.getDefaultImageWidth())
-    self.assertEquals(0, vendor.getDefaultImageHeight())
-    invoice = self.portal.getDefaultModule(self.invoice_portal_type).newContent(
-                              portal_type=self.invoice_portal_type,
-                              start_date=DateTime(2008, 12, 31),
-                              title='Invoice',
-                              source_value=vendor,
-                              source_section_value=vendor,
-                              destination_value=client,
-                              destination_section_value=client)
-    line = invoice.newContent(portal_type=self.invoice_line_portal_type,
-                            resource_value=resource,
-                            quantity=10,
-                            price=3)
-    invoice.confirm()
-    transaction.commit()
-    self.tic()
-
-    odt = invoice.Invoice_viewAsODT()
-    from Products.ERP5OOo.tests.utils import Validator
-    odf_validator = Validator()
-    err_list = odf_validator.validate(odt)
-    if err_list:
-      self.fail(''.join(err_list))
-
-    # the <draw:image> should not be present, because there's no logo
-    parser = OOoParser()
-    parser.openFromString(odt)
-    style_xml = parser.oo_files['styles.xml']
-    self.assert_('<draw:image' not in style_xml)
-
-  def test_Invoice_viewAsODT_invalid_image(self):
-    resource = self.portal.getDefaultModule(
-        self.resource_portal_type).newContent(
-                    portal_type=self.resource_portal_type,
-                    title='Resource',)
-    file_data = FileUpload(__file__, 'rb')
-    client = self.portal.organisation_module.newContent(
-                              portal_type='Organisation', title='Client')
-    client_logo = client.newContent(portal_type='Image',
-                                    id='default_image',
-                                    file=file_data)
-    vendor = self.portal.organisation_module.newContent(
-                              portal_type='Organisation', title='Vendor')
-    vendor_logo = vendor.newContent(portal_type='Image',
-                                    id='default_image',
-                                    file=file_data)
-
-    # width and height of an invalid image are -1 according to
-    # OFS.Image.getImageInfo maybe this is not what we want here ?
-    self.assertEquals(-1, vendor.getDefaultImageWidth())
-    self.assertEquals(-1, vendor.getDefaultImageHeight())
-
-    invoice = self.portal.getDefaultModule(self.invoice_portal_type).newContent(
-                              portal_type=self.invoice_portal_type,
-                              start_date=DateTime(2008, 12, 31),
-                              title='Invoice',
-                              source_value=vendor,
-                              source_section_value=vendor,
-                              destination_value=client,
-                              destination_section_value=client)
-    line = invoice.newContent(portal_type=self.invoice_line_portal_type,
-                            resource_value=resource,
-                            quantity=10,
-                            price=3)
-    invoice.confirm()
-    transaction.commit()
-    self.tic()
-
-    odt = invoice.Invoice_viewAsODT()
-    from Products.ERP5OOo.tests.utils import Validator
-    odf_validator = Validator()
-    err_list = odf_validator.validate(odt)
-    if err_list:
-      self.fail(''.join(err_list))
 
-  def test_invoice_building_with_cells(self):
-    # if the order has cells, the invoice built from that order must have
-    # cells too
-    resource = self.portal.getDefaultModule(
-        self.resource_portal_type).newContent(
-                    portal_type=self.resource_portal_type,
-                    title='Resource',
-                    variation_base_category_list=['size'])
-    currency = self.portal.currency_module.newContent(
-                                portal_type='Currency',
-                                title='Currency')
-
-    client = self.portal.organisation_module.newContent(
-                            portal_type='Organisation',
-                            title='Client')
-    vendor = self.portal.organisation_module.newContent(
-                            portal_type='Organisation',
-                            title='Vendor')
-    order = self.portal.getDefaultModule(self.order_portal_type).newContent(
-                              portal_type=self.order_portal_type,
-                              source_value=vendor,
-                              source_section_value=vendor,
-                              destination_value=client,
-                              destination_section_value=client,
-                              start_date=DateTime(2008, 1, 1),
-                              price_currency_value=currency,
-                              title='Order')
-
-    order_line = order.newContent(portal_type=self.order_line_portal_type,
-                                  resource_value=resource,)
-    order_line.setVariationBaseCategoryList(('size', ))
-    order_line.setVariationCategoryList(['size/Baby', 'size/Child/32'])
-    order_line.updateCellRange()
-
-    cell_baby = order_line.newCell('size/Baby', base_id='movement',
-                             portal_type=self.order_cell_portal_type)
-    cell_baby.edit(quantity=10,
-                   price=4,
-                   variation_category_list=['size/Baby'],
-                   mapped_value_property_list=['quantity', 'price'],)
-
-    cell_child_32 = order_line.newCell('size/Child/32', base_id='movement',
-                                 portal_type=self.order_cell_portal_type)
-    cell_child_32.edit(quantity=20,
-                       price=5,
-                       variation_category_list=['size/Child/32'],
-                       mapped_value_property_list=['quantity', 'price'],)
-    order.confirm()
-    transaction.commit()
-    self.tic()
-
-    related_packing_list = order.getCausalityRelatedValue(
-                                  portal_type=self.packing_list_portal_type)
-    self.assertNotEquals(related_packing_list, None)
-
-    related_packing_list.start()
-    related_packing_list.stop()
-    transaction.commit()
-    self.tic()
+  def stepCheckPackingList(self,sequence=None, sequence_list=None,**kw):
+    """  """
+    packing_list_module = self.getSalePackingListModule()
+    order_rule = sequence.get('order_rule')
+    order = sequence.get('order')
+    sale_packing_list_list = []
+    for o in packing_list_module.objectValues():
+      if o.getCausalityValue() == order:
+        sale_packing_list_list.append(o)
+    self.assertEquals(len(sale_packing_list_list), 1)
+    sale_packing_list = sale_packing_list_list[0]
+    sale_packing_list_line_list = sale_packing_list.objectValues()
+    self.assertEquals(len(sale_packing_list_line_list),1)
+    sale_packing_list_line = sale_packing_list_line_list[0]
+    product = sequence.get('resource')
+    self.assertEquals(sale_packing_list_line.getResourceValue(),
+                      product)
+    self.assertEquals(sale_packing_list_line.getPrice(),
+                      self.price1)
+    LOG('sale_packing_list_line.showDict()',0,
+          sale_packing_list_line.showDict())
+    self.assertEquals(sale_packing_list_line.getQuantity(),
+                      self.quantity1)
+    self.assertEquals(sale_packing_list_line.getTotalPrice(),
+                      self.total_price1)
+    sequence.edit(packing_list = sale_packing_list)
 
-    related_invoice = related_packing_list.getCausalityRelatedValue(
-                                  portal_type=self.invoice_portal_type)
-    self.assertNotEquals(related_invoice, None)
+  def stepCheckTwoInvoices(self,sequence=None, sequence_list=None, **kw):
+    """ checks invoice properties are well set. """
+    # Now we will check that we have two invoices created
+    packing_list = sequence.get('packing_list')
+    invoice_list = packing_list.getCausalityRelatedValueList(
+         portal_type=self.invoice_portal_type)
+    self.assertEquals(len(invoice_list),1)
+    invoice = invoice_list[0]
+    self.assertEquals(invoice.getSimulationState(), 'confirmed')
+    sequence.edit(invoice=invoice)
+    new_packing_list = sequence.get('new_packing_list')
+    new_invoice_list = new_packing_list.getCausalityRelatedValueList(
+        portal_type=self.invoice_portal_type)
+    self.assertEquals(len(new_invoice_list),1)
+    new_invoice = new_invoice_list[0]
+    self.assertEquals(new_invoice.getSimulationState(), 'confirmed')
+    sequence.edit(new_invoice=new_invoice)
 
-    line_list = related_invoice.contentValues(
-                     portal_type=self.invoice_line_portal_type)
-    self.assertEquals(1, len(line_list))
-    invoice_line = line_list[0]
+  def stepStartTwoInvoices(self,sequence=None, sequence_list=None, **kw):
+    """ start both invoices. """
+    portal = self.getPortal()
+    invoice = sequence.get('invoice')
+    new_invoice = sequence.get('new_invoice')
+    portal.portal_workflow.doActionFor(invoice, 'start_action')
+    portal.portal_workflow.doActionFor(new_invoice, 'start_action')
 
-    self.assertEquals(resource, invoice_line.getResourceValue())
-    self.assertEquals(['size'], invoice_line.getVariationBaseCategoryList())
-    self.assertEquals(2,
-          len(invoice_line.getCellValueList(base_id='movement')))
+  def stepCheckTwoInvoicesTransactionLines(self,sequence=None,
+                                           sequence_list=None, **kw):
+    """ checks invoice properties are well set. """
+    invoice = sequence.get('invoice')
+    new_invoice = sequence.get('new_invoice')
+    self.assertEquals(3,len(invoice.objectValues(
+        portal_type=self.invoice_transaction_line_portal_type)))
+    self.assertEquals(3,len(new_invoice.objectValues(
+        portal_type=self.invoice_transaction_line_portal_type)))
+    account_module = self.getAccountModule()
+    found_dict = {}
+    for line in invoice.objectValues(
+        portal_type=self.invoice_transaction_line_portal_type):
+      source_id = line.getSourceId()
+      found_dict[source_id] = line.getQuantity()
+    total_price = (self.default_quantity-1) * self.default_price
+    expected_dict = {
+      'sale' : total_price,
+      'receivable_vat' : total_price * self.vat_rate,
+      'customer' : - (total_price + total_price * self.vat_rate)
+      }
+    self.failIfDifferentSet(expected_dict.keys(),found_dict.keys())
+    for key in found_dict.keys():
+      self.assertAlmostEquals(expected_dict[key],found_dict[key],places=2)
+    found_dict = {}
+    for line in new_invoice.objectValues(
+        portal_type=self.invoice_transaction_line_portal_type):
+      source_id = line.getSourceId()
+      found_dict[source_id] = line.getQuantity()
+    total_price = 1 * self.default_price
+    expected_dict = {
+      'sale' : total_price,
+      'receivable_vat' : total_price * self.vat_rate,
+      'customer' : - (total_price + total_price * self.vat_rate)
+      }
+    self.failIfDifferentSet(expected_dict.keys(), found_dict.keys())
+    for key in found_dict.keys():
+      self.assertAlmostEquals(expected_dict[key], found_dict[key], places=2)
 
-    cell_baby = invoice_line.getCell('size/Baby', base_id='movement')
-    self.assertNotEquals(cell_baby, None)
-    self.assertEquals(resource, cell_baby.getResourceValue())
-    self.assertEquals(10, cell_baby.getQuantity())
-    self.assertEquals(4, cell_baby.getPrice())
-    self.assertTrue('size/Baby' in
-                    cell_baby.getVariationCategoryList())
-    self.assertTrue(cell_baby.isMemberOf('size/Baby'))
+  def stepRebuildAndCheckNothingIsCreated(self, sequence=None,
+                                           sequence_list=None, **kw):
+    """Rebuilds with sale_invoice_builder and checks nothing more is
+    created. """
+    accounting_module = self.getAccountingModule()
+    portal_type_list = ('Sale Invoice Transaction', 'Purchase Invoice Transaction')
+    sale_invoice_transaction_count = len(accounting_module.objectValues(
+      portal_type=portal_type_list))
+    for builder in self.getPortal().portal_deliveries.objectValues():
+      builder.build()
+    self.assertEquals(sale_invoice_transaction_count,
+                      len(accounting_module.objectValues(
+      portal_type=portal_type_list)))
 
-    cell_child_32 = invoice_line.getCell('size/Child/32', base_id='movement')
-    self.assertNotEquals(cell_child_32, None)
-    self.assertEquals(resource, cell_child_32.getResourceValue())
-    self.assertEquals(20, cell_child_32.getQuantity())
-    self.assertEquals(5, cell_child_32.getPrice())
-    self.assertTrue('size/Child/32' in
-                    cell_child_32.getVariationCategoryList())
-    self.assertTrue(cell_child_32.isMemberOf('size/Child/32'))
-  
-  
-  
-  def test_invoice_created_from_packing_list_with_no_order(self):
-    # if the order has cells and an aggregate, the invoice built
-    #from that order must have
-    # cells too
-    resource = self.portal.getDefaultModule(
-        self.resource_portal_type).newContent(
-                    portal_type=self.resource_portal_type,
-                    title='Resource',
-                    variation_base_category_list=['size'])
-    currency = self.portal.currency_module.newContent(
-                                portal_type='Currency',
-                                title='Currency')
+  def stepModifyInvoicesDate(self, sequence=None,
+                                           sequence_list=None, **kw):
+    """Change invoice date"""
+    invoice = sequence.get('invoice')
+    new_invoice = sequence.get('new_invoice')
+    invoice.edit(start_date=self.datetime,
+                 stop_date=self.datetime+1)
+    new_invoice.edit(start_date=self.datetime,
+                 stop_date=self.datetime+1)
 
-    client = self.portal.organisation_module.newContent(
-                            portal_type='Organisation',
-                            title='Client')
-    vendor = self.portal.organisation_module.newContent(
-                            portal_type='Organisation',
-                            title='Vendor')
-    no_order_packing_list = \
-self.portal.getDefaultModule(self.packing_list_portal_type).newContent(
-                              portal_type=self.packing_list_portal_type,
-                              source_value=vendor,
-                              source_section_value=vendor,
-                              destination_value=client,
-                              destination_section_value=client,
-                              start_date=DateTime(2008, 1, 1),
-                              price_currency_value=currency,
-                              title='Order')
+  def stepRemoveDateMovementGroupForTransactionBuilder(self, sequence=None,
+            sequence_list=None, **kw):
+    """
+    Remove DateMovementGroup
+    """
+    portal = self.getPortal()
+    builder = portal.portal_deliveries.sale_invoice_transaction_builder
+    delivery_movement_group_list = builder.getDeliveryMovementGroupList()
+    uf = self.getPortal().acl_users
+    uf._doAddUser('admin', '', ['Manager'], [])
+    user = uf.getUserById('admin').__of__(uf)
+    newSecurityManager(None, user)
+    for movement_group in delivery_movement_group_list:
+      if movement_group.getPortalType() == 'Property Movement Group':
+        # it contains 'start_date' and 'stop_date' only, so we remove
+        # movement group itself.
+        builder.deleteContent(movement_group.getId())
+    builder.newContent(
+      portal_type = 'Parent Explanation Movement Group',
+      collect_order_group='delivery',
+      int_index=len(delivery_movement_group_list)+1
+      )
+    user = uf.getUserById('test_invoice_user').__of__(uf)
+    newSecurityManager(None, user)
 
-    packing_list_line = no_order_packing_list.newContent(
-                        portal_type=self.packing_list_line_portal_type,
-                                  resource_value=resource,)
-    packing_list_line.setVariationBaseCategoryList(('size', ))
-    packing_list_line.setVariationCategoryList(['size/Baby', 'size/Child/32'])
-    packing_list_line.updateCellRange()
+  def stepEditInvoice(self, sequence=None, sequence_list=None, **kw):
+    """Edit the current invoice, to trigger updateAppliedRule."""
+    invoice = sequence.get('invoice')
+    invoice.edit()
 
-    cell_baby = packing_list_line.newCell('size/Baby', base_id='movement',
-                             portal_type=self.packing_list_cell_portal_type)
-    cell_baby.edit(quantity=10,
-                   price=4,
-                   variation_category_list=['size/Baby'],
-                   mapped_value_property_list=['quantity', 'price'],)
+    # call updateAppliedRule directly, don't rely on edit interactions
+    rule_reference = 'default_invoice_rule'
+    self.assertNotEquals(0,
+        len(self.portal.portal_rules.searchFolder(reference=rule_reference)))
+    invoice.updateAppliedRule(rule_reference=rule_reference)
 
-    cell_child_32 = packing_list_line.newCell(
-                                'size/Child/32',base_id='movement',
-                                 portal_type=self.packing_list_cell_portal_type)
-    cell_child_32.edit(quantity=20,
-                       price=5,
-                       variation_category_list=['size/Child/32'],
-                       mapped_value_property_list=['quantity', 'price'],)
-    no_order_packing_list.confirm()
-    transaction.commit()
-    self.tic()
-    self.assertNotEquals(no_order_packing_list, None)
+  def stepCheckInvoiceRuleNotAppliedOnInvoiceEdit(self,
+                    sequence=None, sequence_list=None, **kw):
+    """If we call edit on the invoice, invoice rule should not be
+    applied on lines created by delivery builder."""
+    invoice = sequence.get('invoice')
+    # FIXME: empty applied rule should not be created
+    #self.assertEquals(len(invoice.getCausalityRelatedValueList(
+    #         portal_type=self.applied_rule_portal_type)), 0)
+    for invoice_mvt in invoice.getMovementList():
+      self.assertEquals(len(invoice_mvt.getOrderRelatedValueList(
+            portal_type=self.simulation_movement_portal_type)), 0)
 
-    no_order_packing_list.start()
-    no_order_packing_list.stop()
-    transaction.commit()
-    self.tic()
+  def stepEditPackingList(self, sequence=None, sequence_list=None, **kw):
+    """Edit the current packing list, to trigger updateAppliedRule."""
+    packing_list = sequence.get('packing_list')
+    packing_list.edit()
 
-    related_invoice = no_order_packing_list.getCausalityRelatedValue(
-                                  portal_type=self.invoice_portal_type)
-    self.assertNotEquals(related_invoice, None)
+    # call updateAppliedRule directly, don't rely on edit interactions
+    rule_reference = 'default_delivery_rule'
+    self.assertNotEquals(0,
+        len(self.portal.portal_rules.searchFolder(reference=rule_reference)))
+    packing_list.updateAppliedRule(rule_reference=rule_reference)
 
-    line_list = related_invoice.contentValues(
-                     portal_type=self.invoice_line_portal_type)
-    self.assertEquals(1, len(line_list))
-    invoice_line = line_list[0]
+  def stepCheckDeliveryRuleNotAppliedOnPackingListEdit(self,
+                    sequence=None, sequence_list=None, **kw):
+    """If we call edit on the packing list, delivery rule should not be
+    applied on lines created by delivery builder."""
+    packing_list = sequence.get('packing_list')
+    # FIXME: empty applied rule should not be created
+    #self.assertEquals(len(packing_list.getCausalityRelatedValueList(
+    #         portal_type=self.applied_rule_portal_type)), 0)
+    for delivery_mvt in packing_list.getMovementList():
+      self.assertEquals(len(delivery_mvt.getOrderRelatedValueList(
+            portal_type=self.simulation_movement_portal_type)), 0)
 
-    self.assertEquals(resource, invoice_line.getResourceValue())
-    self.assertEquals(['size'], invoice_line.getVariationBaseCategoryList())
-    self.assertEquals(2,
-          len(invoice_line.getCellValueList(base_id='movement')))
+  def stepDecreaseInvoiceLineQuantity(self, sequence=None, sequence_list=None,
+      **kw):
+    """
+    Set a decreased quantity on invoice lines
+    """
+    invoice = sequence.get('invoice')
+    quantity = sequence.get('line_quantity',default=self.default_quantity)
+    quantity = quantity - 1
+    sequence.edit(line_quantity=quantity)
+    for invoice_line in invoice.objectValues(
+        portal_type=self.invoice_line_portal_type):
+      invoice_line.edit(quantity=quantity)
+    sequence.edit(last_delta = sequence.get('last_delta', 0.0) - 1.0)
 
-    cell_baby = invoice_line.getCell('size/Baby', base_id='movement')
-    self.assertNotEquals(cell_baby, None)
-    self.assertEquals(resource, cell_baby.getResourceValue())
-    self.assertEquals(10, cell_baby.getQuantity())
-    self.assertEquals(4, cell_baby.getPrice())
-    self.assertTrue('size/Baby' in
-                    cell_baby.getVariationCategoryList())
-    self.assertTrue(cell_baby.isMemberOf('size/Baby'))
+  def stepIncreaseInvoiceLineQuantity(self, sequence=None, sequence_list=None,
+      **kw):
+    """
+    Set a Increased quantity on invoice lines
+    """
+    invoice = sequence.get('invoice')
+    quantity = sequence.get('line_quantity',default=self.default_quantity)
+    quantity = quantity + 1
+    sequence.edit(line_quantity=quantity)
+    for invoice_line in invoice.objectValues(
+        portal_type=self.invoice_line_portal_type):
+      invoice_line.edit(quantity=quantity)
+    sequence.edit(last_delta = sequence.get('last_delta', 0.0) + 1.0)
 
-    cell_child_32 = invoice_line.getCell('size/Child/32', base_id='movement')
-    self.assertNotEquals(cell_child_32, None)
-    self.assertEquals(resource, cell_child_32.getResourceValue())
-    self.assertEquals(20, cell_child_32.getQuantity())
-    self.assertEquals(5, cell_child_32.getPrice())
-    self.assertTrue('size/Child/32' in
-                    cell_child_32.getVariationCategoryList())
-    self.assertTrue(cell_child_32.isMemberOf('size/Child/32'))
-    
-  def test_invoice_building_with_cells_and_aggregate(self):
-    # if the order has cells and an aggregate, the invoice built
-    #from that order must have
-    # cells too
-    resource = self.portal.getDefaultModule(
-        self.resource_portal_type).newContent(
-                    portal_type=self.resource_portal_type,
-                    title='Resource',
-                    variation_base_category_list=['size'])
-    currency = self.portal.currency_module.newContent(
-                                portal_type='Currency',
-                                title='Currency')
+  def stepSetInvoiceLineQuantityToZero(self, sequence=None, sequence_list=None,
+      **kw):
+    """
+    Set the quantity on invoice lines to zero
+    """
+    invoice = sequence.get('invoice')
+    #default_quantity = sequence.get('line_quantity',default_quantity)
+    quantity = 0.0
+    sequence.edit(line_quantity=quantity)
+    for invoice_line in invoice.objectValues(
+        portal_type=self.invoice_line_portal_type):
+      invoice_line.edit(quantity=quantity)
+    sequence.edit(last_delta = - self.default_quantity)
 
-    client = self.portal.organisation_module.newContent(
-                            portal_type='Organisation',
-                            title='Client')
-    vendor = self.portal.organisation_module.newContent(
-                            portal_type='Organisation',
-                            title='Vendor')
-    order = self.portal.getDefaultModule(self.order_portal_type).newContent(
-                              portal_type=self.order_portal_type,
-                              source_value=vendor,
-                              source_section_value=vendor,
-                              destination_value=client,
-                              destination_section_value=client,
-                              start_date=DateTime(2008, 1, 1),
-                              price_currency_value=currency,
-                              title='Order')
+  def stepChangeInvoiceStartDate(self, sequence=None, sequence_list=None, **kw):
+    """
+      Change the start_date of the invoice.
+    """
+    invoice = sequence.get('invoice')
+    invoice.edit(start_date=self.datetime + 15)
 
-    order_line = order.newContent(portal_type=self.order_line_portal_type,
-                                  resource_value=resource,)
-    order_line.setVariationBaseCategoryList(('size', ))
-    order_line.setVariationCategoryList(['size/Baby', 'size/Child/32'])
-    order_line.updateCellRange()
+  def stepCheckInvoiceIsCalculating(self, sequence=None, sequence_list=None,
+      **kw):
+    """
+    Test if invoice is calculating
+    """
+    invoice = sequence.get('invoice')
+    self.assertEquals('calculating',invoice.getCausalityState())
 
-    cell_baby = order_line.newCell('size/Baby', base_id='movement',
-                             portal_type=self.order_cell_portal_type)
-    cell_baby.edit(quantity=10,
-                   price=4,
-                   variation_category_list=['size/Baby'],
-                   mapped_value_property_list=['quantity', 'price'],)
+  def stepCheckInvoiceIsDiverged(self, sequence=None, sequence_list=None,
+      **kw):
+    """
+    Test if invoice is diverged
+    """
+    invoice = sequence.get('invoice')
+    self.assertEquals('diverged',invoice.getCausalityState())
 
-    cell_child_32 = order_line.newCell('size/Child/32', base_id='movement',
-                                 portal_type=self.order_cell_portal_type)
-    cell_child_32.edit(quantity=20,
-                       price=5,
-                       variation_category_list=['size/Child/32'],
-                       mapped_value_property_list=['quantity', 'price'],)
-    order.confirm()
-    transaction.commit()
-    self.tic()
+  def stepCheckInvoiceIsSolved(self, sequence=None, sequence_list=None,
+      **kw):
+    """
+    Test if invoice is solved
+    """
+    invoice = sequence.get('invoice')
+    self.assertEquals('solved', invoice.getCausalityState(),
+                      invoice.getDivergenceList())
 
-    related_packing_list = order.getCausalityRelatedValue(
-                                  portal_type=self.packing_list_portal_type)
-    self.assertNotEquals(related_packing_list, None)
+  def stepCheckInvoiceIsDivergent(self, sequence=None, sequence_list=None,
+      **kw):
+    """
+    Test if invoice is divergent
+    """
+    invoice = sequence.get('invoice')
+    self.assertTrue(invoice.isDivergent())
 
-    related_packing_list.start()
-    related_packing_list.stop()
-    transaction.commit()
-    self.tic()
+  def stepCheckInvoiceIsNotDivergent(self, sequence=None, sequence_list=None,
+      **kw):
+    """
+    Test if invoice is not divergent
+    """
+    invoice = sequence.get('invoice')
+    if invoice.isDivergent():
+      self.fail(invoice.getDivergenceList())
 
-    related_invoice = related_packing_list.getCausalityRelatedValue(
-                                  portal_type=self.invoice_portal_type)
-    self.assertNotEquals(related_invoice, None)
+  def stepSplitAndDeferInvoice(self, sequence=None, sequence_list=None,
+      **kw):
+    """
+    split and defer at the invoice level
+    """
+    invoice = sequence.get('invoice')
+    kw = {'listbox':[
+      {'listbox_key':line.getRelativeUrl(),
+       'choice':'SplitAndDefer'} for line in invoice.getMovementList()]}
+    self.portal.portal_workflow.doActionFor(
+      invoice,
+      'split_and_defer_action',
+      start_date=self.datetime + 15,
+      stop_date=self.datetime + 25,
+      **kw)
+    pass
 
-    line_list = related_invoice.contentValues(
-                     portal_type=self.invoice_line_portal_type)
-    self.assertEquals(1, len(line_list))
-    invoice_line = line_list[0]
+  def stepUnifyStartDateWithDecisionInvoice(self, sequence=None,
+                                            sequence_list=None):
+    invoice = sequence.get('invoice')
+    self._solveDeliveryGroupDivergence(invoice, 'start_date',
+                                       invoice.getRelativeUrl())
 
-    self.assertEquals(resource, invoice_line.getResourceValue())
-    self.assertEquals(['size'], invoice_line.getVariationBaseCategoryList())
-    self.assertEquals(2,
-          len(invoice_line.getCellValueList(base_id='movement')))
+  def stepAcceptDecisionQuantityInvoice(self,sequence=None, sequence_list=None):
+    invoice = sequence.get('invoice')
+    self._solveDivergence(invoice, 'quantity', 'accept')
 
-    cell_baby = invoice_line.getCell('size/Baby', base_id='movement')
-    self.assertNotEquals(cell_baby, None)
-    self.assertEquals(resource, cell_baby.getResourceValue())
-    self.assertEquals(10, cell_baby.getQuantity())
-    self.assertEquals(4, cell_baby.getPrice())
-    self.assertTrue('size/Baby' in
-                    cell_baby.getVariationCategoryList())
-    self.assertTrue(cell_baby.isMemberOf('size/Baby'))
+  def stepAcceptDecisionInvoice(self, sequence=None, sequence_list=None,
+      **kw):
+    """
+    accept decision at the invoice level
+    """
+    invoice = sequence.get('invoice')
+    invoice.portal_workflow.doActionFor(invoice,'accept_decision_action')
 
-    cell_child_32 = invoice_line.getCell('size/Child/32', base_id='movement')
-    self.assertNotEquals(cell_child_32, None)
-    self.assertEquals(resource, cell_child_32.getResourceValue())
-    self.assertEquals(20, cell_child_32.getQuantity())
-    self.assertEquals(5, cell_child_32.getPrice())
-    self.assertTrue('size/Child/32' in
-                    cell_child_32.getVariationCategoryList())
-    self.assertTrue(cell_child_32.isMemberOf('size/Child/32'))
-    
-   
-  def test_description_copied_on_lines(self):
-    # if the order lines have different descriptions, description must be
-    # copied in the simulation and on created movements
-    resource = self.portal.getDefaultModule(
-        self.resource_portal_type).newContent(
-                    portal_type=self.resource_portal_type,
-                    title='Resource',)
-    resource2 = self.portal.getDefaultModule(
-        self.resource_portal_type).newContent(
-                    portal_type=self.resource_portal_type,
-                    title='Resource2',)
-    currency = self.portal.currency_module.newContent(
-                                portal_type='Currency',
-                                title='Currency')
+  def stepCheckInvoiceSplitted(self, sequence=None, sequence_list=None, **kw):
+    """
+    Test if invoice was splitted
+    """
+    packing_list = sequence.get('packing_list')
+    invoice_list = packing_list.getCausalityRelatedValueList(
+        portal_type=self.invoice_portal_type)
+    self.assertEquals(2,len(invoice_list))
+    invoice1 = None
+    invoice2 = None
+    for invoice in invoice_list:
+      if invoice.getUid() == sequence.get('invoice').getUid():
+        invoice1 = invoice
+      else:
+        invoice2 = invoice
+    sequence.edit(new_invoice=invoice2)
+    for line in invoice1.objectValues(
+          portal_type=self.invoice_line_portal_type):
+      self.assertEquals(self.default_quantity-1,line.getQuantity())
+    for line in invoice2.objectValues(
+          portal_type=self.invoice_line_portal_type):
+      self.assertEquals(1,line.getQuantity())
 
-    client = self.portal.organisation_module.newContent(
-                            portal_type='Organisation',
-                            title='Client')
-    vendor = self.portal.organisation_module.newContent(
-                            portal_type='Organisation',
-                            title='Vendor')
-    order = self.portal.getDefaultModule(self.order_portal_type).newContent(
-                              portal_type=self.order_portal_type,
-                              source_value=vendor,
-                              source_section_value=vendor,
-                              destination_value=client,
-                              destination_section_value=client,
-                              start_date=DateTime(2008, 1, 1),
-                              price_currency_value=currency,
-                              title='Order')
+  def stepCheckInvoiceNotSplitted(self, sequence=None, sequence_list=None, **kw):
+    """
+    Test if invoice was not splitted
+    """
+    packing_list = sequence.get('packing_list')
+    invoice_list = packing_list.getCausalityRelatedValueList(
+        portal_type=self.invoice_portal_type)
+    self.assertEquals(1,len(invoice_list))
+    invoice1 = None
+    for invoice in invoice_list:
+      if invoice.getUid() == sequence.get('invoice').getUid():
+        invoice1 = invoice
+    last_delta = sequence.get('last_delta', 0.0)
+    for line in invoice1.objectValues(
+        portal_type=self.invoice_line_portal_type):
+      self.assertEquals(self.default_quantity + last_delta,
+          line.getQuantity())
 
-    order.newContent(portal_type=self.order_line_portal_type,
-                                  quantity=3,
-                                  price=10,
-                                  description='The first line',
-                                  resource_value=resource,)
-    order.newContent(portal_type=self.order_line_portal_type,
-                                  quantity=5,
-                                  price=10,
-                                  description='The second line',
-                                  resource_value=resource2,)
+  def stepAddInvoiceLines(self, sequence=None, sequence_list=[]):
+    """
+    add some invoice and accounting lines to the invoice
+    """
+    invoice = sequence.get('invoice')
+    invoice.newContent(portal_type='Invoice Line',
+        resource_value=sequence.get('resource'), quantity=3, price=555)
+    invoice.newContent(portal_type='Sale Invoice Transaction Line',
+        id ='receivable', source='account_module/customer',
+        destination='account_module/supplier', quantity=-1665)
+    invoice.newContent(portal_type='Sale Invoice Transaction Line',
+        id='income', source='account_module/sale',
+        destination='account_module/purchase', quantity=1665)
 
-    order.confirm()
-    transaction.commit()
-    self.tic()
+  def stepAddWrongInvoiceLines(self, sequence=None, sequence_list=[]):
+    """
+    add some wrong invoice and accounting lines to the invoice
+    """
+    invoice = sequence.get('invoice')
+    invoice.newContent(portal_type='Sale Invoice Transaction Line',
+        id='bad_movement', source='account_module/sale',
+        destination='account_module/purchase', quantity=2, price=4)
+    invoice.newContent(portal_type='Sale Invoice Transaction Line',
+        id='counter_bad_movement', source='account_module/sale',
+        destination='account_module/purchase', quantity=-2, price=4)
+    for movement in invoice.getMovementList():
+      movement.edit(resource_value=sequence.get('resource'))
 
-    related_packing_list = order.getCausalityRelatedValue(
-                                  portal_type=self.packing_list_portal_type)
-    self.assertNotEquals(related_packing_list, None)
-    
-    movement_list = related_packing_list.getMovementList()
-    self.assertEquals(2, len(movement_list))
-    self.assertEquals(['The first line'],
-        [m.getDescription() for m in movement_list if m.getQuantity() == 3])
-    self.assertEquals(['The second line'],
-        [m.getDescription() for m in movement_list if m.getQuantity() == 5])
+  def stepCheckStartInvoiceFail(self, sequence=None, sequence_list=[]):
+    """
+    checks that it's not possible to start an invoice with really wrong
+    lines
+    """
+    try:
+      self.tic()
+    except RuntimeError, exc:
+      invoice = sequence.get('invoice')
+      it_builder = self.portal.portal_deliveries.sale_invoice_transaction_builder
+      # check which activities are failing
+      self.assertTrue(str(exc).startswith('tic is looping forever.'),
+          '%s does not start with "tic is looping forever."' % str(exc))
+      msg_list = ['/'.join(x.object_path) for x in
+          self.getActivityTool().getMessageList()]
+      self.assertTrue(it_builder.getPath() in msg_list, '%s in %s' %
+          (it_builder.getPath(), msg_list))
+      # flush failing activities
+      activity_tool = self.getActivityTool()
+      activity_tool.manageClearActivities(keep=0)
+    else:
+      self.fail("Error: stepStartInvoice didn't fail, the builder script"
+          + " InvoiceTransaction_postTransactionLineGeneration should have"
+          + " complained that accounting movements use multiple resources")
 
-    related_packing_list.start()
-    related_packing_list.stop()
-    transaction.commit()
-    self.tic()
+  def stepCheckSimulationTrees(self, sequence=None, sequence_list=[]):
+    """
+    check that rules are created in the order we expect them
+    """
+    applied_rule_set = set()
+    invoice = sequence.get('invoice')
+    for movement in invoice.getMovementList():
+      for sm in movement.getDeliveryRelatedValueList():
+        applied_rule_set.add(sm.getRootAppliedRule())
 
-    related_invoice = related_packing_list.getCausalityRelatedValue(
-                                  portal_type=self.invoice_portal_type)
-    self.assertNotEquals(related_invoice, None)
+    rule_dict = {
+        'Order Rule': {
+          'movement_type_list': ['Sale Order Line', 'Sale Order Cell'],
+          'next_rule_list': ['Delivering Rule', ],
+          },
+        'Delivering Rule': {
+          'movement_type_list': ['Sale Packing List Line', 'Sale Packing List Cell'],
+          'next_rule_list': ['Invoicing Rule', ],
+          },
+        'Invoicing Rule': {
+          'movement_type_list': invoice.getPortalInvoiceMovementTypeList(),
+          'next_rule_list': ['Invoice Transaction Rule', 'Trade Model Rule'],
+          },
+        'Trade Model Rule': {
+          'next_rule_list': ['Invoice Transaction Rule'],
+          },
+        'Invoice Rule': {
+          'movement_type_list': invoice.getPortalInvoiceMovementTypeList() \
+              + invoice.getPortalAccountingMovementTypeList(),
+          'next_rule_list': ['Invoice Transaction Rule', 'Payment Rule',
+            'Trade Model Rule'],
+          },
+        'Invoice Transaction Rule': {
+          'parent_movement_type_list': invoice.getPortalInvoiceMovementTypeList(),
+          'movement_type_list': invoice.getPortalAccountingMovementTypeList(),
+          'next_rule_list': ['Payment Rule'],
+          },
+        'Payment Rule': {
+          'parent_movement_type_list': invoice.getPortalAccountingMovementTypeList(),
+          'next_rule_list': [],
+          },
+        }
 
-    movement_list = related_invoice.getMovementList(
-                              portal_type=self.invoice_line_portal_type)
-    self.assertEquals(2, len(movement_list))
-    self.assertEquals(['The first line'],
-        [m.getDescription() for m in movement_list if m.getQuantity() == 3])
-    self.assertEquals(['The second line'],
-        [m.getDescription() for m in movement_list if m.getQuantity() == 5])
+    def checkTree(rule):
+      """
+      checks the tree recursively
+      """
+      rule_type = rule.getSpecialiseValue().getPortalType()
+      rule_def = rule_dict.get(rule_type, {})
+      for k, v in rule_def.iteritems():
+        if k == 'movement_type_list':
+          for movement in rule.objectValues():
+            if movement.getDeliveryValue() is not None:
+              self.assertTrue(movement.getDeliveryValue().getPortalType() in v,
+                  'looking for %s in %s on %s' % (
+                  movement.getDeliveryValue().getPortalType(), v,
+                  movement.getPath()))
+        elif k == 'next_rule_list':
+          for movement in rule.objectValues():
+            found_rule_dict = {}
+            for next_rule in movement.objectValues():
+              next_rule_type = next_rule.getSpecialiseValue().getPortalType()
+              self.assertTrue(next_rule_type in v,
+                  'looking for %s in %s on %s' % (
+                  next_rule_type, v, next_rule.getPath()))
+              n = found_rule_dict.get(next_rule_type, 0)
+              found_rule_dict[next_rule_type] = n + 1
+            # for each movement, we want to make sure that each rule is not
+            # instanciated more than once
+            if len(found_rule_dict):
+              self.assertEquals(set(found_rule_dict.itervalues()), set([1]))
+        elif k == 'parent_movement_type_list':
+          if rule.getParentValue().getDeliveryValue() is not None:
+            parent_type = rule.getParentValue().getDeliveryValue().getPortalType()
+            self.assertTrue(parent_type in v, 'looking for %s in %s on %s' % (
+                parent_type, v, rule.getParentValue().getPath()))
+        elif k == 'parent_id_list':
+          self.assertTrue(rule.getParentId() in v, 'looking for %s in %s on %s'
+              % (rule.getParentId(), v, rule.getPath()))
+      for movement in rule.objectValues():
+        for next_rule in movement.objectValues():
+          checkTree(next_rule)
 
+    for applied_rule in applied_rule_set:
+      checkTree(applied_rule)
 
-  def test_CopyAndPaste(self):
-    """Test copy on paste on Invoice.
-    When an invoice is copy/pasted, references should be resetted.
+  def stepAddInvoiceLinesManyTransactions(self, sequence=None, sequence_list=[]):
     """
-    accounting_module = self.portal.accounting_module
-    invoice = accounting_module.newContent(
-                    portal_type=self.invoice_portal_type)
-    invoice.edit(reference='reference',
-                 source_reference='source_reference',
-                 destination_reference='destination_reference',)
-    cb_data = accounting_module.manage_copyObjects([invoice.getId()])
-    copied, = accounting_module.manage_pasteObjects(cb_data)
-    new_invoice = accounting_module[copied['new_id']]
-    self.assertNotEquals(invoice.getReference(),
-                         new_invoice.getReference())
-    self.assertNotEquals(invoice.getSourceReference(),
-                         new_invoice.getSourceReference())
-    self.assertNotEquals(invoice.getDestinationReference(),
-                         new_invoice.getDestinationReference())
+    add some invoice and accounting lines to the invoice
+    """
+    invoice = sequence.get('invoice')
+    invoice_line = invoice.newContent(portal_type='Invoice Line')
+    transaction_line_1 = invoice.newContent(portal_type='Sale Invoice Transaction Line')
+    transaction_line_2 = invoice.newContent(portal_type='Sale Invoice Transaction Line')
+    transaction.commit()
+    self.tic()
+    invoice_line.edit(resource_value=sequence.get('resource'), quantity=3,
+        price=555)
+    transaction_line_1.edit(id ='receivable', source='account_module/customer',
+        destination='account_module/supplier', quantity=-1665)
+    transaction_line_2.edit(
+        id='income', source='account_module/sale',
+        destination='account_module/purchase', quantity=1665)
 
-  def test_delivery_mode_and_incoterm_on_invoice(self):
+class TestInvoice(TestInvoiceMixin):
+  """Test methods for sale and purchase invoice.
+  Subclasses must defines portal types to use.
+  """
+  quiet = 1
+  def test_invoice_transaction_line_resource(self):
     """
-    test that categories delivery_mode and incoterm are copied on 
-    the invoice by the delivery builder
-    """ 
-    resource = self.portal.product_module.newContent(
-                    portal_type='Product',
+    tests that simulation movements corresponding to accounting line have a
+    good resource in the simulation
+    """
+    resource = self.portal.getDefaultModule(
+        self.resource_portal_type).newContent(
+                    portal_type=self.resource_portal_type,
                     title='Resource',
                     product_line='apparel')
     currency = self.portal.currency_module.newContent(
                                 portal_type='Currency',
-                                title='euro')
-    currency.setBaseUnitQuantity(0.01)
+                                title='Currency',
+                                base_unit_quantity=0.01)
     self.createInvoiceTransactionRule(currency)
-    transaction.commit()
-    self.tic()#execute transaction
+
     client = self.portal.organisation_module.newContent(
                             portal_type='Organisation',
                             title='Client',
+                            price_currency= currency.getRelativeUrl(),
                             default_address_region=self.default_region)
     vendor = self.portal.organisation_module.newContent(
                             portal_type='Organisation',
                             title='Vendor',
+                            price_currency= currency.getRelativeUrl(),
                             default_address_region=self.default_region)
     order = self.portal.getDefaultModule(self.order_portal_type).newContent(
                               portal_type=self.order_portal_type,
@@ -1367,1272 +1303,1351 @@ self.portal.getDefaultModule(self.packing_list_portal_type).newContent(
                               source_section_value=vendor,
                               destination_value=client,
                               destination_section_value=client,
-                              start_date=DateTime(2008,10, 21),
-                              price_currency_value=currency,
-                              delivery_mode=self.mail_delivery_mode,
-                              incoterm=self.cpt_incoterm,
-                              title='Order')
-    order_line = order.newContent(portal_type=self.order_line_portal_type,
-                                  resource_value=resource,
-                                  quantity=5,
-                                  price=2)
-    order.confirm()
-    transaction.commit()
-    self.tic()
-    related_packing_list = order.getCausalityRelatedValue(
-                                portal_type=self.packing_list_portal_type)
-    self.assertNotEquals(related_packing_list, None)
-    self.assertEquals(related_packing_list.getDeliveryMode(),
-                         order.getDeliveryMode())
-    self.assertEquals(related_packing_list.getIncoterm(),
-                         order.getIncoterm())
-    related_packing_list.start()
-    related_packing_list.stop()
+                              start_date=DateTime(2008, 1, 1),
+                              price_currency_value=currency,
+                              title='Order')
+    order_line = order.newContent(portal_type=self.order_line_portal_type,
+                                  resource_value=resource,
+                                  quantity=1,
+                                  price=2)
+
+    order.confirm()
     transaction.commit()
     self.tic()
-    related_invoice = related_packing_list.getCausalityRelatedValue(
-                                  portal_type=self.invoice_portal_type)
-    self.assertNotEquals(related_invoice, None)
-    self.assertEquals(related_invoice.getDeliveryMode(),
-                         order.getDeliveryMode())
-    self.assertEquals(related_invoice.getIncoterm(),
-                         order.getIncoterm())
-                         
-                         
-  def test_01_quantity_unit_copied(self):
+
+    related_applied_rule = order.getCausalityRelatedValue(
+                             portal_type='Applied Rule')
+    order_movement = related_applied_rule.contentValues()[0]
+    delivery_applied_rule = order_movement.contentValues()[0]
+    delivery_movement = delivery_applied_rule.contentValues()[0]
+    invoice_applied_rule = delivery_movement.contentValues()[0]
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    invoice_transaction_applied_rule = invoice_movement.contentValues()[0]
+    invoice_transaction_movement =\
+         invoice_transaction_applied_rule.contentValues()[0]
+    self.assertEquals(currency,
+          invoice_transaction_movement.getResourceValue())
+    self.assertEquals(currency,
+          delivery_movement.getPriceCurrencyValue())
+
+    
+  def test_modify_planned_order_invoicing_rule(self):
     """
-    tests that when a resource uses different quantity unit that the
-    quantity units are copied on the packing list line and then the invoice
-    line using the delivery builers
-    """           
-    resource = self.portal.product_module.newContent(
-                    portal_type='Product',
+    tests that modifying a planned order affects movements from invoicing
+    rule
+    """
+    resource = self.portal.getDefaultModule(
+        self.resource_portal_type).newContent(
+                    portal_type=self.resource_portal_type,
                     title='Resource',
                     product_line='apparel')
-    resource.setQuantityUnitList([self.unit_piece_quantity_unit,
-                                 self.mass_quantity_unit])
     currency = self.portal.currency_module.newContent(
                                 portal_type='Currency',
-                                title='euro')
-    currency.setBaseUnitQuantity(0.01)
-    transaction.commit()
-    self.tic()#execute transaction
+                                title='Currency',
+                                base_unit_quantity=0.01)
+
     client = self.portal.organisation_module.newContent(
                             portal_type='Organisation',
                             title='Client',
-                            default_address_region=self.default_region)
+                            price_currency= currency.getRelativeUrl())
     vendor = self.portal.organisation_module.newContent(
                             portal_type='Organisation',
                             title='Vendor',
-                            default_address_region=self.default_region)
+                            price_currency= currency.getRelativeUrl())
     order = self.portal.getDefaultModule(self.order_portal_type).newContent(
                               portal_type=self.order_portal_type,
                               source_value=vendor,
                               source_section_value=vendor,
                               destination_value=client,
                               destination_section_value=client,
-                              start_date=DateTime(2008,10, 21),
+                              start_date=DateTime(2008, 1, 1),
                               price_currency_value=currency,
-                              delivery_mode=self.mail_delivery_mode,
-                              incoterm=self.cpt_incoterm,
                               title='Order')
-    first_order_line = order.newContent(
-                          portal_type=self.order_line_portal_type,
-                                  resource_value=resource,
-                             quantity_unit = self.unit_piece_quantity_unit,
-                                  quantity=5,
-                                  price=3)
-    second_order_line = order.newContent( 
-                          portal_type=self.order_line_portal_type,
+    order_line = order.newContent(portal_type=self.order_line_portal_type,
                                   resource_value=resource,
-                             quantity_unit=self.mass_quantity_unit,
-                                  quantity=1.5,
+                                  quantity=1,
                                   price=2)
-    self.assertEquals(first_order_line.getQuantityUnit(),
-                      self.unit_piece_quantity_unit)
-    self.assertEquals(second_order_line.getQuantityUnit(),
-                      self.mass_quantity_unit)
 
-    order.confirm()
+    other_entity = self.portal.organisation_module.newContent(
+                                    portal_type='Organisation',
+                                    title='Other Entity',
+                                    price_currency=currency.getRelativeUrl())
+    other_project = self.portal.project_module.newContent(
+                                    portal_type='Project',
+                                    title='Other Project')
+    order.plan()
     transaction.commit()
     self.tic()
-    related_packing_list = order.getCausalityRelatedValue(
-                                portal_type=self.packing_list_portal_type)
-    self.assertNotEquals(related_packing_list, None)
-    movement_list = related_packing_list.getMovementList()
-    self.assertEquals(len(movement_list),2)
-    movement_list = sorted(movement_list, key=lambda x: x.getQuantity())
-    self.assertEquals(movement_list[0].getQuantityUnit(),
-                      self.mass_quantity_unit)
-    self.assertEquals(movement_list[0].getQuantity(), 1.5)
-    self.assertEquals(movement_list[1].getQuantityUnit(),
-                      self.unit_piece_quantity_unit)
-    self.assertEquals(movement_list[1].getQuantity(), 5)
+    self.assertEquals('planned', order.getSimulationState())
 
-    related_packing_list.start()
-    related_packing_list.stop()
-    related_packing_list.deliver()
+    related_applied_rule = order.getCausalityRelatedValue(
+                             portal_type='Applied Rule')
+    delivery_movement = related_applied_rule.contentValues()[0]
+    invoice_applied_rule = delivery_movement.contentValues()[0]
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+
+    order_line.setSourceValue(other_entity)
     transaction.commit()
     self.tic()
-    related_invoice = related_packing_list.getCausalityRelatedValue(
-                                portal_type=self.invoice_portal_type)
-    self.assertNotEquals(related_invoice, None)
-    movement_list = related_invoice.getMovementList()
-    self.assertEquals(len(movement_list),2)
-    movement_list = sorted(movement_list, key=lambda x: x.getQuantity())
-    self.assertEquals(movement_list[0].getQuantityUnit(),
-                      self.mass_quantity_unit)
-    self.assertEquals(movement_list[0].getQuantity(), 1.5)
-    self.assertEquals(movement_list[1].getQuantityUnit(),
-                      self.unit_piece_quantity_unit)
-    self.assertEquals(movement_list[1].getQuantity(), 5)
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    self.assertEquals(other_entity,
+                      invoice_movement.getSourceValue())
 
- 
+    order_line.setDestinationValue(other_entity)
+    transaction.commit()
+    self.tic()
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    self.assertEquals(other_entity,
+                      invoice_movement.getDestinationValue())
 
-  def _acceptDivergenceOnInvoice(self, invoice, divergence_list):
-    builder_list = invoice.getBuilderList()
-    self.assertEquals(2, len(builder_list))
-    for builder in builder_list:
-      builder.solveDivergence(invoice.getRelativeUrl(),
-                              divergence_to_accept_list=divergence_list)
+    order_line.setSourceSectionValue(other_entity)
+    transaction.commit()
+    self.tic()
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    self.assertEquals(other_entity,
+                      invoice_movement.getSourceSectionValue())
 
-  def test_accept_quantity_divergence_on_invoice_with_stopped_packing_list(
-                self, quiet=quiet):
-    sequence_list = SequenceList()
-    sequence = sequence_list.addSequenceString(self.PACKING_LIST_DEFAULT_SEQUENCE)
-    sequence_list.play(self, quiet=quiet)
+    # make sure destination_section != source_section, this might be needed by
+    # some rules
+    order_line.setSourceSectionValue(order_line.getDestinationSectionValue())
 
-    packing_list = sequence.get('packing_list')
-    packing_list_line = packing_list.getMovementList()[0]
-    previous_quantity = packing_list_line.getQuantity()
-    
-    packing_list.setReady()
-    packing_list.start()
-    packing_list.stop()
-    self.assertEquals('stopped', packing_list.getSimulationState())
+    order_line.setDestinationSectionValue(other_entity)
+    transaction.commit()
+    self.tic()
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    self.assertEquals(other_entity,
+                 invoice_movement.getDestinationSectionValue())
+
+    order_line.setSourceAdministrationValue(other_entity)
+    transaction.commit()
+    self.tic()
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    self.assertEquals(other_entity,
+                 invoice_movement.getSourceAdministrationValue())
+
+    order_line.setDestinationAdministrationValue(other_entity)
+    transaction.commit()
+    self.tic()
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    self.assertEquals(other_entity,
+            invoice_movement.getDestinationAdministrationValue())
+
+    order_line.setSourceDecisionValue(other_entity)
+    transaction.commit()
+    self.tic()
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    self.assertEquals(other_entity,
+                 invoice_movement.getSourceDecisionValue())
+
+    order_line.setDestinationDecisionValue(other_entity)
+    transaction.commit()
+    self.tic()
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    self.assertEquals(other_entity,
+            invoice_movement.getDestinationDecisionValue())
+
+    order_line.setSourceProjectValue(other_project)
+    transaction.commit()
+    self.tic()
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    self.assertEquals(other_project,
+                 invoice_movement.getSourceProjectValue())
+
+    order_line.setDestinationProjectValue(other_project)
+    transaction.commit()
+    self.tic()
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    self.assertEquals(other_project,
+            invoice_movement.getDestinationProjectValue())
+
+    order_line.setSourcePaymentValue(other_entity)
+    transaction.commit()
+    self.tic()
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    self.assertEquals(other_entity,
+                 invoice_movement.getSourcePaymentValue())
+
+    order_line.setDestinationPaymentValue(other_entity)
+    transaction.commit()
+    self.tic()
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    self.assertEquals(other_entity,
+            invoice_movement.getDestinationPaymentValue())
+
+    order_line.setSourceFunctionValue(other_entity)
+    transaction.commit()
+    self.tic()
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    self.assertEquals(other_entity,
+                 invoice_movement.getSourceFunctionValue())
+
+    order_line.setDestinationFunctionValue(other_entity)
+    transaction.commit()
+    self.tic()
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    self.assertEquals(other_entity,
+            invoice_movement.getDestinationFunctionValue())
+
+    self.assertNotEquals(123, order_line.getPrice())
+    order_line.setPrice(123)
+    transaction.commit()
+    self.tic()
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    self.assertEquals(123,
+            invoice_movement.getPrice())
+
+    self.assertNotEquals(456, order_line.getQuantity())
+    order_line.setQuantity(456)
+    transaction.commit()
+    self.tic()
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    self.assertEquals(456,
+            invoice_movement.getQuantity())
+
+    other_resource = self.portal.product_module.newContent(
+                                        portal_type='Product',
+                                        title='Other Resource')
+    order_line.setResourceValue(other_resource)
     transaction.commit()
     self.tic()
+    # after changing 'resource', related simulation movement will be
+    # replaced with another id, and we need to find the appropriate one
+    # here.
+    delivery_movement = related_applied_rule.contentValues()[0]
+    invoice_applied_rule = delivery_movement.contentValues()[0]
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    self.assertEquals(other_resource,
+            invoice_movement.getResourceValue())
 
-    invoice = packing_list.getCausalityRelatedValue(
-                                  portal_type=self.invoice_portal_type)
-    self.assertNotEquals(invoice, None)
-    invoice_line_list = invoice.getMovementList()
-    self.assertEquals(1, len(invoice_line_list))
-    invoice_line = invoice_line_list[0]
-
-    new_quantity = invoice_line.getQuantity() * 2
-    invoice_line.setQuantity(new_quantity)
-    
+    order_line.setStartDate(DateTime(2001, 02, 03))
     transaction.commit()
     self.tic()
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    self.assertEquals(DateTime(2001, 02, 03),
+                 invoice_movement.getStartDate())
 
-    self.assertTrue(invoice.isDivergent())
-    divergence_list = invoice.getDivergenceList()
-    self.assertEquals(1, len(divergence_list))
-
-    divergence = divergence_list[0]
-    self.assertEquals('quantity', divergence.tested_property)
+    order_line.setStopDate(DateTime(2002, 03, 04))
+    transaction.commit()
+    self.tic()
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    self.assertEquals(DateTime(2002, 03, 04),
+                 invoice_movement.getStopDate())
 
-    # accept decision
-    self._acceptDivergenceOnInvoice(invoice, divergence_list)
+  def test_modify_planned_order_invoice_transaction_rule(self):
+    """
+    tests that modifying a planned order affects movements from invoice
+    transaction rule
+    """
+    resource = self.portal.getDefaultModule(
+        self.resource_portal_type).newContent(
+                    portal_type=self.resource_portal_type,
+                    title='Resource',
+                    product_line='apparel')
+    currency = self.portal.currency_module.newContent(
+                                portal_type='Currency',
+                                title='Currency',
+                                base_unit_quantity=0.01)
+    self.createInvoiceTransactionRule(currency)
 
+    client = self.portal.organisation_module.newContent(
+                            portal_type='Organisation',
+                            title='Client',
+                            default_address_region=self.default_region)
+    vendor = self.portal.organisation_module.newContent(
+                            portal_type='Organisation',
+                            title='Vendor',
+                            default_address_region=self.default_region)
+    order = self.portal.getDefaultModule(self.order_portal_type).newContent(
+                              portal_type=self.order_portal_type,
+                              source_value=vendor,
+                              source_section_value=vendor,
+                              destination_value=client,
+                              destination_section_value=client,
+                              start_date=DateTime(2008, 1, 1),
+                              price_currency_value=currency,
+                              title='Order')
+    order_line = order.newContent(portal_type=self.order_line_portal_type,
+                                  resource_value=resource,
+                                  quantity=1,
+                                  price=2)
+    other_entity = self.portal.organisation_module.newContent(
+                                      portal_type='Organisation',
+                                      title='Other Entity',
+                                      default_address_region=self.default_region)
+    other_project = self.portal.project_module.newContent(
+                                      portal_type='Project',
+                                      title='Other Project')
+    order.plan()
     transaction.commit()
     self.tic()
-    self.assertEquals('solved', invoice.getCausalityState())
+    self.assertEquals('planned', order.getSimulationState())
 
-    self.assertEquals([], invoice.getDivergenceList())
-    self.assertEquals(new_quantity, invoice_line.getQuantity())
-    self.assertEquals(new_quantity,
-          invoice_line.getDeliveryRelatedValue(portal_type='Simulation Movement'
-              ).getQuantity())
+    related_applied_rule = order.getCausalityRelatedValue(
+                             portal_type='Applied Rule')
+    order_movement = related_applied_rule.contentValues()[0]
+    delivery_applied_rule = order_movement.contentValues()[0]
+    delivery_movement = delivery_applied_rule.contentValues()[0]
+    invoice_applied_rule = delivery_movement.contentValues()[0]
+    invoice_movement = invoice_applied_rule.contentValues()[0]
+    invoice_transaction_applied_rule = invoice_movement.contentValues()[0]
 
-    self.assertEquals([], packing_list.getDivergenceList())
-    self.assertEquals('solved', packing_list.getCausalityState())
- 
-  def _adoptDivergenceOnInvoice(self, invoice, divergence_list):
-    builder_list = invoice.getBuilderList()
-    self.assertEquals(2, len(builder_list))
-    for builder in builder_list:
-      builder.solveDivergence(invoice.getRelativeUrl(),
-                              divergence_to_adopt_list=divergence_list)
+    # utility function to return the simulation movement that should be used
+    # for "income" line
+    def getIncomeSimulationMovement(applied_rule):
+      for movement in applied_rule.contentValues():
+        if movement.getDestination() == 'account_module/purchase'\
+            and movement.getSource() == 'account_module/sale':
+          return movement
+      self.fail('Income movement not found')
 
-  def test_adopt_quantity_divergence_on_invoice_line_with_stopped_packing_list(
-                self, quiet=quiet):
-    # #1053
-    sequence_list = SequenceList()
-    sequence = sequence_list.addSequenceString(self.PACKING_LIST_DEFAULT_SEQUENCE)
-    sequence_list.play(self, quiet=quiet)
+    self.assertEquals(3, len(invoice_transaction_applied_rule))
+    invoice_transaction_movement = getIncomeSimulationMovement(
+                                        invoice_transaction_applied_rule)
 
-    packing_list = sequence.get('packing_list')
-    packing_list_line = packing_list.getMovementList()[0]
-    previous_quantity = packing_list_line.getQuantity()
-    previous_resource = packing_list_line.getResource()
-    previous_price = packing_list_line.getPrice()
-    
-    packing_list.setReady()
-    packing_list.start()
-    packing_list.stop()
-    self.assertEquals('stopped', packing_list.getSimulationState())
+    order_line.setSourceSectionValue(other_entity)
     transaction.commit()
     self.tic()
+    self.assertEquals(other_entity,
+                      invoice_transaction_movement.getSourceSectionValue())
 
-    invoice = packing_list.getCausalityRelatedValue(
-                                  portal_type=self.invoice_portal_type)
-    self.assertNotEquals(invoice, None)
-    invoice_line_list = invoice.getMovementList()
-    self.assertEquals(1, len(invoice_line_list))
-    invoice_line = invoice_line_list[0]
+    # make sure destination_section != source_section, this might be needed by
+    # some rules
+    order_line.setSourceSectionValue(order_line.getDestinationSectionValue())
 
-    new_quantity = invoice_line.getQuantity() * 2
-    invoice_line.setQuantity(new_quantity)
-    
+    order_line.setDestinationSectionValue(other_entity)
     transaction.commit()
     self.tic()
+    self.assertEquals(3, len(invoice_transaction_applied_rule))
+    invoice_transaction_movement = getIncomeSimulationMovement(
+                                        invoice_transaction_applied_rule)
+    self.assertEquals(other_entity,
+                 invoice_transaction_movement.getDestinationSectionValue())
 
-    self.assertTrue(invoice.isDivergent())
-    divergence_list = invoice.getDivergenceList()
-    self.assertEquals(1, len(divergence_list))
-
-    divergence = divergence_list[0]
-    self.assertEquals('quantity', divergence.tested_property)
+    order_line.setSourceAdministrationValue(other_entity)
+    transaction.commit()
+    self.tic()
+    self.assertEquals(3, len(invoice_transaction_applied_rule))
+    invoice_transaction_movement = getIncomeSimulationMovement(
+                                        invoice_transaction_applied_rule)
+    self.assertEquals(other_entity,
+                 invoice_transaction_movement.getSourceAdministrationValue())
 
-    # adopt prevision
-    self._adoptDivergenceOnInvoice(invoice, divergence_list)
+    order_line.setDestinationAdministrationValue(other_entity)
+    transaction.commit()
+    self.tic()
+    self.assertEquals(3, len(invoice_transaction_applied_rule))
+    invoice_transaction_movement = getIncomeSimulationMovement(
+                                        invoice_transaction_applied_rule)
+    self.assertEquals(other_entity,
+            invoice_transaction_movement.getDestinationAdministrationValue())
 
+    order_line.setSourceDecisionValue(other_entity)
     transaction.commit()
     self.tic()
-    self.assertEquals([], invoice.getDivergenceList())
-    self.assertEquals('solved', invoice.getCausalityState())
+    self.assertEquals(3, len(invoice_transaction_applied_rule))
+    invoice_transaction_movement = getIncomeSimulationMovement(
+                                        invoice_transaction_applied_rule)
+    self.assertEquals(other_entity,
+                 invoice_transaction_movement.getSourceDecisionValue())
 
-    self.assertEquals(1,
-        len(invoice.getMovementList(portal_type=self.invoice_line_portal_type)))
-    self.assertEquals(0,
-        len(invoice.getMovementList(portal_type=self.invoice_transaction_line_portal_type)))
+    order_line.setDestinationDecisionValue(other_entity)
+    transaction.commit()
+    self.tic()
+    self.assertEquals(3, len(invoice_transaction_applied_rule))
+    invoice_transaction_movement = getIncomeSimulationMovement(
+                                        invoice_transaction_applied_rule)
+    self.assertEquals(other_entity,
+            invoice_transaction_movement.getDestinationDecisionValue())
 
-    self.assertEquals(previous_resource, invoice_line.getResource())
-    self.assertEquals(previous_quantity, invoice_line.getQuantity())
-    self.assertEquals(previous_price, invoice_line.getPrice())
-    self.assertEquals(previous_quantity,
-          invoice_line.getDeliveryRelatedValue(portal_type='Simulation Movement'
-              ).getQuantity())
+    order_line.setSourceProjectValue(other_project)
+    transaction.commit()
+    self.tic()
+    self.assertEquals(3, len(invoice_transaction_applied_rule))
+    invoice_transaction_movement = getIncomeSimulationMovement(
+                                        invoice_transaction_applied_rule)
+    self.assertEquals(other_project,
+                 invoice_transaction_movement.getSourceProjectValue())
 
-    self.assertEquals([], packing_list.getDivergenceList())
-    self.assertEquals('solved', packing_list.getCausalityState())
- 
+    order_line.setDestinationProjectValue(other_project)
+    transaction.commit()
+    self.tic()
+    self.assertEquals(3, len(invoice_transaction_applied_rule))
+    invoice_transaction_movement = getIncomeSimulationMovement(
+                                        invoice_transaction_applied_rule)
+    self.assertEquals(other_project,
+            invoice_transaction_movement.getDestinationProjectValue())
 
+    order_line.setSourceFunctionValue(other_entity)
+    transaction.commit()
+    self.tic()
+    self.assertEquals(3, len(invoice_transaction_applied_rule))
+    invoice_transaction_movement = getIncomeSimulationMovement(
+                                        invoice_transaction_applied_rule)
+    self.assertEquals(other_entity,
+                 invoice_transaction_movement.getSourceFunctionValue())
 
-class TestSaleInvoiceMixin(TestInvoiceMixin,
-                           ERP5TypeTestCase):
-  """Test sale invoice are created from orders then packing lists.
+    order_line.setDestinationFunctionValue(other_entity)
+    transaction.commit()
+    self.tic()
+    self.assertEquals(3, len(invoice_transaction_applied_rule))
+    invoice_transaction_movement = getIncomeSimulationMovement(
+                                        invoice_transaction_applied_rule)
+    self.assertEquals(other_entity,
+            invoice_transaction_movement.getDestinationFunctionValue())
 
-    Those tests methods only work for sale, because sale and purchase invoice
-    are not built at the same time on packing list workflow.
-  """
-  quiet = 0
-  invoice_portal_type = 'Sale Invoice Transaction'
-  invoice_line_portal_type = 'Invoice Line'
-  invoice_cell_portal_type = 'Invoice Cell'
-  invoice_transaction_line_portal_type = 'Sale Invoice Transaction Line'
-  payment_portal_type = 'Payment Transaction'
+    order_line.setSourcePaymentValue(other_entity)
+    transaction.commit()
+    self.tic()
+    self.assertEquals(3, len(invoice_transaction_applied_rule))
+    invoice_transaction_movement = getIncomeSimulationMovement(
+                                        invoice_transaction_applied_rule)
+    self.assertEquals(other_entity,
+                 invoice_transaction_movement.getSourcePaymentValue())
 
-  # default sequence for one line of not varianted resource.
-  PACKING_LIST_DEFAULT_SEQUENCE = """
-      stepCreateEntities
-      stepCreateCurrency
-      stepCreateSaleInvoiceTransactionRule
-      stepCreateOrder
-      stepSetOrderProfile
-      stepSetOrderPriceCurrency
-      stepCreateNotVariatedResource
-      stepTic
-      stepCreateOrderLine
-      stepSetOrderLineResource
-      stepSetOrderLineDefaultValues
-      stepOrderOrder
-      stepTic
-      stepCheckDeliveryBuilding
-      stepConfirmOrder
-      stepTic
-      stepCheckOrderRule
-      stepCheckOrderSimulation
-      stepCheckDeliveryBuilding
-      stepAddPackingListContainer
-      stepAddPackingListContainerLine
-      stepSetContainerLineFullQuantity
-      stepTic
-      stepCheckPackingListIsPacked
-    """
+    order_line.setDestinationPaymentValue(other_entity)
+    transaction.commit()
+    self.tic()
+    self.assertEquals(3, len(invoice_transaction_applied_rule))
+    invoice_transaction_movement = getIncomeSimulationMovement(
+                                        invoice_transaction_applied_rule)
+    self.assertEquals(other_entity,
+            invoice_transaction_movement.getDestinationPaymentValue())
 
-  # default sequence for two lines of not varianted resource.
-  PACKING_LIST_TWO_LINES_DEFAULT_SEQUENCE = """
-      stepCreateEntities
-      stepCreateCurrency
-      stepCreateSaleInvoiceTransactionRule
-      stepCreateOrder
-      stepSetOrderProfile
-      stepSetOrderPriceCurrency
-      stepCreateNotVariatedResource
-      stepTic
-      stepCreateOrderLine
-      stepSetOrderLineResource
-      stepSetOrderLineDefaultValues
-      stepCreateNotVariatedResource
-      stepTic
-      stepCreateOrderLine
-      stepSetOrderLineResource
-      stepSetOrderLineDefaultValues
-      stepOrderOrder
-      stepTic
-      stepCheckDeliveryBuilding
-      stepConfirmOrder
-      stepTic
-      stepCheckOrderRule
-      stepCheckOrderSimulation
-      stepCheckDeliveryBuilding
-      stepAddPackingListContainer
-      stepAddPackingListContainerLine
-      stepTic
-      stepSetContainerFullQuantity
-      stepTic
-      stepCheckPackingListIsPacked
-    """
+    order_line.setQuantity(1)
+    order_line.setPrice(123)
+    transaction.commit()
+    self.tic()
+    self.assertEquals(3, len(invoice_transaction_applied_rule))
+    invoice_transaction_movement = getIncomeSimulationMovement(
+                                        invoice_transaction_applied_rule)
+    self.assertEquals(123,
+            invoice_transaction_movement.getQuantity())
 
-  # default sequence for one line of not varianted resource.
-  TWO_PACKING_LIST_DEFAULT_SEQUENCE = """
-      stepCreateEntities
-      stepCreateCurrency
-      stepCreateSaleInvoiceTransactionRule
-      stepCreateOrder
-      stepSetOrderProfile
-      stepSetOrderPriceCurrency
-      stepCreateNotVariatedResource
-      stepTic
-      stepCreateOrderLine
-      stepSetOrderLineResource
-      stepSetOrderLineDefaultValues
-      stepOrderOrder
-      stepTic
-      stepCheckDeliveryBuilding
-      stepConfirmOrder
-      stepTic
-      stepCheckOrderRule
-      stepCheckOrderSimulation
-      stepCheckDeliveryBuilding
-      stepDecreasePackingListLineQuantity
-      stepCheckPackingListIsCalculating
-      stepTic
-      stepCheckPackingListIsDiverged
-      stepSplitAndDeferPackingList
-      stepTic
-      stepCheckPackingListIsSolved
-      stepCheckPackingListSplitted
-      stepAddPackingListContainer
-      stepAddPackingListContainerLine
-      stepSetContainerLineFullQuantity
-      stepTic
-      stepCheckPackingListIsPacked
-      stepDefineNewPackingListContainer
-      stepTic
-      stepCheckNewPackingListIsPacked
-    """
+    order_line.setQuantity(456)
+    order_line.setPrice(1)
+    transaction.commit()
+    self.tic()
+    self.assertEquals(3, len(invoice_transaction_applied_rule))
+    invoice_transaction_movement = getIncomeSimulationMovement(
+                                        invoice_transaction_applied_rule)
+    self.assertEquals(456,
+            invoice_transaction_movement.getQuantity())
 
-  def modifyPackingListState(self, transition_name,
-                             sequence,packing_list=None):
-    """ calls the workflow for the packing list """
-    if packing_list is None:
-      packing_list = sequence.get('packing_list')
-    packing_list.portal_workflow.doActionFor(packing_list, transition_name)
+    order_line.setStartDate(DateTime(2001, 02, 03))
+    transaction.commit()
+    self.tic()
+    self.assertEquals(3, len(invoice_transaction_applied_rule))
+    invoice_transaction_movement = getIncomeSimulationMovement(
+                                        invoice_transaction_applied_rule)
+    self.assertEquals(DateTime(2001, 02, 03),
+                 invoice_transaction_movement.getStartDate())
 
-  def stepSetReadyPackingList(self, sequence=None, sequence_list=None, **kw):
-    """ set the Packing List as Ready. This must build the invoice. """
-    self.modifyPackingListState('set_ready_action', sequence=sequence)
-    packing_list = sequence.get('packing_list')
-    self.assertEquals(packing_list.getSimulationState(), 'ready')
+    order_line.setStopDate(DateTime(2002, 03, 04))
+    transaction.commit()
+    self.tic()
+    self.assertEquals(3, len(invoice_transaction_applied_rule))
+    invoice_transaction_movement = getIncomeSimulationMovement(
+                                        invoice_transaction_applied_rule)
+    self.assertEquals(DateTime(2002, 03, 04),
+                 invoice_transaction_movement.getStopDate())
 
-  def stepSetReadyNewPackingList(self, sequence=None,
-                                 sequence_list=None, **kw):
-    """ set the Packing List as Ready. This must build the invoice. """
-    packing_list = sequence.get('new_packing_list')
-    self.modifyPackingListState('set_ready_action', sequence=sequence,
-                                packing_list=packing_list)
-    self.assertEquals(packing_list.getSimulationState(), 'ready')
 
-  def stepStartPackingList(self, sequence=None, sequence_list=None, **kw):
-    self.modifyPackingListState('start_action', sequence=sequence)
-    packing_list = sequence.get('packing_list')
-    self.assertEquals(packing_list.getSimulationState(), 'started')
+  def test_Invoice_viewAsODT(self):
+    resource = self.portal.getDefaultModule(
+        self.resource_portal_type).newContent(
+                    portal_type=self.resource_portal_type,
+                    title='Resource',)
+    client = self.portal.organisation_module.newContent(
+                              portal_type='Organisation', title='Client')
+    vendor = self.portal.organisation_module.newContent(
+                              portal_type='Organisation', title='Vendor')
+    invoice = self.portal.getDefaultModule(self.invoice_portal_type).newContent(
+                              portal_type=self.invoice_portal_type,
+                              start_date=DateTime(2008, 12, 31),
+                              title='Invoice',
+                              source_value=vendor,
+                              source_section_value=vendor,
+                              destination_value=client,
+                              destination_section_value=client)
+    line = invoice.newContent(portal_type=self.invoice_line_portal_type,
+                            resource_value=resource,
+                            quantity=10,
+                            price=3)
+    invoice.confirm()
+    transaction.commit()
+    self.tic()
 
-  def stepStartNewPackingList(self, sequence=None, sequence_list=None, **kw):
-    packing_list = sequence.get('new_packing_list')
-    self.modifyPackingListState('start_action', sequence=sequence,
-                                packing_list=packing_list)
-    self.assertEquals(packing_list.getSimulationState(), 'started')
+    odt = invoice.Invoice_viewAsODT()
+    from Products.ERP5OOo.tests.utils import Validator
+    odf_validator = Validator()
+    err_list = odf_validator.validate(odt)
+    if err_list:
+      self.fail(''.join(err_list))
 
-  def stepStopPackingList(self, sequence=None, sequence_list=None, **kw):
-    self.modifyPackingListState('stop_action', sequence=sequence)
-    packing_list = sequence.get('packing_list')
-    self.assertEquals(packing_list.getSimulationState(), 'stopped')
+  def test_Invoice_viewAsODT_empty_image(self):
+    resource = self.portal.getDefaultModule(
+        self.resource_portal_type).newContent(
+                    portal_type=self.resource_portal_type,
+                    title='Resource',)
+    client = self.portal.organisation_module.newContent(
+                              portal_type='Organisation', title='Client')
+    client_logo = client.newContent(portal_type='Image',
+                                    id='default_image')
+    vendor = self.portal.organisation_module.newContent(
+                              portal_type='Organisation', title='Vendor')
+    vendor_logo = vendor.newContent(portal_type='Image',
+                                    id='default_image')
+    self.assertEquals(0, vendor_logo.getSize())
+    self.assertEquals(0, vendor.getDefaultImageWidth())
+    self.assertEquals(0, vendor.getDefaultImageHeight())
+    invoice = self.portal.getDefaultModule(self.invoice_portal_type).newContent(
+                              portal_type=self.invoice_portal_type,
+                              start_date=DateTime(2008, 12, 31),
+                              title='Invoice',
+                              source_value=vendor,
+                              source_section_value=vendor,
+                              destination_value=client,
+                              destination_section_value=client)
+    line = invoice.newContent(portal_type=self.invoice_line_portal_type,
+                            resource_value=resource,
+                            quantity=10,
+                            price=3)
+    invoice.confirm()
+    transaction.commit()
+    self.tic()
 
-  def stepDeliverPackingList(self, sequence=None, sequence_list=None, **kw):
-    self.modifyPackingListState('deliver_action', sequence=sequence)
-    packing_list = sequence.get('packing_list')
-    self.assertEquals(packing_list.getSimulationState(), 'delivered')
+    odt = invoice.Invoice_viewAsODT()
+    from Products.ERP5OOo.tests.utils import Validator
+    odf_validator = Validator()
+    err_list = odf_validator.validate(odt)
+    if err_list:
+      self.fail(''.join(err_list))
 
-  def stepCancelPackingList(self, sequence=None, sequence_list=None, **kw):
-    self.modifyPackingListState('cancel_action', sequence=sequence)
-    packing_list = sequence.get('packing_list')
-    self.assertEquals(packing_list.getSimulationState(), 'cancelled')
+    # the <draw:image> should not be present, because there's no logo
+    parser = OOoParser()
+    parser.openFromString(odt)
+    style_xml = parser.oo_files['styles.xml']
+    self.assert_('<draw:image' not in style_xml)
 
-  def modifyInvoiceState(self, transition_name,
-                             sequence,invoice=None):
-    """ calls the workflow for the invoice """
-    if invoice is None:
-      invoice = sequence.get('invoice')
-    invoice.portal_workflow.doActionFor(invoice, transition_name)
+  def test_Invoice_viewAsODT_invalid_image(self):
+    resource = self.portal.getDefaultModule(
+        self.resource_portal_type).newContent(
+                    portal_type=self.resource_portal_type,
+                    title='Resource',)
+    file_data = FileUpload(__file__, 'rb')
+    client = self.portal.organisation_module.newContent(
+                              portal_type='Organisation', title='Client')
+    client_logo = client.newContent(portal_type='Image',
+                                    id='default_image',
+                                    file=file_data)
+    vendor = self.portal.organisation_module.newContent(
+                              portal_type='Organisation', title='Vendor')
+    vendor_logo = vendor.newContent(portal_type='Image',
+                                    id='default_image',
+                                    file=file_data)
 
-  def stepStartInvoice(self, sequence=None, sequence_list=None, **kw):
-    self.modifyInvoiceState('start_action', sequence=sequence)
-    invoice = sequence.get('invoice')
-    self.assertEquals(invoice.getSimulationState(), 'started')
+    # width and height of an invalid image are -1 according to
+    # OFS.Image.getImageInfo maybe this is not what we want here ?
+    self.assertEquals(-1, vendor.getDefaultImageWidth())
+    self.assertEquals(-1, vendor.getDefaultImageHeight())
 
-  def stepStartNewInvoice(self, sequence=None, sequence_list=None, **kw):
-    invoice = sequence.get('new_invoice')
-    self.modifyInvoiceState('start_action', sequence=sequence,
-                                invoice=invoice)
-    self.assertEquals(invoice.getSimulationState(), 'started')
+    invoice = self.portal.getDefaultModule(self.invoice_portal_type).newContent(
+                              portal_type=self.invoice_portal_type,
+                              start_date=DateTime(2008, 12, 31),
+                              title='Invoice',
+                              source_value=vendor,
+                              source_section_value=vendor,
+                              destination_value=client,
+                              destination_section_value=client)
+    line = invoice.newContent(portal_type=self.invoice_line_portal_type,
+                            resource_value=resource,
+                            quantity=10,
+                            price=3)
+    invoice.confirm()
+    transaction.commit()
+    self.tic()
 
-  def stepStopInvoice(self, sequence=None, sequence_list=None, **kw):
-    self.modifyInvoiceState('stop_action', sequence=sequence)
-    invoice = sequence.get('invoice')
-    self.assertEquals(invoice.getSimulationState(), 'stopped')
+    odt = invoice.Invoice_viewAsODT()
+    from Products.ERP5OOo.tests.utils import Validator
+    odf_validator = Validator()
+    err_list = odf_validator.validate(odt)
+    if err_list:
+      self.fail(''.join(err_list))
 
-  def stepDeliverInvoice(self, sequence=None, sequence_list=None, **kw):
-    self.modifyInvoiceState('deliver_action', sequence=sequence)
-    invoice = sequence.get('invoice')
-    self.assertEquals(invoice.getSimulationState(), 'delivered')
+  def test_invoice_building_with_cells(self):
+    # if the order has cells, the invoice built from that order must have
+    # cells too
+    resource = self.portal.getDefaultModule(
+        self.resource_portal_type).newContent(
+                    portal_type=self.resource_portal_type,
+                    title='Resource',
+                    variation_base_category_list=['size'])
+    currency = self.portal.currency_module.newContent(
+                                portal_type='Currency',
+                                title='Currency')
 
-  def stepCancelInvoice(self, sequence=None, sequence_list=None, **kw):
-    self.modifyInvoiceState('cancel_action', sequence=sequence)
-    invoice = sequence.get('invoice')
-    self.assertEquals(invoice.getSimulationState(), 'cancelled')
+    client = self.portal.organisation_module.newContent(
+                            portal_type='Organisation',
+                            title='Client')
+    vendor = self.portal.organisation_module.newContent(
+                            portal_type='Organisation',
+                            title='Vendor')
+    order = self.portal.getDefaultModule(self.order_portal_type).newContent(
+                              portal_type=self.order_portal_type,
+                              source_value=vendor,
+                              source_section_value=vendor,
+                              destination_value=client,
+                              destination_section_value=client,
+                              start_date=DateTime(2008, 1, 1),
+                              price_currency_value=currency,
+                              title='Order')
 
+    order_line = order.newContent(portal_type=self.order_line_portal_type,
+                                  resource_value=resource,)
+    order_line.setVariationBaseCategoryList(('size', ))
+    order_line.setVariationCategoryList(['size/Baby', 'size/Child/32'])
+    order_line.updateCellRange()
 
-  def stepSwitchPackingLists(self, sequence=None, sequence_list=None, **kw):
-    packing_list = sequence.get('packing_list')
-    new_packing_list = sequence.get('new_packing_list')
-    #invoice = new_packing_list.getDefaultCausalityRelatedValue(
-        #portal_type=self.invoice_portal_type)
-    sequence.edit(packing_list=new_packing_list,
-        new_packing_list=packing_list)#, invoice=invoice)
+    cell_baby = order_line.newCell('size/Baby', base_id='movement',
+                             portal_type=self.order_cell_portal_type)
+    cell_baby.edit(quantity=10,
+                   price=4,
+                   variation_category_list=['size/Baby'],
+                   mapped_value_property_list=['quantity', 'price'],)
 
-  def stepSwitchInvoices(self, sequence=None, sequence_list=None, **kw):
-    invoice = sequence.get('invoice')
-    new_invoice = sequence.get('new_invoice')
-    sequence.edit(invoice=new_invoice, new_invoice=invoice)
+    cell_child_32 = order_line.newCell('size/Child/32', base_id='movement',
+                                 portal_type=self.order_cell_portal_type)
+    cell_child_32.edit(quantity=20,
+                       price=5,
+                       variation_category_list=['size/Child/32'],
+                       mapped_value_property_list=['quantity', 'price'],)
+    order.confirm()
+    transaction.commit()
+    self.tic()
 
-  def stepCheckPackingListSimulation(self, sequence=None, sequence_list=None, **kw):
-    """ checks that simulation movements related to the packing list are OK """
-    packing_list = sequence.get('packing_list')
-    order = sequence.get('order')
-    order_root_applied_rule = order.getCausalityRelatedValueList(
-                                  portal_type = 'Applied Rule')[0]
-    # check simulation movements from this packing list
-    for movement in packing_list.getMovementList() :
-      simulation_movement_list = movement.getOrderRelatedValueList()
-      self.assertNotEquals(len(simulation_movement_list), 0)
-      total_quantity = 0
-      for simulation_movement in simulation_movement_list :
-        total_quantity += simulation_movement.getQuantity()
-        # check that those movements come from the same root applied
-        # rule than the order.
-        self.assertEquals( simulation_movement.getRootAppliedRule(),
-                           order_root_applied_rule)
-      self.assertEquals(total_quantity, movement.getQuantity())
+    related_packing_list = order.getCausalityRelatedValue(
+                                  portal_type=self.packing_list_portal_type)
+    self.assertNotEquals(related_packing_list, None)
 
-  def stepCheckInvoiceBuilding(self, sequence=None, sequence_list=None, **kw):
-    """
-    checks that the invoice is built with the default_invoice_builder
-    """
-    packing_list = sequence.get('packing_list')
-    related_invoice_list = packing_list.getCausalityRelatedValueList(
-                     portal_type=self.invoice_portal_type)
+    related_packing_list.start()
+    related_packing_list.stop()
+    transaction.commit()
+    self.tic()
 
-    packing_list_building_state = 'started'
-    packing_list_state = packing_list.getSimulationState()
-    if packing_list_state != packing_list_building_state :
-      self.assertEquals(0, len(related_invoice_list))
-    else:
-      self.assertEquals(1, len(related_invoice_list))
+    related_invoice = related_packing_list.getCausalityRelatedValue(
+                                  portal_type=self.invoice_portal_type)
+    self.assertNotEquals(related_invoice, None)
 
-      invoice = related_invoice_list[0].getObject()
-      self.failUnless(invoice is not None)
-      # Invoices created by Delivery Builder are in confirmed state
-      self.assertEquals(invoice.getSimulationState(), 'confirmed')
+    line_list = related_invoice.contentValues(
+                     portal_type=self.invoice_line_portal_type)
+    self.assertEquals(1, len(line_list))
+    invoice_line = line_list[0]
 
-      # Get the list of simulation movements of packing list ...
-      packing_list_simulation_movement_list = []
-      for packing_list_movement in packing_list.getMovementList():
-           packing_list_simulation_movement_list.extend(
-                packing_list_movement.getDeliveryRelatedValueList())
-      # ... invoice simulation movement are their childrens.
-      simulation_movement_list = []
-      for p_l_simulation_movement in packing_list_simulation_movement_list :
-        for applied_rule in p_l_simulation_movement.objectValues() :
-          simulation_movement_list.extend(applied_rule.objectValues())
+    self.assertEquals(resource, invoice_line.getResourceValue())
+    self.assertEquals(['size'], invoice_line.getVariationBaseCategoryList())
+    self.assertEquals(2,
+          len(invoice_line.getCellValueList(base_id='movement')))
 
-      # First, test if each Simulation Movement is related to an
-      # Invoice Movement
-      invoice_relative_url = invoice.getRelativeUrl()
-      for simulation_movement in simulation_movement_list:
-        invoice_movement_list = simulation_movement.getDeliveryValueList()
-        self.assertEquals(len(invoice_movement_list), 1)
-        invoice_movement = invoice_movement_list[0]
-        self.failUnless(invoice_movement is not None)
-        self.assert_(invoice_movement.getRelativeUrl().\
-                              startswith(invoice_relative_url))
+    cell_baby = invoice_line.getCell('size/Baby', base_id='movement')
+    self.assertNotEquals(cell_baby, None)
+    self.assertEquals(resource, cell_baby.getResourceValue())
+    self.assertEquals(10, cell_baby.getQuantity())
+    self.assertEquals(4, cell_baby.getPrice())
+    self.assertTrue('size/Baby' in
+                    cell_baby.getVariationCategoryList())
+    self.assertTrue(cell_baby.isMemberOf('size/Baby'))
 
-      # Then, test if each Invoice movement is equals to the sum of somes
-      # Simulation Movements
-      for invoice_movement in invoice.getMovementList(portal_type = [
-                          self.invoice_cell_portal_type,
-                          self.invoice_line_portal_type]) :
-        related_simulation_movement_list = invoice_movement.\
-                 getDeliveryRelatedValueList(portal_type='Simulation Movement')
-        quantity = 0
-        total_price = 0
-        invoice_movement_quantity = invoice_movement.getQuantity()
-        for related_simulation_movement in related_simulation_movement_list:
-          quantity += related_simulation_movement.getQuantity()
-          total_price += related_simulation_movement.getPrice() *\
-                         related_simulation_movement.getQuantity()
-          # Test resource
-          self.assertEquals(invoice_movement.getResource(), \
-                            related_simulation_movement.getResource())
-          # Test resource variation
-          self.assertEquals(invoice_movement.getVariationText(), \
-                            related_simulation_movement.getVariationText())
-          self.assertEquals(invoice_movement.getVariationCategoryList(), \
-                        related_simulation_movement.getVariationCategoryList())
-          # Test acquisition
-          self.checkAcquisition(invoice_movement,
-                                related_simulation_movement)
-          # Test delivery ratio
-          self.assertEquals(related_simulation_movement.getQuantity() /\
-                            invoice_movement_quantity, \
-                            related_simulation_movement.getDeliveryRatio())
+    cell_child_32 = invoice_line.getCell('size/Child/32', base_id='movement')
+    self.assertNotEquals(cell_child_32, None)
+    self.assertEquals(resource, cell_child_32.getResourceValue())
+    self.assertEquals(20, cell_child_32.getQuantity())
+    self.assertEquals(5, cell_child_32.getPrice())
+    self.assertTrue('size/Child/32' in
+                    cell_child_32.getVariationCategoryList())
+    self.assertTrue(cell_child_32.isMemberOf('size/Child/32'))
+  
+  
+  
+  def test_invoice_created_from_packing_list_with_no_order(self):
+    # if the order has cells and an aggregate, the invoice built
+    #from that order must have
+    # cells too
+    resource = self.portal.getDefaultModule(
+        self.resource_portal_type).newContent(
+                    portal_type=self.resource_portal_type,
+                    title='Resource',
+                    variation_base_category_list=['size'])
+    currency = self.portal.currency_module.newContent(
+                                portal_type='Currency',
+                                title='Currency')
 
-        self.assertEquals(quantity, invoice_movement.getQuantity())
-        # Test price
-        self.assertEquals(total_price / quantity, invoice_movement.getPrice())
+    client = self.portal.organisation_module.newContent(
+                            portal_type='Organisation',
+                            title='Client')
+    vendor = self.portal.organisation_module.newContent(
+                            portal_type='Organisation',
+                            title='Vendor')
+    no_order_packing_list = \
+self.portal.getDefaultModule(self.packing_list_portal_type).newContent(
+                              portal_type=self.packing_list_portal_type,
+                              source_value=vendor,
+                              source_section_value=vendor,
+                              destination_value=client,
+                              destination_section_value=client,
+                              start_date=DateTime(2008, 1, 1),
+                              price_currency_value=currency,
+                              title='Order')
 
-      sequence.edit(invoice = invoice)
+    packing_list_line = no_order_packing_list.newContent(
+                        portal_type=self.packing_list_line_portal_type,
+                                  resource_value=resource,)
+    packing_list_line.setVariationBaseCategoryList(('size', ))
+    packing_list_line.setVariationCategoryList(['size/Baby', 'size/Child/32'])
+    packing_list_line.updateCellRange()
 
-      # Test causality
-      self.assertEquals(len(invoice.getCausalityValueList(
-                      portal_type = self.packing_list_portal_type)), 1)
-      self.assertEquals(invoice.getCausalityValue(), packing_list)
+    cell_baby = packing_list_line.newCell('size/Baby', base_id='movement',
+                             portal_type=self.packing_list_cell_portal_type)
+    cell_baby.edit(quantity=10,
+                   price=4,
+                   variation_category_list=['size/Baby'],
+                   mapped_value_property_list=['quantity', 'price'],)
 
-      # Finally, test getTotalQuantity and getTotalPrice on Invoice
-      self.assertEquals(packing_list.getTotalQuantity(),
-                        invoice.getTotalQuantity())
-      self.assertEquals(packing_list.getTotalPrice(),
-                        invoice.getTotalPrice())
+    cell_child_32 = packing_list_line.newCell(
+                                'size/Child/32',base_id='movement',
+                                 portal_type=self.packing_list_cell_portal_type)
+    cell_child_32.edit(quantity=20,
+                       price=5,
+                       variation_category_list=['size/Child/32'],
+                       mapped_value_property_list=['quantity', 'price'],)
+    no_order_packing_list.confirm()
+    transaction.commit()
+    self.tic()
+    self.assertNotEquals(no_order_packing_list, None)
 
-  def stepCheckPaymentBuilding(self, sequence=None, sequence_list=None, **kw):
-    """
-    checks that the payment is built with the default_payment_builder
-    """
-    invoice = sequence.get('invoice')
-    related_payment_list = invoice.getCausalityRelatedValueList(
-      portal_type=self.payment_portal_type)
+    no_order_packing_list.start()
+    no_order_packing_list.stop()
+    transaction.commit()
+    self.tic()
 
-    invoice_building_state = 'started'
-    invoice_state = invoice.getSimulationState()
-    if invoice_state != invoice_building_state :
-      self.assertEquals(0, len(related_payment_list))
-    else:
-      self.assertEquals(1, len(related_payment_list))
+    related_invoice = no_order_packing_list.getCausalityRelatedValue(
+                                  portal_type=self.invoice_portal_type)
+    self.assertNotEquals(related_invoice, None)
 
-      payment = related_payment_list[0].getObject()
-      self.failUnless(payment is not None)
-      # Payments created by Delivery Builder are in planned state
-      self.assertEquals(payment.getSimulationState(), 'planned')
+    line_list = related_invoice.contentValues(
+                     portal_type=self.invoice_line_portal_type)
+    self.assertEquals(1, len(line_list))
+    invoice_line = line_list[0]
 
-      # Get the list of simulation movements of packing list ...
-      invoice_simulation_movement_list = []
-      for invoice_movement in invoice.getMovementList(
-        portal_type=self.portal.getPortalAccountingMovementTypeList()):
-        invoice_simulation_movement_list.extend(
-          invoice_movement.getDeliveryRelatedValueList())
-      # ... payment simulation movement are their childrens.
-      simulation_movement_list = []
-      for p_l_simulation_movement in invoice_simulation_movement_list :
-        for applied_rule in p_l_simulation_movement.objectValues() :
-          simulation_movement_list.extend(applied_rule.objectValues())
+    self.assertEquals(resource, invoice_line.getResourceValue())
+    self.assertEquals(['size'], invoice_line.getVariationBaseCategoryList())
+    self.assertEquals(2,
+          len(invoice_line.getCellValueList(base_id='movement')))
 
-      # First, test if each Simulation Movement is related to an
-      # Payment Movement
-      payment_relative_url = payment.getRelativeUrl()
-      for simulation_movement in simulation_movement_list:
-        payment_movement_list = simulation_movement.getDeliveryValueList()
-        self.assertEquals(len(payment_movement_list), 1)
-        payment_movement = payment_movement_list[0]
-        self.failUnless(payment_movement is not None)
-        self.assert_(payment_movement.getRelativeUrl().\
-                              startswith(payment_relative_url))
+    cell_baby = invoice_line.getCell('size/Baby', base_id='movement')
+    self.assertNotEquals(cell_baby, None)
+    self.assertEquals(resource, cell_baby.getResourceValue())
+    self.assertEquals(10, cell_baby.getQuantity())
+    self.assertEquals(4, cell_baby.getPrice())
+    self.assertTrue('size/Baby' in
+                    cell_baby.getVariationCategoryList())
+    self.assertTrue(cell_baby.isMemberOf('size/Baby'))
 
-      # Then, test if each Payment movement is equals to the sum of somes
-      # Simulation Movements
-      for payment_movement in payment.getMovementList():
-        related_simulation_movement_list = payment_movement.\
-                 getDeliveryRelatedValueList(portal_type='Simulation Movement')
-        quantity = 0
-        total_price = 0
-        payment_movement_quantity = payment_movement.getQuantity()
-        for related_simulation_movement in related_simulation_movement_list:
-          quantity += related_simulation_movement.getQuantity()
-          total_price += related_simulation_movement.getPrice() *\
-                         related_simulation_movement.getQuantity()
-          # Test resource
-          self.assertEquals(payment_movement.getResource(), \
-                            related_simulation_movement.getResource())
-          # Test resource variation
-          self.assertEquals(payment_movement.getVariationText(), \
-                            related_simulation_movement.getVariationText())
-          self.assertEquals(payment_movement.getVariationCategoryList(), \
-                        related_simulation_movement.getVariationCategoryList())
-          # Test acquisition
-          self.checkAcquisition(payment_movement,
-                                related_simulation_movement)
-          # Test delivery ratio
-          self.assertEquals(related_simulation_movement.getQuantity() /\
-                            payment_movement_quantity, \
-                            related_simulation_movement.getDeliveryRatio())
+    cell_child_32 = invoice_line.getCell('size/Child/32', base_id='movement')
+    self.assertNotEquals(cell_child_32, None)
+    self.assertEquals(resource, cell_child_32.getResourceValue())
+    self.assertEquals(20, cell_child_32.getQuantity())
+    self.assertEquals(5, cell_child_32.getPrice())
+    self.assertTrue('size/Child/32' in
+                    cell_child_32.getVariationCategoryList())
+    self.assertTrue(cell_child_32.isMemberOf('size/Child/32'))
+    
+  def test_invoice_building_with_cells_and_aggregate(self):
+    # if the order has cells and an aggregate, the invoice built
+    #from that order must have
+    # cells too
+    resource = self.portal.getDefaultModule(
+        self.resource_portal_type).newContent(
+                    portal_type=self.resource_portal_type,
+                    title='Resource',
+                    variation_base_category_list=['size'])
+    currency = self.portal.currency_module.newContent(
+                                portal_type='Currency',
+                                title='Currency')
 
-        self.assertEquals(quantity, payment_movement.getQuantity())
-        # Test price
-        self.assertEquals(total_price / quantity, payment_movement.getPrice())
+    client = self.portal.organisation_module.newContent(
+                            portal_type='Organisation',
+                            title='Client')
+    vendor = self.portal.organisation_module.newContent(
+                            portal_type='Organisation',
+                            title='Vendor')
+    order = self.portal.getDefaultModule(self.order_portal_type).newContent(
+                              portal_type=self.order_portal_type,
+                              source_value=vendor,
+                              source_section_value=vendor,
+                              destination_value=client,
+                              destination_section_value=client,
+                              start_date=DateTime(2008, 1, 1),
+                              price_currency_value=currency,
+                              title='Order')
 
-      sequence.edit(payment = payment)
+    order_line = order.newContent(portal_type=self.order_line_portal_type,
+                                  resource_value=resource,)
+    order_line.setVariationBaseCategoryList(('size', ))
+    order_line.setVariationCategoryList(['size/Baby', 'size/Child/32'])
+    order_line.updateCellRange()
 
-      # Test causality
-      self.assertEquals(len(payment.getCausalityValueList(
-                      portal_type = self.invoice_portal_type)), 1)
-      self.assertEquals(payment.getCausalityValue(), invoice)
+    cell_baby = order_line.newCell('size/Baby', base_id='movement',
+                             portal_type=self.order_cell_portal_type)
+    cell_baby.edit(quantity=10,
+                   price=4,
+                   variation_category_list=['size/Baby'],
+                   mapped_value_property_list=['quantity', 'price'],)
 
-      # Finally, test getTotalQuantity and getTotalPrice on Payment
-      self.assertEquals(0, payment.getTotalQuantity())
-      self.assertEquals(0, payment.getTotalPrice())
+    cell_child_32 = order_line.newCell('size/Child/32', base_id='movement',
+                                 portal_type=self.order_cell_portal_type)
+    cell_child_32.edit(quantity=20,
+                       price=5,
+                       variation_category_list=['size/Child/32'],
+                       mapped_value_property_list=['quantity', 'price'],)
+    order.confirm()
+    transaction.commit()
+    self.tic()
 
-  def stepCheckInvoicesConsistency(self, sequence=None, sequence_list=None,
-      **kw):
-    """
-    Checks that all invoices are consistent:
-    - transaction lines match invoice lines
-    - no movement is divergent
-    """
-    invoice_list = self.getPortal()['accounting_module'].objectValues()
-    for invoice in invoice_list:
-      accounting_state_list = \
-          list(self.getPortal().getPortalCurrentInventoryStateList())
-      accounting_state_list.append('cancelled')
-      if invoice.getSimulationState() in accounting_state_list:
-        invoice_line_list = invoice.contentValues(
-            portal_type=self.invoice_line_portal_type)
-        invoice_transaction_line_list = invoice.contentValues(
-            portal_type=self.invoice_transaction_line_portal_type)
-        self.assertEquals(3, len(invoice_transaction_line_list))
-        expected_price = 0.0
-        for line in invoice_line_list:
-          expected_price += line.getTotalPrice()
-        for line_id, line_source, line_dest, line_ratio in \
-            self.transaction_line_definition_list:
-          for line in invoice.contentValues(
-              portal_type=self.invoice_transaction_line_portal_type):
-            if line.getSource() == 'account_module/%s' % line_source and \
-                line.getDestination() == 'account_module/%s' % line_dest:
-              break
-          else:
-            self.fail('No line found that matches %s' % line_id)
-          resource_precision = line.getResourceValue().getQuantityPrecision()
-          self.assertEquals(round(line.getQuantity(), resource_precision),
-              round(expected_price * line_ratio, resource_precision))
+    related_packing_list = order.getCausalityRelatedValue(
+                                  portal_type=self.packing_list_portal_type)
+    self.assertNotEquals(related_packing_list, None)
 
-  def stepCheckInvoiceLineHasReferenceAndIntIndex(self, sequence=None, **kw):
-    """Check that the unique invoice line in the invoice has reference and int
-    index.
-    """
-    invoice = sequence.get('invoice')
-    invoice_line_list = invoice.contentValues(
-                            portal_type=self.invoice_line_portal_type)
-    self.assertEquals(1, len(invoice_line_list))
-    invoice_line = invoice_line_list[0]
-    self.assertEquals(1, invoice_line.getIntIndex())
-    self.assertEquals('1', invoice_line.getReference())
+    related_packing_list.start()
+    related_packing_list.stop()
+    transaction.commit()
+    self.tic()
 
-  def stepCheckPackingListInvoice(
-                      self, sequence=None, sequence_list=None, **kw):
-    """ Checks if the delivery builder is working as expected,
-        coping the atributes from packing list to invoice."""
-    packing_list = sequence.get('packing_list')
-    related_invoice_list = packing_list.getCausalityRelatedValueList(
-                     portal_type=self.invoice_portal_type)
-    self.assertEquals(len(related_invoice_list), 1)
-    invoice = related_invoice_list[0]
-    self.assertEquals(packing_list.getSource(), invoice.getSource())
-    self.assertEquals(packing_list.getDestination(), invoice.getDestination())
-    self.assertEquals(packing_list.getDestinationSection(), \
-                                       invoice.getDestinationSection())
-    self.assertEquals(packing_list.getSourceSection(), \
-                                       invoice.getSourceSection())
-    self.assertEquals(packing_list.getDestinationDecision(), \
-                                       invoice.getDestinationDecision())
-    self.assertEquals(packing_list.getSourceDecision(), \
-                                       invoice.getSourceDecision())
-    self.assertEquals(packing_list.getDestinationAdministration(), \
-                                       invoice.getDestinationAdministration())
-    self.assertEquals(packing_list.getSourceAdministration(), \
-                                       invoice.getSourceAdministration())
-    self.assertEquals(packing_list.getDestinationProject(), \
-                                       invoice.getDestinationProject())
-    self.assertEquals(packing_list.getSourceProject(), \
-                                       invoice.getSourceProject())
-    self.assertEquals(packing_list.getPriceCurrency(), \
-                                       invoice.getPriceCurrency())
+    related_invoice = related_packing_list.getCausalityRelatedValue(
+                                  portal_type=self.invoice_portal_type)
+    self.assertNotEquals(related_invoice, None)
 
+    line_list = related_invoice.contentValues(
+                     portal_type=self.invoice_line_portal_type)
+    self.assertEquals(1, len(line_list))
+    invoice_line = line_list[0]
 
+    self.assertEquals(resource, invoice_line.getResourceValue())
+    self.assertEquals(['size'], invoice_line.getVariationBaseCategoryList())
+    self.assertEquals(2,
+          len(invoice_line.getCellValueList(base_id='movement')))
 
-  def stepCheckDeliveryRuleForDeferred(
-                      self, sequence=None, sequence_list=None, **kw):
-    """ Checks that a delivery rule has been created when we took 'split
-        and defer' decision on the divergeant Packing List. """
-    # TODO
+    cell_baby = invoice_line.getCell('size/Baby', base_id='movement')
+    self.assertNotEquals(cell_baby, None)
+    self.assertEquals(resource, cell_baby.getResourceValue())
+    self.assertEquals(10, cell_baby.getQuantity())
+    self.assertEquals(4, cell_baby.getPrice())
+    self.assertTrue('size/Baby' in
+                    cell_baby.getVariationCategoryList())
+    self.assertTrue(cell_baby.isMemberOf('size/Baby'))
 
-  def stepCheckDeliveryRuleIsEmpty(
-                      self, sequence=None, sequence_list=None, **kw):
-    """ Checks that an empty delivery rule is created for the
-        convergeant Packing List"""
-    packing_list = sequence.get('packing_list')
-    self.failUnless(packing_list is not None)
-    simulation_tool = self.getSimulationTool()
-    # Check that there is an applied rule for our packing list
-    rule_list = [x for x in simulation_tool.objectValues()
-                          if x.getCausalityValue()==packing_list]
-    self.assertEquals(len(rule_list),1)
-    packing_list_rule = rule_list[0]
-    sequence.edit(packing_list_rule=packing_list_rule)
-    rule_line_list = packing_list_rule.objectValues()
-    packing_list_line_list = packing_list.objectValues()
-    self.assertEquals(len(packing_list_line_list),
-                      len(rule_line_list))
-    self.assertEquals(1, len(rule_line_list))
-    rule_line = rule_line_list[0]
-    packing_list_line = packing_list_line_list[0]
-    self.assertEquals(rule_line.getQuantity(), 10)
-    self.assertEquals(rule_line.getPrice(), 100)
-    self.assertEquals(rule_line.getDeliveryValue(),
-                      packing_list_line)
-    self.assertEquals(rule_line.getStartDate(),
-                      packing_list_line.getStartDate())
-    self.assertEquals(rule_line.getStopDate(),
-                      packing_list_line.getStopDate())
-    self.assertEquals(rule_line.getPortalType(),
-                      'Simulation Movement')
+    cell_child_32 = invoice_line.getCell('size/Child/32', base_id='movement')
+    self.assertNotEquals(cell_child_32, None)
+    self.assertEquals(resource, cell_child_32.getResourceValue())
+    self.assertEquals(20, cell_child_32.getQuantity())
+    self.assertEquals(5, cell_child_32.getPrice())
+    self.assertTrue('size/Child/32' in
+                    cell_child_32.getVariationCategoryList())
+    self.assertTrue(cell_child_32.isMemberOf('size/Child/32'))
+    
+   
+  def test_description_copied_on_lines(self):
+    # if the order lines have different descriptions, description must be
+    # copied in the simulation and on created movements
+    resource = self.portal.getDefaultModule(
+        self.resource_portal_type).newContent(
+                    portal_type=self.resource_portal_type,
+                    title='Resource',)
+    resource2 = self.portal.getDefaultModule(
+        self.resource_portal_type).newContent(
+                    portal_type=self.resource_portal_type,
+                    title='Resource2',)
+    currency = self.portal.currency_module.newContent(
+                                portal_type='Currency',
+                                title='Currency')
 
+    client = self.portal.organisation_module.newContent(
+                            portal_type='Organisation',
+                            title='Client')
+    vendor = self.portal.organisation_module.newContent(
+                            portal_type='Organisation',
+                            title='Vendor')
+    order = self.portal.getDefaultModule(self.order_portal_type).newContent(
+                              portal_type=self.order_portal_type,
+                              source_value=vendor,
+                              source_section_value=vendor,
+                              destination_value=client,
+                              destination_section_value=client,
+                              start_date=DateTime(2008, 1, 1),
+                              price_currency_value=currency,
+                              title='Order')
 
-  def stepCheckPackingList(self,sequence=None, sequence_list=None,**kw):
-    """  """
-    packing_list_module = self.getSalePackingListModule()
-    order_rule = sequence.get('order_rule')
-    order = sequence.get('order')
-    sale_packing_list_list = []
-    for o in packing_list_module.objectValues():
-      if o.getCausalityValue() == order:
-        sale_packing_list_list.append(o)
-    self.assertEquals(len(sale_packing_list_list), 1)
-    sale_packing_list = sale_packing_list_list[0]
-    sale_packing_list_line_list = sale_packing_list.objectValues()
-    self.assertEquals(len(sale_packing_list_line_list),1)
-    sale_packing_list_line = sale_packing_list_line_list[0]
-    product = sequence.get('resource')
-    self.assertEquals(sale_packing_list_line.getResourceValue(),
-                      product)
-    self.assertEquals(sale_packing_list_line.getPrice(),
-                      self.price1)
-    LOG('sale_packing_list_line.showDict()',0,
-          sale_packing_list_line.showDict())
-    self.assertEquals(sale_packing_list_line.getQuantity(),
-                      self.quantity1)
-    self.assertEquals(sale_packing_list_line.getTotalPrice(),
-                      self.total_price1)
-    sequence.edit(packing_list = sale_packing_list)
+    order.newContent(portal_type=self.order_line_portal_type,
+                                  quantity=3,
+                                  price=10,
+                                  description='The first line',
+                                  resource_value=resource,)
+    order.newContent(portal_type=self.order_line_portal_type,
+                                  quantity=5,
+                                  price=10,
+                                  description='The second line',
+                                  resource_value=resource2,)
 
-  def stepCheckTwoInvoices(self,sequence=None, sequence_list=None, **kw):
-    """ checks invoice properties are well set. """
-    # Now we will check that we have two invoices created
-    packing_list = sequence.get('packing_list')
-    invoice_list = packing_list.getCausalityRelatedValueList(
-         portal_type=self.invoice_portal_type)
-    self.assertEquals(len(invoice_list),1)
-    invoice = invoice_list[0]
-    self.assertEquals(invoice.getSimulationState(), 'confirmed')
-    sequence.edit(invoice=invoice)
-    new_packing_list = sequence.get('new_packing_list')
-    new_invoice_list = new_packing_list.getCausalityRelatedValueList(
-        portal_type=self.invoice_portal_type)
-    self.assertEquals(len(new_invoice_list),1)
-    new_invoice = new_invoice_list[0]
-    self.assertEquals(new_invoice.getSimulationState(), 'confirmed')
-    sequence.edit(new_invoice=new_invoice)
+    order.confirm()
+    transaction.commit()
+    self.tic()
 
-  def stepStartTwoInvoices(self,sequence=None, sequence_list=None, **kw):
-    """ start both invoices. """
-    portal = self.getPortal()
-    invoice = sequence.get('invoice')
-    new_invoice = sequence.get('new_invoice')
-    portal.portal_workflow.doActionFor(invoice, 'start_action')
-    portal.portal_workflow.doActionFor(new_invoice, 'start_action')
+    related_packing_list = order.getCausalityRelatedValue(
+                                  portal_type=self.packing_list_portal_type)
+    self.assertNotEquals(related_packing_list, None)
+    
+    movement_list = related_packing_list.getMovementList()
+    self.assertEquals(2, len(movement_list))
+    self.assertEquals(['The first line'],
+        [m.getDescription() for m in movement_list if m.getQuantity() == 3])
+    self.assertEquals(['The second line'],
+        [m.getDescription() for m in movement_list if m.getQuantity() == 5])
 
-  def stepCheckTwoInvoicesTransactionLines(self,sequence=None,
-                                           sequence_list=None, **kw):
-    """ checks invoice properties are well set. """
-    invoice = sequence.get('invoice')
-    new_invoice = sequence.get('new_invoice')
-    self.assertEquals(3,len(invoice.objectValues(
-        portal_type=self.invoice_transaction_line_portal_type)))
-    self.assertEquals(3,len(new_invoice.objectValues(
-        portal_type=self.invoice_transaction_line_portal_type)))
-    account_module = self.getAccountModule()
-    found_dict = {}
-    for line in invoice.objectValues(
-        portal_type=self.invoice_transaction_line_portal_type):
-      source_id = line.getSourceId()
-      found_dict[source_id] = line.getQuantity()
-    total_price = (self.default_quantity-1) * self.default_price
-    expected_dict = {
-      'sale' : total_price,
-      'receivable_vat' : total_price * self.vat_rate,
-      'customer' : - (total_price + total_price * self.vat_rate)
-      }
-    self.failIfDifferentSet(expected_dict.keys(),found_dict.keys())
-    for key in found_dict.keys():
-      self.assertAlmostEquals(expected_dict[key],found_dict[key],places=2)
-    found_dict = {}
-    for line in new_invoice.objectValues(
-        portal_type=self.invoice_transaction_line_portal_type):
-      source_id = line.getSourceId()
-      found_dict[source_id] = line.getQuantity()
-    total_price = 1 * self.default_price
-    expected_dict = {
-      'sale' : total_price,
-      'receivable_vat' : total_price * self.vat_rate,
-      'customer' : - (total_price + total_price * self.vat_rate)
-      }
-    self.failIfDifferentSet(expected_dict.keys(), found_dict.keys())
-    for key in found_dict.keys():
-      self.assertAlmostEquals(expected_dict[key], found_dict[key], places=2)
+    related_packing_list.start()
+    related_packing_list.stop()
+    transaction.commit()
+    self.tic()
 
-  def stepRebuildAndCheckNothingIsCreated(self, sequence=None,
-                                           sequence_list=None, **kw):
-    """Rebuilds with sale_invoice_builder and checks nothing more is
-    created. """
-    accounting_module = self.getAccountingModule()
-    portal_type_list = ('Sale Invoice Transaction', 'Purchase Invoice Transaction')
-    sale_invoice_transaction_count = len(accounting_module.objectValues(
-      portal_type=portal_type_list))
-    for builder in self.getPortal().portal_deliveries.objectValues():
-      builder.build()
-    self.assertEquals(sale_invoice_transaction_count,
-                      len(accounting_module.objectValues(
-      portal_type=portal_type_list)))
+    related_invoice = related_packing_list.getCausalityRelatedValue(
+                                  portal_type=self.invoice_portal_type)
+    self.assertNotEquals(related_invoice, None)
 
-  def stepModifyInvoicesDate(self, sequence=None,
-                                           sequence_list=None, **kw):
-    """Change invoice date"""
-    invoice = sequence.get('invoice')
-    new_invoice = sequence.get('new_invoice')
-    invoice.edit(start_date=self.datetime,
-                 stop_date=self.datetime+1)
-    new_invoice.edit(start_date=self.datetime,
-                 stop_date=self.datetime+1)
+    movement_list = related_invoice.getMovementList(
+                              portal_type=self.invoice_line_portal_type)
+    self.assertEquals(2, len(movement_list))
+    self.assertEquals(['The first line'],
+        [m.getDescription() for m in movement_list if m.getQuantity() == 3])
+    self.assertEquals(['The second line'],
+        [m.getDescription() for m in movement_list if m.getQuantity() == 5])
 
-  def stepRemoveDateMovementGroupForTransactionBuilder(self, sequence=None,
-            sequence_list=None, **kw):
+
+  def test_CopyAndPaste(self):
+    """Test copy on paste on Invoice.
+    When an invoice is copy/pasted, references should be resetted.
     """
-    Remove DateMovementGroup
+    accounting_module = self.portal.accounting_module
+    invoice = accounting_module.newContent(
+                    portal_type=self.invoice_portal_type)
+    invoice.edit(reference='reference',
+                 source_reference='source_reference',
+                 destination_reference='destination_reference',)
+    cb_data = accounting_module.manage_copyObjects([invoice.getId()])
+    copied, = accounting_module.manage_pasteObjects(cb_data)
+    new_invoice = accounting_module[copied['new_id']]
+    self.assertNotEquals(invoice.getReference(),
+                         new_invoice.getReference())
+    self.assertNotEquals(invoice.getSourceReference(),
+                         new_invoice.getSourceReference())
+    self.assertNotEquals(invoice.getDestinationReference(),
+                         new_invoice.getDestinationReference())
+
+  def test_delivery_mode_and_incoterm_on_invoice(self):
     """
-    portal = self.getPortal()
-    builder = portal.portal_deliveries.sale_invoice_transaction_builder
-    delivery_movement_group_list = builder.getDeliveryMovementGroupList()
-    uf = self.getPortal().acl_users
-    uf._doAddUser('admin', '', ['Manager'], [])
-    user = uf.getUserById('admin').__of__(uf)
-    newSecurityManager(None, user)
-    for movement_group in delivery_movement_group_list:
-      if movement_group.getPortalType() == 'Property Movement Group':
-        # it contains 'start_date' and 'stop_date' only, so we remove
-        # movement group itself.
-        builder.deleteContent(movement_group.getId())
-    builder.newContent(
-      portal_type = 'Parent Explanation Movement Group',
-      collect_order_group='delivery',
-      int_index=len(delivery_movement_group_list)+1
-      )
-    user = uf.getUserById('test_invoice_user').__of__(uf)
-    newSecurityManager(None, user)
+    test that categories delivery_mode and incoterm are copied on 
+    the invoice by the delivery builder
+    """ 
+    resource = self.portal.product_module.newContent(
+                    portal_type='Product',
+                    title='Resource',
+                    product_line='apparel')
+    currency = self.portal.currency_module.newContent(
+                                portal_type='Currency',
+                                title='euro')
+    currency.setBaseUnitQuantity(0.01)
+    self.createInvoiceTransactionRule(currency)
+    transaction.commit()
+    self.tic()#execute transaction
+    client = self.portal.organisation_module.newContent(
+                            portal_type='Organisation',
+                            title='Client',
+                            default_address_region=self.default_region)
+    vendor = self.portal.organisation_module.newContent(
+                            portal_type='Organisation',
+                            title='Vendor',
+                            default_address_region=self.default_region)
+    order = self.portal.getDefaultModule(self.order_portal_type).newContent(
+                              portal_type=self.order_portal_type,
+                              source_value=vendor,
+                              source_section_value=vendor,
+                              destination_value=client,
+                              destination_section_value=client,
+                              start_date=DateTime(2008,10, 21),
+                              price_currency_value=currency,
+                              delivery_mode=self.mail_delivery_mode,
+                              incoterm=self.cpt_incoterm,
+                              title='Order')
+    order_line = order.newContent(portal_type=self.order_line_portal_type,
+                                  resource_value=resource,
+                                  quantity=5,
+                                  price=2)
+    order.confirm()
+    transaction.commit()
+    self.tic()
+    related_packing_list = order.getCausalityRelatedValue(
+                                portal_type=self.packing_list_portal_type)
+    self.assertNotEquals(related_packing_list, None)
+    self.assertEquals(related_packing_list.getDeliveryMode(),
+                         order.getDeliveryMode())
+    self.assertEquals(related_packing_list.getIncoterm(),
+                         order.getIncoterm())
+    related_packing_list.start()
+    related_packing_list.stop()
+    transaction.commit()
+    self.tic()
+    related_invoice = related_packing_list.getCausalityRelatedValue(
+                                  portal_type=self.invoice_portal_type)
+    self.assertNotEquals(related_invoice, None)
+    self.assertEquals(related_invoice.getDeliveryMode(),
+                         order.getDeliveryMode())
+    self.assertEquals(related_invoice.getIncoterm(),
+                         order.getIncoterm())
+                         
+                         
+  def test_01_quantity_unit_copied(self):
+    """
+    tests that when a resource uses different quantity unit that the
+    quantity units are copied on the packing list line and then the invoice
+    line using the delivery builers
+    """           
+    resource = self.portal.product_module.newContent(
+                    portal_type='Product',
+                    title='Resource',
+                    product_line='apparel')
+    resource.setQuantityUnitList([self.unit_piece_quantity_unit,
+                                 self.mass_quantity_unit])
+    currency = self.portal.currency_module.newContent(
+                                portal_type='Currency',
+                                title='euro')
+    currency.setBaseUnitQuantity(0.01)
+    transaction.commit()
+    self.tic()#execute transaction
+    client = self.portal.organisation_module.newContent(
+                            portal_type='Organisation',
+                            title='Client',
+                            default_address_region=self.default_region)
+    vendor = self.portal.organisation_module.newContent(
+                            portal_type='Organisation',
+                            title='Vendor',
+                            default_address_region=self.default_region)
+    order = self.portal.getDefaultModule(self.order_portal_type).newContent(
+                              portal_type=self.order_portal_type,
+                              source_value=vendor,
+                              source_section_value=vendor,
+                              destination_value=client,
+                              destination_section_value=client,
+                              start_date=DateTime(2008,10, 21),
+                              price_currency_value=currency,
+                              delivery_mode=self.mail_delivery_mode,
+                              incoterm=self.cpt_incoterm,
+                              title='Order')
+    first_order_line = order.newContent(
+                          portal_type=self.order_line_portal_type,
+                                  resource_value=resource,
+                             quantity_unit = self.unit_piece_quantity_unit,
+                                  quantity=5,
+                                  price=3)
+    second_order_line = order.newContent( 
+                          portal_type=self.order_line_portal_type,
+                                  resource_value=resource,
+                             quantity_unit=self.mass_quantity_unit,
+                                  quantity=1.5,
+                                  price=2)
+    self.assertEquals(first_order_line.getQuantityUnit(),
+                      self.unit_piece_quantity_unit)
+    self.assertEquals(second_order_line.getQuantityUnit(),
+                      self.mass_quantity_unit)
 
-  def stepEditInvoice(self, sequence=None, sequence_list=None, **kw):
-    """Edit the current invoice, to trigger updateAppliedRule."""
-    invoice = sequence.get('invoice')
-    invoice.edit()
+    order.confirm()
+    transaction.commit()
+    self.tic()
+    related_packing_list = order.getCausalityRelatedValue(
+                                portal_type=self.packing_list_portal_type)
+    self.assertNotEquals(related_packing_list, None)
+    movement_list = related_packing_list.getMovementList()
+    self.assertEquals(len(movement_list),2)
+    movement_list = sorted(movement_list, key=lambda x: x.getQuantity())
+    self.assertEquals(movement_list[0].getQuantityUnit(),
+                      self.mass_quantity_unit)
+    self.assertEquals(movement_list[0].getQuantity(), 1.5)
+    self.assertEquals(movement_list[1].getQuantityUnit(),
+                      self.unit_piece_quantity_unit)
+    self.assertEquals(movement_list[1].getQuantity(), 5)
 
-    # call updateAppliedRule directly, don't rely on edit interactions
-    rule_reference = 'default_invoice_rule'
-    self.assertNotEquals(0,
-        len(self.portal.portal_rules.searchFolder(reference=rule_reference)))
-    invoice.updateAppliedRule(rule_reference=rule_reference)
+    related_packing_list.start()
+    related_packing_list.stop()
+    related_packing_list.deliver()
+    transaction.commit()
+    self.tic()
+    related_invoice = related_packing_list.getCausalityRelatedValue(
+                                portal_type=self.invoice_portal_type)
+    self.assertNotEquals(related_invoice, None)
+    movement_list = related_invoice.getMovementList()
+    self.assertEquals(len(movement_list),2)
+    movement_list = sorted(movement_list, key=lambda x: x.getQuantity())
+    self.assertEquals(movement_list[0].getQuantityUnit(),
+                      self.mass_quantity_unit)
+    self.assertEquals(movement_list[0].getQuantity(), 1.5)
+    self.assertEquals(movement_list[1].getQuantityUnit(),
+                      self.unit_piece_quantity_unit)
+    self.assertEquals(movement_list[1].getQuantity(), 5)
 
-  def stepCheckInvoiceRuleNotAppliedOnInvoiceEdit(self,
-                    sequence=None, sequence_list=None, **kw):
-    """If we call edit on the invoice, invoice rule should not be
-    applied on lines created by delivery builder."""
-    invoice = sequence.get('invoice')
-    # FIXME: empty applied rule should not be created
-    #self.assertEquals(len(invoice.getCausalityRelatedValueList(
-    #         portal_type=self.applied_rule_portal_type)), 0)
-    for invoice_mvt in invoice.getMovementList():
-      self.assertEquals(len(invoice_mvt.getOrderRelatedValueList(
-            portal_type=self.simulation_movement_portal_type)), 0)
+ 
+
+  def _acceptDivergenceOnInvoice(self, invoice, divergence_list):
+    builder_list = invoice.getBuilderList()
+    self.assertEquals(2, len(builder_list))
+    for builder in builder_list:
+      builder.solveDivergence(invoice.getRelativeUrl(),
+                              divergence_to_accept_list=divergence_list)
+
+  def test_accept_quantity_divergence_on_invoice_with_stopped_packing_list(
+                self, quiet=quiet):
+    sequence_list = SequenceList()
+    sequence = sequence_list.addSequenceString(self.PACKING_LIST_DEFAULT_SEQUENCE)
+    sequence_list.play(self, quiet=quiet)
 
-  def stepEditPackingList(self, sequence=None, sequence_list=None, **kw):
-    """Edit the current packing list, to trigger updateAppliedRule."""
     packing_list = sequence.get('packing_list')
-    packing_list.edit()
+    packing_list_line = packing_list.getMovementList()[0]
+    previous_quantity = packing_list_line.getQuantity()
+    
+    packing_list.setReady()
+    packing_list.start()
+    packing_list.stop()
+    self.assertEquals('stopped', packing_list.getSimulationState())
+    transaction.commit()
+    self.tic()
 
-    # call updateAppliedRule directly, don't rely on edit interactions
-    rule_reference = 'default_delivery_rule'
-    self.assertNotEquals(0,
-        len(self.portal.portal_rules.searchFolder(reference=rule_reference)))
-    packing_list.updateAppliedRule(rule_reference=rule_reference)
+    invoice = packing_list.getCausalityRelatedValue(
+                                  portal_type=self.invoice_portal_type)
+    self.assertNotEquals(invoice, None)
+    invoice_line_list = invoice.getMovementList()
+    self.assertEquals(1, len(invoice_line_list))
+    invoice_line = invoice_line_list[0]
 
-  def stepCheckDeliveryRuleNotAppliedOnPackingListEdit(self,
-                    sequence=None, sequence_list=None, **kw):
-    """If we call edit on the packing list, delivery rule should not be
-    applied on lines created by delivery builder."""
-    packing_list = sequence.get('packing_list')
-    # FIXME: empty applied rule should not be created
-    #self.assertEquals(len(packing_list.getCausalityRelatedValueList(
-    #         portal_type=self.applied_rule_portal_type)), 0)
-    for delivery_mvt in packing_list.getMovementList():
-      self.assertEquals(len(delivery_mvt.getOrderRelatedValueList(
-            portal_type=self.simulation_movement_portal_type)), 0)
+    new_quantity = invoice_line.getQuantity() * 2
+    invoice_line.setQuantity(new_quantity)
+    
+    transaction.commit()
+    self.tic()
 
-  def stepDecreaseInvoiceLineQuantity(self, sequence=None, sequence_list=None,
-      **kw):
-    """
-    Set a decreased quantity on invoice lines
-    """
-    invoice = sequence.get('invoice')
-    quantity = sequence.get('line_quantity',default=self.default_quantity)
-    quantity = quantity - 1
-    sequence.edit(line_quantity=quantity)
-    for invoice_line in invoice.objectValues(
-        portal_type=self.invoice_line_portal_type):
-      invoice_line.edit(quantity=quantity)
-    sequence.edit(last_delta = sequence.get('last_delta', 0.0) - 1.0)
+    self.assertTrue(invoice.isDivergent())
+    divergence_list = invoice.getDivergenceList()
+    self.assertEquals(1, len(divergence_list))
 
-  def stepIncreaseInvoiceLineQuantity(self, sequence=None, sequence_list=None,
-      **kw):
-    """
-    Set a Increased quantity on invoice lines
-    """
-    invoice = sequence.get('invoice')
-    quantity = sequence.get('line_quantity',default=self.default_quantity)
-    quantity = quantity + 1
-    sequence.edit(line_quantity=quantity)
-    for invoice_line in invoice.objectValues(
-        portal_type=self.invoice_line_portal_type):
-      invoice_line.edit(quantity=quantity)
-    sequence.edit(last_delta = sequence.get('last_delta', 0.0) + 1.0)
+    divergence = divergence_list[0]
+    self.assertEquals('quantity', divergence.tested_property)
 
-  def stepSetInvoiceLineQuantityToZero(self, sequence=None, sequence_list=None,
-      **kw):
-    """
-    Set the quantity on invoice lines to zero
-    """
-    invoice = sequence.get('invoice')
-    #default_quantity = sequence.get('line_quantity',default_quantity)
-    quantity = 0.0
-    sequence.edit(line_quantity=quantity)
-    for invoice_line in invoice.objectValues(
-        portal_type=self.invoice_line_portal_type):
-      invoice_line.edit(quantity=quantity)
-    sequence.edit(last_delta = - self.default_quantity)
+    # accept decision
+    self._acceptDivergenceOnInvoice(invoice, divergence_list)
 
-  def stepChangeInvoiceStartDate(self, sequence=None, sequence_list=None, **kw):
-    """
-      Change the start_date of the invoice.
-    """
-    invoice = sequence.get('invoice')
-    invoice.edit(start_date=self.datetime + 15)
+    transaction.commit()
+    self.tic()
+    self.assertEquals('solved', invoice.getCausalityState())
 
-  def stepCheckInvoiceIsCalculating(self, sequence=None, sequence_list=None,
-      **kw):
-    """
-    Test if invoice is calculating
-    """
-    invoice = sequence.get('invoice')
-    self.assertEquals('calculating',invoice.getCausalityState())
+    self.assertEquals([], invoice.getDivergenceList())
+    self.assertEquals(new_quantity, invoice_line.getQuantity())
+    self.assertEquals(new_quantity,
+          invoice_line.getDeliveryRelatedValue(portal_type='Simulation Movement'
+              ).getQuantity())
 
-  def stepCheckInvoiceIsDiverged(self, sequence=None, sequence_list=None,
-      **kw):
-    """
-    Test if invoice is diverged
-    """
-    invoice = sequence.get('invoice')
-    self.assertEquals('diverged',invoice.getCausalityState())
+    self.assertEquals([], packing_list.getDivergenceList())
+    self.assertEquals('solved', packing_list.getCausalityState())
+ 
+  def _adoptDivergenceOnInvoice(self, invoice, divergence_list):
+    builder_list = invoice.getBuilderList()
+    self.assertEquals(2, len(builder_list))
+    for builder in builder_list:
+      builder.solveDivergence(invoice.getRelativeUrl(),
+                              divergence_to_adopt_list=divergence_list)
 
-  def stepCheckInvoiceIsSolved(self, sequence=None, sequence_list=None,
-      **kw):
-    """
-    Test if invoice is solved
-    """
-    invoice = sequence.get('invoice')
-    self.assertEquals('solved', invoice.getCausalityState(),
-                      invoice.getDivergenceList())
+  def test_adopt_quantity_divergence_on_invoice_line_with_stopped_packing_list(
+                self, quiet=quiet):
+    # #1053
+    sequence_list = SequenceList()
+    sequence = sequence_list.addSequenceString(self.PACKING_LIST_DEFAULT_SEQUENCE)
+    sequence_list.play(self, quiet=quiet)
 
-  def stepCheckInvoiceIsDivergent(self, sequence=None, sequence_list=None,
-      **kw):
-    """
-    Test if invoice is divergent
-    """
-    invoice = sequence.get('invoice')
-    self.assertTrue(invoice.isDivergent())
+    packing_list = sequence.get('packing_list')
+    packing_list_line = packing_list.getMovementList()[0]
+    previous_quantity = packing_list_line.getQuantity()
+    previous_resource = packing_list_line.getResource()
+    previous_price = packing_list_line.getPrice()
+    
+    packing_list.setReady()
+    packing_list.start()
+    packing_list.stop()
+    self.assertEquals('stopped', packing_list.getSimulationState())
+    transaction.commit()
+    self.tic()
 
-  def stepCheckInvoiceIsNotDivergent(self, sequence=None, sequence_list=None,
-      **kw):
-    """
-    Test if invoice is not divergent
-    """
-    invoice = sequence.get('invoice')
-    if invoice.isDivergent():
-      self.fail(invoice.getDivergenceList())
+    invoice = packing_list.getCausalityRelatedValue(
+                                  portal_type=self.invoice_portal_type)
+    self.assertNotEquals(invoice, None)
+    invoice_line_list = invoice.getMovementList()
+    self.assertEquals(1, len(invoice_line_list))
+    invoice_line = invoice_line_list[0]
 
-  def stepSplitAndDeferInvoice(self, sequence=None, sequence_list=None,
-      **kw):
-    """
-    split and defer at the invoice level
-    """
-    invoice = sequence.get('invoice')
-    kw = {'listbox':[
-      {'listbox_key':line.getRelativeUrl(),
-       'choice':'SplitAndDefer'} for line in invoice.getMovementList()]}
-    self.portal.portal_workflow.doActionFor(
-      invoice,
-      'split_and_defer_action',
-      start_date=self.datetime + 15,
-      stop_date=self.datetime + 25,
-      **kw)
-    pass
+    new_quantity = invoice_line.getQuantity() * 2
+    invoice_line.setQuantity(new_quantity)
+    
+    transaction.commit()
+    self.tic()
 
-  def stepUnifyStartDateWithDecisionInvoice(self, sequence=None,
-                                            sequence_list=None):
-    invoice = sequence.get('invoice')
-    self._solveDeliveryGroupDivergence(invoice, 'start_date',
-                                       invoice.getRelativeUrl())
+    self.assertTrue(invoice.isDivergent())
+    divergence_list = invoice.getDivergenceList()
+    self.assertEquals(1, len(divergence_list))
 
-  def stepAcceptDecisionQuantityInvoice(self,sequence=None, sequence_list=None):
-    invoice = sequence.get('invoice')
-    self._solveDivergence(invoice, 'quantity', 'accept')
+    divergence = divergence_list[0]
+    self.assertEquals('quantity', divergence.tested_property)
 
-  def stepAcceptDecisionInvoice(self, sequence=None, sequence_list=None,
-      **kw):
-    """
-    accept decision at the invoice level
-    """
-    invoice = sequence.get('invoice')
-    invoice.portal_workflow.doActionFor(invoice,'accept_decision_action')
+    # adopt prevision
+    self._adoptDivergenceOnInvoice(invoice, divergence_list)
 
-  def stepCheckInvoiceSplitted(self, sequence=None, sequence_list=None, **kw):
-    """
-    Test if invoice was splitted
-    """
-    packing_list = sequence.get('packing_list')
-    invoice_list = packing_list.getCausalityRelatedValueList(
-        portal_type=self.invoice_portal_type)
-    self.assertEquals(2,len(invoice_list))
-    invoice1 = None
-    invoice2 = None
-    for invoice in invoice_list:
-      if invoice.getUid() == sequence.get('invoice').getUid():
-        invoice1 = invoice
-      else:
-        invoice2 = invoice
-    sequence.edit(new_invoice=invoice2)
-    for line in invoice1.objectValues(
-          portal_type=self.invoice_line_portal_type):
-      self.assertEquals(self.default_quantity-1,line.getQuantity())
-    for line in invoice2.objectValues(
-          portal_type=self.invoice_line_portal_type):
-      self.assertEquals(1,line.getQuantity())
+    transaction.commit()
+    self.tic()
+    self.assertEquals([], invoice.getDivergenceList())
+    self.assertEquals('solved', invoice.getCausalityState())
 
-  def stepCheckInvoiceNotSplitted(self, sequence=None, sequence_list=None, **kw):
-    """
-    Test if invoice was not splitted
-    """
-    packing_list = sequence.get('packing_list')
-    invoice_list = packing_list.getCausalityRelatedValueList(
-        portal_type=self.invoice_portal_type)
-    self.assertEquals(1,len(invoice_list))
-    invoice1 = None
-    for invoice in invoice_list:
-      if invoice.getUid() == sequence.get('invoice').getUid():
-        invoice1 = invoice
-    last_delta = sequence.get('last_delta', 0.0)
-    for line in invoice1.objectValues(
-        portal_type=self.invoice_line_portal_type):
-      self.assertEquals(self.default_quantity + last_delta,
-          line.getQuantity())
+    self.assertEquals(1,
+        len(invoice.getMovementList(portal_type=self.invoice_line_portal_type)))
+    self.assertEquals(0,
+        len(invoice.getMovementList(portal_type=self.invoice_transaction_line_portal_type)))
 
-  def stepAddInvoiceLines(self, sequence=None, sequence_list=[]):
-    """
-    add some invoice and accounting lines to the invoice
-    """
-    invoice = sequence.get('invoice')
-    invoice.newContent(portal_type='Invoice Line',
-        resource_value=sequence.get('resource'), quantity=3, price=555)
-    invoice.newContent(portal_type='Sale Invoice Transaction Line',
-        id ='receivable', source='account_module/customer',
-        destination='account_module/supplier', quantity=-1665)
-    invoice.newContent(portal_type='Sale Invoice Transaction Line',
-        id='income', source='account_module/sale',
-        destination='account_module/purchase', quantity=1665)
+    self.assertEquals(previous_resource, invoice_line.getResource())
+    self.assertEquals(previous_quantity, invoice_line.getQuantity())
+    self.assertEquals(previous_price, invoice_line.getPrice())
+    self.assertEquals(previous_quantity,
+          invoice_line.getDeliveryRelatedValue(portal_type='Simulation Movement'
+              ).getQuantity())
 
-  def stepAddWrongInvoiceLines(self, sequence=None, sequence_list=[]):
-    """
-    add some wrong invoice and accounting lines to the invoice
-    """
-    invoice = sequence.get('invoice')
-    invoice.newContent(portal_type='Sale Invoice Transaction Line',
-        id='bad_movement', source='account_module/sale',
-        destination='account_module/purchase', quantity=2, price=4)
-    invoice.newContent(portal_type='Sale Invoice Transaction Line',
-        id='counter_bad_movement', source='account_module/sale',
-        destination='account_module/purchase', quantity=-2, price=4)
-    for movement in invoice.getMovementList():
-      movement.edit(resource_value=sequence.get('resource'))
+    self.assertEquals([], packing_list.getDivergenceList())
+    self.assertEquals('solved', packing_list.getCausalityState())
+ 
 
-  def stepCheckStartInvoiceFail(self, sequence=None, sequence_list=[]):
-    """
-    checks that it's not possible to start an invoice with really wrong
-    lines
-    """
-    try:
-      self.tic()
-    except RuntimeError, exc:
-      invoice = sequence.get('invoice')
-      it_builder = self.portal.portal_deliveries.sale_invoice_transaction_builder
-      # check which activities are failing
-      self.assertTrue(str(exc).startswith('tic is looping forever.'),
-          '%s does not start with "tic is looping forever."' % str(exc))
-      msg_list = ['/'.join(x.object_path) for x in
-          self.getActivityTool().getMessageList()]
-      self.assertTrue(it_builder.getPath() in msg_list, '%s in %s' %
-          (it_builder.getPath(), msg_list))
-      # flush failing activities
-      activity_tool = self.getActivityTool()
-      activity_tool.manageClearActivities(keep=0)
-    else:
-      self.fail("Error: stepStartInvoice didn't fail, the builder script"
-          + " InvoiceTransaction_postTransactionLineGeneration should have"
-          + " complained that accounting movements use multiple resources")
 
-  def stepCheckSimulationTrees(self, sequence=None, sequence_list=[]):
-    """
-    check that rules are created in the order we expect them
-    """
-    applied_rule_set = set()
-    invoice = sequence.get('invoice')
-    for movement in invoice.getMovementList():
-      for sm in movement.getDeliveryRelatedValueList():
-        applied_rule_set.add(sm.getRootAppliedRule())
+class TestSaleInvoiceMixin(TestInvoiceMixin,
+                           ERP5TypeTestCase):
+  """Test sale invoice are created from orders then packing lists.
 
-    rule_dict = {
-        'Order Rule': {
-          'movement_type_list': ['Sale Order Line', 'Sale Order Cell'],
-          'next_rule_list': ['Delivering Rule', ],
-          },
-        'Delivering Rule': {
-          'movement_type_list': ['Sale Packing List Line', 'Sale Packing List Cell'],
-          'next_rule_list': ['Invoicing Rule', ],
-          },
-        'Invoicing Rule': {
-          'movement_type_list': invoice.getPortalInvoiceMovementTypeList(),
-          'next_rule_list': ['Invoice Transaction Rule', 'Trade Model Rule'],
-          },
-        'Trade Model Rule': {
-          'next_rule_list': ['Invoice Transaction Rule'],
-          },
-        'Invoice Rule': {
-          'movement_type_list': invoice.getPortalInvoiceMovementTypeList() \
-              + invoice.getPortalAccountingMovementTypeList(),
-          'next_rule_list': ['Invoice Transaction Rule', 'Payment Rule',
-            'Trade Model Rule'],
-          },
-        'Invoice Transaction Rule': {
-          'parent_movement_type_list': invoice.getPortalInvoiceMovementTypeList(),
-          'movement_type_list': invoice.getPortalAccountingMovementTypeList(),
-          'next_rule_list': ['Payment Rule'],
-          },
-        'Payment Rule': {
-          'parent_movement_type_list': invoice.getPortalAccountingMovementTypeList(),
-          'next_rule_list': [],
-          },
-        }
+    Those tests methods only work for sale, because sale and purchase invoice
+    are not built at the same time on packing list workflow.
+  """
+  quiet = 0
+  invoice_portal_type = 'Sale Invoice Transaction'
+  invoice_line_portal_type = 'Invoice Line'
+  invoice_cell_portal_type = 'Invoice Cell'
+  invoice_transaction_line_portal_type = 'Sale Invoice Transaction Line'
+  payment_portal_type = 'Payment Transaction'
 
-    def checkTree(rule):
-      """
-      checks the tree recursively
-      """
-      rule_type = rule.getSpecialiseValue().getPortalType()
-      rule_def = rule_dict.get(rule_type, {})
-      for k, v in rule_def.iteritems():
-        if k == 'movement_type_list':
-          for movement in rule.objectValues():
-            if movement.getDeliveryValue() is not None:
-              self.assertTrue(movement.getDeliveryValue().getPortalType() in v,
-                  'looking for %s in %s on %s' % (
-                  movement.getDeliveryValue().getPortalType(), v,
-                  movement.getPath()))
-        elif k == 'next_rule_list':
-          for movement in rule.objectValues():
-            found_rule_dict = {}
-            for next_rule in movement.objectValues():
-              next_rule_type = next_rule.getSpecialiseValue().getPortalType()
-              self.assertTrue(next_rule_type in v,
-                  'looking for %s in %s on %s' % (
-                  next_rule_type, v, next_rule.getPath()))
-              n = found_rule_dict.get(next_rule_type, 0)
-              found_rule_dict[next_rule_type] = n + 1
-            # for each movement, we want to make sure that each rule is not
-            # instanciated more than once
-            if len(found_rule_dict):
-              self.assertEquals(set(found_rule_dict.itervalues()), set([1]))
-        elif k == 'parent_movement_type_list':
-          if rule.getParentValue().getDeliveryValue() is not None:
-            parent_type = rule.getParentValue().getDeliveryValue().getPortalType()
-            self.assertTrue(parent_type in v, 'looking for %s in %s on %s' % (
-                parent_type, v, rule.getParentValue().getPath()))
-        elif k == 'parent_id_list':
-          self.assertTrue(rule.getParentId() in v, 'looking for %s in %s on %s'
-              % (rule.getParentId(), v, rule.getPath()))
-      for movement in rule.objectValues():
-        for next_rule in movement.objectValues():
-          checkTree(next_rule)
+  # default sequence for one line of not varianted resource.
+  PACKING_LIST_DEFAULT_SEQUENCE = """
+      stepCreateEntities
+      stepCreateCurrency
+      stepCreateSaleInvoiceTransactionRule
+      stepCreateOrder
+      stepSetOrderProfile
+      stepSetOrderPriceCurrency
+      stepCreateNotVariatedResource
+      stepTic
+      stepCreateOrderLine
+      stepSetOrderLineResource
+      stepSetOrderLineDefaultValues
+      stepOrderOrder
+      stepTic
+      stepCheckDeliveryBuilding
+      stepConfirmOrder
+      stepTic
+      stepCheckOrderRule
+      stepCheckOrderSimulation
+      stepCheckDeliveryBuilding
+      stepAddPackingListContainer
+      stepAddPackingListContainerLine
+      stepSetContainerLineFullQuantity
+      stepTic
+      stepCheckPackingListIsPacked
+    """
 
-    for applied_rule in applied_rule_set:
-      checkTree(applied_rule)
+  # default sequence for two lines of not varianted resource.
+  PACKING_LIST_TWO_LINES_DEFAULT_SEQUENCE = """
+      stepCreateEntities
+      stepCreateCurrency
+      stepCreateSaleInvoiceTransactionRule
+      stepCreateOrder
+      stepSetOrderProfile
+      stepSetOrderPriceCurrency
+      stepCreateNotVariatedResource
+      stepTic
+      stepCreateOrderLine
+      stepSetOrderLineResource
+      stepSetOrderLineDefaultValues
+      stepCreateNotVariatedResource
+      stepTic
+      stepCreateOrderLine
+      stepSetOrderLineResource
+      stepSetOrderLineDefaultValues
+      stepOrderOrder
+      stepTic
+      stepCheckDeliveryBuilding
+      stepConfirmOrder
+      stepTic
+      stepCheckOrderRule
+      stepCheckOrderSimulation
+      stepCheckDeliveryBuilding
+      stepAddPackingListContainer
+      stepAddPackingListContainerLine
+      stepTic
+      stepSetContainerFullQuantity
+      stepTic
+      stepCheckPackingListIsPacked
+    """
 
+  # default sequence for one line of not varianted resource.
+  TWO_PACKING_LIST_DEFAULT_SEQUENCE = """
+      stepCreateEntities
+      stepCreateCurrency
+      stepCreateSaleInvoiceTransactionRule
+      stepCreateOrder
+      stepSetOrderProfile
+      stepSetOrderPriceCurrency
+      stepCreateNotVariatedResource
+      stepTic
+      stepCreateOrderLine
+      stepSetOrderLineResource
+      stepSetOrderLineDefaultValues
+      stepOrderOrder
+      stepTic
+      stepCheckDeliveryBuilding
+      stepConfirmOrder
+      stepTic
+      stepCheckOrderRule
+      stepCheckOrderSimulation
+      stepCheckDeliveryBuilding
+      stepDecreasePackingListLineQuantity
+      stepCheckPackingListIsCalculating
+      stepTic
+      stepCheckPackingListIsDiverged
+      stepSplitAndDeferPackingList
+      stepTic
+      stepCheckPackingListIsSolved
+      stepCheckPackingListSplitted
+      stepAddPackingListContainer
+      stepAddPackingListContainerLine
+      stepSetContainerLineFullQuantity
+      stepTic
+      stepCheckPackingListIsPacked
+      stepDefineNewPackingListContainer
+      stepTic
+      stepCheckNewPackingListIsPacked
+    """
 
 class TestSaleInvoice(TestSaleInvoiceMixin, TestInvoice, ERP5TypeTestCase):
   """Tests for sale invoice.
@@ -3012,25 +3027,6 @@ class TestSaleInvoice(TestSaleInvoiceMixin, TestInvoice, ERP5TypeTestCase):
       sequence_list.addSequenceString(sequence)
     sequence_list.play(self, quiet=quiet)
 
-  def stepAddInvoiceLinesManyTransactions(self, sequence=None, sequence_list=[]):
-    """
-    add some invoice and accounting lines to the invoice
-    """
-    invoice = sequence.get('invoice')
-    invoice_line = invoice.newContent(portal_type='Invoice Line')
-    transaction_line_1 = invoice.newContent(portal_type='Sale Invoice Transaction Line')
-    transaction_line_2 = invoice.newContent(portal_type='Sale Invoice Transaction Line')
-    transaction.commit()
-    self.tic()
-    invoice_line.edit(resource_value=sequence.get('resource'), quantity=3,
-        price=555)
-    transaction_line_1.edit(id ='receivable', source='account_module/customer',
-        destination='account_module/supplier', quantity=-1665)
-    transaction_line_2.edit(
-        id='income', source='account_module/sale',
-        destination='account_module/purchase', quantity=1665)
-
-
   def test_16a_ManuallyAddedMovementsManyTransactions(self, quiet=quiet):
     """
     Checks that adding invoice lines and accounting lines to one invoice