diff --git a/product/ERP5/tests/testBPMCore.py b/product/ERP5/tests/testBPMCore.py
index 1fc6311aa62f2a86187d55e846e05004c642c387..23fa1a0e53cb77020d555e0e032806c24356e169 100644
--- a/product/ERP5/tests/testBPMCore.py
+++ b/product/ERP5/tests/testBPMCore.py
@@ -3,6 +3,7 @@
 # Copyright (c) 2009 Nexedi SA and Contributors. All Rights Reserved.
 #          艁ukasz Nowak <luke@nexedi.com>
 #          Yusuke Muraoka <yusuke@nexedi.com>
+#          Fabien Morin <fabien@nexedi.com>
 #
 # WARNING: This program as such is intended to be used by professional
 # programmers who take the whole responsibility of assessing all potential
@@ -33,45 +34,20 @@ import transaction
 from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
 from DateTime import DateTime
 
-from Products.ERP5Type.tests.Sequence import SequenceList
 from Products.CMFCore.utils import getToolByName
 from Products.ERP5Type.tests.utils import reindex
 
-# XXX TODO:
-#  * move test.* methods to other classes, group by testing area
-#  * subclass TestBPMMixin from TestInvoiceMixin and refactor methods and
-#    style
-
 class TestBPMMixin(ERP5TypeTestCase):
-  """Skeletons for tests for ERP5 BPM"""
+  """Skeletons for tests which depend on BPM"""
 
   def getBusinessTemplateList(self):
     return ('erp5_base', 'erp5_pdm', 'erp5_trade', 'erp5_accounting',
       'erp5_invoicing', 'erp5_simplified_invoicing')
 
-  default_discount_ratio = -0.05 # -5%
-  default_tax_ratio = 0.196 # 19,6%
-
-  new_discount_ratio = -0.04 # -4%
-  new_tax_ratio = 0.22 # 22%
-
-  node_portal_type = 'Organisation'
-  order_date = DateTime()
-  default_business_process = \
-      'business_process_module/erp5_default_business_process'
-
   business_process_portal_type = 'Business Process'
   business_path_portal_type = 'Business Path'
   business_state_portal_type = 'Business State'
 
-  modified_order_line_price_ratio = 2.0
-  modified_invoice_line_quantity_ratio = modified_order_line_quantity_ratio \
-      = 2.5
-
-  modified_packing_list_line_quantity_ratio = 0.5
-
-  base_unit_quantity = 0.01
-
   normal_resource_use_category_list = ['normal']
   invoicing_resource_use_category_list = ['discount', 'tax']
 
@@ -102,9 +78,6 @@ class TestBPMMixin(ERP5TypeTestCase):
         portal_type=self.business_process_portal_type)
     return module.newContent(portal_type=self.business_process_portal_type)
 
-  def stepCreateBusinessProcess(self, sequence=None, **kw):
-    sequence.edit(business_process=self.createBusinessProcess())
-
   @reindex
   def createBusinessPath(self, business_process=None):
     if business_process is None:
@@ -114,59 +87,6 @@ class TestBPMMixin(ERP5TypeTestCase):
       portal_type=self.business_path_portal_type)
     return business_path
 
-  def stepCreateBusinessPath(self, sequence=None, **kw):
-    business_process = sequence.get('business_process')
-    sequence.edit(business_path=self.createBusinessPath(business_process))
-
-  def stepModifyBusinessPathTaxing(self, sequence=None, **kw):
-    predecessor = sequence.get('business_state_invoiced')
-    successor = sequence.get('business_state_taxed')
-    business_path = sequence.get('business_path')
-    self.assertNotEqual(None, predecessor)
-    self.assertNotEqual(None, successor)
-
-    business_path.edit(
-      predecessor_value = predecessor,
-      successor_value = successor,
-      trade_phase = 'default/tax'
-    )
-    sequence.edit(business_path=None, business_path_taxing=business_path)
-
-  def _solveDivergence(self, obj, property, decision, group='line'):
-    kw = {'%s_group_listbox' % group:{}}
-    for divergence in obj.getDivergenceList():
-      if divergence.getProperty('tested_property') != property:
-        continue
-      sm_url = divergence.getProperty('simulation_movement').getRelativeUrl()
-      kw['line_group_listbox']['%s&%s' % (sm_url, property)] = {
-        'choice':decision}
-    self.portal.portal_workflow.doActionFor(
-      obj,
-      'solve_divergence_action',
-      **kw)
-
-  def stepAcceptDecisionQuantityInvoice(self, sequence=None, **kw):
-    invoice = sequence.get('invoice')
-    self._solveDivergence(invoice, 'quantity', 'accept')
-
-  def stepAdoptPrevisionQuantityInvoice(self, sequence=None, **kw):
-    invoice = sequence.get('invoice')
-    self._solveDivergence(invoice, 'quantity', 'adopt')
-
-  def stepModifyBusinessPathDiscounting(self, sequence=None, **kw):
-    predecessor = sequence.get('business_state_invoiced')
-    successor = sequence.get('business_state_taxed')
-    business_path = sequence.get('business_path')
-    self.assertNotEqual(None, predecessor)
-    self.assertNotEqual(None, successor)
-
-    business_path.edit(
-      predecessor_value = predecessor,
-      successor_value = successor,
-      trade_phase = 'default/discount'
-    )
-    sequence.edit(business_path=None, business_path_discounting=business_path)
-
   @reindex
   def createBusinessState(self, business_process=None):
     if business_process is None:
@@ -176,21 +96,6 @@ class TestBPMMixin(ERP5TypeTestCase):
         portal_type=self.business_state_portal_type)
     return business_path
 
-  def stepCreateBusinessState(self, sequence=None, **kw):
-    business_process = sequence.get('business_process')
-    sequence.edit(business_state=self.createBusinessState(business_process))
-
-  def stepModifyBusinessStateTaxed(self, sequence=None, **kw):
-    business_state = sequence.get('business_state')
-    business_state.edit(reference='taxed')
-    sequence.edit( business_state=None, business_state_taxed=business_state)
-
-  def stepModifyBusinessStateInvoiced(self, sequence=None,
-                sequence_string=None):
-    business_state = sequence.get('business_state')
-    business_state.edit(reference='invoiced')
-    sequence.edit(business_state=None, business_state_invoiced=business_state)
-
   def createMovement(self):
     # returns a movement for testing
     applied_rule = self.portal.portal_simulation.newContent(
@@ -330,2098 +235,6 @@ class TestBPMMixin(ERP5TypeTestCase):
     self.portal.portal_rules.manage_delObjects(
         ids=['test_invoice_transaction_rule'])
 
-  def stepCreateSource(self, sequence=None, **kw):
-    module = self.portal.getDefaultModule(portal_type=self.node_portal_type)
-    node = module.newContent(portal_type=self.node_portal_type)
-    sequence.edit(source = node)
-
-  def stepCreateSourceSection(self, sequence=None, **kw):
-    module = self.portal.getDefaultModule(portal_type=self.node_portal_type)
-    node = module.newContent(portal_type=self.node_portal_type)
-    sequence.edit(source_section = node)
-
-  def stepCreateDestination(self, sequence=None, **kw):
-    module = self.portal.getDefaultModule(portal_type=self.node_portal_type)
-    node = module.newContent(portal_type=self.node_portal_type)
-    sequence.edit(destination = node)
-
-  def stepCreateDestinationSection(self, sequence=None, **kw):
-    module = self.portal.getDefaultModule(portal_type=self.node_portal_type)
-    node = module.newContent(portal_type=self.node_portal_type)
-    sequence.edit(destination_section = node)
-
-  def createOrder(self):
-    module = self.portal.getDefaultModule(portal_type=self.order_portal_type)
-    return module.newContent(portal_type=self.order_portal_type,
-        title=self.id())
-
-  def stepCreateOrder(self, sequence=None, **kw):
-    sequence.edit(order = self.createOrder())
-
-  def stepSpecialiseOrderTradeCondition(self, sequence=None, **kw):
-    order = sequence.get('order')
-    trade_condition = sequence.get('trade_condition')
-
-    order.edit(specialise_value = trade_condition)
-
-  def stepSpecialiseInvoiceTradeCondition(self, sequence=None, **kw):
-    invoice = sequence.get('invoice')
-    trade_condition = sequence.get('trade_condition')
-
-    invoice.edit(specialise_value = trade_condition)
-
-  def stepPlanOrder(self, sequence=None, **kw):
-    order = sequence.get('order')
-    workflow_tool = getToolByName(self.portal, 'portal_workflow')
-    workflow_tool.doActionFor(order, 'plan_action')
-
-  def stepStartInvoice(self, sequence=None, **kw):
-    invoice = sequence.get('invoice')
-    workflow_tool = getToolByName(self.portal, 'portal_workflow')
-    workflow_tool.doActionFor(invoice, 'start_action')
-
-  def stepStopInvoice(self, sequence=None, **kw):
-    invoice = sequence.get('invoice')
-    workflow_tool = getToolByName(self.portal, 'portal_workflow')
-    workflow_tool.doActionFor(invoice, 'stop_action')
-
-  def stepDeliverInvoice(self, sequence=None, **kw):
-    invoice = sequence.get('invoice')
-    workflow_tool = getToolByName(self.portal, 'portal_workflow')
-    workflow_tool.doActionFor(invoice, 'deliver_action')
-
-  def stepStartPackingList(self, sequence=None, **kw):
-    packing_list = sequence.get('packing_list')
-    workflow_tool = getToolByName(self.portal, 'portal_workflow')
-    workflow_tool.doActionFor(packing_list, 'start_action')
-
-  def stepStopPackingList(self, sequence=None, **kw):
-    packing_list = sequence.get('packing_list')
-    workflow_tool = getToolByName(self.portal, 'portal_workflow')
-    workflow_tool.doActionFor(packing_list, 'stop_action')
-
-  def stepDeliverPackingList(self, sequence=None, **kw):
-    packing_list = sequence.get('packing_list')
-    workflow_tool = getToolByName(self.portal, 'portal_workflow')
-    workflow_tool.doActionFor(packing_list, 'deliver_action')
-
-  def stepCheckPackingListDiverged(self, sequence=None, **kw):
-    packing_list = sequence.get('packing_list')
-    self.assertEqual(
-      'diverged',
-      packing_list.getCausalityState()
-    )
-
-  def stepSplitAndDeferPackingList(self, sequence=None, **kw):
-    packing_list = sequence.get('packing_list')
-    kw = {'listbox':[
-      {'listbox_key':line.getRelativeUrl(),
-       'choice':'SplitAndDefer'} for line in packing_list.getMovementList() \
-      if line.isDivergent()]}
-    self.portal.portal_workflow.doActionFor(
-      packing_list,
-      'split_and_defer_action',
-      start_date=packing_list.getStartDate() + 15,
-      stop_date=packing_list.getStopDate() + 25,
-      **kw)
-
-  def stepDecreasePackingListLineListQuantity(self, sequence=None, **kw):
-    packing_list = sequence.get('packing_list')
-    for movement in packing_list.getMovementList():
-      movement.edit(
-        quantity = movement.getQuantity() * \
-            self.modified_packing_list_line_quantity_ratio
-      )
-
-  def stepPackPackingList(self, sequence=None, **kw):
-    packing_list = sequence.get('packing_list')
-    if getattr(packing_list,'getContainerState', None) is None:
-      return
-    if packing_list.getContainerState() == 'packed':
-      return
-
-    packing_list.manage_delObjects(ids=[q.getId() for q in
-      packing_list.objectValues(portal_type='Container')])
-    transaction.commit()
-    cntr = packing_list.newContent(portal_type='Container')
-    for movement in packing_list.getMovementList(
-        portal_type=self.portal.getPortalMovementTypeList()):
-      cntr.newContent(
-        portal_type='Container Line',
-        resource = movement.getResource(),
-        quantity = movement.getQuantity())
-    transaction.commit()
-    self.tic()
-    self.assertEqual('packed', packing_list.getContainerState() )
-
-  def stepCheckInvoiceNormalMovements(self, sequence=None, **kw):
-    self.logMessage('Assuming, that it is good...')
-
-  def stepCheckInvoiceAccountingMovements(self, sequence=None, **kw):
-    invoice = sequence.get('invoice')
-    currency = sequence.get('price_currency')
-    currency_precision = currency.getQuantityPrecision()
-    aggregated_amount_list_list = [
-      (q.getResourceValue().getUse(), q)
-      for q in invoice.getSpecialiseValue().getAggregatedAmountList(invoice)]
-    invoice_line_tax = [q[1] for q in aggregated_amount_list_list
-        if q[0] == 'tax'][0]
-    invoice_line_discount = [q[1] for q in aggregated_amount_list_list
-        if q[0] == 'discount'][0]
-
-    movement_list = invoice.getMovementList(
-        portal_type=invoice.getPortalAccountingMovementTypeList())
-    self.assertEqual(3, len(movement_list))
-    income_expense_line = [q for q in movement_list if
-        q.getSourceValue().getAccountType() in ['income', 'expense']][0]
-    payable_receivable_line = [q for q in movement_list if
-        q.getSourceValue().getAccountType() in ['asset/receivable',
-          'liability/payable']][0]
-    vat_line = [q for q in movement_list if q.getSourceValue() \
-        .getAccountType() in ['liability/payable/collected_vat',
-          'asset/receivable/refundable_vat']][0]
-
-    rounded_total_price = round(invoice.getTotalPrice(), currency_precision)
-    rounded_tax_price = round(invoice_line_tax.getTotalPrice(),
-        currency_precision)
-    rounded_discount_price = round(invoice_line_discount.getTotalPrice(),
-        currency_precision)
-
-    self.assertEqual(abs(payable_receivable_line.getTotalPrice()),
-        rounded_total_price + rounded_tax_price + rounded_discount_price)
-
-    self.assertEqual(abs(vat_line.getTotalPrice()),
-        rounded_tax_price)
-
-    self.assertEquals(abs(income_expense_line.getTotalPrice()),
-        rounded_total_price + rounded_discount_price)
-
-  def stepSetTradeConditionOld(self, sequence=None, **kw):
-    trade_condition = sequence.get('trade_condition')
-
-    self.assertNotEqual(None, trade_condition)
-
-    sequence.edit(
-      trade_condition = None,
-      old_trade_condition = trade_condition
-    )
-
-  def stepSetTradeConditionNew(self, sequence=None, **kw):
-    trade_condition = sequence.get('trade_condition')
-
-    self.assertNotEqual(None, trade_condition)
-
-    sequence.edit(
-      trade_condition = None,
-      new_trade_condition = trade_condition
-    )
-
-  def stepGetOldTradeCondition(self, sequence=None, **kw):
-    trade_condition = sequence.get('old_trade_condition')
-
-    self.assertNotEqual(None, trade_condition)
-
-    sequence.edit(
-      trade_condition = trade_condition,
-    )
-
-  def stepGetNewTradeCondition(self, sequence=None, **kw):
-    trade_condition = sequence.get('new_trade_condition')
-
-    self.assertNotEqual(None, trade_condition)
-
-    sequence.edit(
-      trade_condition = trade_condition,
-    )
-
-  def stepAcceptDecisionInvoice(self, sequence=None, **kw):
-    invoice = sequence.get('invoice')
-    invoice.portal_workflow.doActionFor(invoice,'accept_decision_action')
-
-  def stepCheckInvoiceCausalityStateSolved(self, sequence=None, **kw):
-    invoice = sequence.get('invoice')
-    self.assertEqual('solved', invoice.getCausalityState(),
-      invoice.getDivergenceList())
-
-  def stepCheckInvoiceCausalityStateDiverged(self, sequence=None, **kw):
-    invoice = sequence.get('invoice')
-    self.assertEqual('diverged', invoice.getCausalityState())
-
-  def stepGetInvoice(self, sequence=None, **kw):
-    packing_list = sequence.get('packing_list')
-    invoice_list = packing_list.getCausalityRelatedValueList(
-        portal_type=self.invoice_portal_type)
-    self.assertEqual(1, len(invoice_list)) # XXX 1 HC
-    sequence.edit(invoice = invoice_list[0])
-
-  def stepSetNewPackingListAsPackingList(self, sequence=None, **kw):
-    packing_list = sequence.get('packing_list')
-    new_packing_list = sequence.get('new_packing_list')
-    sequence.edit(
-      packing_list = new_packing_list,
-      new_packing_list = None
-    )
-
-  def stepGetNewPackingList(self, sequence=None, **kw):
-    order = sequence.get('order')
-    packing_list = sequence.get('packing_list')
-    packing_list_list = order.getCausalityRelatedValueList(
-        portal_type=self.packing_list_portal_type)
-    self.assertEqual(2, len(packing_list_list)) # XXX 2 HC
-    new_packing_list = [q for q in packing_list_list if q != packing_list][0]
-    sequence.edit(new_packing_list = new_packing_list)
-
-  def stepGetPackingList(self, sequence=None, **kw):
-    order = sequence.get('order')
-    packing_list_list = order.getCausalityRelatedValueList(
-        portal_type=self.packing_list_portal_type)
-    self.assertEqual(1, len(packing_list_list)) # XXX 1 HC
-    sequence.edit(packing_list = packing_list_list[0])
-
-  def stepConfirmOrder(self, sequence=None, **kw):
-    order = sequence.get('order')
-    workflow_tool = getToolByName(self.portal, 'portal_workflow')
-    workflow_tool.doActionFor(order, 'confirm_action')
-
-  def getTradeModelSimulationMovementList(self, order_line):
-    result_list = []
-    for line_simulation_movement in order_line.getOrderRelatedValueList(
-        portal_type='Simulation Movement'):
-      invoicing_applied_rule = [x for x in
-          line_simulation_movement.objectValues()
-          if x.getSpecialiseValue().getPortalType() == 'Invoicing Rule'][0]
-      invoicing_movement = invoicing_applied_rule.objectValues()[0]
-      trade_model_rule = [x for x in invoicing_movement.objectValues()
-          if x.getSpecialiseValue().getPortalType() == 'Trade Model Rule'][0]
-      result_list.append(trade_model_rule.objectValues())
-    return result_list
-
-  def stepCheckOrderTaxNoSimulation(self, sequence=None, **kw):
-    order_line_taxed = sequence.get('order_line_taxed')
-    for trade_model_simulation_movement_list in \
-        self.getTradeModelSimulationMovementList(order_line_taxed):
-      self.assertEquals(0, len(trade_model_simulation_movement_list))
-
-  # XXX: Merge: stepCheckOrderLineDiscountedSimulation stepCheckOrderLineTaxedSimulation stepCheckOrderLineDiscountedTaxedSimulation
-
-  def stepCheckOrderLineDiscountedTaxedSimulation(self, sequence=None, **kw):
-    order_line = sequence.get('order_line_discounted_taxed')
-    business_path_discounting = sequence.get('business_path_discounting')
-    business_path_taxing = sequence.get('business_path_taxing')
-    price_currency = sequence.get('price_currency')
-
-    service_tax = sequence.get('service_tax')
-    service_discount = sequence.get('service_discount')
-
-    self.assertNotEqual(None, business_path_discounting)
-    self.assertNotEqual(None, business_path_taxing)
-    self.assertNotEqual(None, price_currency)
-
-    for trade_model_simulation_movement_list in \
-        self.getTradeModelSimulationMovementList(order_line):
-
-      self.assertEquals(2, len(trade_model_simulation_movement_list))
-      trade_model_simulation_movement_discount_complex = [q for q in \
-          trade_model_simulation_movement_list \
-          if q.getResourceValue() == service_discount][0]
-
-      trade_model_simulation_movement_tax_complex = [q for q in \
-          trade_model_simulation_movement_list \
-          if q.getResourceValue() == service_tax][0]
-
-      # discount complex
-      self.assertEqual(
-        trade_model_simulation_movement_discount_complex.getParentValue() \
-            .getParentValue().getTotalPrice() * self.default_discount_ratio,
-        trade_model_simulation_movement_discount_complex.getTotalPrice()
-      )
-
-      self.assertEqual(
-        business_path_discounting,
-        trade_model_simulation_movement_discount_complex.getCausalityValue()
-      )
-
-      self.assertEqual(
-        price_currency,
-        trade_model_simulation_movement_discount_complex \
-            .getPriceCurrencyValue()
-      )
-
-      self.assertSameSet(
-        ['base_amount/tax'],
-        trade_model_simulation_movement_discount_complex \
-            .getBaseContributionList()
-      )
-
-      self.assertSameSet(
-        ['base_amount/discount'],
-        trade_model_simulation_movement_discount_complex \
-            .getBaseApplicationList()
-      )
-
-      self.checkInvoiceTransactionRule(
-          trade_model_simulation_movement_discount_complex)
-
-      # TODO:
-      #  * trade_phase ???
-      #  * arrow
-      #  * dates
-
-      # tax complex
-      self.assertEqual(
-        (trade_model_simulation_movement_tax_complex.getParentValue()\
-            .getParentValue().getTotalPrice() + \
-            trade_model_simulation_movement_tax_complex.getParentValue()\
-            .getParentValue().getTotalPrice() * self.default_discount_ratio) \
-            * self.default_tax_ratio,
-        trade_model_simulation_movement_tax_complex.getTotalPrice()
-      )
-
-      self.assertEqual(
-        business_path_taxing,
-        trade_model_simulation_movement_tax_complex.getCausalityValue()
-      )
-
-      self.assertEqual(
-        price_currency,
-        trade_model_simulation_movement_tax_complex.getPriceCurrencyValue()
-      )
-
-      self.assertSameSet(
-        [],
-        trade_model_simulation_movement_tax_complex.getBaseContributionList()
-      )
-
-      self.assertSameSet(
-        ['base_amount/tax'],
-        trade_model_simulation_movement_tax_complex.getBaseApplicationList()
-      )
-
-      self.checkInvoiceTransactionRule(
-        trade_model_simulation_movement_tax_complex)
-      # TODO:
-      #  * trade_phase ???
-      #  * arrow
-      #  * dates
-
-  def stepCheckOrderLineDiscountedSimulation(self, sequence=None, **kw):
-    order_line = sequence.get('order_line_discounted')
-    business_path_discounting = sequence.get('business_path_discounting')
-    business_path_taxing = sequence.get('business_path_taxing')
-    price_currency = sequence.get('price_currency')
-
-    service_tax = sequence.get('service_tax')
-    service_discount = sequence.get('service_discount')
-
-    self.assertNotEqual(None, business_path_discounting)
-    self.assertNotEqual(None, business_path_taxing)
-    self.assertNotEqual(None, price_currency)
-
-    for trade_model_simulation_movement_list in \
-        self.getTradeModelSimulationMovementList(order_line):
-
-      self.assertEquals(2, len(trade_model_simulation_movement_list))
-      trade_model_simulation_movement_discount_only = [q for q in \
-          trade_model_simulation_movement_list \
-          if q.getResourceValue() == service_discount][0]
-
-      trade_model_simulation_movement_tax_only = [q for q in \
-          trade_model_simulation_movement_list \
-          if q.getResourceValue() == service_tax][0]
-
-      # discount only
-      self.assertEqual(
-        trade_model_simulation_movement_discount_only.getParentValue()\
-            .getParentValue().getTotalPrice() * self.default_discount_ratio,
-        trade_model_simulation_movement_discount_only.getTotalPrice()
-      )
-
-      self.assertEqual(
-        business_path_discounting,
-        trade_model_simulation_movement_discount_only.getCausalityValue()
-      )
-
-      self.assertEqual(
-        price_currency,
-        trade_model_simulation_movement_discount_only.getPriceCurrencyValue()
-      )
-
-      self.assertSameSet(
-        ['base_amount/tax'],
-        trade_model_simulation_movement_discount_only \
-            .getBaseContributionList()
-      )
-
-      self.assertSameSet(
-        ['base_amount/discount'],
-        trade_model_simulation_movement_discount_only.getBaseApplicationList()
-      )
-
-      self.checkInvoiceTransactionRule(
-          trade_model_simulation_movement_discount_only)
-      # TODO:
-      #  * trade_phase ???
-      #  * arrow
-      #  * dates
-
-      # tax only
-      # below tax is applied only to discount part
-      self.assertEqual(trade_model_simulation_movement_discount_only. \
-          getTotalPrice() * self.default_tax_ratio,
-          trade_model_simulation_movement_tax_only.getTotalPrice())
-
-      self.assertEqual(
-        business_path_taxing,
-        trade_model_simulation_movement_tax_only.getCausalityValue()
-      )
-
-      self.assertEqual(
-        price_currency,
-        trade_model_simulation_movement_tax_only.getPriceCurrencyValue()
-      )
-
-      self.assertSameSet(
-        [],
-        trade_model_simulation_movement_tax_only.getBaseContributionList()
-      )
-
-      self.assertSameSet(
-        ['base_amount/tax'],
-        trade_model_simulation_movement_tax_only.getBaseApplicationList()
-      )
-
-      self.checkInvoiceTransactionRule(
-          trade_model_simulation_movement_tax_only)
-
-      # TODO:
-      #  * trade_phase ???
-      #  * arrow
-      #  * dates
-
-  def stepCheckOrderLineTaxedSimulation(self, sequence=None, **kw):
-    order_line = sequence.get('order_line_taxed')
-    business_path = sequence.get('business_path_taxing')
-    price_currency = sequence.get('price_currency')
-    self.assertNotEqual(None, business_path)
-    self.assertNotEqual(None, price_currency)
-    for trade_model_simulation_movement_list in \
-        self.getTradeModelSimulationMovementList(order_line):
-      self.assertEquals(1, len(trade_model_simulation_movement_list))
-      trade_model_simulation_movement = \
-          trade_model_simulation_movement_list[0]
-
-      self.assertEqual(
-        trade_model_simulation_movement.getParentValue().getParentValue() \
-            .getTotalPrice() * self.default_tax_ratio,
-        trade_model_simulation_movement.getTotalPrice()
-      )
-
-      self.assertEqual(
-        business_path,
-        trade_model_simulation_movement.getCausalityValue()
-      )
-
-      self.assertEqual(
-        price_currency,
-        trade_model_simulation_movement.getPriceCurrencyValue()
-      )
-
-      self.assertSameSet(
-        [],
-        trade_model_simulation_movement.getBaseContributionList()
-      )
-
-      self.assertSameSet(
-        ['base_amount/tax'],
-        trade_model_simulation_movement.getBaseApplicationList()
-      )
-      self.checkInvoiceTransactionRule(trade_model_simulation_movement)
-
-      # TODO:
-      #  * trade_phase ???
-      #  * arrow
-      #  * dates
-
-  def checkInvoiceTransactionRule(self, trade_model_simulation_movement):
-    invoice_transaction_rule_list = trade_model_simulation_movement\
-        .objectValues()
-    self.assertEquals(1, len(invoice_transaction_rule_list))
-    invoice_transaction_rule = invoice_transaction_rule_list[0]
-    self.assertEqual('Invoice Transaction Rule',
-        invoice_transaction_rule.getSpecialiseValue().getPortalType())
-
-    invoice_transaction_simulation_movement_list = invoice_transaction_rule \
-        .objectValues()
-
-    self.assertEqual(2, len(invoice_transaction_simulation_movement_list))
-
-    for movement in invoice_transaction_simulation_movement_list:
-      self.assertEqual(abs(movement.getQuantity()),
-          abs(trade_model_simulation_movement.getTotalPrice()))
-
-  def stepFillOrder(self, sequence=None, **kw):
-    order = sequence.get('order')
-    price_currency = sequence.get('price_currency')
-    source = sequence.get('source')
-    destination = sequence.get('destination')
-    source_section = sequence.get('source_section')
-    destination_section = sequence.get('destination_section')
-    self.assertNotEqual(None, price_currency)
-    self.assertNotEqual(None, source)
-    self.assertNotEqual(None, destination)
-    self.assertNotEqual(None, source_section)
-    self.assertNotEqual(None, destination_section)
-    order.edit(
-        source_value=source,
-        destination_value=destination,
-        source_section_value=source_section,
-        destination_section_value=destination_section,
-        start_date=self.order_date,
-        price_currency_value = price_currency)
-
-  def createResource(self, portal_type, **kw):
-    module = self.portal.getDefaultModule(portal_type=portal_type)
-    return module.newContent(portal_type=portal_type, **kw)
-
-  def stepCreatePriceCurrency(self, sequence=None, **kw):
-    sequence.edit(price_currency = self.createResource('Currency', \
-        title='Currency', base_unit_quantity=self.base_unit_quantity))
-
-  def stepCreateProductTaxed(self, sequence=None, **kw):
-    sequence.edit(product_taxed = self.createResource('Product',
-      title='Product Taxed',
-      base_contribution=['base_amount/tax'],
-      use='normal',
-    ))
-
-  def stepCreateProductDiscounted(self, sequence=None, **kw):
-    sequence.edit(product_discounted = self.createResource('Product',
-      title='Product Discounted',
-      base_contribution=['base_amount/discount'],
-      use='normal',
-    ))
-
-  def stepCreateProductDiscountedTaxed(self, sequence=None, **kw):
-    sequence.edit(product_discounted_taxed = self.createResource('Product',
-      title='Product Discounted & Taxed',
-      base_contribution=['base_amount/discount', 'base_amount/tax'],
-      use='normal',
-    ))
-
-  def stepCreateServiceTax(self, sequence=None, **kw):
-    sequence.edit(service_tax = self.createResource('Service',
-      title='Tax',
-      use='tax',
-    ))
-
-  def stepCreateServiceDiscount(self, sequence=None, **kw):
-    sequence.edit(service_discount = self.createResource('Service',
-      title='Discount',
-      use='discount',
-    ))
-
-  def createTradeCondition(self):
-    module = self.portal.getDefaultModule(
-        portal_type=self.trade_condition_portal_type)
-    trade_condition = module.newContent(
-        portal_type=self.trade_condition_portal_type,
-        title=self.id())
-    return trade_condition
-
-  def stepCreateTradeCondition(self, sequence=None, **kw):
-    sequence.edit(trade_condition = self.createTradeCondition())
-
-  def stepCreateInvoiceLine(self, sequence=None, **kw):
-    invoice = sequence.get('invoice')
-    invoice_line = invoice.newContent(portal_type=self.invoice_line_portal_type)
-    sequence.edit(invoice_line = invoice_line)
-
-  def stepCreateOrderLine(self, sequence=None, **kw):
-    order = sequence.get('order')
-    order_line = order.newContent(portal_type=self.order_line_portal_type)
-    sequence.edit(order_line = order_line)
-
-  def stepGetInvoiceLineDiscounted(self, sequence=None, **kw):
-    invoice = sequence.get('invoice')
-    resource = sequence.get('product_discounted')
-    self.assertNotEqual(None, resource)
-    sequence.edit(invoice_line_discounted = [m for m in
-      invoice.getMovementList() if m.getResourceValue() == resource][0])
-
-  def stepGetInvoiceLineDiscountedTaxed(self, sequence=None, **kw):
-    invoice = sequence.get('invoice')
-    resource = sequence.get('product_discounted_taxed')
-    self.assertNotEqual(None, resource)
-    sequence.edit(invoice_line_discounted_taxed = [m for m in
-      invoice.getMovementList() if m.getResourceValue() == resource][0])
-
-  def stepGetInvoiceLineTaxed(self, sequence=None, **kw):
-    invoice = sequence.get('invoice')
-    resource = sequence.get('product_taxed')
-    self.assertNotEqual(None, resource)
-    sequence.edit(invoice_line_taxed = [m for m in
-      invoice.getMovementList() if m.getResourceValue() == resource][0])
-
-  def stepModifyQuantityInvoiceLineTaxed(self, sequence=None, **kw):
-    invoice_line = sequence.get('invoice_line_taxed')
-    invoice_line.edit(
-      quantity=invoice_line.getQuantity() * \
-          self.modified_invoice_line_quantity_ratio,
-    )
-
-  def stepModifyQuantityInvoiceLineDiscounted(self, sequence=None, **kw):
-    invoice_line = sequence.get('invoice_line_discounted')
-    invoice_line.edit(
-      quantity=invoice_line.getQuantity() * \
-          self.modified_invoice_line_quantity_ratio,
-    )
-
-  def stepModifyQuantityInvoiceLineDiscountedTaxed(self, sequence=None, **kw):
-    invoice_line = sequence.get('invoice_line_discounted_taxed')
-    invoice_line.edit(
-      quantity=invoice_line.getQuantity() * \
-          self.modified_invoice_line_quantity_ratio,
-    )
-
-  def stepModifyAgainOrderLineTaxed(self, sequence=None, **kw):
-    order_line = sequence.get('order_line_taxed')
-    order_line.edit(
-      price=order_line.getPrice() * self.modified_order_line_price_ratio,
-      quantity=order_line.getQuantity() * \
-          self.modified_order_line_quantity_ratio,
-    )
-
-  def stepModifyAgainOrderLineDiscounted(self, sequence=None, **kw):
-    order_line = sequence.get('order_line_discounted')
-    order_line.edit(
-      price=order_line.getPrice() * self.modified_order_line_price_ratio,
-      quantity=order_line.getQuantity() * \
-          self.modified_order_line_quantity_ratio,
-    )
-
-  def stepModifyAgainOrderLineDiscountedTaxed(self, sequence=None, **kw):
-    order_line = sequence.get('order_line_discounted_taxed')
-    order_line.edit(
-      price=order_line.getPrice() * self.modified_order_line_price_ratio,
-      quantity=order_line.getQuantity() * \
-          self.modified_order_line_quantity_ratio,
-    )
-
-  def stepModifyOrderLineTaxed(self, sequence=None, **kw):
-    order_line = sequence.get('order_line')
-    resource = sequence.get('product_taxed')
-    self.assertNotEqual(None, resource)
-    order_line.edit(
-      price=1.0,
-      quantity=2.0,
-      resource_value=resource
-    )
-    sequence.edit(
-      order_line = None,
-      order_line_taxed = order_line
-    )
-
-  def stepModifyOrderLineDiscounted(self, sequence=None, **kw):
-    order_line = sequence.get('order_line')
-    resource = sequence.get('product_discounted')
-    self.assertNotEqual(None, resource)
-    order_line.edit(
-      price=3.0,
-      quantity=4.0,
-      resource_value=resource
-    )
-    sequence.edit(
-      order_line = None,
-      order_line_discounted = order_line
-    )
-
-  def stepModifyOrderLineDiscountedTaxed(self, sequence=None, **kw):
-    order_line = sequence.get('order_line')
-    resource = sequence.get('product_discounted_taxed')
-    self.assertNotEqual(None, resource)
-    order_line.edit(
-      price=5.0,
-      quantity=6.0,
-      resource_value=resource
-    )
-    sequence.edit(
-      order_line = None,
-      order_line_discounted_taxed = order_line
-    )
-
-  def stepModifyInvoiceLineTaxed(self, sequence=None, **kw):
-    invoice_line = sequence.get('invoice_line')
-    resource = sequence.get('product_taxed')
-    self.assertNotEqual(None, resource)
-    invoice_line.edit(
-      price=1.0,
-      quantity=2.0,
-      resource_value=resource
-    )
-    sequence.edit(
-      invoice_line = None,
-      invoice_line_taxed = invoice_line
-    )
-
-  def stepModifyInvoiceLineDiscounted(self, sequence=None, **kw):
-    invoice_line = sequence.get('invoice_line')
-    resource = sequence.get('product_discounted')
-    self.assertNotEqual(None, resource)
-    invoice_line.edit(
-      price=3.0,
-      quantity=4.0,
-      resource_value=resource
-    )
-    sequence.edit(
-      invoice_line = None,
-      invoice_line_discounted = invoice_line
-    )
-
-  def stepModifyInvoiceLineDiscountedTaxed(self, sequence=None, **kw):
-    invoice_line = sequence.get('invoice_line')
-    resource = sequence.get('product_discounted_taxed')
-    self.assertNotEqual(None, resource)
-    invoice_line.edit(
-      price=5.0,
-      quantity=6.0,
-      resource_value=resource
-    )
-    sequence.edit(
-      invoice_line = None,
-      invoice_line_discounted_taxed = invoice_line
-    )
-
-  def createTradeModelLine(self, document, **kw):
-    return document.newContent(
-        portal_type='Trade Model Line',
-        **kw)
-
-  def stepOrderCreateTradeModelLine(self, sequence=None, **kw):
-    order = sequence.get('order')
-    sequence.edit(trade_model_line = self.createTradeModelLine(order))
-
-  def stepCreateTradeModelLine(self, sequence=None, **kw):
-    trade_condition = sequence.get('trade_condition')
-    sequence.edit(
-      trade_model_line = self.createTradeModelLine(trade_condition))
-
-  def stepSpecialiseTradeConditionWithBusinessProcess(self, sequence=None,
-      **kw):
-    business_process = sequence.get('business_process')
-    trade_condition = sequence.get('trade_condition')
-    self.assertNotEqual(None, business_process)
-    trade_condition.setSpecialiseValue(business_process)
-
-  def stepModifyTradeModelLineNewDiscount(self, sequence=None, **kw):
-    trade_model_line = sequence.get('trade_model_line')
-    service_discount = sequence.get('service_discount')
-
-    trade_model_line.edit(
-      price=self.new_discount_ratio,
-      base_application='base_amount/discount',
-      base_contribution='base_amount/tax',
-      trade_phase='default/discount',
-      resource_value=service_discount,
-      reference='service_discount',
-    )
-    sequence.edit(
-      trade_model_line = None,
-      trade_model_line_discount = trade_model_line
-    )
-
-  def stepModifyTradeModelLineDiscount(self, sequence=None, **kw):
-    trade_model_line = sequence.get('trade_model_line')
-    service_discount = sequence.get('service_discount')
-
-    trade_model_line.edit(
-      price=self.default_discount_ratio,
-      base_application='base_amount/discount',
-      base_contribution='base_amount/tax',
-      trade_phase='default/discount',
-      resource_value=service_discount,
-      reference='discount',
-    )
-    sequence.edit(
-      trade_model_line = None,
-      trade_model_line_discount = trade_model_line
-    )
-
-  def stepModifyTradeModelLineTotalDiscount(self, sequence=None, **kw):
-    trade_model_line = sequence.get('trade_model_line')
-    service_discount = sequence.get('service_discount')
-
-    trade_model_line.edit(
-      price=0.8,
-      base_application='base_amount/total_discount',
-      trade_phase='default/discount',
-      resource_value=service_discount,
-      reference='total_discount',
-    )
-    sequence.edit(
-      trade_model_line = None,
-      trade_model_line_discount = trade_model_line
-    )
-
-  def stepModifyTradeModelLineDiscountContributingToTotalDiscount(self,
-      sequence=None, **kw):
-    trade_model_line = sequence.get('trade_model_line')
-    service_discount = sequence.get('service_discount')
-
-    trade_model_line.edit(
-      price=0.32,
-      base_application='base_amount/discount',
-      base_contribution='base_amount/total_discount',
-      trade_phase='default/discount',
-      resource_value=service_discount,
-      reference='total_dicount_2',
-    )
-    sequence.edit(
-      trade_model_line = None,
-      trade_model_line_discount = trade_model_line
-    )
-
-  def stepModifyTradeModelLineNewTax(self, sequence=None, **kw):
-    trade_model_line = sequence.get('trade_model_line')
-    service_tax = sequence.get('service_tax')
-
-    trade_model_line.edit(
-      price=self.new_tax_ratio,
-      base_application='base_amount/tax',
-      trade_phase='default/tax',
-      resource_value=service_tax,
-      reference='tax_2',
-    )
-    sequence.edit(
-      trade_model_line = None,
-      trade_model_line_tax = trade_model_line
-    )
-
-  def stepModifyTradeModelLineTax(self, sequence=None, **kw):
-    trade_model_line = sequence.get('trade_model_line')
-    service_tax = sequence.get('service_tax')
-
-    trade_model_line.edit(
-      price=self.default_tax_ratio,
-      base_application='base_amount/tax',
-      trade_phase='default/tax',
-      resource_value=service_tax,
-      reference='tax',
-    )
-    sequence.edit(
-      trade_model_line = None,
-      trade_model_line_tax = trade_model_line
-    )
-
-  def stepModifyTradeModelLineTotalTax(self, sequence=None, **kw):
-    trade_model_line = sequence.get('trade_model_line')
-    service_tax = sequence.get('service_tax')
-
-    trade_model_line.edit(
-      price=0.12,
-      base_application='base_amount/total_tax',
-      base_contribution='base_amount/total_discount',
-      trade_phase='default/tax',
-      resource_value=service_tax,
-      reference='tax_3',
-    )
-    sequence.edit(
-      trade_model_line = None,
-      trade_model_line_tax = trade_model_line
-    )
-
-  def stepModifyTradeModelLineTaxContributingToTotalTax(self,
-      sequence=None, **kw):
-    trade_model_line = sequence.get('trade_model_line')
-    service_tax = sequence.get('service_tax')
-
-    trade_model_line.edit(
-      price=0.2,
-      base_application='base_amount/tax',
-      base_contribution='base_amount/total_tax',
-      trade_phase='default/tax',
-      resource_value=service_tax,
-      reference='service_tax',
-    )
-    sequence.edit(
-      trade_model_line = None,
-      trade_model_line_tax = trade_model_line
-    )
-
-  def stepModifyTradeModelLineTaxContributingToTotalTax2(self,
-      sequence=None, **kw):
-    trade_model_line = sequence.get('trade_model_line')
-    service_tax = sequence.get('service_tax')
-
-    trade_model_line.edit(
-      price=0.2,
-      base_application='base_amount/tax',
-      base_contribution='base_amount/total_tax',
-      trade_phase='default/tax',
-      resource_value=service_tax,
-      reference='service_tax_2',
-    )
-    sequence.edit(
-      trade_model_line = None,
-      trade_model_line_tax = trade_model_line
-    )
-
-  def stepUpdateAggregatedAmountListOnOrder(self,
-      sequence=None, **kw):
-    order = sequence.get('order')
-    order.Delivery_updateAggregatedAmountList(batch_mode=1)
-
-  def stepCheckOrderLineTaxedAggregatedAmountList(self, sequence=None, **kw):
-    order_line = sequence.get('order_line_taxed')
-    trade_condition = sequence.get('trade_condition')
-    trade_model_line_tax = sequence.get('trade_model_line_tax')
-    amount_list = trade_condition.getAggregatedAmountList(order_line)
-
-    self.assertEquals(1, len(amount_list))
-    tax_amount_list = [q for q in amount_list
-        if q.getBaseApplication() == 'base_amount/tax']
-    self.assertEquals(1, len(tax_amount_list))
-
-    tax_amount = tax_amount_list[0]
-
-    self.assertEqual(tax_amount.getReference(),
-        trade_model_line_tax.getReference())
-    self.assertSameSet(['base_amount/tax'],
-        tax_amount.getBaseApplicationList())
-    self.assertSameSet([], tax_amount.getBaseContributionList())
-
-    self.assertEqual(order_line.getTotalPrice() * self.default_tax_ratio,
-        tax_amount.getTotalPrice())
-
-  def stepCheckOrderLineDiscountedTaxedAggregatedAmountList(self,
-      sequence=None, **kw):
-    order_line = sequence.get('order_line_discounted_taxed')
-    trade_condition = sequence.get('trade_condition')
-    trade_model_line_discount = sequence.get('trade_model_line_discount')
-    trade_model_line_tax = sequence.get('trade_model_line_tax')
-    amount_list = trade_condition.getAggregatedAmountList(order_line)
-
-    self.assertEquals(2, len(amount_list))
-    tax_amount_list = [q for q in amount_list
-        if q.getBaseApplication() == 'base_amount/tax']
-    self.assertEquals(1, len(tax_amount_list))
-    tax_amount = tax_amount_list[0]
-
-    discount_amount_list = [q for q in amount_list
-        if q.getBaseApplication() == 'base_amount/discount']
-    self.assertEquals(1, len(discount_amount_list))
-
-    discount_amount = discount_amount_list[0]
-
-    self.assertEqual(tax_amount.getReference(),
-        trade_model_line_tax.getReference())
-    self.assertSameSet(['base_amount/tax'], tax_amount. \
-        getBaseApplicationList())
-    self.assertSameSet([], tax_amount.getBaseContributionList())
-
-    self.assertEqual(discount_amount.getReference(),
-        trade_model_line_discount.getReference())
-    self.assertSameSet(['base_amount/discount'], discount_amount. \
-        getBaseApplicationList())
-    self.assertSameSet(['base_amount/tax'], discount_amount. \
-        getBaseContributionList())
-
-    self.assertEqual(order_line.getTotalPrice() * \
-        self.default_discount_ratio, discount_amount.getTotalPrice())
-
-    self.assertEqual((order_line.getTotalPrice() + discount_amount. \
-        getTotalPrice()) * self.default_tax_ratio,
-        tax_amount.getTotalPrice())
-
-  def stepCheckOrderLineDiscountedAggregatedAmountList(self, sequence=None,
-      **kw):
-    order_line = sequence.get('order_line_discounted')
-    trade_condition = sequence.get('trade_condition')
-    trade_model_line_discount = sequence.get('trade_model_line_discount')
-    amount_list = trade_condition.getAggregatedAmountList(order_line)
-
-    self.assertEquals(2, len(amount_list))
-    tax_amount_list = [q for q in amount_list
-        if q.getBaseApplication() == 'base_amount/tax']
-    self.assertEquals(1, len(tax_amount_list))
-    tax_amount = tax_amount_list[0]
-
-    discount_amount_list = [q for q in amount_list
-        if q.getBaseApplication() == 'base_amount/discount']
-    self.assertEquals(1, len(discount_amount_list))
-
-    discount_amount = discount_amount_list[0]
-
-    self.assertEqual(discount_amount.getReference(),
-        trade_model_line_discount.getReference())
-    self.assertSameSet(['base_amount/tax'], tax_amount. \
-        getBaseApplicationList())
-    self.assertSameSet([], tax_amount.getBaseContributionList())
-
-    self.assertSameSet(['base_amount/discount'], discount_amount. \
-        getBaseApplicationList())
-    self.assertSameSet(['base_amount/tax'], discount_amount. \
-        getBaseContributionList())
-
-    self.assertEqual(order_line.getTotalPrice() * \
-        self.default_discount_ratio, discount_amount.getTotalPrice())
-
-    # below tax is applied only to discount part
-    self.assertEqual(discount_amount.getTotalPrice() * self.default_tax_ratio,
-        tax_amount.getTotalPrice())
-
-  def stepCheckOrderComplexTradeConditionAggregatedAmountList(self,
-      sequence=None, **kw):
-    trade_condition = sequence.get('trade_condition')
-    order = sequence.get('order')
-    order_line_discounted = sequence.get('order_line_discounted')
-    order_line_discounted_taxed = sequence.get('order_line_discounted_taxed')
-    order_line_taxed = sequence.get('order_line_taxed')
-    trade_model_line_tax = sequence.get('trade_model_line_tax')
-    trade_model_line_discount = sequence.get('trade_model_line_discount')
-
-    amount_list = trade_condition.getAggregatedAmountList(order)
-    self.assertEquals(2, len(amount_list))
-    discount_amount_list = [q for q in amount_list
-        if q.getBaseApplication() == 'base_amount/discount']
-    tax_amount_list = [q for q in amount_list
-        if q.getBaseApplication() == 'base_amount/tax']
-
-    self.assertEquals(1, len(discount_amount_list))
-    self.assertEquals(1, len(tax_amount_list))
-
-    discount_amount = discount_amount_list[0]
-    tax_amount = tax_amount_list[0]
-
-    self.assertEqual(discount_amount.getReference(),
-        trade_model_line_discount.getReference())
-    self.assertSameSet(['base_amount/discount'], discount_amount. \
-        getBaseApplicationList())
-
-    self.assertSameSet(['base_amount/tax'], discount_amount. \
-        getBaseContributionList())
-
-    self.assertSameSet(['base_amount/tax'], tax_amount. \
-        getBaseApplicationList())
-
-    self.assertSameSet([], tax_amount.getBaseContributionList())
-    self.assertEqual(tax_amount.getReference(),
-        trade_model_line_tax.getReference())
-
-    self.assertEqual(
-      discount_amount.getTotalPrice(),
-      (order_line_discounted.getTotalPrice()
-        + order_line_discounted_taxed.getTotalPrice() )
-      * self.default_discount_ratio
-    )
-
-    self.assertEqual(
-      tax_amount.getTotalPrice(),
-      (order_line_taxed.getTotalPrice()
-        + order_line_discounted_taxed.getTotalPrice()
-        + discount_amount.getTotalPrice()) * self.default_tax_ratio
-    )
-
-  def stepCheckAggregatedAmountListWithComplexBaseContributionBaseApplication(self,
-      sequence=None, **kw):
-    trade_condition = sequence.get('trade_condition')
-    order = sequence.get('order')
-    order_line_discounted = sequence.get('order_line_discounted')
-    order_line_discounted_taxed = sequence.get('order_line_discounted_taxed')
-    order_line_taxed = sequence.get('order_line_taxed')
-
-    amount_list = trade_condition.getAggregatedAmountList(order)
-    self.assertEquals(5, len(amount_list))
-    tax_amount_list = [q for q in amount_list
-        if q.getBaseApplication() == 'base_amount/tax']
-    total_tax_amount_list = [q for q in amount_list
-        if q.getBaseApplication() == 'base_amount/total_tax']
-    discount_amount_list = [q for q in amount_list
-        if q.getBaseApplication() == 'base_amount/discount']
-    total_discount_amount_list = [q for q in amount_list
-        if q.getBaseApplication() == 'base_amount/total_discount']
-
-    self.assertEquals(2, len(tax_amount_list))
-    self.assertEquals(1, len(total_tax_amount_list))
-    self.assertEquals(1, len(discount_amount_list))
-    self.assertEquals(1, len(total_discount_amount_list))
-
-    total_tax_amount = total_tax_amount_list[0]
-    discount_amount = discount_amount_list[0]
-    total_discount_amount = total_discount_amount_list[0]
-
-    self.assertSameSet(['base_amount/total_tax'], total_tax_amount. \
-        getBaseApplicationList())
-    self.assertSameSet(['base_amount/total_discount'], total_tax_amount. \
-        getBaseContributionList())
-
-    self.assertSameSet(['base_amount/discount'], discount_amount. \
-        getBaseApplicationList())
-    self.assertSameSet(['base_amount/total_discount'], discount_amount. \
-        getBaseContributionList())
-
-    self.assertSameSet(['base_amount/total_discount'], total_discount_amount. \
-        getBaseApplicationList())
-    self.assertSameSet([], total_discount_amount.getBaseContributionList())
-
-    for tax_amount in tax_amount_list:
-      self.assertSameSet(['base_amount/tax'], tax_amount. \
-          getBaseApplicationList())
-      self.assertSameSet(['base_amount/total_tax'], tax_amount. \
-          getBaseContributionList())
-
-    for tax_amount in tax_amount_list:
-      self.assertEqual(
-        tax_amount.getTotalPrice(),
-        order_line_taxed.getTotalPrice() * 0.2
-      )
-
-    self.assertEqual(
-      total_tax_amount.getTotalPrice(),
-      (order_line_taxed.getTotalPrice() * 0.2) * 2 * 0.12
-    )
-
-    self.assertEqual(
-      discount_amount.getTotalPrice(),
-      order_line_discounted.getTotalPrice() * 0.32
-    )
-
-    self.assertEqual(
-      total_discount_amount.getTotalPrice(),
-      ((order_line_taxed.getTotalPrice() * 0.2) * 2 * 0.12 + \
-      order_line_discounted.getTotalPrice() * 0.32) * 0.8
-    )
-
-class TestBPMTestCases(TestBPMMixin):
-  COMMON_DOCUMENTS_CREATION_SEQUENCE_STRING = """
-              CreateServiceTax
-              CreateServiceDiscount
-              CreatePriceCurrency
-              CreateProductDiscounted
-              CreateProductTaxed
-              CreateProductDiscountedTaxed
-              CreateSource
-              CreateSourceSection
-              CreateDestination
-              CreateDestinationSection
-              Tic
-  """
-
-  AGGREGATED_AMOUNT_LIST_CHECK_SEQUENCE_STRING = """
-              CheckOrderComplexTradeConditionAggregatedAmountList
-              CheckOrderLineTaxedAggregatedAmountList
-              CheckOrderLineDiscountedTaxedAggregatedAmountList
-              CheckOrderLineDiscountedAggregatedAmountList
-  """
-
-  AGGREGATED_AMOUNT_LIST_COMMON_SEQUENCE_STRING = \
-      COMMON_DOCUMENTS_CREATION_SEQUENCE_STRING + """
-              CreateBusinessProcess
-              CreateBusinessState
-              ModifyBusinessStateTaxed
-              CreateBusinessState
-              ModifyBusinessStateInvoiced
-              CreateBusinessPath
-              ModifyBusinessPathTaxing
-              CreateBusinessPath
-              ModifyBusinessPathDiscounting
-              CreateTradeCondition
-              SpecialiseTradeConditionWithBusinessProcess
-              CreateTradeModelLine
-              ModifyTradeModelLineTax
-              CreateTradeModelLine
-              ModifyTradeModelLineDiscount
-              Tic
-              CreateOrder
-              SpecialiseOrderTradeCondition
-              FillOrder
-              Tic
-              CreateOrderLine
-              ModifyOrderLineTaxed
-              CreateOrderLine
-              ModifyOrderLineDiscounted
-              CreateOrderLine
-              ModifyOrderLineDiscountedTaxed
-              Tic
-  """ + AGGREGATED_AMOUNT_LIST_CHECK_SEQUENCE_STRING
-
-  def test_TradeConditionTradeModelLineCircularComposition(self):
-    """
-      If Trade Condition is specialised by another Trade Condition they
-      Trade Model Lines shall be merged.
-    """
-    trade_condition_1 = self.createTradeCondition()
-    trade_condition_2 = self.createTradeCondition()
-
-    trade_condition_1.setSpecialiseValue(trade_condition_2)
-    trade_condition_2.setSpecialiseValue(trade_condition_1)
-
-    self.assertEquals(trade_condition_1. \
-        findSpecialiseValueList(trade_condition_1),
-        [trade_condition_1, trade_condition_2]
-    )
-
-  def test_TradeConditionTradeModelLineBasicComposition(self):
-    """
-      If Trade Condition is specialised by another Trade Condition they
-      Trade Model Lines shall be merged.
-    """
-    service_1 = self.createResource('Service')
-    service_2 = self.createResource('Service')
-
-    trade_condition_1 = self.createTradeCondition()
-    trade_condition_2 = self.createTradeCondition()
-
-    trade_condition_1.setSpecialiseValue(trade_condition_2)
-
-    trade_condition_1_trade_model_line = self.createTradeModelLine(
-        trade_condition_1,
-        resource_value = service_1)
-
-    trade_condition_2_trade_model_line = self.createTradeModelLine(
-        trade_condition_2,
-        resource_value = service_2)
-
-    self.assertSameSet(
-      [trade_condition_1_trade_model_line,
-        trade_condition_2_trade_model_line],
-      trade_condition_1.getTradeModelLineComposedList()
-    )
-
-  def test_findSpecialiseValueList(self):
-    '''
-      check that findSpecialiseValueList is able to return all the inheritance
-      model tree using Depth-first search
-
-                                  trade_condition_1
-                                    /           \
-                                   /             \
-                                  /               \
-                       trade_condition_2       trade_condition_3
-                               |
-                               |
-                               |
-                        trade_condition_4
-
-       according to Depth-first search algorihm, result of this graph should be
-       [trade_condition_1, trade_condition_2, trade_condition_3,
-       trade_condition_4]
-    '''
-    trade_condition_1 = self.createTradeCondition()
-    trade_condition_2 = self.createTradeCondition()
-    trade_condition_3 = self.createTradeCondition()
-    trade_condition_4 = self.createTradeCondition()
-
-    trade_condition_1.setSpecialiseValueList((trade_condition_2,
-      trade_condition_3))
-    trade_condition_2.setSpecialiseValue(trade_condition_4)
-
-    speciliase_value_list = trade_condition_1.findSpecialiseValueList(context=\
-        trade_condition_1)
-    self.assertEquals(len(speciliase_value_list), 4)
-    self.assertEquals(
-      [trade_condition_1, trade_condition_2, trade_condition_3,
-       trade_condition_4], speciliase_value_list)
-
-  def test_TradeConditionTradeModelLineBasicCompositionWithOrder(self):
-    """
-      If Trade Condition is specialised by another Trade Condition they
-      Trade Model Lines shall be merged.
-    """
-    service_1 = self.createResource('Service')
-    service_2 = self.createResource('Service')
-    service_3 = self.createResource('Service')
-
-    trade_condition_1 = self.createTradeCondition()
-    trade_condition_2 = self.createTradeCondition()
-    order = self.createOrder()
-
-    trade_condition_1.setSpecialiseValue(trade_condition_2)
-    order.setSpecialiseValue(trade_condition_1)
-
-    trade_condition_1_trade_model_line = self.createTradeModelLine(
-        trade_condition_1,
-        resource_value = service_1)
-
-    trade_condition_2_trade_model_line = self.createTradeModelLine(
-        trade_condition_2,
-        resource_value = service_2)
-
-    order_trade_model_line = self.createTradeModelLine(
-        order,
-        resource_value = service_3)
-
-    self.assertSameSet(
-      [trade_condition_1_trade_model_line, trade_condition_2_trade_model_line],
-      trade_condition_1.getTradeModelLineComposedList()
-    )
-
-    self.assertSameSet(
-      [trade_condition_1_trade_model_line, trade_condition_2_trade_model_line,
-        order_trade_model_line],
-      trade_condition_1.getTradeModelLineComposedList(context=order)
-    )
-
-  def test_TradeConditionTradeModelLineResourceIsShadowingCompositionWithOrder(self):
-    """
-      If Trade Condition is specialised by another Trade Condition they
-      Trade Model Lines shall be merged.
-    """
-    service_1 = self.createResource('Service')
-    service_2 = self.createResource('Service')
-
-    trade_condition_1 = self.createTradeCondition()
-    trade_condition_2 = self.createTradeCondition()
-    order = self.createOrder()
-
-    trade_condition_1.setSpecialiseValue(trade_condition_2)
-    order.setSpecialiseValue(trade_condition_1)
-
-    trade_condition_1_trade_model_line = self.createTradeModelLine(
-        trade_condition_1,
-        resource_value = service_1,
-        reference = 'A')
-
-    trade_condition_2_trade_model_line = self.createTradeModelLine(
-        trade_condition_2,
-        resource_value = service_2,
-        reference = 'B')
-
-    order_trade_model_line = self.createTradeModelLine(
-        order,
-        resource_value = service_2,
-        reference = 'B')
-
-    self.assertSameSet(
-      [trade_condition_1_trade_model_line,
-        trade_condition_2_trade_model_line],
-      trade_condition_1.getTradeModelLineComposedList()
-    )
-
-    self.assertSameSet(
-      [trade_condition_1_trade_model_line, order_trade_model_line],
-      trade_condition_1.getTradeModelLineComposedList(context=order)
-    )
-
-  def test_TradeConditionTradeModelLineResourceIsShadowingComposition(self):
-    """
-      If Trade Condition is specialised by another Trade Condition
-      and resource is repeated, only first Trade Model Line shall be returned.
-    """
-    service = self.createResource('Service')
-
-    trade_condition_1 = self.createTradeCondition()
-    trade_condition_2 = self.createTradeCondition()
-
-    trade_condition_1.setSpecialiseValue(trade_condition_2)
-
-    trade_condition_1_trade_model_line = self.createTradeModelLine(
-        trade_condition_1,
-        resource_value = service,
-        reference = 'A')
-
-    trade_condition_2_trade_model_line = self.createTradeModelLine(
-        trade_condition_2,
-        resource_value = service,
-        reference = 'A')
-
-    self.assertSameSet(
-      [trade_condition_1_trade_model_line],
-      trade_condition_1.getTradeModelLineComposedList()
-    )
-
-  def test_getTradeModelLineComposedList(self):
-    """Test that list of contribution/application relations is sorted to do easy traversal
-
-    Let assume such graph of contribution/application dependency:
-
-    D -----> B
-          /   \
-    E ---/     > A
-              /
-    F -----> C
-          /
-    G ---/
-
-    It shall return list which is sorted like:
-      * (DE) B (FG) C A
-        or
-      * (FG) C (DE) B A
-        or
-      * (DEFG) (BC) A
-    where everything in parenthesis can be not sorted
-    """
-    trade_condition = self.createTradeCondition()
-
-    A = self.createTradeModelLine(trade_condition, reference='A',
-        base_application_list=['base_amount/total'])
-
-    B = self.createTradeModelLine(trade_condition, reference='B',
-        base_contribution_list=['base_amount/total'],
-        base_application_list=['base_amount/total_tax'])
-
-    C = self.createTradeModelLine(trade_condition, reference='C',
-        base_contribution_list=['base_amount/total'],
-        base_application_list=['base_amount/total_discount'])
-
-    D = self.createTradeModelLine(trade_condition, reference='D',
-        base_contribution_list=['base_amount/total_tax'],
-        base_application_list=['base_amount/tax'])
-
-    E = self.createTradeModelLine(trade_condition, reference='E',
-        base_contribution_list=['base_amount/total_tax'],
-        base_application_list=['base_amount/tax'])
-
-    F = self.createTradeModelLine(trade_condition, reference='F',
-        base_contribution_list=['base_amount/total_discount'],
-        base_application_list=['base_amount/discount'])
-
-    G = self.createTradeModelLine(trade_condition, reference='G',
-        base_contribution_list=['base_amount/total_discount'],
-        base_application_list=['base_amount/discount'])
-
-    trade_model_line_list = trade_condition.getTradeModelLineComposedList()
-
-    # XXX: This is only one good possible sorting
-    self.assertEquals([q.getReference() for q in trade_model_line_list],
-        [q.getReference() for q in [G, F, E, D, C, B, A]])
-
-  def test_getComplexTradeModelLineComposedList(self):
-    """Test that list of contribution/application relations is sorted to do easy traversal
-
-    Let assume such graph of contribution/application dependency:
-
-             /--------\
-            /          \
-      A----+ -----B-----+-D
-            \          /
-             \----C---/
-
-    It shall return list which is sorted like:
-      * A (BC) D
-    where everything in parenthesis can be not sorted
-    """
-    trade_condition = self.createTradeCondition()
-
-    C = self.createTradeModelLine(trade_condition, reference='C',
-        base_contribution_list=['base_amount/total'],
-        base_application_list=['base_amount/total_discount'])
-
-    A = self.createTradeModelLine(trade_condition, reference='A',
-        base_contribution_list=['base_amount/total', 'base_amount/total_tax',
-          'base_amount/total_discount'],
-        base_application_list=['base_amount/tax'])
-
-    D = self.createTradeModelLine(trade_condition, reference='D',
-        base_application_list=['base_amount/total'])
-
-    B = self.createTradeModelLine(trade_condition, reference='B',
-        base_contribution_list=['base_amount/total'],
-        base_application_list=['base_amount/total_tax'])
-
-    trade_model_line_list = trade_condition.getTradeModelLineComposedList()
-
-    # XXX: This is only one good possible sorting
-    self.assertEquals([q.getReference() for q in trade_model_line_list],
-        [q.getReference() for q in [A, B, C, D]])
-
-  def test_tradeModelLineWithFixedPrice(self):
-    """
-      Check it's possible to have fixed quantity on lines. Sometimes we want
-      to say "discount 10 euros" or "pay more 10 euros" instead of saying "10%
-      discount from total"
-    """
-    trade_condition = self.createTradeCondition()
-
-    # create a model line with 100 euros
-    A = self.createTradeModelLine(trade_condition, reference='A',
-        base_contribution_list=['base_amount/total'])
-    A.edit(quantity=100, price=1)
-
-    # add a discount of 10 euros
-    B = self.createTradeModelLine(trade_condition, reference='B',
-        base_contribution_list=['base_amount/total'])
-    B.edit(quantity=10, price=-1)
-
-    order = self.createOrder()
-    order.setSpecialiseValue(trade_condition)
-    amount_list = trade_condition.getAggregatedAmountList(order)
-    self.assertEquals(2, len(amount_list))
-    total_amount_list = [q for q in amount_list
-        if q.getBaseContribution() == 'base_amount/total']
-
-    self.assertEquals(2, len(total_amount_list))
-
-    # the total amount for base_amount/total should be of 100 - 10 = 90 euros
-    total_amount = 0
-    for amount in total_amount_list:
-      total_amount += amount.getTotalPrice()
-
-    self.assertEqual(total_amount, 100 - 10)
-
-  def test_getAggregatedAmountList(self):
-    """
-      Test for case, when discount contributes to tax, and order has mix of contributing lines
-    """
-    sequence_list = SequenceList()
-    sequence_string = self.AGGREGATED_AMOUNT_LIST_COMMON_SEQUENCE_STRING
-
-    sequence_list.addSequenceString(sequence_string)
-    sequence_list.play(self)
-
-  ORDER_SPECIALISE_AGGREGATED_AMOUNT_COMMON_SEQUENCE_STRING = \
-      COMMON_DOCUMENTS_CREATION_SEQUENCE_STRING + """
-              CreateBusinessProcess
-              CreateBusinessState
-              ModifyBusinessStateTaxed
-              CreateBusinessState
-              ModifyBusinessStateInvoiced
-              CreateBusinessPath
-              ModifyBusinessPathTaxing
-              CreateBusinessPath
-              ModifyBusinessPathDiscounting
-              CreateTradeCondition
-              SpecialiseTradeConditionWithBusinessProcess
-              CreateTradeModelLine
-              ModifyTradeModelLineTax
-              Tic
-              CreateOrder
-              OrderCreateTradeModelLine
-              ModifyTradeModelLineDiscount
-              SpecialiseOrderTradeCondition
-              FillOrder
-              Tic
-              CreateOrderLine
-              ModifyOrderLineTaxed
-              CreateOrderLine
-              ModifyOrderLineDiscounted
-              CreateOrderLine
-              ModifyOrderLineDiscountedTaxed
-              Tic
-    """ + AGGREGATED_AMOUNT_LIST_CHECK_SEQUENCE_STRING
-
-  def test_getAggregatedAmountListOrderSpecialise(self):
-    """
-      Test for case, when discount contributes to tax, and order has mix of contributing lines and order itself defines Trade Model Line
-    """
-    sequence_list = SequenceList()
-    sequence_string = self\
-        .ORDER_SPECIALISE_AGGREGATED_AMOUNT_COMMON_SEQUENCE_STRING
-
-    sequence_list.addSequenceString(sequence_string)
-    sequence_list.play(self)
-
-  def test_getAggregatedAmountList_afterUpdateAggregatedAmountList(self):
-    """
-      Test for case, when discount contributes to tax, and order has mix of contributing lines
-
-      Check if it is stable if updateAggregatedAmountList was invoked.
-
-      Note: This test assumes, that somethings contributes after update, shall
-            be rewritten in a way, that adds explicitly movement which shall
-            not be aggregated.
-    """
-    sequence_list = SequenceList()
-    sequence_string = self.AGGREGATED_AMOUNT_LIST_COMMON_SEQUENCE_STRING + """
-              UpdateAggregatedAmountListOnOrder
-              Tic
-    """ + self.AGGREGATED_AMOUNT_LIST_CHECK_SEQUENCE_STRING
-
-    sequence_list.addSequenceString(sequence_string)
-    sequence_list.play(self)
-
-  AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING = """
-              CheckOrderLineTaxedSimulation
-              CheckOrderLineDiscountedSimulation
-              CheckOrderLineDiscountedTaxedSimulation
-  """
-  TRADE_MODEL_RULE_SIMULATION_SEQUENCE_STRING = \
-      AGGREGATED_AMOUNT_LIST_COMMON_SEQUENCE_STRING + """
-              Tic
-              PlanOrder
-              Tic
-  """ + AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING
-
-  def test_TradeModelRuleSimulationExpand(self):
-    """Tests tree of simulations from Trade Model Rule"""
-    sequence_list = SequenceList()
-    sequence_string = self.TRADE_MODEL_RULE_SIMULATION_SEQUENCE_STRING
-    sequence_list.addSequenceString(sequence_string)
-    sequence_list.play(self)
-
-  def test_TradeModelRuleSimulationReexpand(self):
-    """Tests tree of simulations from Trade Model Rule with reexpanding"""
-    sequence_list = SequenceList()
-    sequence_string = self.TRADE_MODEL_RULE_SIMULATION_SEQUENCE_STRING + """
-              ModifyAgainOrderLineTaxed
-              ModifyAgainOrderLineDiscounted
-              ModifyAgainOrderLineDiscountedTaxed
-              Tic
-    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING
-    sequence_list.addSequenceString(sequence_string)
-    sequence_list.play(self)
-
-  def test_TradeModelRuleSimulationReexpandResourceChange(self):
-    """Tests tree of simulations from Trade Model Rule with reexpanding when resource changes on model"""
-    sequence_list = SequenceList()
-    sequence_string = self.TRADE_MODEL_RULE_SIMULATION_SEQUENCE_STRING + """
-              CreateServiceTax
-              CreateServiceDiscount
-              OrderCreateTradeModelLine
-              ModifyTradeModelLineDiscount
-              OrderCreateTradeModelLine
-              ModifyTradeModelLineTax
-              Tic
-    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING
-    sequence_list.addSequenceString(sequence_string)
-    sequence_list.play(self)
-
-  TRADE_MODEL_RULE_SIMULATION_ORDER_SPECIALISED_SEQUENCE_STRING = \
-      ORDER_SPECIALISE_AGGREGATED_AMOUNT_COMMON_SEQUENCE_STRING + """
-              Tic
-              PlanOrder
-              Tic
-  """ + AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING
-
-  def test_TradeModelRuleSimulationExpandOrderSpecialise(self):
-    """Tests tree of simulations from Trade Model Rule"""
-    sequence_list = SequenceList()
-    sequence_string = self \
-        .TRADE_MODEL_RULE_SIMULATION_ORDER_SPECIALISED_SEQUENCE_STRING
-    sequence_list.addSequenceString(sequence_string)
-    sequence_list.play(self)
-
-  def test_TradeModelRuleSimulationReexpandOrderSpecialise(self):
-    """Tests tree of simulations from Trade Model Rule with reexpanding"""
-    sequence_list = SequenceList()
-    sequence_string = self \
-        .TRADE_MODEL_RULE_SIMULATION_ORDER_SPECIALISED_SEQUENCE_STRING+ """
-              ModifyAgainOrderLineTaxed
-              ModifyAgainOrderLineDiscounted
-              ModifyAgainOrderLineDiscountedTaxed
-              Tic
-    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING
-    sequence_list.addSequenceString(sequence_string)
-    sequence_list.play(self)
-
-  def test_TradeModelRuleSimulationWithoutBPM(self):
-    """Tests tree of simulations from Trade Model Rule when there is no BPM"""
-    sequence_list = SequenceList()
-    sequence_string = self.COMMON_DOCUMENTS_CREATION_SEQUENCE_STRING + """
-              CreateTradeCondition
-              CreateTradeModelLine
-              ModifyTradeModelLineTax
-              Tic
-              CreateOrder
-              SpecialiseOrderTradeCondition
-              FillOrder
-              Tic
-              CreateOrderLine
-              ModifyOrderLineTaxed
-              Tic
-              PlanOrder
-              Tic
-              CheckOrderTaxNoSimulation
-    """
-    sequence_list.addSequenceString(sequence_string)
-    sequence_list.play(self)
-
-  def test_TradeModelRuleSimulationWithoutTradeCondition(self):
-    """Tests tree of simulations from Trade Model Rule when there is no Trade Condition"""
-    sequence_list = SequenceList()
-    sequence_string = self.COMMON_DOCUMENTS_CREATION_SEQUENCE_STRING + """
-              CreateOrder
-              FillOrder
-              Tic
-              CreateOrderLine
-              ModifyOrderLineTaxed
-              Tic
-              PlanOrder
-              Tic
-              CheckOrderTaxNoSimulation
-    """
-    sequence_list.addSequenceString(sequence_string)
-    sequence_list.play(self)
-
-  def test_TradeModelRuleSimulationBuildInvoice(self):
-    """Check that invoice lines on invoice are correctly set"""
-    sequence_list = SequenceList()
-    sequence_string = self.TRADE_MODEL_RULE_SIMULATION_SEQUENCE_STRING
-    sequence_string += """
-              ConfirmOrder
-              Tic
-    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              GetPackingList
-              PackPackingList
-              Tic
-    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              StartPackingList
-              StopPackingList
-              DeliverPackingList
-              Tic
-    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              GetInvoice
-              CheckInvoiceCausalityStateSolved
-              CheckInvoiceNormalMovements
-    """
-    sequence_list.addSequenceString(sequence_string)
-    sequence_list.play(self)
-
-  def test_TradeModelRuleSimulationBuildInvoiceNewTradeCondition(self):
-    """Check that after changing trade condition invoice is not diverged"""
-    sequence_list = SequenceList()
-    sequence_string = self.TRADE_MODEL_RULE_SIMULATION_SEQUENCE_STRING
-    sequence_string += """
-              ConfirmOrder
-              Tic
-    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              GetPackingList
-              PackPackingList
-              Tic
-    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              StartPackingList
-              StopPackingList
-              DeliverPackingList
-              Tic
-    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              GetInvoice
-              CheckInvoiceCausalityStateSolved
-              CheckInvoiceNormalMovements
-
-              SetTradeConditionOld
-
-              CreateTradeCondition
-              SpecialiseTradeConditionWithBusinessProcess
-              CreateTradeModelLine
-              ModifyTradeModelLineNewTax
-              CreateTradeModelLine
-              ModifyTradeModelLineNewDiscount
-              Tic
-
-              SpecialiseInvoiceTradeCondition
-              Tic
-              CheckInvoiceCausalityStateSolved
-    """
-    sequence_list.addSequenceString(sequence_string)
-    sequence_list.play(self)
-
-  def test_TradeModelRuleSimulationBuildInvoiceNewInvoiceLineSupport(self):
-    """Check how is supported addition of invoice line to invoice build from order"""
-    sequence_list = SequenceList()
-    sequence_string = self.TRADE_MODEL_RULE_SIMULATION_SEQUENCE_STRING
-    sequence_string += """
-              ConfirmOrder
-              Tic
-    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              GetPackingList
-              PackPackingList
-              Tic
-    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              StartPackingList
-              StopPackingList
-              DeliverPackingList
-              Tic
-    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              GetInvoice
-              CheckInvoiceCausalityStateSolved
-              CheckInvoiceNormalMovements
-
-              CreateInvoiceLine
-              ModifyInvoiceLineDiscounted
-              CreateInvoiceLine
-              ModifyInvoiceLineDiscountedTaxed
-              CreateInvoiceLine
-              ModifyInvoiceLineTaxed
-
-              Tic
-
-              CheckInvoiceCausalityStateSolved
-
-              StartInvoice
-              Tic
-              CheckInvoiceCausalityStateSolved
-              CheckInvoiceNormalMovements
-              CheckInvoiceAccountingMovements
-              StopInvoice
-              DeliverInvoice
-              Tic
-    """
-    sequence_list.addSequenceString(sequence_string)
-    sequence_list.play(self)
-
-  def test_TradeModelRuleSimulationBuildInvoiceInvoiceLineModifyDivergencyAndSolving(self):
-    """Check that after changing invoice line invoice is properly diverged and it is possible to solve"""
-    sequence_list = SequenceList()
-    sequence_string = self.TRADE_MODEL_RULE_SIMULATION_SEQUENCE_STRING
-    sequence_string += """
-              ConfirmOrder
-              Tic
-    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              GetPackingList
-              PackPackingList
-              Tic
-    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              StartPackingList
-              StopPackingList
-              DeliverPackingList
-              Tic
-    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              GetInvoice
-              CheckInvoiceCausalityStateSolved
-              CheckInvoiceNormalMovements
-
-              GetInvoiceLineDiscounted
-              GetInvoiceLineDiscountedTaxed
-              GetInvoiceLineTaxed
-
-              ModifyQuantityInvoiceLineDiscounted
-              ModifyQuantityInvoiceLineDiscountedTaxed
-              ModifyQuantityInvoiceLineTaxed
-              Tic
-              CheckInvoiceCausalityStateDiverged
-              AcceptDecisionQuantityInvoice
-              Tic
-              CheckInvoiceCausalityStateSolved
-              CheckInvoiceNormalMovements
-    """
-    sequence_list.addSequenceString(sequence_string)
-    sequence_list.play(self)
-
-  def test_TradeModelRuleSimulationBuildInvoiceBuildInvoiceTransactionLines(self):
-    """Check that having properly configured invoice transaction rule it invoice transaction lines are nicely generated and have proper amounts"""
-    sequence_list = SequenceList()
-    sequence_string = self.TRADE_MODEL_RULE_SIMULATION_SEQUENCE_STRING
-    sequence_string += """
-              ConfirmOrder
-              Tic
-    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              GetPackingList
-              PackPackingList
-              Tic
-    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              StartPackingList
-              StopPackingList
-              DeliverPackingList
-              Tic
-    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              GetInvoice
-              CheckInvoiceCausalityStateSolved
-              CheckInvoiceNormalMovements
-
-              StartInvoice
-              Tic
-              CheckInvoiceCausalityStateSolved
-              CheckInvoiceNormalMovements
-              CheckInvoiceAccountingMovements
-              StopInvoice
-              DeliverInvoice
-              Tic
-    """
-    sequence_list.addSequenceString(sequence_string)
-    sequence_list.play(self)
-
-  PACKING_LIST_SPLIT_INVOICE_BUILD_SEQUENCE_STRING = \
-      TRADE_MODEL_RULE_SIMULATION_SEQUENCE_STRING + """
-              ConfirmOrder
-              Tic
-    """ + AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              GetPackingList
-              DecreasePackingListLineListQuantity
-              Tic
-    """ + AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              CheckPackingListDiverged
-              SplitAndDeferPackingList
-              Tic
-    """ + AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              GetNewPackingList
-              PackPackingList
-              Tic
-    """ + AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              StartPackingList
-              StopPackingList
-              DeliverPackingList
-              Tic
-    """ + AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              GetInvoice
-              CheckInvoiceCausalityStateSolved
-              CheckInvoiceNormalMovements
-
-              SetNewPackingListAsPackingList
-              PackPackingList
-              Tic
-              StartPackingList
-    """ + AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              StopPackingList
-              DeliverPackingList
-              Tic
-    """ + AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
-              GetInvoice
-              CheckInvoiceCausalityStateSolved
-              CheckInvoiceNormalMovements
-    """
-
-  def test_TradeModelRuleSimulationPackingListSplitBuildInvoiceBuildDifferentRatio(self):
-    """Check building invoice after splitting packing list using different ratio"""
-    self.modified_packing_list_line_quantity_ratio = 0.4
-    sequence_list = SequenceList()
-    sequence_list.addSequenceString(
-        self.PACKING_LIST_SPLIT_INVOICE_BUILD_SEQUENCE_STRING)
-    sequence_list.play(self)
-
-  def test_TradeModelRuleSimulationPackingListSplitBuildInvoiceBuild(self):
-    """Check building invoice after splitting packing list"""
-    sequence_list = SequenceList()
-    sequence_list.addSequenceString(
-        self.PACKING_LIST_SPLIT_INVOICE_BUILD_SEQUENCE_STRING)
-    sequence_list.play(self)
-
-  def test_getAggregatedAmountListWithComplexModelLinesCreateInEasyOrder(self):
-    """
-    Test the return of getAggregatedAmountList in the case of many model lines
-    depending each others. In this test, lines are created in the order of the
-    dependancies (it means that if a line A depend of a line B, line B is
-    created before A). This is the most easy case.
-
-    Dependance tree :
-    ModelLineTaxContributingToTotalTax : A
-    ModelLineDiscountContributingToTotalDiscount : B
-    ModelLineTaxContributingToTotalTax2 : C
-    ModelLineTotalTax : D
-    ModelLineTotalDiscount : E
-
-                              D       E
-                               \     /
-                                \   /
-                                 \ /
-                                  C      B
-                                   \    /
-                                    \  /
-                                     \/
-                                      A
-    Model line creation order : E, D, C, B, A
-    """
-    sequence_list = SequenceList()
-    sequence_string = self.COMMON_DOCUMENTS_CREATION_SEQUENCE_STRING + """
-              CreateBusinessProcess
-              CreateBusinessState
-              ModifyBusinessStateTaxed
-              CreateBusinessState
-              ModifyBusinessStateInvoiced
-              CreateBusinessPath
-              ModifyBusinessPathTaxing
-              CreateBusinessPath
-              ModifyBusinessPathDiscounting
-              CreateTradeCondition
-              SpecialiseTradeConditionWithBusinessProcess
-              CreateTradeModelLine
-              ModifyTradeModelLineTotalDiscount
-              CreateTradeModelLine
-              ModifyTradeModelLineTotalTax
-              CreateTradeModelLine
-              ModifyTradeModelLineTaxContributingToTotalTax2
-              CreateTradeModelLine
-              ModifyTradeModelLineDiscountContributingToTotalDiscount
-              CreateTradeModelLine
-              ModifyTradeModelLineTaxContributingToTotalTax
-              Tic
-              CreateOrder
-              SpecialiseOrderTradeCondition
-              FillOrder
-              Tic
-              CreateOrderLine
-              ModifyOrderLineTaxed
-              CreateOrderLine
-              ModifyOrderLineDiscounted
-              Tic
-              CheckAggregatedAmountListWithComplexBaseContributionBaseApplication
-    """
-    sequence_list.addSequenceString(sequence_string)
-    sequence_list.play(self)
-
-  def test_getAggregatedAmountListWithComplexModelLinesCreateInRandomOrder(self):
-    """
-    Test the return of getAggregatedAmountList in the case of many model lines
-    depending each others. In this test, lines are created in a random order,
-    not in the dependancies order (it means that if a line A depend of a 
-    line B, line A can be created before line B). getAggregatedAmountList
-    should be able to handle this case and redo calculation unill all
-    dependancies are satified
-
-    Dependance tree :
-    ModelLineTaxContributingToTotalTax : A
-    ModelLineDiscountContributingToTotalDiscount : B
-    ModelLineTaxContributingToTotalTax2 : C
-    ModelLineTotalTax : D
-    ModelLineTotalDiscount : E
-
-                              D       E
-                               \     /
-                                \   /
-                                 \ /
-                                  C      B
-                                   \    /
-                                    \  /
-                                     \/
-                                      A
-    Model line creation order : A, C, D, B, E
-    """
-    sequence_list = SequenceList()
-    sequence_string = self.COMMON_DOCUMENTS_CREATION_SEQUENCE_STRING + """
-              CreateBusinessProcess
-              CreateBusinessState
-              ModifyBusinessStateTaxed
-              CreateBusinessState
-              ModifyBusinessStateInvoiced
-              CreateBusinessPath
-              ModifyBusinessPathTaxing
-              CreateBusinessPath
-              ModifyBusinessPathDiscounting
-              CreateTradeCondition
-              SpecialiseTradeConditionWithBusinessProcess
-              CreateTradeModelLine
-              ModifyTradeModelLineTaxContributingToTotalTax
-              CreateTradeModelLine
-              ModifyTradeModelLineTaxContributingToTotalTax2
-              CreateTradeModelLine
-              ModifyTradeModelLineTotalTax
-              CreateTradeModelLine
-              ModifyTradeModelLineDiscountContributingToTotalDiscount
-              CreateTradeModelLine
-              ModifyTradeModelLineTotalDiscount
-              Tic
-              CreateOrder
-              SpecialiseOrderTradeCondition
-              FillOrder
-              Tic
-              CreateOrderLine
-              ModifyOrderLineTaxed
-              CreateOrderLine
-              ModifyOrderLineDiscounted
-              Tic
-              CheckAggregatedAmountListWithComplexBaseContributionBaseApplication
-    """
-    sequence_list.addSequenceString(sequence_string)
-    sequence_list.play(self)
-
-class TestBPMSale(TestBPMTestCases):
-  invoice_portal_type = 'Sale Invoice Transaction'
-  invoice_line_portal_type = 'Invoice Line'
-  order_portal_type = 'Sale Order'
-  order_line_portal_type = 'Sale Order Line'
-  packing_list_portal_type = 'Sale Packing List'
-  trade_condition_portal_type = 'Sale Trade Condition'
-  trade_model_line_portal_type = 'Trade Model Line'
-
-
-class TestBPMPurchase(TestBPMTestCases):
-  invoice_portal_type = 'Purchase Invoice Transaction'
-  invoice_line_portal_type = 'Invoice Line'
-  order_portal_type = 'Purchase Order'
-  order_line_portal_type = 'Purchase Order Line'
-  packing_list_portal_type = 'Purchase Packing List'
-  trade_condition_portal_type = 'Purchase Trade Condition'
-  trade_model_line_portal_type = 'Trade Model Line'
-
-
 class TestBPMImplementation(TestBPMMixin):
   """Business Process implementation tests"""
   def test_BusinessProcess_getPathValueList(self):
@@ -2784,7 +597,5 @@ class TestBPMImplementation(TestBPMMixin):
 
 def test_suite():
   suite = unittest.TestSuite()
-  suite.addTest(unittest.makeSuite(TestBPMSale))
-  suite.addTest(unittest.makeSuite(TestBPMPurchase))
   suite.addTest(unittest.makeSuite(TestBPMImplementation))
   return suite
diff --git a/product/ERP5/tests/testMRP.py b/product/ERP5/tests/testMRP.py
index 7c4a9bf4a9fd68db37a30453f41fd244a522c57e..47c7d5ae2af560d3deaeb35696d9e26409a8ef1d 100644
--- a/product/ERP5/tests/testMRP.py
+++ b/product/ERP5/tests/testMRP.py
@@ -30,10 +30,8 @@ import unittest
 import transaction
 
 from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
-from AccessControl.SecurityManagement import newSecurityManager
 from DateTime import DateTime
 
-from Products.ERP5Type.tests.Sequence import SequenceList
 from Products.CMFCore.utils import getToolByName
 from Products.ERP5Type.tests.utils import reindex
 
@@ -48,8 +46,7 @@ class TestMRPMixin(TestBPMMixin):
   order_line_portal_type = 'Production Order Line'
 
   def getBusinessTemplateList(self):
-    return ('erp5_base', 'erp5_pdm', 'erp5_trade', 'erp5_accounting',
-      'erp5_invoicing', 'erp5_simplified_invoicing', 'erp5_mrp')
+    return TestBPMMixin.getBusinessTemplateList(self) + ('erp5_mrp', )
 
   def invalidateRules(self):
     """
diff --git a/product/ERP5/tests/testPayroll.py b/product/ERP5/tests/testPayroll.py
index 55ad07542e1ac9c7a5ad8b32e3101876ad0b44d8..a5cdeec46d424f2005f3e1278b43438495cb3eb0 100644
--- a/product/ERP5/tests/testPayroll.py
+++ b/product/ERP5/tests/testPayroll.py
@@ -26,7 +26,7 @@
 #
 ##############################################################################
 from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5ReportTestCase
-from Products.ERP5.tests.testBPMCore import TestBPMMixin
+from Products.ERP5.tests.testTradeModelLine import TestTradeModelLineMixin
 from AccessControl.SecurityManagement import newSecurityManager
 from Products.ERP5Type.tests.Sequence import SequenceList
 from Products.ERP5Type.tests.utils import reindex
@@ -34,7 +34,7 @@ from Products.CMFCore.utils import getToolByName
 from DateTime import DateTime
 import transaction
 
-class TestPayrollMixin(ERP5ReportTestCase, TestBPMMixin):
+class TestPayrollMixin(ERP5ReportTestCase, TestTradeModelLineMixin):
   normal_resource_use_category_list = ['payroll/base_salary']
   invoicing_resource_use_category_list = ['payroll/tax']
 
@@ -174,10 +174,7 @@ class TestPayrollMixin(ERP5ReportTestCase, TestBPMMixin):
            )
 
   def getBusinessTemplateList(self):
-    """ """
-    return ('erp5_base', 'erp5_pdm', 'erp5_trade', 'erp5_accounting',
-            'erp5_invoicing', 'erp5_simplified_invoicing', 'erp5_mrp',
-            'erp5_payroll')
+    return TestTradeModelLineMixin.getBusinessTemplateList(self) + ('erp5_payroll', )
 
   def createService(self):
     module = self.portal.getDefaultModule(portal_type='Service')
diff --git a/product/ERP5/tests/testTradeModelLine.py b/product/ERP5/tests/testTradeModelLine.py
new file mode 100644
index 0000000000000000000000000000000000000000..20724a91c94c7fcf33618329ca604fb37ede1248
--- /dev/null
+++ b/product/ERP5/tests/testTradeModelLine.py
@@ -0,0 +1,2234 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+# Copyright (c) 2009 Nexedi SA and Contributors. All Rights Reserved.
+#          艁ukasz Nowak <luke@nexedi.com>
+#          Fabien Morin <fabien@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsibility of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# guarantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import unittest
+import transaction
+
+from Products.ERP5.tests.testBPMCore import TestBPMMixin
+from Products.ERP5Type.tests.Sequence import SequenceList
+from DateTime import DateTime
+from Products.CMFCore.utils import getToolByName
+
+# XXX TODO:
+#  * subclass TestTradeModelLine from TestInvoiceMixin and refactor methods and
+#    style
+
+class TestTradeModelLineMixin(TestBPMMixin):
+  """Provides methods to implementations sharing similar logic to Trade Model Lines"""
+  # Constants and variables shared by tests
+  base_unit_quantity = 0.01
+
+  # Helpers
+  def createResource(self, portal_type, **kw):
+    module = self.portal.getDefaultModule(portal_type=portal_type)
+    return module.newContent(portal_type=portal_type, **kw)
+
+  # Steps
+  def stepCreatePriceCurrency(self, sequence=None, **kw):
+    sequence.edit(price_currency = self.createResource('Currency', \
+        title='Currency', base_unit_quantity=self.base_unit_quantity))
+
+  def stepCreateBusinessProcess(self, sequence=None, **kw):
+    sequence.edit(business_process=self.createBusinessProcess())
+
+  def stepCreateBusinessPath(self, sequence=None, **kw):
+    business_process = sequence.get('business_process')
+    sequence.edit(business_path=self.createBusinessPath(business_process))
+
+class TestTradeModelLine(TestTradeModelLineMixin):
+  # Constants and variables shared by tests
+  default_discount_ratio = -0.05 # -5%
+  default_tax_ratio = 0.196 # 19,6%
+
+  new_discount_ratio = -0.04 # -4%
+  new_tax_ratio = 0.22 # 22%
+
+  node_portal_type = 'Organisation'
+  order_date = DateTime()
+
+  modified_order_line_price_ratio = 2.0
+  modified_invoice_line_quantity_ratio = modified_order_line_quantity_ratio \
+      = 2.5
+
+  modified_packing_list_line_quantity_ratio = 0.5
+
+  COMMON_DOCUMENTS_CREATION_SEQUENCE_STRING = """
+              CreateServiceTax
+              CreateServiceDiscount
+              CreatePriceCurrency
+              CreateProductDiscounted
+              CreateProductTaxed
+              CreateProductDiscountedTaxed
+              CreateSource
+              CreateSourceSection
+              CreateDestination
+              CreateDestinationSection
+              Tic
+  """
+
+  AGGREGATED_AMOUNT_LIST_CHECK_SEQUENCE_STRING = """
+              CheckOrderComplexTradeConditionAggregatedAmountList
+              CheckOrderLineTaxedAggregatedAmountList
+              CheckOrderLineDiscountedTaxedAggregatedAmountList
+              CheckOrderLineDiscountedAggregatedAmountList
+  """
+
+  AGGREGATED_AMOUNT_LIST_COMMON_SEQUENCE_STRING = \
+      COMMON_DOCUMENTS_CREATION_SEQUENCE_STRING + """
+              CreateBusinessProcess
+              CreateBusinessState
+              ModifyBusinessStateTaxed
+              CreateBusinessState
+              ModifyBusinessStateInvoiced
+              CreateBusinessPath
+              ModifyBusinessPathTaxing
+              CreateBusinessPath
+              ModifyBusinessPathDiscounting
+              CreateTradeCondition
+              SpecialiseTradeConditionWithBusinessProcess
+              CreateTradeModelLine
+              ModifyTradeModelLineTax
+              CreateTradeModelLine
+              ModifyTradeModelLineDiscount
+              Tic
+              CreateOrder
+              SpecialiseOrderTradeCondition
+              FillOrder
+              Tic
+              CreateOrderLine
+              ModifyOrderLineTaxed
+              CreateOrderLine
+              ModifyOrderLineDiscounted
+              CreateOrderLine
+              ModifyOrderLineDiscountedTaxed
+              Tic
+  """ + AGGREGATED_AMOUNT_LIST_CHECK_SEQUENCE_STRING
+
+  # Helper methods
+  def _solveDivergence(self, obj, property, decision, group='line'):
+    kw = {'%s_group_listbox' % group:{}}
+    for divergence in obj.getDivergenceList():
+      if divergence.getProperty('tested_property') != property:
+        continue
+      sm_url = divergence.getProperty('simulation_movement').getRelativeUrl()
+      kw['line_group_listbox']['%s&%s' % (sm_url, property)] = {
+        'choice':decision}
+    self.portal.portal_workflow.doActionFor(
+      obj,
+      'solve_divergence_action',
+      **kw)
+
+  def createOrder(self):
+    module = self.portal.getDefaultModule(portal_type=self.order_portal_type)
+    return module.newContent(portal_type=self.order_portal_type,
+        title=self.id())
+
+  def getTradeModelSimulationMovementList(self, order_line):
+    result_list = []
+    for line_simulation_movement in order_line.getOrderRelatedValueList(
+        portal_type='Simulation Movement'):
+      invoicing_applied_rule = [x for x in
+          line_simulation_movement.objectValues()
+          if x.getSpecialiseValue().getPortalType() == 'Invoicing Rule'][0]
+      invoicing_movement = invoicing_applied_rule.objectValues()[0]
+      trade_model_rule = [x for x in invoicing_movement.objectValues()
+          if x.getSpecialiseValue().getPortalType() == 'Trade Model Rule'][0]
+      result_list.append(trade_model_rule.objectValues())
+    return result_list
+
+  def checkInvoiceTransactionRule(self, trade_model_simulation_movement):
+    invoice_transaction_rule_list = trade_model_simulation_movement\
+        .objectValues()
+    self.assertEquals(1, len(invoice_transaction_rule_list))
+    invoice_transaction_rule = invoice_transaction_rule_list[0]
+    self.assertEqual('Invoice Transaction Rule',
+        invoice_transaction_rule.getSpecialiseValue().getPortalType())
+
+    invoice_transaction_simulation_movement_list = invoice_transaction_rule \
+        .objectValues()
+
+    self.assertEqual(2, len(invoice_transaction_simulation_movement_list))
+
+    for movement in invoice_transaction_simulation_movement_list:
+      self.assertEqual(abs(movement.getQuantity()),
+          abs(trade_model_simulation_movement.getTotalPrice()))
+
+  def createTradeCondition(self):
+    module = self.portal.getDefaultModule(
+        portal_type=self.trade_condition_portal_type)
+    trade_condition = module.newContent(
+        portal_type=self.trade_condition_portal_type,
+        title=self.id())
+    return trade_condition
+
+  def createTradeModelLine(self, document, **kw):
+    return document.newContent(
+        portal_type='Trade Model Line',
+        **kw)
+
+  # Steps
+  def stepCreateBusinessState(self, sequence=None, **kw):
+    business_process = sequence.get('business_process')
+    sequence.edit(business_state=self.createBusinessState(business_process))
+
+  def stepModifyBusinessPathDiscounting(self, sequence=None, **kw):
+    predecessor = sequence.get('business_state_invoiced')
+    successor = sequence.get('business_state_taxed')
+    business_path = sequence.get('business_path')
+    self.assertNotEqual(None, predecessor)
+    self.assertNotEqual(None, successor)
+
+    business_path.edit(
+      predecessor_value = predecessor,
+      successor_value = successor,
+      trade_phase = 'default/discount'
+    )
+    sequence.edit(business_path=None, business_path_discounting=business_path)
+
+  def stepModifyBusinessPathTaxing(self, sequence=None, **kw):
+    predecessor = sequence.get('business_state_invoiced')
+    successor = sequence.get('business_state_taxed')
+    business_path = sequence.get('business_path')
+    self.assertNotEqual(None, predecessor)
+    self.assertNotEqual(None, successor)
+
+    business_path.edit(
+      predecessor_value = predecessor,
+      successor_value = successor,
+      trade_phase = 'default/tax'
+    )
+    sequence.edit(business_path=None, business_path_taxing=business_path)
+
+  def stepModifyBusinessStateTaxed(self, sequence=None, **kw):
+    business_state = sequence.get('business_state')
+    business_state.edit(reference='taxed')
+    sequence.edit( business_state=None, business_state_taxed=business_state)
+
+  def stepModifyBusinessStateInvoiced(self, sequence=None,
+                sequence_string=None):
+    business_state = sequence.get('business_state')
+    business_state.edit(reference='invoiced')
+    sequence.edit(business_state=None, business_state_invoiced=business_state)
+
+  def stepAcceptDecisionQuantityInvoice(self, sequence=None, **kw):
+    invoice = sequence.get('invoice')
+    self._solveDivergence(invoice, 'quantity', 'accept')
+
+  def stepAdoptPrevisionQuantityInvoice(self, sequence=None, **kw):
+    invoice = sequence.get('invoice')
+    self._solveDivergence(invoice, 'quantity', 'adopt')
+
+  def stepCreateSource(self, sequence=None, **kw):
+    module = self.portal.getDefaultModule(portal_type=self.node_portal_type)
+    node = module.newContent(portal_type=self.node_portal_type)
+    sequence.edit(source = node)
+
+  def stepCreateSourceSection(self, sequence=None, **kw):
+    module = self.portal.getDefaultModule(portal_type=self.node_portal_type)
+    node = module.newContent(portal_type=self.node_portal_type)
+    sequence.edit(source_section = node)
+
+  def stepCreateDestination(self, sequence=None, **kw):
+    module = self.portal.getDefaultModule(portal_type=self.node_portal_type)
+    node = module.newContent(portal_type=self.node_portal_type)
+    sequence.edit(destination = node)
+
+  def stepCreateDestinationSection(self, sequence=None, **kw):
+    module = self.portal.getDefaultModule(portal_type=self.node_portal_type)
+    node = module.newContent(portal_type=self.node_portal_type)
+    sequence.edit(destination_section = node)
+
+  def stepCreateOrder(self, sequence=None, **kw):
+    sequence.edit(order = self.createOrder())
+
+  def stepSpecialiseOrderTradeCondition(self, sequence=None, **kw):
+    order = sequence.get('order')
+    trade_condition = sequence.get('trade_condition')
+
+    order.edit(specialise_value = trade_condition)
+
+  def stepSpecialiseInvoiceTradeCondition(self, sequence=None, **kw):
+    invoice = sequence.get('invoice')
+    trade_condition = sequence.get('trade_condition')
+
+    invoice.edit(specialise_value = trade_condition)
+
+  def stepPlanOrder(self, sequence=None, **kw):
+    order = sequence.get('order')
+    workflow_tool = getToolByName(self.portal, 'portal_workflow')
+    workflow_tool.doActionFor(order, 'plan_action')
+
+  def stepStartInvoice(self, sequence=None, **kw):
+    invoice = sequence.get('invoice')
+    workflow_tool = getToolByName(self.portal, 'portal_workflow')
+    workflow_tool.doActionFor(invoice, 'start_action')
+
+  def stepStopInvoice(self, sequence=None, **kw):
+    invoice = sequence.get('invoice')
+    workflow_tool = getToolByName(self.portal, 'portal_workflow')
+    workflow_tool.doActionFor(invoice, 'stop_action')
+
+  def stepDeliverInvoice(self, sequence=None, **kw):
+    invoice = sequence.get('invoice')
+    workflow_tool = getToolByName(self.portal, 'portal_workflow')
+    workflow_tool.doActionFor(invoice, 'deliver_action')
+
+  def stepStartPackingList(self, sequence=None, **kw):
+    packing_list = sequence.get('packing_list')
+    workflow_tool = getToolByName(self.portal, 'portal_workflow')
+    workflow_tool.doActionFor(packing_list, 'start_action')
+
+  def stepStopPackingList(self, sequence=None, **kw):
+    packing_list = sequence.get('packing_list')
+    workflow_tool = getToolByName(self.portal, 'portal_workflow')
+    workflow_tool.doActionFor(packing_list, 'stop_action')
+
+  def stepDeliverPackingList(self, sequence=None, **kw):
+    packing_list = sequence.get('packing_list')
+    workflow_tool = getToolByName(self.portal, 'portal_workflow')
+    workflow_tool.doActionFor(packing_list, 'deliver_action')
+
+  def stepCheckPackingListDiverged(self, sequence=None, **kw):
+    packing_list = sequence.get('packing_list')
+    self.assertEqual(
+      'diverged',
+      packing_list.getCausalityState()
+    )
+
+  def stepSplitAndDeferPackingList(self, sequence=None, **kw):
+    packing_list = sequence.get('packing_list')
+    kw = {'listbox':[
+      {'listbox_key':line.getRelativeUrl(),
+       'choice':'SplitAndDefer'} for line in packing_list.getMovementList() \
+      if line.isDivergent()]}
+    self.portal.portal_workflow.doActionFor(
+      packing_list,
+      'split_and_defer_action',
+      start_date=packing_list.getStartDate() + 15,
+      stop_date=packing_list.getStopDate() + 25,
+      **kw)
+
+  def stepDecreasePackingListLineListQuantity(self, sequence=None, **kw):
+    packing_list = sequence.get('packing_list')
+    for movement in packing_list.getMovementList():
+      movement.edit(
+        quantity = movement.getQuantity() * \
+            self.modified_packing_list_line_quantity_ratio
+      )
+
+  def stepPackPackingList(self, sequence=None, **kw):
+    packing_list = sequence.get('packing_list')
+    if getattr(packing_list,'getContainerState', None) is None:
+      return
+    if packing_list.getContainerState() == 'packed':
+      return
+
+    packing_list.manage_delObjects(ids=[q.getId() for q in
+      packing_list.objectValues(portal_type='Container')])
+    transaction.commit()
+    cntr = packing_list.newContent(portal_type='Container')
+    for movement in packing_list.getMovementList(
+        portal_type=self.portal.getPortalMovementTypeList()):
+      cntr.newContent(
+        portal_type='Container Line',
+        resource = movement.getResource(),
+        quantity = movement.getQuantity())
+    transaction.commit()
+    self.tic()
+    self.assertEqual('packed', packing_list.getContainerState() )
+
+  def stepCheckInvoiceNormalMovements(self, sequence=None, **kw):
+    self.logMessage('Assuming, that it is good...')
+
+  def stepCheckInvoiceAccountingMovements(self, sequence=None, **kw):
+    invoice = sequence.get('invoice')
+    currency = sequence.get('price_currency')
+    currency_precision = currency.getQuantityPrecision()
+    aggregated_amount_list_list = [
+      (q.getResourceValue().getUse(), q)
+      for q in invoice.getSpecialiseValue().getAggregatedAmountList(invoice)]
+    invoice_line_tax = [q[1] for q in aggregated_amount_list_list
+        if q[0] == 'tax'][0]
+    invoice_line_discount = [q[1] for q in aggregated_amount_list_list
+        if q[0] == 'discount'][0]
+
+    movement_list = invoice.getMovementList(
+        portal_type=invoice.getPortalAccountingMovementTypeList())
+    self.assertEqual(3, len(movement_list))
+    income_expense_line = [q for q in movement_list if
+        q.getSourceValue().getAccountType() in ['income', 'expense']][0]
+    payable_receivable_line = [q for q in movement_list if
+        q.getSourceValue().getAccountType() in ['asset/receivable',
+          'liability/payable']][0]
+    vat_line = [q for q in movement_list if q.getSourceValue() \
+        .getAccountType() in ['liability/payable/collected_vat',
+          'asset/receivable/refundable_vat']][0]
+
+    rounded_total_price = round(invoice.getTotalPrice(), currency_precision)
+    rounded_tax_price = round(invoice_line_tax.getTotalPrice(),
+        currency_precision)
+    rounded_discount_price = round(invoice_line_discount.getTotalPrice(),
+        currency_precision)
+
+    self.assertEqual(abs(payable_receivable_line.getTotalPrice()),
+        rounded_total_price + rounded_tax_price + rounded_discount_price)
+
+    self.assertEqual(abs(vat_line.getTotalPrice()),
+        rounded_tax_price)
+
+    self.assertEquals(abs(income_expense_line.getTotalPrice()),
+        rounded_total_price + rounded_discount_price)
+
+  def stepSetTradeConditionOld(self, sequence=None, **kw):
+    trade_condition = sequence.get('trade_condition')
+
+    self.assertNotEqual(None, trade_condition)
+
+    sequence.edit(
+      trade_condition = None,
+      old_trade_condition = trade_condition
+    )
+
+  def stepSetTradeConditionNew(self, sequence=None, **kw):
+    trade_condition = sequence.get('trade_condition')
+
+    self.assertNotEqual(None, trade_condition)
+
+    sequence.edit(
+      trade_condition = None,
+      new_trade_condition = trade_condition
+    )
+
+  def stepGetOldTradeCondition(self, sequence=None, **kw):
+    trade_condition = sequence.get('old_trade_condition')
+
+    self.assertNotEqual(None, trade_condition)
+
+    sequence.edit(
+      trade_condition = trade_condition,
+    )
+
+  def stepGetNewTradeCondition(self, sequence=None, **kw):
+    trade_condition = sequence.get('new_trade_condition')
+
+    self.assertNotEqual(None, trade_condition)
+
+    sequence.edit(
+      trade_condition = trade_condition,
+    )
+
+  def stepAcceptDecisionInvoice(self, sequence=None, **kw):
+    invoice = sequence.get('invoice')
+    invoice.portal_workflow.doActionFor(invoice,'accept_decision_action')
+
+  def stepCheckInvoiceCausalityStateSolved(self, sequence=None, **kw):
+    invoice = sequence.get('invoice')
+    self.assertEqual('solved', invoice.getCausalityState(),
+      invoice.getDivergenceList())
+
+  def stepCheckInvoiceCausalityStateDiverged(self, sequence=None, **kw):
+    invoice = sequence.get('invoice')
+    self.assertEqual('diverged', invoice.getCausalityState())
+
+  def stepGetInvoice(self, sequence=None, **kw):
+    packing_list = sequence.get('packing_list')
+    invoice_list = packing_list.getCausalityRelatedValueList(
+        portal_type=self.invoice_portal_type)
+    self.assertEqual(1, len(invoice_list)) # XXX 1 HC
+    sequence.edit(invoice = invoice_list[0])
+
+  def stepSetNewPackingListAsPackingList(self, sequence=None, **kw):
+    packing_list = sequence.get('packing_list')
+    new_packing_list = sequence.get('new_packing_list')
+    sequence.edit(
+      packing_list = new_packing_list,
+      new_packing_list = None
+    )
+
+  def stepGetNewPackingList(self, sequence=None, **kw):
+    order = sequence.get('order')
+    packing_list = sequence.get('packing_list')
+    packing_list_list = order.getCausalityRelatedValueList(
+        portal_type=self.packing_list_portal_type)
+    self.assertEqual(2, len(packing_list_list)) # XXX 2 HC
+    new_packing_list = [q for q in packing_list_list if q != packing_list][0]
+    sequence.edit(new_packing_list = new_packing_list)
+
+  def stepGetPackingList(self, sequence=None, **kw):
+    order = sequence.get('order')
+    packing_list_list = order.getCausalityRelatedValueList(
+        portal_type=self.packing_list_portal_type)
+    self.assertEqual(1, len(packing_list_list)) # XXX 1 HC
+    sequence.edit(packing_list = packing_list_list[0])
+
+  def stepConfirmOrder(self, sequence=None, **kw):
+    order = sequence.get('order')
+    workflow_tool = getToolByName(self.portal, 'portal_workflow')
+    workflow_tool.doActionFor(order, 'confirm_action')
+
+  def stepCheckOrderTaxNoSimulation(self, sequence=None, **kw):
+    order_line_taxed = sequence.get('order_line_taxed')
+    for trade_model_simulation_movement_list in \
+        self.getTradeModelSimulationMovementList(order_line_taxed):
+      self.assertEquals(0, len(trade_model_simulation_movement_list))
+
+  # XXX: Merge: stepCheckOrderLineDiscountedSimulation stepCheckOrderLineTaxedSimulation stepCheckOrderLineDiscountedTaxedSimulation
+
+  def stepCheckOrderLineDiscountedTaxedSimulation(self, sequence=None, **kw):
+    order_line = sequence.get('order_line_discounted_taxed')
+    business_path_discounting = sequence.get('business_path_discounting')
+    business_path_taxing = sequence.get('business_path_taxing')
+    price_currency = sequence.get('price_currency')
+
+    service_tax = sequence.get('service_tax')
+    service_discount = sequence.get('service_discount')
+
+    self.assertNotEqual(None, business_path_discounting)
+    self.assertNotEqual(None, business_path_taxing)
+    self.assertNotEqual(None, price_currency)
+
+    for trade_model_simulation_movement_list in \
+        self.getTradeModelSimulationMovementList(order_line):
+
+      self.assertEquals(2, len(trade_model_simulation_movement_list))
+      trade_model_simulation_movement_discount_complex = [q for q in \
+          trade_model_simulation_movement_list \
+          if q.getResourceValue() == service_discount][0]
+
+      trade_model_simulation_movement_tax_complex = [q for q in \
+          trade_model_simulation_movement_list \
+          if q.getResourceValue() == service_tax][0]
+
+      # discount complex
+      self.assertEqual(
+        trade_model_simulation_movement_discount_complex.getParentValue() \
+            .getParentValue().getTotalPrice() * self.default_discount_ratio,
+        trade_model_simulation_movement_discount_complex.getTotalPrice()
+      )
+
+      self.assertEqual(
+        business_path_discounting,
+        trade_model_simulation_movement_discount_complex.getCausalityValue()
+      )
+
+      self.assertEqual(
+        price_currency,
+        trade_model_simulation_movement_discount_complex \
+            .getPriceCurrencyValue()
+      )
+
+      self.assertSameSet(
+        ['base_amount/tax'],
+        trade_model_simulation_movement_discount_complex \
+            .getBaseContributionList()
+      )
+
+      self.assertSameSet(
+        ['base_amount/discount'],
+        trade_model_simulation_movement_discount_complex \
+            .getBaseApplicationList()
+      )
+
+      self.checkInvoiceTransactionRule(
+          trade_model_simulation_movement_discount_complex)
+
+      # TODO:
+      #  * trade_phase ???
+      #  * arrow
+      #  * dates
+
+      # tax complex
+      self.assertEqual(
+        (trade_model_simulation_movement_tax_complex.getParentValue()\
+            .getParentValue().getTotalPrice() + \
+            trade_model_simulation_movement_tax_complex.getParentValue()\
+            .getParentValue().getTotalPrice() * self.default_discount_ratio) \
+            * self.default_tax_ratio,
+        trade_model_simulation_movement_tax_complex.getTotalPrice()
+      )
+
+      self.assertEqual(
+        business_path_taxing,
+        trade_model_simulation_movement_tax_complex.getCausalityValue()
+      )
+
+      self.assertEqual(
+        price_currency,
+        trade_model_simulation_movement_tax_complex.getPriceCurrencyValue()
+      )
+
+      self.assertSameSet(
+        [],
+        trade_model_simulation_movement_tax_complex.getBaseContributionList()
+      )
+
+      self.assertSameSet(
+        ['base_amount/tax'],
+        trade_model_simulation_movement_tax_complex.getBaseApplicationList()
+      )
+
+      self.checkInvoiceTransactionRule(
+        trade_model_simulation_movement_tax_complex)
+      # TODO:
+      #  * trade_phase ???
+      #  * arrow
+      #  * dates
+
+  def stepCheckOrderLineDiscountedSimulation(self, sequence=None, **kw):
+    order_line = sequence.get('order_line_discounted')
+    business_path_discounting = sequence.get('business_path_discounting')
+    business_path_taxing = sequence.get('business_path_taxing')
+    price_currency = sequence.get('price_currency')
+
+    service_tax = sequence.get('service_tax')
+    service_discount = sequence.get('service_discount')
+
+    self.assertNotEqual(None, business_path_discounting)
+    self.assertNotEqual(None, business_path_taxing)
+    self.assertNotEqual(None, price_currency)
+
+    for trade_model_simulation_movement_list in \
+        self.getTradeModelSimulationMovementList(order_line):
+
+      self.assertEquals(2, len(trade_model_simulation_movement_list))
+      trade_model_simulation_movement_discount_only = [q for q in \
+          trade_model_simulation_movement_list \
+          if q.getResourceValue() == service_discount][0]
+
+      trade_model_simulation_movement_tax_only = [q for q in \
+          trade_model_simulation_movement_list \
+          if q.getResourceValue() == service_tax][0]
+
+      # discount only
+      self.assertEqual(
+        trade_model_simulation_movement_discount_only.getParentValue()\
+            .getParentValue().getTotalPrice() * self.default_discount_ratio,
+        trade_model_simulation_movement_discount_only.getTotalPrice()
+      )
+
+      self.assertEqual(
+        business_path_discounting,
+        trade_model_simulation_movement_discount_only.getCausalityValue()
+      )
+
+      self.assertEqual(
+        price_currency,
+        trade_model_simulation_movement_discount_only.getPriceCurrencyValue()
+      )
+
+      self.assertSameSet(
+        ['base_amount/tax'],
+        trade_model_simulation_movement_discount_only \
+            .getBaseContributionList()
+      )
+
+      self.assertSameSet(
+        ['base_amount/discount'],
+        trade_model_simulation_movement_discount_only.getBaseApplicationList()
+      )
+
+      self.checkInvoiceTransactionRule(
+          trade_model_simulation_movement_discount_only)
+      # TODO:
+      #  * trade_phase ???
+      #  * arrow
+      #  * dates
+
+      # tax only
+      # below tax is applied only to discount part
+      self.assertEqual(trade_model_simulation_movement_discount_only. \
+          getTotalPrice() * self.default_tax_ratio,
+          trade_model_simulation_movement_tax_only.getTotalPrice())
+
+      self.assertEqual(
+        business_path_taxing,
+        trade_model_simulation_movement_tax_only.getCausalityValue()
+      )
+
+      self.assertEqual(
+        price_currency,
+        trade_model_simulation_movement_tax_only.getPriceCurrencyValue()
+      )
+
+      self.assertSameSet(
+        [],
+        trade_model_simulation_movement_tax_only.getBaseContributionList()
+      )
+
+      self.assertSameSet(
+        ['base_amount/tax'],
+        trade_model_simulation_movement_tax_only.getBaseApplicationList()
+      )
+
+      self.checkInvoiceTransactionRule(
+          trade_model_simulation_movement_tax_only)
+
+      # TODO:
+      #  * trade_phase ???
+      #  * arrow
+      #  * dates
+
+  def stepCheckOrderLineTaxedSimulation(self, sequence=None, **kw):
+    order_line = sequence.get('order_line_taxed')
+    business_path = sequence.get('business_path_taxing')
+    price_currency = sequence.get('price_currency')
+    self.assertNotEqual(None, business_path)
+    self.assertNotEqual(None, price_currency)
+    for trade_model_simulation_movement_list in \
+        self.getTradeModelSimulationMovementList(order_line):
+      self.assertEquals(1, len(trade_model_simulation_movement_list))
+      trade_model_simulation_movement = \
+          trade_model_simulation_movement_list[0]
+
+      self.assertEqual(
+        trade_model_simulation_movement.getParentValue().getParentValue() \
+            .getTotalPrice() * self.default_tax_ratio,
+        trade_model_simulation_movement.getTotalPrice()
+      )
+
+      self.assertEqual(
+        business_path,
+        trade_model_simulation_movement.getCausalityValue()
+      )
+
+      self.assertEqual(
+        price_currency,
+        trade_model_simulation_movement.getPriceCurrencyValue()
+      )
+
+      self.assertSameSet(
+        [],
+        trade_model_simulation_movement.getBaseContributionList()
+      )
+
+      self.assertSameSet(
+        ['base_amount/tax'],
+        trade_model_simulation_movement.getBaseApplicationList()
+      )
+      self.checkInvoiceTransactionRule(trade_model_simulation_movement)
+
+      # TODO:
+      #  * trade_phase ???
+      #  * arrow
+      #  * dates
+
+  def stepFillOrder(self, sequence=None, **kw):
+    order = sequence.get('order')
+    price_currency = sequence.get('price_currency')
+    source = sequence.get('source')
+    destination = sequence.get('destination')
+    source_section = sequence.get('source_section')
+    destination_section = sequence.get('destination_section')
+    self.assertNotEqual(None, price_currency)
+    self.assertNotEqual(None, source)
+    self.assertNotEqual(None, destination)
+    self.assertNotEqual(None, source_section)
+    self.assertNotEqual(None, destination_section)
+    order.edit(
+        source_value=source,
+        destination_value=destination,
+        source_section_value=source_section,
+        destination_section_value=destination_section,
+        start_date=self.order_date,
+        price_currency_value = price_currency)
+
+  def stepCreateProductTaxed(self, sequence=None, **kw):
+    sequence.edit(product_taxed = self.createResource('Product',
+      title='Product Taxed',
+      base_contribution=['base_amount/tax'],
+      use='normal',
+    ))
+
+  def stepCreateProductDiscounted(self, sequence=None, **kw):
+    sequence.edit(product_discounted = self.createResource('Product',
+      title='Product Discounted',
+      base_contribution=['base_amount/discount'],
+      use='normal',
+    ))
+
+  def stepCreateProductDiscountedTaxed(self, sequence=None, **kw):
+    sequence.edit(product_discounted_taxed = self.createResource('Product',
+      title='Product Discounted & Taxed',
+      base_contribution=['base_amount/discount', 'base_amount/tax'],
+      use='normal',
+    ))
+
+  def stepCreateServiceTax(self, sequence=None, **kw):
+    sequence.edit(service_tax = self.createResource('Service',
+      title='Tax',
+      use='tax',
+    ))
+
+  def stepCreateServiceDiscount(self, sequence=None, **kw):
+    sequence.edit(service_discount = self.createResource('Service',
+      title='Discount',
+      use='discount',
+    ))
+
+  def stepCreateTradeCondition(self, sequence=None, **kw):
+    sequence.edit(trade_condition = self.createTradeCondition())
+
+  def stepCreateInvoiceLine(self, sequence=None, **kw):
+    invoice = sequence.get('invoice')
+    invoice_line = invoice.newContent(portal_type=self.invoice_line_portal_type)
+    sequence.edit(invoice_line = invoice_line)
+
+  def stepCreateOrderLine(self, sequence=None, **kw):
+    order = sequence.get('order')
+    order_line = order.newContent(portal_type=self.order_line_portal_type)
+    sequence.edit(order_line = order_line)
+
+  def stepGetInvoiceLineDiscounted(self, sequence=None, **kw):
+    invoice = sequence.get('invoice')
+    resource = sequence.get('product_discounted')
+    self.assertNotEqual(None, resource)
+    sequence.edit(invoice_line_discounted = [m for m in
+      invoice.getMovementList() if m.getResourceValue() == resource][0])
+
+  def stepGetInvoiceLineDiscountedTaxed(self, sequence=None, **kw):
+    invoice = sequence.get('invoice')
+    resource = sequence.get('product_discounted_taxed')
+    self.assertNotEqual(None, resource)
+    sequence.edit(invoice_line_discounted_taxed = [m for m in
+      invoice.getMovementList() if m.getResourceValue() == resource][0])
+
+  def stepGetInvoiceLineTaxed(self, sequence=None, **kw):
+    invoice = sequence.get('invoice')
+    resource = sequence.get('product_taxed')
+    self.assertNotEqual(None, resource)
+    sequence.edit(invoice_line_taxed = [m for m in
+      invoice.getMovementList() if m.getResourceValue() == resource][0])
+
+  def stepModifyQuantityInvoiceLineTaxed(self, sequence=None, **kw):
+    invoice_line = sequence.get('invoice_line_taxed')
+    invoice_line.edit(
+      quantity=invoice_line.getQuantity() * \
+          self.modified_invoice_line_quantity_ratio,
+    )
+
+  def stepModifyQuantityInvoiceLineDiscounted(self, sequence=None, **kw):
+    invoice_line = sequence.get('invoice_line_discounted')
+    invoice_line.edit(
+      quantity=invoice_line.getQuantity() * \
+          self.modified_invoice_line_quantity_ratio,
+    )
+
+  def stepModifyQuantityInvoiceLineDiscountedTaxed(self, sequence=None, **kw):
+    invoice_line = sequence.get('invoice_line_discounted_taxed')
+    invoice_line.edit(
+      quantity=invoice_line.getQuantity() * \
+          self.modified_invoice_line_quantity_ratio,
+    )
+
+  def stepModifyAgainOrderLineTaxed(self, sequence=None, **kw):
+    order_line = sequence.get('order_line_taxed')
+    order_line.edit(
+      price=order_line.getPrice() * self.modified_order_line_price_ratio,
+      quantity=order_line.getQuantity() * \
+          self.modified_order_line_quantity_ratio,
+    )
+
+  def stepModifyAgainOrderLineDiscounted(self, sequence=None, **kw):
+    order_line = sequence.get('order_line_discounted')
+    order_line.edit(
+      price=order_line.getPrice() * self.modified_order_line_price_ratio,
+      quantity=order_line.getQuantity() * \
+          self.modified_order_line_quantity_ratio,
+    )
+
+  def stepModifyAgainOrderLineDiscountedTaxed(self, sequence=None, **kw):
+    order_line = sequence.get('order_line_discounted_taxed')
+    order_line.edit(
+      price=order_line.getPrice() * self.modified_order_line_price_ratio,
+      quantity=order_line.getQuantity() * \
+          self.modified_order_line_quantity_ratio,
+    )
+
+  def stepModifyOrderLineTaxed(self, sequence=None, **kw):
+    order_line = sequence.get('order_line')
+    resource = sequence.get('product_taxed')
+    self.assertNotEqual(None, resource)
+    order_line.edit(
+      price=1.0,
+      quantity=2.0,
+      resource_value=resource
+    )
+    sequence.edit(
+      order_line = None,
+      order_line_taxed = order_line
+    )
+
+  def stepModifyOrderLineDiscounted(self, sequence=None, **kw):
+    order_line = sequence.get('order_line')
+    resource = sequence.get('product_discounted')
+    self.assertNotEqual(None, resource)
+    order_line.edit(
+      price=3.0,
+      quantity=4.0,
+      resource_value=resource
+    )
+    sequence.edit(
+      order_line = None,
+      order_line_discounted = order_line
+    )
+
+  def stepModifyOrderLineDiscountedTaxed(self, sequence=None, **kw):
+    order_line = sequence.get('order_line')
+    resource = sequence.get('product_discounted_taxed')
+    self.assertNotEqual(None, resource)
+    order_line.edit(
+      price=5.0,
+      quantity=6.0,
+      resource_value=resource
+    )
+    sequence.edit(
+      order_line = None,
+      order_line_discounted_taxed = order_line
+    )
+
+  def stepModifyInvoiceLineTaxed(self, sequence=None, **kw):
+    invoice_line = sequence.get('invoice_line')
+    resource = sequence.get('product_taxed')
+    self.assertNotEqual(None, resource)
+    invoice_line.edit(
+      price=1.0,
+      quantity=2.0,
+      resource_value=resource
+    )
+    sequence.edit(
+      invoice_line = None,
+      invoice_line_taxed = invoice_line
+    )
+
+  def stepModifyInvoiceLineDiscounted(self, sequence=None, **kw):
+    invoice_line = sequence.get('invoice_line')
+    resource = sequence.get('product_discounted')
+    self.assertNotEqual(None, resource)
+    invoice_line.edit(
+      price=3.0,
+      quantity=4.0,
+      resource_value=resource
+    )
+    sequence.edit(
+      invoice_line = None,
+      invoice_line_discounted = invoice_line
+    )
+
+  def stepModifyInvoiceLineDiscountedTaxed(self, sequence=None, **kw):
+    invoice_line = sequence.get('invoice_line')
+    resource = sequence.get('product_discounted_taxed')
+    self.assertNotEqual(None, resource)
+    invoice_line.edit(
+      price=5.0,
+      quantity=6.0,
+      resource_value=resource
+    )
+    sequence.edit(
+      invoice_line = None,
+      invoice_line_discounted_taxed = invoice_line
+    )
+
+  def stepOrderCreateTradeModelLine(self, sequence=None, **kw):
+    order = sequence.get('order')
+    sequence.edit(trade_model_line = self.createTradeModelLine(order))
+
+  def stepCreateTradeModelLine(self, sequence=None, **kw):
+    trade_condition = sequence.get('trade_condition')
+    sequence.edit(
+      trade_model_line = self.createTradeModelLine(trade_condition))
+
+  def stepSpecialiseTradeConditionWithBusinessProcess(self, sequence=None,
+      **kw):
+    business_process = sequence.get('business_process')
+    trade_condition = sequence.get('trade_condition')
+    self.assertNotEqual(None, business_process)
+    trade_condition.setSpecialiseValue(business_process)
+
+  def stepModifyTradeModelLineNewDiscount(self, sequence=None, **kw):
+    trade_model_line = sequence.get('trade_model_line')
+    service_discount = sequence.get('service_discount')
+
+    trade_model_line.edit(
+      price=self.new_discount_ratio,
+      base_application='base_amount/discount',
+      base_contribution='base_amount/tax',
+      trade_phase='default/discount',
+      resource_value=service_discount,
+      reference='service_discount',
+    )
+    sequence.edit(
+      trade_model_line = None,
+      trade_model_line_discount = trade_model_line
+    )
+
+  def stepModifyTradeModelLineDiscount(self, sequence=None, **kw):
+    trade_model_line = sequence.get('trade_model_line')
+    service_discount = sequence.get('service_discount')
+
+    trade_model_line.edit(
+      price=self.default_discount_ratio,
+      base_application='base_amount/discount',
+      base_contribution='base_amount/tax',
+      trade_phase='default/discount',
+      resource_value=service_discount,
+      reference='discount',
+    )
+    sequence.edit(
+      trade_model_line = None,
+      trade_model_line_discount = trade_model_line
+    )
+
+  def stepModifyTradeModelLineTotalDiscount(self, sequence=None, **kw):
+    trade_model_line = sequence.get('trade_model_line')
+    service_discount = sequence.get('service_discount')
+
+    trade_model_line.edit(
+      price=0.8,
+      base_application='base_amount/total_discount',
+      trade_phase='default/discount',
+      resource_value=service_discount,
+      reference='total_discount',
+    )
+    sequence.edit(
+      trade_model_line = None,
+      trade_model_line_discount = trade_model_line
+    )
+
+  def stepModifyTradeModelLineDiscountContributingToTotalDiscount(self,
+      sequence=None, **kw):
+    trade_model_line = sequence.get('trade_model_line')
+    service_discount = sequence.get('service_discount')
+
+    trade_model_line.edit(
+      price=0.32,
+      base_application='base_amount/discount',
+      base_contribution='base_amount/total_discount',
+      trade_phase='default/discount',
+      resource_value=service_discount,
+      reference='total_dicount_2',
+    )
+    sequence.edit(
+      trade_model_line = None,
+      trade_model_line_discount = trade_model_line
+    )
+
+  def stepModifyTradeModelLineNewTax(self, sequence=None, **kw):
+    trade_model_line = sequence.get('trade_model_line')
+    service_tax = sequence.get('service_tax')
+
+    trade_model_line.edit(
+      price=self.new_tax_ratio,
+      base_application='base_amount/tax',
+      trade_phase='default/tax',
+      resource_value=service_tax,
+      reference='tax_2',
+    )
+    sequence.edit(
+      trade_model_line = None,
+      trade_model_line_tax = trade_model_line
+    )
+
+  def stepModifyTradeModelLineTax(self, sequence=None, **kw):
+    trade_model_line = sequence.get('trade_model_line')
+    service_tax = sequence.get('service_tax')
+
+    trade_model_line.edit(
+      price=self.default_tax_ratio,
+      base_application='base_amount/tax',
+      trade_phase='default/tax',
+      resource_value=service_tax,
+      reference='tax',
+    )
+    sequence.edit(
+      trade_model_line = None,
+      trade_model_line_tax = trade_model_line
+    )
+
+  def stepModifyTradeModelLineTotalTax(self, sequence=None, **kw):
+    trade_model_line = sequence.get('trade_model_line')
+    service_tax = sequence.get('service_tax')
+
+    trade_model_line.edit(
+      price=0.12,
+      base_application='base_amount/total_tax',
+      base_contribution='base_amount/total_discount',
+      trade_phase='default/tax',
+      resource_value=service_tax,
+      reference='tax_3',
+    )
+    sequence.edit(
+      trade_model_line = None,
+      trade_model_line_tax = trade_model_line
+    )
+
+  def stepModifyTradeModelLineTaxContributingToTotalTax(self,
+      sequence=None, **kw):
+    trade_model_line = sequence.get('trade_model_line')
+    service_tax = sequence.get('service_tax')
+
+    trade_model_line.edit(
+      price=0.2,
+      base_application='base_amount/tax',
+      base_contribution='base_amount/total_tax',
+      trade_phase='default/tax',
+      resource_value=service_tax,
+      reference='service_tax',
+    )
+    sequence.edit(
+      trade_model_line = None,
+      trade_model_line_tax = trade_model_line
+    )
+
+  def stepModifyTradeModelLineTaxContributingToTotalTax2(self,
+      sequence=None, **kw):
+    trade_model_line = sequence.get('trade_model_line')
+    service_tax = sequence.get('service_tax')
+
+    trade_model_line.edit(
+      price=0.2,
+      base_application='base_amount/tax',
+      base_contribution='base_amount/total_tax',
+      trade_phase='default/tax',
+      resource_value=service_tax,
+      reference='service_tax_2',
+    )
+    sequence.edit(
+      trade_model_line = None,
+      trade_model_line_tax = trade_model_line
+    )
+
+  def stepUpdateAggregatedAmountListOnOrder(self,
+      sequence=None, **kw):
+    order = sequence.get('order')
+    order.Delivery_updateAggregatedAmountList(batch_mode=1)
+
+  def stepCheckOrderLineTaxedAggregatedAmountList(self, sequence=None, **kw):
+    order_line = sequence.get('order_line_taxed')
+    trade_condition = sequence.get('trade_condition')
+    trade_model_line_tax = sequence.get('trade_model_line_tax')
+    amount_list = trade_condition.getAggregatedAmountList(order_line)
+
+    self.assertEquals(1, len(amount_list))
+    tax_amount_list = [q for q in amount_list
+        if q.getBaseApplication() == 'base_amount/tax']
+    self.assertEquals(1, len(tax_amount_list))
+
+    tax_amount = tax_amount_list[0]
+
+    self.assertEqual(tax_amount.getReference(),
+        trade_model_line_tax.getReference())
+    self.assertSameSet(['base_amount/tax'],
+        tax_amount.getBaseApplicationList())
+    self.assertSameSet([], tax_amount.getBaseContributionList())
+
+    self.assertEqual(order_line.getTotalPrice() * self.default_tax_ratio,
+        tax_amount.getTotalPrice())
+
+  def stepCheckOrderLineDiscountedTaxedAggregatedAmountList(self,
+      sequence=None, **kw):
+    order_line = sequence.get('order_line_discounted_taxed')
+    trade_condition = sequence.get('trade_condition')
+    trade_model_line_discount = sequence.get('trade_model_line_discount')
+    trade_model_line_tax = sequence.get('trade_model_line_tax')
+    amount_list = trade_condition.getAggregatedAmountList(order_line)
+
+    self.assertEquals(2, len(amount_list))
+    tax_amount_list = [q for q in amount_list
+        if q.getBaseApplication() == 'base_amount/tax']
+    self.assertEquals(1, len(tax_amount_list))
+    tax_amount = tax_amount_list[0]
+
+    discount_amount_list = [q for q in amount_list
+        if q.getBaseApplication() == 'base_amount/discount']
+    self.assertEquals(1, len(discount_amount_list))
+
+    discount_amount = discount_amount_list[0]
+
+    self.assertEqual(tax_amount.getReference(),
+        trade_model_line_tax.getReference())
+    self.assertSameSet(['base_amount/tax'], tax_amount. \
+        getBaseApplicationList())
+    self.assertSameSet([], tax_amount.getBaseContributionList())
+
+    self.assertEqual(discount_amount.getReference(),
+        trade_model_line_discount.getReference())
+    self.assertSameSet(['base_amount/discount'], discount_amount. \
+        getBaseApplicationList())
+    self.assertSameSet(['base_amount/tax'], discount_amount. \
+        getBaseContributionList())
+
+    self.assertEqual(order_line.getTotalPrice() * \
+        self.default_discount_ratio, discount_amount.getTotalPrice())
+
+    self.assertEqual((order_line.getTotalPrice() + discount_amount. \
+        getTotalPrice()) * self.default_tax_ratio,
+        tax_amount.getTotalPrice())
+
+  def stepCheckOrderLineDiscountedAggregatedAmountList(self, sequence=None,
+      **kw):
+    order_line = sequence.get('order_line_discounted')
+    trade_condition = sequence.get('trade_condition')
+    trade_model_line_discount = sequence.get('trade_model_line_discount')
+    amount_list = trade_condition.getAggregatedAmountList(order_line)
+
+    self.assertEquals(2, len(amount_list))
+    tax_amount_list = [q for q in amount_list
+        if q.getBaseApplication() == 'base_amount/tax']
+    self.assertEquals(1, len(tax_amount_list))
+    tax_amount = tax_amount_list[0]
+
+    discount_amount_list = [q for q in amount_list
+        if q.getBaseApplication() == 'base_amount/discount']
+    self.assertEquals(1, len(discount_amount_list))
+
+    discount_amount = discount_amount_list[0]
+
+    self.assertEqual(discount_amount.getReference(),
+        trade_model_line_discount.getReference())
+    self.assertSameSet(['base_amount/tax'], tax_amount. \
+        getBaseApplicationList())
+    self.assertSameSet([], tax_amount.getBaseContributionList())
+
+    self.assertSameSet(['base_amount/discount'], discount_amount. \
+        getBaseApplicationList())
+    self.assertSameSet(['base_amount/tax'], discount_amount. \
+        getBaseContributionList())
+
+    self.assertEqual(order_line.getTotalPrice() * \
+        self.default_discount_ratio, discount_amount.getTotalPrice())
+
+    # below tax is applied only to discount part
+    self.assertEqual(discount_amount.getTotalPrice() * self.default_tax_ratio,
+        tax_amount.getTotalPrice())
+
+  def stepCheckOrderComplexTradeConditionAggregatedAmountList(self,
+      sequence=None, **kw):
+    trade_condition = sequence.get('trade_condition')
+    order = sequence.get('order')
+    order_line_discounted = sequence.get('order_line_discounted')
+    order_line_discounted_taxed = sequence.get('order_line_discounted_taxed')
+    order_line_taxed = sequence.get('order_line_taxed')
+    trade_model_line_tax = sequence.get('trade_model_line_tax')
+    trade_model_line_discount = sequence.get('trade_model_line_discount')
+
+    amount_list = trade_condition.getAggregatedAmountList(order)
+    self.assertEquals(2, len(amount_list))
+    discount_amount_list = [q for q in amount_list
+        if q.getBaseApplication() == 'base_amount/discount']
+    tax_amount_list = [q for q in amount_list
+        if q.getBaseApplication() == 'base_amount/tax']
+
+    self.assertEquals(1, len(discount_amount_list))
+    self.assertEquals(1, len(tax_amount_list))
+
+    discount_amount = discount_amount_list[0]
+    tax_amount = tax_amount_list[0]
+
+    self.assertEqual(discount_amount.getReference(),
+        trade_model_line_discount.getReference())
+    self.assertSameSet(['base_amount/discount'], discount_amount. \
+        getBaseApplicationList())
+
+    self.assertSameSet(['base_amount/tax'], discount_amount. \
+        getBaseContributionList())
+
+    self.assertSameSet(['base_amount/tax'], tax_amount. \
+        getBaseApplicationList())
+
+    self.assertSameSet([], tax_amount.getBaseContributionList())
+    self.assertEqual(tax_amount.getReference(),
+        trade_model_line_tax.getReference())
+
+    self.assertEqual(
+      discount_amount.getTotalPrice(),
+      (order_line_discounted.getTotalPrice()
+        + order_line_discounted_taxed.getTotalPrice() )
+      * self.default_discount_ratio
+    )
+
+    self.assertEqual(
+      tax_amount.getTotalPrice(),
+      (order_line_taxed.getTotalPrice()
+        + order_line_discounted_taxed.getTotalPrice()
+        + discount_amount.getTotalPrice()) * self.default_tax_ratio
+    )
+
+  def stepCheckAggregatedAmountListWithComplexBaseContributionBaseApplication(self,
+      sequence=None, **kw):
+    trade_condition = sequence.get('trade_condition')
+    order = sequence.get('order')
+    order_line_discounted = sequence.get('order_line_discounted')
+    order_line_discounted_taxed = sequence.get('order_line_discounted_taxed')
+    order_line_taxed = sequence.get('order_line_taxed')
+
+    amount_list = trade_condition.getAggregatedAmountList(order)
+    self.assertEquals(5, len(amount_list))
+    tax_amount_list = [q for q in amount_list
+        if q.getBaseApplication() == 'base_amount/tax']
+    total_tax_amount_list = [q for q in amount_list
+        if q.getBaseApplication() == 'base_amount/total_tax']
+    discount_amount_list = [q for q in amount_list
+        if q.getBaseApplication() == 'base_amount/discount']
+    total_discount_amount_list = [q for q in amount_list
+        if q.getBaseApplication() == 'base_amount/total_discount']
+
+    self.assertEquals(2, len(tax_amount_list))
+    self.assertEquals(1, len(total_tax_amount_list))
+    self.assertEquals(1, len(discount_amount_list))
+    self.assertEquals(1, len(total_discount_amount_list))
+
+    total_tax_amount = total_tax_amount_list[0]
+    discount_amount = discount_amount_list[0]
+    total_discount_amount = total_discount_amount_list[0]
+
+    self.assertSameSet(['base_amount/total_tax'], total_tax_amount. \
+        getBaseApplicationList())
+    self.assertSameSet(['base_amount/total_discount'], total_tax_amount. \
+        getBaseContributionList())
+
+    self.assertSameSet(['base_amount/discount'], discount_amount. \
+        getBaseApplicationList())
+    self.assertSameSet(['base_amount/total_discount'], discount_amount. \
+        getBaseContributionList())
+
+    self.assertSameSet(['base_amount/total_discount'], total_discount_amount. \
+        getBaseApplicationList())
+    self.assertSameSet([], total_discount_amount.getBaseContributionList())
+
+    for tax_amount in tax_amount_list:
+      self.assertSameSet(['base_amount/tax'], tax_amount. \
+          getBaseApplicationList())
+      self.assertSameSet(['base_amount/total_tax'], tax_amount. \
+          getBaseContributionList())
+
+    for tax_amount in tax_amount_list:
+      self.assertEqual(
+        tax_amount.getTotalPrice(),
+        order_line_taxed.getTotalPrice() * 0.2
+      )
+
+    self.assertEqual(
+      total_tax_amount.getTotalPrice(),
+      (order_line_taxed.getTotalPrice() * 0.2) * 2 * 0.12
+    )
+
+    self.assertEqual(
+      discount_amount.getTotalPrice(),
+      order_line_discounted.getTotalPrice() * 0.32
+    )
+
+    self.assertEqual(
+      total_discount_amount.getTotalPrice(),
+      ((order_line_taxed.getTotalPrice() * 0.2) * 2 * 0.12 + \
+      order_line_discounted.getTotalPrice() * 0.32) * 0.8
+    )
+
+  # Tests
+  def test_TradeConditionTradeModelLineCircularComposition(self):
+    """
+      If Trade Condition is specialised by another Trade Condition they
+      Trade Model Lines shall be merged.
+    """
+    trade_condition_1 = self.createTradeCondition()
+    trade_condition_2 = self.createTradeCondition()
+
+    trade_condition_1.setSpecialiseValue(trade_condition_2)
+    trade_condition_2.setSpecialiseValue(trade_condition_1)
+
+    self.assertEquals(trade_condition_1. \
+        findSpecialiseValueList(trade_condition_1),
+        [trade_condition_1, trade_condition_2]
+    )
+
+  def test_TradeConditionTradeModelLineBasicComposition(self):
+    """
+      If Trade Condition is specialised by another Trade Condition they
+      Trade Model Lines shall be merged.
+    """
+    service_1 = self.createResource('Service')
+    service_2 = self.createResource('Service')
+
+    trade_condition_1 = self.createTradeCondition()
+    trade_condition_2 = self.createTradeCondition()
+
+    trade_condition_1.setSpecialiseValue(trade_condition_2)
+
+    trade_condition_1_trade_model_line = self.createTradeModelLine(
+        trade_condition_1,
+        resource_value = service_1)
+
+    trade_condition_2_trade_model_line = self.createTradeModelLine(
+        trade_condition_2,
+        resource_value = service_2)
+
+    self.assertSameSet(
+      [trade_condition_1_trade_model_line,
+        trade_condition_2_trade_model_line],
+      trade_condition_1.getTradeModelLineComposedList()
+    )
+
+  def test_findSpecialiseValueList(self):
+    '''
+      check that findSpecialiseValueList is able to return all the inheritance
+      model tree using Depth-first search
+
+                                  trade_condition_1
+                                    /           \
+                                   /             \
+                                  /               \
+                       trade_condition_2       trade_condition_3
+                               |
+                               |
+                               |
+                        trade_condition_4
+
+       according to Depth-first search algorihm, result of this graph should be
+       [trade_condition_1, trade_condition_2, trade_condition_3,
+       trade_condition_4]
+    '''
+    trade_condition_1 = self.createTradeCondition()
+    trade_condition_2 = self.createTradeCondition()
+    trade_condition_3 = self.createTradeCondition()
+    trade_condition_4 = self.createTradeCondition()
+
+    trade_condition_1.setSpecialiseValueList((trade_condition_2,
+      trade_condition_3))
+    trade_condition_2.setSpecialiseValue(trade_condition_4)
+
+    speciliase_value_list = trade_condition_1.findSpecialiseValueList(context=\
+        trade_condition_1)
+    self.assertEquals(len(speciliase_value_list), 4)
+    self.assertEquals(
+      [trade_condition_1, trade_condition_2, trade_condition_3,
+       trade_condition_4], speciliase_value_list)
+
+  def test_TradeConditionTradeModelLineBasicCompositionWithOrder(self):
+    """
+      If Trade Condition is specialised by another Trade Condition they
+      Trade Model Lines shall be merged.
+    """
+    service_1 = self.createResource('Service')
+    service_2 = self.createResource('Service')
+    service_3 = self.createResource('Service')
+
+    trade_condition_1 = self.createTradeCondition()
+    trade_condition_2 = self.createTradeCondition()
+    order = self.createOrder()
+
+    trade_condition_1.setSpecialiseValue(trade_condition_2)
+    order.setSpecialiseValue(trade_condition_1)
+
+    trade_condition_1_trade_model_line = self.createTradeModelLine(
+        trade_condition_1,
+        resource_value = service_1)
+
+    trade_condition_2_trade_model_line = self.createTradeModelLine(
+        trade_condition_2,
+        resource_value = service_2)
+
+    order_trade_model_line = self.createTradeModelLine(
+        order,
+        resource_value = service_3)
+
+    self.assertSameSet(
+      [trade_condition_1_trade_model_line, trade_condition_2_trade_model_line],
+      trade_condition_1.getTradeModelLineComposedList()
+    )
+
+    self.assertSameSet(
+      [trade_condition_1_trade_model_line, trade_condition_2_trade_model_line,
+        order_trade_model_line],
+      trade_condition_1.getTradeModelLineComposedList(context=order)
+    )
+
+  def test_TradeConditionTradeModelLineResourceIsShadowingCompositionWithOrder(self):
+    """
+      If Trade Condition is specialised by another Trade Condition they
+      Trade Model Lines shall be merged.
+    """
+    service_1 = self.createResource('Service')
+    service_2 = self.createResource('Service')
+
+    trade_condition_1 = self.createTradeCondition()
+    trade_condition_2 = self.createTradeCondition()
+    order = self.createOrder()
+
+    trade_condition_1.setSpecialiseValue(trade_condition_2)
+    order.setSpecialiseValue(trade_condition_1)
+
+    trade_condition_1_trade_model_line = self.createTradeModelLine(
+        trade_condition_1,
+        resource_value = service_1,
+        reference = 'A')
+
+    trade_condition_2_trade_model_line = self.createTradeModelLine(
+        trade_condition_2,
+        resource_value = service_2,
+        reference = 'B')
+
+    order_trade_model_line = self.createTradeModelLine(
+        order,
+        resource_value = service_2,
+        reference = 'B')
+
+    self.assertSameSet(
+      [trade_condition_1_trade_model_line,
+        trade_condition_2_trade_model_line],
+      trade_condition_1.getTradeModelLineComposedList()
+    )
+
+    self.assertSameSet(
+      [trade_condition_1_trade_model_line, order_trade_model_line],
+      trade_condition_1.getTradeModelLineComposedList(context=order)
+    )
+
+  def test_TradeConditionTradeModelLineResourceIsShadowingComposition(self):
+    """
+      If Trade Condition is specialised by another Trade Condition
+      and resource is repeated, only first Trade Model Line shall be returned.
+    """
+    service = self.createResource('Service')
+
+    trade_condition_1 = self.createTradeCondition()
+    trade_condition_2 = self.createTradeCondition()
+
+    trade_condition_1.setSpecialiseValue(trade_condition_2)
+
+    trade_condition_1_trade_model_line = self.createTradeModelLine(
+        trade_condition_1,
+        resource_value = service,
+        reference = 'A')
+
+    trade_condition_2_trade_model_line = self.createTradeModelLine(
+        trade_condition_2,
+        resource_value = service,
+        reference = 'A')
+
+    self.assertSameSet(
+      [trade_condition_1_trade_model_line],
+      trade_condition_1.getTradeModelLineComposedList()
+    )
+
+  def test_getTradeModelLineComposedList(self):
+    """Test that list of contribution/application relations is sorted to do easy traversal
+
+    Let assume such graph of contribution/application dependency:
+
+    D -----> B
+          /   \
+    E ---/     > A
+              /
+    F -----> C
+          /
+    G ---/
+
+    It shall return list which is sorted like:
+      * (DE) B (FG) C A
+        or
+      * (FG) C (DE) B A
+        or
+      * (DEFG) (BC) A
+    where everything in parenthesis can be not sorted
+    """
+    trade_condition = self.createTradeCondition()
+
+    A = self.createTradeModelLine(trade_condition, reference='A',
+        base_application_list=['base_amount/total'])
+
+    B = self.createTradeModelLine(trade_condition, reference='B',
+        base_contribution_list=['base_amount/total'],
+        base_application_list=['base_amount/total_tax'])
+
+    C = self.createTradeModelLine(trade_condition, reference='C',
+        base_contribution_list=['base_amount/total'],
+        base_application_list=['base_amount/total_discount'])
+
+    D = self.createTradeModelLine(trade_condition, reference='D',
+        base_contribution_list=['base_amount/total_tax'],
+        base_application_list=['base_amount/tax'])
+
+    E = self.createTradeModelLine(trade_condition, reference='E',
+        base_contribution_list=['base_amount/total_tax'],
+        base_application_list=['base_amount/tax'])
+
+    F = self.createTradeModelLine(trade_condition, reference='F',
+        base_contribution_list=['base_amount/total_discount'],
+        base_application_list=['base_amount/discount'])
+
+    G = self.createTradeModelLine(trade_condition, reference='G',
+        base_contribution_list=['base_amount/total_discount'],
+        base_application_list=['base_amount/discount'])
+
+    trade_model_line_list = trade_condition.getTradeModelLineComposedList()
+
+    # XXX: This is only one good possible sorting
+    self.assertEquals([q.getReference() for q in trade_model_line_list],
+        [q.getReference() for q in [G, F, E, D, C, B, A]])
+
+  def test_getComplexTradeModelLineComposedList(self):
+    """Test that list of contribution/application relations is sorted to do easy traversal
+
+    Let assume such graph of contribution/application dependency:
+
+             /--------\
+            /          \
+      A----+ -----B-----+-D
+            \          /
+             \----C---/
+
+    It shall return list which is sorted like:
+      * A (BC) D
+    where everything in parenthesis can be not sorted
+    """
+    trade_condition = self.createTradeCondition()
+
+    C = self.createTradeModelLine(trade_condition, reference='C',
+        base_contribution_list=['base_amount/total'],
+        base_application_list=['base_amount/total_discount'])
+
+    A = self.createTradeModelLine(trade_condition, reference='A',
+        base_contribution_list=['base_amount/total', 'base_amount/total_tax',
+          'base_amount/total_discount'],
+        base_application_list=['base_amount/tax'])
+
+    D = self.createTradeModelLine(trade_condition, reference='D',
+        base_application_list=['base_amount/total'])
+
+    B = self.createTradeModelLine(trade_condition, reference='B',
+        base_contribution_list=['base_amount/total'],
+        base_application_list=['base_amount/total_tax'])
+
+    trade_model_line_list = trade_condition.getTradeModelLineComposedList()
+
+    # XXX: This is only one good possible sorting
+    self.assertEquals([q.getReference() for q in trade_model_line_list],
+        [q.getReference() for q in [A, B, C, D]])
+
+  def test_tradeModelLineWithFixedPrice(self):
+    """
+      Check it's possible to have fixed quantity on lines. Sometimes we want
+      to say "discount 10 euros" or "pay more 10 euros" instead of saying "10%
+      discount from total"
+    """
+    trade_condition = self.createTradeCondition()
+
+    # create a model line with 100 euros
+    A = self.createTradeModelLine(trade_condition, reference='A',
+        base_contribution_list=['base_amount/total'])
+    A.edit(quantity=100, price=1)
+
+    # add a discount of 10 euros
+    B = self.createTradeModelLine(trade_condition, reference='B',
+        base_contribution_list=['base_amount/total'])
+    B.edit(quantity=10, price=-1)
+
+    order = self.createOrder()
+    order.setSpecialiseValue(trade_condition)
+    amount_list = trade_condition.getAggregatedAmountList(order)
+    self.assertEquals(2, len(amount_list))
+    total_amount_list = [q for q in amount_list
+        if q.getBaseContribution() == 'base_amount/total']
+
+    self.assertEquals(2, len(total_amount_list))
+
+    # the total amount for base_amount/total should be of 100 - 10 = 90 euros
+    total_amount = 0
+    for amount in total_amount_list:
+      total_amount += amount.getTotalPrice()
+
+    self.assertEqual(total_amount, 100 - 10)
+
+  def test_getAggregatedAmountList(self):
+    """
+      Test for case, when discount contributes to tax, and order has mix of contributing lines
+    """
+    sequence_list = SequenceList()
+    sequence_string = self.AGGREGATED_AMOUNT_LIST_COMMON_SEQUENCE_STRING
+
+    sequence_list.addSequenceString(sequence_string)
+    sequence_list.play(self)
+
+  ORDER_SPECIALISE_AGGREGATED_AMOUNT_COMMON_SEQUENCE_STRING = \
+      COMMON_DOCUMENTS_CREATION_SEQUENCE_STRING + """
+              CreateBusinessProcess
+              CreateBusinessState
+              ModifyBusinessStateTaxed
+              CreateBusinessState
+              ModifyBusinessStateInvoiced
+              CreateBusinessPath
+              ModifyBusinessPathTaxing
+              CreateBusinessPath
+              ModifyBusinessPathDiscounting
+              CreateTradeCondition
+              SpecialiseTradeConditionWithBusinessProcess
+              CreateTradeModelLine
+              ModifyTradeModelLineTax
+              Tic
+              CreateOrder
+              OrderCreateTradeModelLine
+              ModifyTradeModelLineDiscount
+              SpecialiseOrderTradeCondition
+              FillOrder
+              Tic
+              CreateOrderLine
+              ModifyOrderLineTaxed
+              CreateOrderLine
+              ModifyOrderLineDiscounted
+              CreateOrderLine
+              ModifyOrderLineDiscountedTaxed
+              Tic
+    """ + AGGREGATED_AMOUNT_LIST_CHECK_SEQUENCE_STRING
+
+  def test_getAggregatedAmountListOrderSpecialise(self):
+    """
+      Test for case, when discount contributes to tax, and order has mix of contributing lines and order itself defines Trade Model Line
+    """
+    sequence_list = SequenceList()
+    sequence_string = self\
+        .ORDER_SPECIALISE_AGGREGATED_AMOUNT_COMMON_SEQUENCE_STRING
+
+    sequence_list.addSequenceString(sequence_string)
+    sequence_list.play(self)
+
+  def test_getAggregatedAmountList_afterUpdateAggregatedAmountList(self):
+    """
+      Test for case, when discount contributes to tax, and order has mix of contributing lines
+
+      Check if it is stable if updateAggregatedAmountList was invoked.
+
+      Note: This test assumes, that somethings contributes after update, shall
+            be rewritten in a way, that adds explicitly movement which shall
+            not be aggregated.
+    """
+    sequence_list = SequenceList()
+    sequence_string = self.AGGREGATED_AMOUNT_LIST_COMMON_SEQUENCE_STRING + """
+              UpdateAggregatedAmountListOnOrder
+              Tic
+    """ + self.AGGREGATED_AMOUNT_LIST_CHECK_SEQUENCE_STRING
+
+    sequence_list.addSequenceString(sequence_string)
+    sequence_list.play(self)
+
+  AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING = """
+              CheckOrderLineTaxedSimulation
+              CheckOrderLineDiscountedSimulation
+              CheckOrderLineDiscountedTaxedSimulation
+  """
+  TRADE_MODEL_RULE_SIMULATION_SEQUENCE_STRING = \
+      AGGREGATED_AMOUNT_LIST_COMMON_SEQUENCE_STRING + """
+              Tic
+              PlanOrder
+              Tic
+  """ + AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING
+
+  def test_TradeModelRuleSimulationExpand(self):
+    """Tests tree of simulations from Trade Model Rule"""
+    sequence_list = SequenceList()
+    sequence_string = self.TRADE_MODEL_RULE_SIMULATION_SEQUENCE_STRING
+    sequence_list.addSequenceString(sequence_string)
+    sequence_list.play(self)
+
+  def test_TradeModelRuleSimulationReexpand(self):
+    """Tests tree of simulations from Trade Model Rule with reexpanding"""
+    sequence_list = SequenceList()
+    sequence_string = self.TRADE_MODEL_RULE_SIMULATION_SEQUENCE_STRING + """
+              ModifyAgainOrderLineTaxed
+              ModifyAgainOrderLineDiscounted
+              ModifyAgainOrderLineDiscountedTaxed
+              Tic
+    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING
+    sequence_list.addSequenceString(sequence_string)
+    sequence_list.play(self)
+
+  def test_TradeModelRuleSimulationReexpandResourceChange(self):
+    """Tests tree of simulations from Trade Model Rule with reexpanding when resource changes on model"""
+    sequence_list = SequenceList()
+    sequence_string = self.TRADE_MODEL_RULE_SIMULATION_SEQUENCE_STRING + """
+              CreateServiceTax
+              CreateServiceDiscount
+              OrderCreateTradeModelLine
+              ModifyTradeModelLineDiscount
+              OrderCreateTradeModelLine
+              ModifyTradeModelLineTax
+              Tic
+    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING
+    sequence_list.addSequenceString(sequence_string)
+    sequence_list.play(self)
+
+  TRADE_MODEL_RULE_SIMULATION_ORDER_SPECIALISED_SEQUENCE_STRING = \
+      ORDER_SPECIALISE_AGGREGATED_AMOUNT_COMMON_SEQUENCE_STRING + """
+              Tic
+              PlanOrder
+              Tic
+  """ + AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING
+
+  def test_TradeModelRuleSimulationExpandOrderSpecialise(self):
+    """Tests tree of simulations from Trade Model Rule"""
+    sequence_list = SequenceList()
+    sequence_string = self \
+        .TRADE_MODEL_RULE_SIMULATION_ORDER_SPECIALISED_SEQUENCE_STRING
+    sequence_list.addSequenceString(sequence_string)
+    sequence_list.play(self)
+
+  def test_TradeModelRuleSimulationReexpandOrderSpecialise(self):
+    """Tests tree of simulations from Trade Model Rule with reexpanding"""
+    sequence_list = SequenceList()
+    sequence_string = self \
+        .TRADE_MODEL_RULE_SIMULATION_ORDER_SPECIALISED_SEQUENCE_STRING+ """
+              ModifyAgainOrderLineTaxed
+              ModifyAgainOrderLineDiscounted
+              ModifyAgainOrderLineDiscountedTaxed
+              Tic
+    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING
+    sequence_list.addSequenceString(sequence_string)
+    sequence_list.play(self)
+
+  def test_TradeModelRuleSimulationWithoutBPM(self):
+    """Tests tree of simulations from Trade Model Rule when there is no BPM"""
+    sequence_list = SequenceList()
+    sequence_string = self.COMMON_DOCUMENTS_CREATION_SEQUENCE_STRING + """
+              CreateTradeCondition
+              CreateTradeModelLine
+              ModifyTradeModelLineTax
+              Tic
+              CreateOrder
+              SpecialiseOrderTradeCondition
+              FillOrder
+              Tic
+              CreateOrderLine
+              ModifyOrderLineTaxed
+              Tic
+              PlanOrder
+              Tic
+              CheckOrderTaxNoSimulation
+    """
+    sequence_list.addSequenceString(sequence_string)
+    sequence_list.play(self)
+
+  def test_TradeModelRuleSimulationWithoutTradeCondition(self):
+    """Tests tree of simulations from Trade Model Rule when there is no Trade Condition"""
+    sequence_list = SequenceList()
+    sequence_string = self.COMMON_DOCUMENTS_CREATION_SEQUENCE_STRING + """
+              CreateOrder
+              FillOrder
+              Tic
+              CreateOrderLine
+              ModifyOrderLineTaxed
+              Tic
+              PlanOrder
+              Tic
+              CheckOrderTaxNoSimulation
+    """
+    sequence_list.addSequenceString(sequence_string)
+    sequence_list.play(self)
+
+  def test_TradeModelRuleSimulationBuildInvoice(self):
+    """Check that invoice lines on invoice are correctly set"""
+    sequence_list = SequenceList()
+    sequence_string = self.TRADE_MODEL_RULE_SIMULATION_SEQUENCE_STRING
+    sequence_string += """
+              ConfirmOrder
+              Tic
+    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              GetPackingList
+              PackPackingList
+              Tic
+    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              StartPackingList
+              StopPackingList
+              DeliverPackingList
+              Tic
+    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              GetInvoice
+              CheckInvoiceCausalityStateSolved
+              CheckInvoiceNormalMovements
+    """
+    sequence_list.addSequenceString(sequence_string)
+    sequence_list.play(self)
+
+  def test_TradeModelRuleSimulationBuildInvoiceNewTradeCondition(self):
+    """Check that after changing trade condition invoice is not diverged"""
+    sequence_list = SequenceList()
+    sequence_string = self.TRADE_MODEL_RULE_SIMULATION_SEQUENCE_STRING
+    sequence_string += """
+              ConfirmOrder
+              Tic
+    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              GetPackingList
+              PackPackingList
+              Tic
+    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              StartPackingList
+              StopPackingList
+              DeliverPackingList
+              Tic
+    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              GetInvoice
+              CheckInvoiceCausalityStateSolved
+              CheckInvoiceNormalMovements
+
+              SetTradeConditionOld
+
+              CreateTradeCondition
+              SpecialiseTradeConditionWithBusinessProcess
+              CreateTradeModelLine
+              ModifyTradeModelLineNewTax
+              CreateTradeModelLine
+              ModifyTradeModelLineNewDiscount
+              Tic
+
+              SpecialiseInvoiceTradeCondition
+              Tic
+              CheckInvoiceCausalityStateSolved
+    """
+    sequence_list.addSequenceString(sequence_string)
+    sequence_list.play(self)
+
+  def test_TradeModelRuleSimulationBuildInvoiceNewInvoiceLineSupport(self):
+    """Check how is supported addition of invoice line to invoice build from order"""
+    sequence_list = SequenceList()
+    sequence_string = self.TRADE_MODEL_RULE_SIMULATION_SEQUENCE_STRING
+    sequence_string += """
+              ConfirmOrder
+              Tic
+    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              GetPackingList
+              PackPackingList
+              Tic
+    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              StartPackingList
+              StopPackingList
+              DeliverPackingList
+              Tic
+    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              GetInvoice
+              CheckInvoiceCausalityStateSolved
+              CheckInvoiceNormalMovements
+
+              CreateInvoiceLine
+              ModifyInvoiceLineDiscounted
+              CreateInvoiceLine
+              ModifyInvoiceLineDiscountedTaxed
+              CreateInvoiceLine
+              ModifyInvoiceLineTaxed
+
+              Tic
+
+              CheckInvoiceCausalityStateSolved
+
+              StartInvoice
+              Tic
+              CheckInvoiceCausalityStateSolved
+              CheckInvoiceNormalMovements
+              CheckInvoiceAccountingMovements
+              StopInvoice
+              DeliverInvoice
+              Tic
+    """
+    sequence_list.addSequenceString(sequence_string)
+    sequence_list.play(self)
+
+  def test_TradeModelRuleSimulationBuildInvoiceInvoiceLineModifyDivergencyAndSolving(self):
+    """Check that after changing invoice line invoice is properly diverged and it is possible to solve"""
+    sequence_list = SequenceList()
+    sequence_string = self.TRADE_MODEL_RULE_SIMULATION_SEQUENCE_STRING
+    sequence_string += """
+              ConfirmOrder
+              Tic
+    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              GetPackingList
+              PackPackingList
+              Tic
+    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              StartPackingList
+              StopPackingList
+              DeliverPackingList
+              Tic
+    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              GetInvoice
+              CheckInvoiceCausalityStateSolved
+              CheckInvoiceNormalMovements
+
+              GetInvoiceLineDiscounted
+              GetInvoiceLineDiscountedTaxed
+              GetInvoiceLineTaxed
+
+              ModifyQuantityInvoiceLineDiscounted
+              ModifyQuantityInvoiceLineDiscountedTaxed
+              ModifyQuantityInvoiceLineTaxed
+              Tic
+              CheckInvoiceCausalityStateDiverged
+              AcceptDecisionQuantityInvoice
+              Tic
+              CheckInvoiceCausalityStateSolved
+              CheckInvoiceNormalMovements
+    """
+    sequence_list.addSequenceString(sequence_string)
+    sequence_list.play(self)
+
+  def test_TradeModelRuleSimulationBuildInvoiceBuildInvoiceTransactionLines(self):
+    """Check that having properly configured invoice transaction rule it invoice transaction lines are nicely generated and have proper amounts"""
+    sequence_list = SequenceList()
+    sequence_string = self.TRADE_MODEL_RULE_SIMULATION_SEQUENCE_STRING
+    sequence_string += """
+              ConfirmOrder
+              Tic
+    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              GetPackingList
+              PackPackingList
+              Tic
+    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              StartPackingList
+              StopPackingList
+              DeliverPackingList
+              Tic
+    """ + self.AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              GetInvoice
+              CheckInvoiceCausalityStateSolved
+              CheckInvoiceNormalMovements
+
+              StartInvoice
+              Tic
+              CheckInvoiceCausalityStateSolved
+              CheckInvoiceNormalMovements
+              CheckInvoiceAccountingMovements
+              StopInvoice
+              DeliverInvoice
+              Tic
+    """
+    sequence_list.addSequenceString(sequence_string)
+    sequence_list.play(self)
+
+  PACKING_LIST_SPLIT_INVOICE_BUILD_SEQUENCE_STRING = \
+      TRADE_MODEL_RULE_SIMULATION_SEQUENCE_STRING + """
+              ConfirmOrder
+              Tic
+    """ + AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              GetPackingList
+              DecreasePackingListLineListQuantity
+              Tic
+    """ + AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              CheckPackingListDiverged
+              SplitAndDeferPackingList
+              Tic
+    """ + AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              GetNewPackingList
+              PackPackingList
+              Tic
+    """ + AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              StartPackingList
+              StopPackingList
+              DeliverPackingList
+              Tic
+    """ + AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              GetInvoice
+              CheckInvoiceCausalityStateSolved
+              CheckInvoiceNormalMovements
+
+              SetNewPackingListAsPackingList
+              PackPackingList
+              Tic
+              StartPackingList
+    """ + AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              StopPackingList
+              DeliverPackingList
+              Tic
+    """ + AGGREGATED_AMOUNT_SIMULATION_CHECK_SEQUENCE_STRING + """
+              GetInvoice
+              CheckInvoiceCausalityStateSolved
+              CheckInvoiceNormalMovements
+    """
+
+  def test_TradeModelRuleSimulationPackingListSplitBuildInvoiceBuildDifferentRatio(self):
+    """Check building invoice after splitting packing list using different ratio"""
+    self.modified_packing_list_line_quantity_ratio = 0.4
+    sequence_list = SequenceList()
+    sequence_list.addSequenceString(
+        self.PACKING_LIST_SPLIT_INVOICE_BUILD_SEQUENCE_STRING)
+    sequence_list.play(self)
+
+  def test_TradeModelRuleSimulationPackingListSplitBuildInvoiceBuild(self):
+    """Check building invoice after splitting packing list"""
+    sequence_list = SequenceList()
+    sequence_list.addSequenceString(
+        self.PACKING_LIST_SPLIT_INVOICE_BUILD_SEQUENCE_STRING)
+    sequence_list.play(self)
+
+  def test_getAggregatedAmountListWithComplexModelLinesCreateInEasyOrder(self):
+    """
+    Test the return of getAggregatedAmountList in the case of many model lines
+    depending each others. In this test, lines are created in the order of the
+    dependancies (it means that if a line A depend of a line B, line B is
+    created before A). This is the most easy case.
+
+    Dependance tree :
+    ModelLineTaxContributingToTotalTax : A
+    ModelLineDiscountContributingToTotalDiscount : B
+    ModelLineTaxContributingToTotalTax2 : C
+    ModelLineTotalTax : D
+    ModelLineTotalDiscount : E
+
+                              D       E
+                               \     /
+                                \   /
+                                 \ /
+                                  C      B
+                                   \    /
+                                    \  /
+                                     \/
+                                      A
+    Model line creation order : E, D, C, B, A
+    """
+    sequence_list = SequenceList()
+    sequence_string = self.COMMON_DOCUMENTS_CREATION_SEQUENCE_STRING + """
+              CreateBusinessProcess
+              CreateBusinessState
+              ModifyBusinessStateTaxed
+              CreateBusinessState
+              ModifyBusinessStateInvoiced
+              CreateBusinessPath
+              ModifyBusinessPathTaxing
+              CreateBusinessPath
+              ModifyBusinessPathDiscounting
+              CreateTradeCondition
+              SpecialiseTradeConditionWithBusinessProcess
+              CreateTradeModelLine
+              ModifyTradeModelLineTotalDiscount
+              CreateTradeModelLine
+              ModifyTradeModelLineTotalTax
+              CreateTradeModelLine
+              ModifyTradeModelLineTaxContributingToTotalTax2
+              CreateTradeModelLine
+              ModifyTradeModelLineDiscountContributingToTotalDiscount
+              CreateTradeModelLine
+              ModifyTradeModelLineTaxContributingToTotalTax
+              Tic
+              CreateOrder
+              SpecialiseOrderTradeCondition
+              FillOrder
+              Tic
+              CreateOrderLine
+              ModifyOrderLineTaxed
+              CreateOrderLine
+              ModifyOrderLineDiscounted
+              Tic
+              CheckAggregatedAmountListWithComplexBaseContributionBaseApplication
+    """
+    sequence_list.addSequenceString(sequence_string)
+    sequence_list.play(self)
+
+  def test_getAggregatedAmountListWithComplexModelLinesCreateInRandomOrder(self):
+    """
+    Test the return of getAggregatedAmountList in the case of many model lines
+    depending each others. In this test, lines are created in a random order,
+    not in the dependancies order (it means that if a line A depend of a 
+    line B, line A can be created before line B). getAggregatedAmountList
+    should be able to handle this case and redo calculation unill all
+    dependancies are satified
+
+    Dependance tree :
+    ModelLineTaxContributingToTotalTax : A
+    ModelLineDiscountContributingToTotalDiscount : B
+    ModelLineTaxContributingToTotalTax2 : C
+    ModelLineTotalTax : D
+    ModelLineTotalDiscount : E
+
+                              D       E
+                               \     /
+                                \   /
+                                 \ /
+                                  C      B
+                                   \    /
+                                    \  /
+                                     \/
+                                      A
+    Model line creation order : A, C, D, B, E
+    """
+    sequence_list = SequenceList()
+    sequence_string = self.COMMON_DOCUMENTS_CREATION_SEQUENCE_STRING + """
+              CreateBusinessProcess
+              CreateBusinessState
+              ModifyBusinessStateTaxed
+              CreateBusinessState
+              ModifyBusinessStateInvoiced
+              CreateBusinessPath
+              ModifyBusinessPathTaxing
+              CreateBusinessPath
+              ModifyBusinessPathDiscounting
+              CreateTradeCondition
+              SpecialiseTradeConditionWithBusinessProcess
+              CreateTradeModelLine
+              ModifyTradeModelLineTaxContributingToTotalTax
+              CreateTradeModelLine
+              ModifyTradeModelLineTaxContributingToTotalTax2
+              CreateTradeModelLine
+              ModifyTradeModelLineTotalTax
+              CreateTradeModelLine
+              ModifyTradeModelLineDiscountContributingToTotalDiscount
+              CreateTradeModelLine
+              ModifyTradeModelLineTotalDiscount
+              Tic
+              CreateOrder
+              SpecialiseOrderTradeCondition
+              FillOrder
+              Tic
+              CreateOrderLine
+              ModifyOrderLineTaxed
+              CreateOrderLine
+              ModifyOrderLineDiscounted
+              Tic
+              CheckAggregatedAmountListWithComplexBaseContributionBaseApplication
+    """
+    sequence_list.addSequenceString(sequence_string)
+    sequence_list.play(self)
+
+class TestTradeModelLineSale(TestTradeModelLine):
+  invoice_portal_type = 'Sale Invoice Transaction'
+  invoice_line_portal_type = 'Invoice Line'
+  order_portal_type = 'Sale Order'
+  order_line_portal_type = 'Sale Order Line'
+  packing_list_portal_type = 'Sale Packing List'
+  trade_condition_portal_type = 'Sale Trade Condition'
+  trade_model_line_portal_type = 'Trade Model Line'
+
+
+class TestTradeModelLinePurchase(TestTradeModelLine):
+  invoice_portal_type = 'Purchase Invoice Transaction'
+  invoice_line_portal_type = 'Invoice Line'
+  order_portal_type = 'Purchase Order'
+  order_line_portal_type = 'Purchase Order Line'
+  packing_list_portal_type = 'Purchase Packing List'
+  trade_condition_portal_type = 'Purchase Trade Condition'
+  trade_model_line_portal_type = 'Trade Model Line'
+
+def test_suite():
+  suite = unittest.TestSuite()
+  suite.addTest(unittest.makeSuite(TestTradeModelLineSale))
+  suite.addTest(unittest.makeSuite(TestTradeModelLinePurchase))
+  return suite