##############################################################################
#
# Copyright (c) 2004, 2005 Nexedi SARL and Contributors. All Rights Reserved.
#          Guillaume Michon <guillaume.michon@e-asc.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################

# XXX test 1 :
#   - stepTestGetInventoryWithSelectionReport is not launched yet,
#       since it tests a behavior which does not exist yet
# XXX test 2 :
#   - There is an issue about inventory in inventory module :
#       if a movement which is older than the inventory is modified by quantity,
#       the inventory (and the following ones) must be automatically reindexed
#       (and sorted by date). It is not the case now
#   - If an aggregated item is modified by quantity, the same problem appears, but
#       should the inventory be updated by a later quantity modification on an
#       aggregated item ?


import unittest
import transaction

from Products.ERP5Type.Utils import cartesianProduct
from copy import copy


from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from DateTime import DateTime
from zLOG import LOG
from Products.ERP5Type.tests.Sequence import SequenceList
from Products.ERP5Type.DateUtils import addToDate
from Products.ERP5.tests.testOrder import TestOrderMixin

from Products.ERP5Form.Selection import DomainSelection

class TestInventory(TestOrderMixin, ERP5TypeTestCase):
  """
    Test Inventory API
  """
  run_all_test = 1
  packing_list_portal_type = 'Sale Packing List'
  packing_list_line_portal_type = packing_list_portal_type + ' Line'
  item_portal_type = "Apparel Fabric Item"
  inventory_portal_type = "Inventory"
  inventory_line_portal_type = inventory_portal_type + ' Line'
  inventory_cell_portal_type = inventory_portal_type + ' Cell'
  price_currency =  'currency_module/euro'

  def getTitle(self):
    return "Inventory"

  def getBusinessTemplateList(self):
    """Business Templates required for this test.
    """
    return ('erp5_base', 'erp5_pdm', 'erp5_simulation', 'erp5_trade',
            'erp5_configurator_standard_trade_template',
            'erp5_apparel', 'erp5_simulation_test')

  def setUpPreferences(self):
    #create apparel variation preferences
    portal_preferences = self.getPreferenceTool()
    preference = getattr(portal_preferences, 'test_site_preference', None)
    if preference is None:
      preference = portal_preferences.newContent(portal_type='System Preference',
                                title='Default Site Preference',
                                id='test_site_preference')
      if preference.getPreferenceState() == 'disabled':
        preference.enable()

    preference.setPreferredApparelModelVariationBaseCategoryList(('colour', 'size', 'morphology', 'industrial_phase',))
    preference.setPreferredApparelClothVariationBaseCategoryList(('size',))
    preference.setPreferredApparelComponentVariationBaseCategoryList(('variation',))
    if preference.getPreferenceState() == 'disabled':
      preference.enable()
    transaction.commit()
    self.tic()

  def afterSetUp(self, quiet=1, run=run_all_test):
    self.login()
    self.category_tool = self.getCategoryTool()
    self.createCategories()
    self.validateRules()
    # Patch PackingList.asPacked so that we do not need
    # to manage containers here, this not the job of this test
    def isPacked(self):
      return 1
    from Products.ERP5Type.Document.PackingList import PackingList
    PackingList.isPacked = isPacked
    self.createCurrency()
    self.setUpPreferences()

  def createCategory(self, parent, id_list):
      last_category = None
      for category_id in id_list:
        if type(category_id) == type('a'):
          last_category = parent.newContent(portal_type='Category',
                                            id=category_id)
        else:
          self.createCategory(last_category, category_id)

  def stepCreateItemList(self, sequence=None, sequence_list=None, **kw):
    """
      Create some items to manipulate during the module test
    """
    item_list = []
    portal = self.getPortal()
    item_module = portal.getDefaultModule(portal_type=self.item_portal_type)
    for i in range(5):
      item = item_module.newContent(portal_type=self.item_portal_type)
      item_list.append(item)
      item.edit(quantity = (i+1)*10)
    sequence.edit(item_list = item_list)

  def stepCreateOrganisationsForModule(self, sequence=None,
                                        sequence_list=None, **kw):
    """
      Create sections and nodes.
    """
    self.stepCreateOrganisation(sequence=sequence,
                        sequence_list=sequence_list, **kw)
    node = sequence.get('organisation')
    self.stepCreateOrganisation(sequence=sequence,
                        sequence_list=sequence_list, **kw)
    mirror_node = sequence.get('organisation')
    self.stepCreateOrganisation(sequence=sequence,
                        sequence_list=sequence_list, **kw)
    section = sequence.get('organisation')
    self.stepCreateOrganisation(sequence=sequence,
                        sequence_list=sequence_list, **kw)
    mirror_section = sequence.get('organisation')
    sequence.edit(
          node = node,
          section = section,
          mirror_node = mirror_node,
          mirror_section = mirror_section,
        )

  def stepCreateAggregatingInventory(self, sequence=None, sequence_list=None, **kw):
    """
      Create a Inventory object, with a line which aggregates Items
    """
    inventory_list = sequence.get('inventory_list')
    if inventory_list is None:
      inventory_list = []
    portal = self.getPortal()
    node = sequence.get('node')
    section = sequence.get('section')
    item_list = sequence.get('item_list')
    resource = sequence.get('resource')
    inventory_module = portal.getDefaultModule(portal_type = self.inventory_portal_type)
    inventory = inventory_module.newContent(portal_type = self.inventory_portal_type)
    inventory.edit(destination_value = node,
                   destination_section_value = section,
                   start_date = DateTime(),
                  )
    aggregate_value_list = [item_list[0], item_list[2]]
    inventory_line = inventory.newContent(portal_type = self.inventory_line_portal_type)
    inventory_line.edit(resource_value = resource,
                        aggregate_value_list = aggregate_value_list)
    # Now, quantity is not defined any more automatically.
    inventory_line.edit(quantity=sum([x.getQuantity() for x in \
        aggregate_value_list]))
    inventory.deliver()
    inventory_list.append(inventory)
    sequence.edit(inventory_list = inventory_list)

  def createInventory(self, sequence=None):
    """
    """
    portal = self.getPortal()
    inventory_list = sequence.get('inventory_list',[])
    inventory_module = portal.getDefaultModule(portal_type = self.inventory_portal_type)
    inventory = inventory_module.newContent(portal_type = self.inventory_portal_type)
    inventory.edit(destination_value = sequence.get('node'),
                   destination_section_value = sequence.get('section'),
                   start_date = DateTime() + 1
                  )
    inventory_list.append(inventory)
    sequence.edit(inventory_list=inventory_list)
    return inventory

  def stepCreateSingleInventory(self, sequence=None, sequence_list=None, **kw):
    """
      Create a single Inventory object for Inventory Module testing
    """
    inventory = self.createInventory(sequence=sequence)
    inventory_list = sequence.get('inventory_list',[])
    inventory_line = inventory.newContent(portal_type = self.inventory_line_portal_type)
    inventory_line.edit(resource_value = sequence.get('resource'),
                        inventory = 24.
                       )
    inventory.deliver()
    inventory_list.append(inventory)
    sequence.edit(inventory_list=inventory_list)

  def stepCreateSingleVariatedInventory(self, sequence=None, sequence_list=None, **kw):
    """
      Create a single Inventory object for Inventory Module testing
    """
    inventory = self.createInventory(sequence=sequence)
    inventory_line = inventory.newContent(portal_type = self.inventory_line_portal_type)
    category_list = sequence.get('variation_1')
    inventory_line.edit(resource_value = sequence.get('resource'),
                        variation_category_list=category_list
                       )
    cell = inventory_line.newCell(base_id='movement',*category_list)
    quantity=5
    cell.edit(
        quantity = quantity,
        predicate_category_list = category_list,
        variation_category_list = category_list,
        mapped_value_property_list = ['quantity'],
        )
    category_list = sequence.get('variation_2')
    inventory_line = inventory.newContent(portal_type = self.inventory_line_portal_type)
    inventory_line.edit(resource_value = sequence.get('resource'),
                        variation_category_list=category_list
                       )
    cell = inventory_line.newCell(base_id='movement',*category_list)
    quantity=0
    cell.edit(
        quantity = quantity,
        predicate_category_list = category_list,
        variation_category_list = category_list,
        mapped_value_property_list = ['quantity'],
        )
    inventory.deliver()

  def stepCreatePackingListForModule(self, sequence=None,
                                      sequence_list=None, **kw):
    """
      Create a single packing_list for Inventory Module testing
    """
    node = sequence.get('node')
    section = sequence.get('section')
    mirror_node = sequence.get('mirror_node')
    mirror_section = sequence.get('mirror_section')
    resource = sequence.get('resource')
    packing_list_module = self.getPortal().getDefaultModule(
                              portal_type=self.packing_list_portal_type)
    packing_list = packing_list_module.newContent(
                              portal_type=self.packing_list_portal_type)
    packing_list.edit(
                      specialise=self.business_process,
                      source_section_value = mirror_section,
                      source_value = mirror_node,
                      destination_section_value = section,
                      destination_value = node,
                      start_date = DateTime() - 2,
                      stop_date = DateTime() - 2,
                      price_currency = self.price_currency
                     )
    self.assertNotEquals( packing_list.getSourceSectionValue(), None)
    self.assertNotEquals( packing_list.getSourceValue(), None)
    self.assertNotEquals( packing_list.getSourceSectionValue(),
                          packing_list.getDestinationSectionValue() )
    sequence.edit(packing_list=packing_list)

  def stepCreatePackingListLine(self, sequence=None,
                                      sequence_list=None, **kw):
    """
    Create a line not variated
    """
    packing_list = sequence.get('packing_list')
    resource = sequence.get('resource')
    packing_list_line = packing_list.newContent(
                  portal_type=self.packing_list_line_portal_type)
    packing_list_line.edit(resource_value = resource,
                           quantity = 100.
                          )

  def stepCreateVariatedPackingListLine(self, sequence=None,
                                      sequence_list=None, **kw):
    """
    Create a line not variated
    """
    packing_list = sequence.get('packing_list')
    delivery_line_list = sequence.get('delivery_line_list',[])
    # Create Packing List Line
    packing_list_line = packing_list.newContent(portal_type=self.packing_list_line_portal_type)
    delivery_line_list.append(packing_list_line)
    resource = sequence.get('resource')
    variation_category_list = ['size/Child/32',
                               'size/Child/34',
                               'colour/%s/1' % resource.getRelativeUrl(),
                               'morphology/%s/4' % resource.getRelativeUrl()]
    packing_list_line.edit(
        resource_value = resource,
        variation_category_list=variation_category_list)
    # Set cell range

    cell_range = packing_list_line.getCellRange(base_id='movement')
    cartesian_product = cartesianProduct(cell_range)
    for cell_key in cartesian_product:
      cell = packing_list_line.newCell(base_id='movement', *cell_key)
      if 'size/Child/32' in cell_key:
        quantity = 1
        sequence.edit(variation_1=cell_key)
      elif 'size/Child/34' in cell_key:
        sequence.edit(variation_2=cell_key)
        quantity = 3
      cell.edit(
          quantity = quantity,
          predicate_category_list = cell_key,
          variation_category_list = cell_key,
          mapped_value_property_list = ['quantity'],
          )
    sequence.edit(delivery_line_list=delivery_line_list)

  def stepCreateVariatedNonDefaultQuantityUnitPackingListLine(
    self, sequence=None, sequence_list=None, **kw):
    """
    Create a line not variated
    """
    self.stepCreateVariatedPackingListLine(sequence, sequence_list, **kw)
    delivery_line = sequence.get('delivery_line_list')[-1]
    delivery_line.setQuantityUnitValue(self.portal.portal_categories.quantity_unit.unit.drum)

  def stepDeliverPackingList(self, sequence=None,
                                      sequence_list=None, **kw):
    # Switch to "started" state
    packing_list = sequence.get('packing_list')
    workflow_tool = self.getPortal().portal_workflow
    workflow_tool.doActionFor(packing_list,
                      "confirm_action", "packing_list_workflow")
    transaction.commit()
    # Apply tic so that the packing list is not in building state
    self.tic() # acceptable here because this is not the job
               # of the test to check if can do all transition
               # without processing messages
    workflow_tool.doActionFor(packing_list,
                      "set_ready_action", "packing_list_workflow")
    transaction.commit()
    self.tic()
    workflow_tool.doActionFor(packing_list,
                      "start_action", "packing_list_workflow")
    workflow_tool.doActionFor(packing_list,
                      "stop_action", "packing_list_workflow")
    workflow_tool.doActionFor(packing_list,
                      "deliver_action", "packing_list_workflow")

  def stepCreateOrganisationList(self, sequence=None, sequence_list=None, **kw):
    """
      Create some organisations to manipulate during the test
      Organisations organigram :
        section 0 :
          - payment 1
          - nodes 2, 3
        section 4 (provider) :
          - payment 5
          - node 6
        section 7 (customer) :
          - payment  8
          - node 9
    """
    organisation_list = []
    for i in range(10):
      self.stepCreateOrganisation(sequence=sequence, sequence_list=sequence_list, **kw)
      organisation_list.append(sequence.get('organisation'))

    category_tool = self.getPortal().portal_categories
    bc = category_tool.site
    self.createCategory(bc, ['Place1', ['A', 'B'], 'Place2', ['C'], 'Place3', ['D']])
    organisation_list[2] = bc.Place1.A
    organisation_list[3] = bc.Place1.B
    organisation_list[6] = bc.Place2.C
    organisation_list[9] = bc.Place3.D

    sequence.edit(
      organisation = None,
      organisation_list = organisation_list)


  def stepCreateVariatedResourceList(self, sequence=None, sequence_list=None, **kw):
    """
      Create some variated resources to manipulate during the test
    """
    resource_list = []
    for i in range(3):
      self.stepCreateVariatedResource(sequence=sequence, sequence_list=sequence_list, **kw)
      resource_list.append(sequence.get('resource'))
    sequence.edit(
      resource=None,
      resource_list = resource_list)


  def stepCreatePackingListList(self, sequence=None, sequence_list=None, **kw):
    """
      Create some packing lists
    """
    base_category_list = ['size', 'colour', 'morphology']
    data_list = [
      { 'source':6, 'destination':2, 'source_section':4, 'destination_section':0,
        'source_payment':5, 'destination_payment':1, 'start_date':DateTime()-30, 'lines':[
           {'resource':0, 'cells': [
                             #size, colour, morphology
               {'variation':['size/Baby', '1', '4'], 'quantity':.5},
               {'variation':['size/Baby', '2', '4'], 'quantity':1.},
               {'variation':['size/Baby', '3', '4'], 'quantity':1.5},
               {'variation':['size/Baby', '1', '5'], 'quantity':2.},
               {'variation':['size/Baby', '2', '5'], 'quantity':2.5},
               {'variation':['size/Baby', '3', '5'], 'quantity':3.},

               {'variation':['size/Child/32', '1', '4'], 'quantity':3.5},
               {'variation':['size/Child/32', '2', '4'], 'quantity':4.},
               {'variation':['size/Child/32', '3', '4'], 'quantity':4.5},
               {'variation':['size/Child/32', '1', '5'], 'quantity':5.},
               {'variation':['size/Child/32', '2', '5'], 'quantity':5.5},
               {'variation':['size/Child/32', '3', '5'], 'quantity':6.},

               {'variation':['size/Child/34', '1', '4'], 'quantity':6.5},
               {'variation':['size/Child/34', '2', '4'], 'quantity':7.},
               {'variation':['size/Child/34', '3', '4'], 'quantity':7.5},
               {'variation':['size/Child/34', '1', '5'], 'quantity':8.},
               {'variation':['size/Child/34', '2', '5'], 'quantity':8.5},
               {'variation':['size/Child/34', '3', '5'], 'quantity':9.},

               {'variation':['size/Man', '1', '4'], 'quantity':9.5},
               {'variation':['size/Man', '2', '4'], 'quantity':10.},
               {'variation':['size/Man', '3', '4'], 'quantity':10.5},
               {'variation':['size/Man', '1', '5'], 'quantity':11.},
               {'variation':['size/Man', '2', '5'], 'quantity':11.5},
               {'variation':['size/Man', '3', '5'], 'quantity':12.},

               {'variation':['size/Woman', '1', '4'], 'quantity':12.5},
               {'variation':['size/Woman', '2', '4'], 'quantity':13.},
               {'variation':['size/Woman', '3', '4'], 'quantity':13.5},
               {'variation':['size/Woman', '1', '5'], 'quantity':14.},
               {'variation':['size/Woman', '2', '5'], 'quantity':14.5},
               {'variation':['size/Woman', '3', '5'], 'quantity':15.},
             ]
           }, # line end
           {'resource':1, 'cells': [
               {'variation':['size/Man', '2', '4'], 'quantity':15.5},
               {'variation':['size/Man', '3', '4'], 'quantity':16.},
             ]
           }, # line end
           {'resource':2, 'cells': [
               {'variation':['size/Baby', '3', '5'], 'quantity':16.5},
             ]
           }  # line end
        ]
      }, # packing list end
      { 'source':6, 'destination':3, 'source_section':4, 'destination_section':0,
        'source_payment':5, 'destination_payment':1, 'start_date':DateTime()-25, 'lines':[
           {'resource':0, 'cells': [
               {'variation':['size/Baby', '1', '4'], 'quantity':16.5},
               {'variation':['size/Baby', '2', '4'], 'quantity':17.},
               {'variation':['size/Baby', '3', '4'], 'quantity':17.5},
               {'variation':['size/Baby', '1', '5'], 'quantity':18.},
               {'variation':['size/Baby', '2', '5'], 'quantity':18.5},
               {'variation':['size/Baby', '3', '5'], 'quantity':19.},
               {'variation':['size/Woman', '2', '4'], 'quantity':19.5},
             ]
           }, # line end
           {'resource':2, 'cells': [
               {'variation':['size/Baby', '3', '5'], 'quantity':20.},
             ]
           } # line end
        ]
      }, # packing list end
      { 'source':2, 'destination':9, 'source_section':0, 'destination_section':7,
        'source_payment':1, 'destination_payment':8, 'start_date':DateTime()-15, 'lines':[
           {'resource':0, 'cells': [
               {'variation':['size/Baby', '2', '4'], 'quantity':.25},
               {'variation':['size/Baby', '3', '4'], 'quantity':.5},
               {'variation':['size/Baby', '1', '5'], 'quantity':.75},
               {'variation':['size/Baby', '2', '5'], 'quantity':1.},
               {'variation':['size/Baby', '3', '5'], 'quantity':1.25},

               {'variation':['size/Child/32', '1', '4'], 'quantity':1.5},
               {'variation':['size/Child/32', '2', '4'], 'quantity':1.75},
               {'variation':['size/Child/32', '3', '4'], 'quantity':2.},
               {'variation':['size/Child/32', '1', '5'], 'quantity':2.25},
               {'variation':['size/Child/32', '2', '5'], 'quantity':2.5},
               {'variation':['size/Child/32', '3', '5'], 'quantity':2.75},

               {'variation':['size/Child/34', '1', '4'], 'quantity':3.},
               {'variation':['size/Child/34', '2', '4'], 'quantity':3.25},
               {'variation':['size/Child/34', '3', '4'], 'quantity':3.5},
               {'variation':['size/Child/34', '1', '5'], 'quantity':3.75},
               {'variation':['size/Child/34', '2', '5'], 'quantity':4.},
               {'variation':['size/Child/34', '3', '5'], 'quantity':4.25},

               {'variation':['size/Man', '1', '4'], 'quantity':4.5},
               {'variation':['size/Man', '2', '4'], 'quantity':4.75},
               {'variation':['size/Man', '3', '4'], 'quantity':5.},
               {'variation':['size/Man', '1', '5'], 'quantity':5.25},
               {'variation':['size/Man', '2', '5'], 'quantity':5.5},
               {'variation':['size/Man', '3', '5'], 'quantity':5.75},

               {'variation':['size/Woman', '1', '4'], 'quantity':6.},
               {'variation':['size/Woman', '2', '4'], 'quantity':6.5},
               {'variation':['size/Woman', '3', '4'], 'quantity':7.},
               {'variation':['size/Woman', '1', '5'], 'quantity':7.5},
               {'variation':['size/Woman', '2', '5'], 'quantity':8.},
               {'variation':['size/Woman', '3', '5'], 'quantity':8.5},
             ]
           }, # line end
           {'resource':1, 'cells': [
               {'variation':['size/Man', '3', '4'], 'quantity':6.},
             ]
           }, # line end
        ]
      }, # packing list end
      { 'source':3, 'destination':9, 'source_section':0, 'destination_section':7,
        'source_payment':1, 'destination_payment':8, 'start_date':DateTime()-10, 'lines':[
           {'resource':0, 'cells': [
               {'variation':['size/Baby', '1', '5'], 'quantity':7.5},
               {'variation':['size/Baby', '2', '5'], 'quantity':5.},
               {'variation':['size/Baby', '3', '5'], 'quantity':3.},
             ]
           }, # line end
           {'resource':2, 'cells': [
               {'variation':['size/Baby', '3', '5'], 'quantity':18.},
             ]
           }, # line end
        ]
      }, # packing list end
    ]

    packing_list_list = []
    delivery_line_list = []
    organisation_list = sequence.get('organisation_list')
    resource_list = sequence.get('resource_list')
    order = sequence.get('order')
    packing_list_module = self.getPortal().getDefaultModule(self.packing_list_portal_type)

    for data in data_list:
      # Create Packing List
      packing_list = packing_list_module.newContent(
          portal_type=self.packing_list_portal_type,
          specialise=self.business_process)
      packing_list_list.append(packing_list)
      # Add properties
      property_list = [x for x in data.items() if x[0] not in ('lines','start_date')]
      property_list = [(x[0], organisation_list[x[1]].getRelativeUrl()) for x in property_list] + \
                      [x for x in data.items() if x[0] in ('start_date',)]
      property_dict = {}
      property_dict['price_currency'] = self.price_currency
      for (id, value) in property_list: property_dict[id] = value
      packing_list.edit(**property_dict)
      for line in data['lines']:
        # Create Packing List Line
        packing_list_line = packing_list.newContent(portal_type=self.packing_list_line_portal_type)
        delivery_line_list.append(packing_list_line)
        resource_value = resource_list[line['resource']]
        resource_value.setVariationBaseCategoryList(base_category_list)
        variation_category_list = resource_value.getVariationRangeCategoryList(base_category_list=['size']) + \
            ['colour/' + x.getRelativeUrl() for x in resource_value.objectValues(portal_type='Apparel Model Colour Variation')] + \
            ['morphology/' + x.getRelativeUrl() for x in resource_value.objectValues(portal_type='Apparel Model Morphology Variation')]

        packing_list_line.edit(
            resource_value = resource_value,
            variation_category_list=variation_category_list
        )

        # Set cell range
        base_category_dict = {}
        for i in range(len(base_category_list)):
          base_category_dict[base_category_list[i]] = i

        # Set cells
        for cell in line['cells']:
          variation = cell['variation']
          for i in range(len(variation)):
            c = variation[i]
            if len(c.split('/')) == 1:
              variation[i] = '%s/%s' % (base_category_list[i], resource_value[c].getRelativeUrl())
          new_variation = []
          self.failUnless(len(packing_list_line.getVariationBaseCategoryList())>0)
          for bc in packing_list_line.getVariationBaseCategoryList():
            new_variation.append(variation[base_category_dict[bc]])
          variation = new_variation
          packing_list_cell = packing_list_line.newCell(base_id='movement', *variation)
          packing_list_cell.edit(
              quantity = cell['quantity'],
              predicate_category_list = variation,
              variation_category_list = variation,
              mapped_value_property_list = ['quantity'],
              )
    sequence.edit(packing_list_list = packing_list_list)

  def stepCreateTestingCategories(self, sequence=None, sequence_list=None, **kw):
    """
      Create some categories and affect them to resources and organisations
    """
    category_tool = self.getPortal().portal_categories
    organisation_list = sequence.get('organisation_list')
    resource_list = sequence.get('resource_list')

    bc = category_tool.newContent(portal_type = 'Base Category', id = 'testing_category')
    self.createCategory(bc, ['a', ['aa', 'ab'], 'o', 'z', ['za', 'zb', ['zba', 'zbb'], 'zc'] ])
    self.stepTic()

    category_org_list = [ ['testing_category/a/aa', 'testing_category/o'], # 0
                          ['testing_category/a/aa', 'testing_category/z'], # 1
                          ['testing_category/a/aa', 'testing_category/z/zb/zba'], # 2
                          ['testing_category/a/aa', 'testing_category/z/zb/zbb'], # 3
                          ['testing_category/o', 'testing_category/z'], # 4
                          ['testing_category/z', 'testing_category/z/zc'], # 5
                          ['testing_category/z', 'testing_category/a/ab'],# 6
                          ['testing_category/o', 'testing_category/z/zc'], # 7
                          ['testing_category/z', 'testing_category/a/ab'], # 8
                          ['testing_category/a', 'testing_category/z/zb'],# 9
                        ]

    category_res_list = [ ['testing_category/a/aa', 'testing_category/z'],
                          ['testing_category/a/aa', 'testing_category/z/za'],
                          ['testing_category/a/aa', 'testing_category/o']
                        ]

    for i in range(len(category_org_list)):
      organisation = organisation_list[i]
      new_categories = category_org_list[i]
      organisation.edit(categories = organisation.getCategoryList() + new_categories)
    for i in range(len(category_res_list)):
      resource = resource_list[i]
      new_categories = category_res_list[i]
      resource.edit(categories = resource.getCategoryList() + new_categories)


  def stepTestGetInventoryOnNode(self, sequence=None, sequence_list=None, **kw):
    """
      Test getInventory on each node
    """
    organisation_list = sequence.get('organisation_list')
    expected_values_list = [
      {'id':2, 'values':[{'date':DateTime()-28, 'inventory':280.5},
                         {'date':DateTime()-20, 'inventory':280.5},
                         {'date':DateTime()-12, 'inventory':162.},
                         {'date':DateTime(),    'inventory':162.},]
      },
      {'id':3, 'values':[{'date':DateTime()-28, 'inventory':0.},
                         {'date':DateTime()-20, 'inventory':146.},
                         {'date':DateTime()-12, 'inventory':146.},
                         {'date':DateTime(),    'inventory':112.5},]
      },
      {'id':6, 'values':[{'date':DateTime()-28, 'inventory':-280.5},
                         {'date':DateTime()-20, 'inventory':-426.5},
                         {'date':DateTime()-12, 'inventory':-426.5},
                         {'date':DateTime(),    'inventory':-426.5},]
      },
      {'id':9, 'values':[{'date':DateTime()-28, 'inventory':0.},
                         {'date':DateTime()-20, 'inventory':0.},
                         {'date':DateTime()-12, 'inventory':118.5},
                         {'date':DateTime(),    'inventory':152.},]
      },
    ]

    for expected_values in expected_values_list:
      organisation = organisation_list[expected_values['id']]
      url = organisation.getRelativeUrl()
      values = expected_values['values']
      for value in values:
        date = value['date']
        e_inventory = value['inventory']
        self._testGetInventory(expected=e_inventory, at_date=date, node=url)


  def stepTestGetInventoryOnPayment(self, sequence=None, sequence_list=None, **kw):
    """
      Test getInventory on each payment
    """
    organisation_list = sequence.get('organisation_list')
    expected_values_list = [
      {'id':1, 'values':[{'date':DateTime()-28, 'inventory':280.5},
                         {'date':DateTime()-20, 'inventory':426.5},
                         {'date':DateTime()-12, 'inventory':308.},
                         {'date':DateTime(),    'inventory':274.5},]
      },
      {'id':5, 'values':[{'date':DateTime()-28, 'inventory':-280.5},
                         {'date':DateTime()-20, 'inventory':-426.5},
                         {'date':DateTime()-12, 'inventory':-426.5},
                         {'date':DateTime(),    'inventory':-426.5},]
      },
      {'id':8, 'values':[{'date':DateTime()-28, 'inventory':0.},
                         {'date':DateTime()-20, 'inventory':0.},
                         {'date':DateTime()-12, 'inventory':118.5},
                         {'date':DateTime(),    'inventory':152.},]
      },
    ]

    for expected_values in expected_values_list:
      organisation = organisation_list[expected_values['id']]
      url = organisation.getRelativeUrl()
      values = expected_values['values']
      for value in values:
        date = value['date']
        e_inventory = value['inventory']
        self._testGetInventory(expected=e_inventory, at_date=date, payment=url)


  def stepTestGetInventoryOnSection(self, sequence=None, sequence_list=None, **kw):
    """
      Test getInventory on each section
    """
    organisation_list = sequence.get('organisation_list')
    expected_values_list = [
      {'id':0, 'values':[{'date':DateTime()-28, 'inventory':280.5},
                         {'date':DateTime()-20, 'inventory':426.5},
                         {'date':DateTime()-12, 'inventory':308.},
                         {'date':DateTime(),    'inventory':274.5},]
      },
      {'id':4, 'values':[{'date':DateTime()-28, 'inventory':-280.5},
                         {'date':DateTime()-20, 'inventory':-426.5},
                         {'date':DateTime()-12, 'inventory':-426.5},
                         {'date':DateTime(),    'inventory':-426.5},]
      },
      {'id':7, 'values':[{'date':DateTime()-28, 'inventory':0.},
                         {'date':DateTime()-20, 'inventory':0.},
                         {'date':DateTime()-12, 'inventory':118.5},
                         {'date':DateTime(),    'inventory':152.},]
      },
    ]

    for expected_values in expected_values_list:
      organisation = organisation_list[expected_values['id']]
      url = organisation.getRelativeUrl()
      values = expected_values['values']
      for value in values:
        date = value['date']
        e_inventory = value['inventory']
        self._testGetInventory(expected=e_inventory, at_date=date, section=url)


  def stepTestGetInventoryOnMirrorSection(self, sequence=None, sequence_list=None, **kw):
    """
      Test getInventory on each mirror section
    """
    organisation_list = sequence.get('organisation_list')
    expected_values_list = [
      {'id':0, 'values':[{'date':DateTime()-28, 'inventory':-280.5},
                         {'date':DateTime()-20, 'inventory':-426.5},
                         {'date':DateTime()-12, 'inventory':-308.},
                         {'date':DateTime(),    'inventory':-274.5},]
      },
      {'id':4, 'values':[{'date':DateTime()-28, 'inventory':280.5},
                         {'date':DateTime()-20, 'inventory':426.5},
                         {'date':DateTime()-12, 'inventory':426.5},
                         {'date':DateTime(),    'inventory':426.5},]
      },
      {'id':7, 'values':[{'date':DateTime()-28, 'inventory':0.},
                         {'date':DateTime()-20, 'inventory':0.},
                         {'date':DateTime()-12, 'inventory':-118.5},
                         {'date':DateTime(),    'inventory':-152.},]
      },
    ]

    for expected_values in expected_values_list:
      organisation = organisation_list[expected_values['id']]
      url = organisation.getRelativeUrl()
      values = expected_values['values']
      for value in values:
        date = value['date']
        e_inventory = value['inventory']
        self._testGetInventory(expected=e_inventory, at_date=date, mirror_section=url)


  def stepTestGetInventoryOnResource(self, sequence=None, sequence_list=None, **kw):
    """
      Test getInventory on each resource
    """
    resource_list = sequence.get('resource_list')
    organisation_list = sequence.get('organisation_list')
    expected_values_list = [
      {'id':0, 'values':[{'date':DateTime()-28, 'inventory':232.5},
                         {'date':DateTime()-20, 'inventory':358.5},
                         {'date':DateTime()-12, 'inventory':246.},
                         {'date':DateTime(),    'inventory':230.5},]
      },
      {'id':1, 'values':[{'date':DateTime()-28, 'inventory':31.5},
                         {'date':DateTime()-20, 'inventory':31.5},
                         {'date':DateTime()-12, 'inventory':25.5},
                         {'date':DateTime(),    'inventory':25.5},]
      },
      {'id':2, 'values':[{'date':DateTime()-28, 'inventory':16.5},
                         {'date':DateTime()-20, 'inventory':36.5},
                         {'date':DateTime()-12, 'inventory':36.5},
                         {'date':DateTime(),    'inventory':18.5},]
      },
    ]

    organisation_url = organisation_list[0].getRelativeUrl()
    for expected_values in expected_values_list:
      resource = resource_list[expected_values['id']]
      url = resource.getRelativeUrl()
      values = expected_values['values']
      for value in values:
        date = value['date']
        e_inventory = value['inventory']
        self._testGetInventory(expected=e_inventory, at_date=date, resource=url, section=organisation_url)


  def stepTestGetInventoryOnVariationText(self, sequence=None, sequence_list=None, **kw):
    """

    """
    simulation = self.getPortal().portal_simulation
    delivery = sequence.get('packing_list_list')[0]
    expected_values_list = [
      {'text':delivery['1']['movement_0_0_0'],
              'values':[{'inventory':17.},]
      },
    ]

    organisation_list = sequence.get('organisation_list')
    organisation_url = organisation_list[0].getRelativeUrl()
    for expected_values in expected_values_list:
      variation_text = expected_values['text'].getVariationText()
      values = expected_values['values']
      for value in values:
        e_inventory = value['inventory']
        self._testGetInventory(expected=e_inventory, variation_text=variation_text, section=organisation_url)

  def stepTestInventoryListBrainGetQuantity(self, sequence=None, sequence_list=None, **kw):
    """

    """
    simulation = self.getPortal().portal_simulation
    delivery = sequence.get('packing_list_list')[0]

    organisation_list = sequence.get('organisation_list')
    organisation_url = organisation_list[0].getRelativeUrl()
    movement = delivery['1']['movement_0_0_0']
    variation_text = movement.getVariationText()
    inventory_kw = {'section':organisation_url,
                    'variation_text':variation_text}
    simulation = self.getPortal().portal_simulation
    uid = movement.getUid()
    inventory_list = simulation.getInventoryList(**inventory_kw)
    found = 0
    for inventory in inventory_list:
      inventory_object = inventory.getObject()
      if inventory_object.getUid()==uid:
        found=1
        self.assertEquals(inventory_object.getQuantity(), 0.5)
        self.assertEquals(inventory.getQuantity(), 0.5)
    self.failUnless(found==1)



  def stepTestGetInventoryOnVariationCategory(self, sequence=None, sequence_list=None, **kw):
    """
      Test getInventory on some variation categories
    """
    resource_list = sequence.get('resource_list')
    organisation_list = sequence.get('organisation_list')
    expected_values_list = [
      {'id':'size/Baby', 'values':[{'date':DateTime()-28, 'inventory':27.},
                                   {'date':DateTime()-20, 'inventory':153.5},
                                   {'date':DateTime()-12, 'inventory':149.75},
                                   {'date':DateTime(),    'inventory':116.25},]
      },
      {'id':'size/Child/32', 'values':[{'date':DateTime()-28, 'inventory':28.5},
                                       {'date':DateTime()-20, 'inventory':28.5},
                                       {'date':DateTime()-12, 'inventory':15.75},
                                       {'date':DateTime(),    'inventory':15.75},]
      },
      {'id':'size/Child/34', 'values':[{'date':DateTime()-28, 'inventory':46.5},
                                       {'date':DateTime()-20, 'inventory':46.5},
                                       {'date':DateTime()-12, 'inventory':24.75},
                                       {'date':DateTime(),    'inventory':24.75},]
      },
      {'id':'size/Man', 'values':[{'date':DateTime()-28, 'inventory':96.},
                                  {'date':DateTime()-20, 'inventory':96.},
                                  {'date':DateTime()-12, 'inventory':59.25},
                                  {'date':DateTime(),    'inventory':59.25},]
      },
      {'id':'size/Woman', 'values':[{'date':DateTime()-28, 'inventory':82.5},
                                    {'date':DateTime()-20, 'inventory':102.},
                                    {'date':DateTime()-12, 'inventory':58.5},
                                    {'date':DateTime(),    'inventory':58.5},]
      },
      {'id':['size/Baby', 'colour/' + resource_list[0]['3'].getRelativeUrl()],
                        'values':[{'date':DateTime()-28, 'inventory':105.},
                                  {'date':DateTime()-20, 'inventory':231.5},
                                  {'date':DateTime()-12, 'inventory':189.},
                                  {'date':DateTime(),    'inventory':155.5},]
      },
      {'id':['size/Man', 'colour/' + resource_list[0]['3'].getRelativeUrl(), 'morphology/' + resource_list[0]['4'].getRelativeUrl()],
                        'values':[{'date':DateTime()-28, 'inventory':204.},
                                  {'date':DateTime()-20, 'inventory':293.5},
                                  {'date':DateTime()-12, 'inventory':204.75},
                                  {'date':DateTime(),    'inventory':201.75},]
      },


    ]

    organisation_url = organisation_list[0].getRelativeUrl()
    for expected_values in expected_values_list:
      category_list = expected_values['id']
      values = expected_values['values']
      for value in values:
        date = value['date']
        e_inventory = value['inventory']
        self._testGetInventory(expected=e_inventory,
                               at_date=date,
                               variation_category=category_list,
                               section=organisation_url)


  def stepTestGetInventoryWithOmitOutput(self, sequence=None,
                                         sequence_list=None, **kw):
    """
      Test getInventory on each node with omit_output
    """
    organisation_list = sequence.get('organisation_list')
    expected_values_list = [
      {'id':2, 'values':[{'date':DateTime()-28, 'inventory':280.5},
                         {'date':DateTime()-20, 'inventory':280.5},
                         {'date':DateTime()-12, 'inventory':280.5},
                         {'date':DateTime(),    'inventory':280.5},]
      },
      {'id':3, 'values':[{'date':DateTime()-28, 'inventory':0.},
                         {'date':DateTime()-20, 'inventory':146.},
                         {'date':DateTime()-12, 'inventory':146.},
                         {'date':DateTime(),    'inventory':146.},]
      },
      {'id':6, 'values':[{'date':DateTime()-28, 'inventory':0.},
                         {'date':DateTime()-20, 'inventory':0.},
                         {'date':DateTime()-12, 'inventory':0.},
                         {'date':DateTime(),    'inventory':0.},]
      },
      {'id':9, 'values':[{'date':DateTime()-28, 'inventory':0.},
                         {'date':DateTime()-20, 'inventory':0.},
                         {'date':DateTime()-12, 'inventory':118.5},
                         {'date':DateTime(),    'inventory':152.},]
      },
    ]

    for expected_values in expected_values_list:
      organisation = organisation_list[expected_values['id']]
      url = organisation.getRelativeUrl()
      values = expected_values['values']
      for value in values:
        date = value['date']
        e_inventory = value['inventory']
        self._testGetInventory(expected=e_inventory,
                               at_date=date,
                               node=url,
                               omit_output=1)


  def stepTestGetInventoryWithOmitInput(self, sequence=None, sequence_list=None, **kw):
    """
      Test getInventory on each node with omit_input
    """
    organisation_list = sequence.get('organisation_list')
    expected_values_list = [
      {'id':2, 'values':[{'date':DateTime()-28, 'inventory':0.},
                         {'date':DateTime()-20, 'inventory':0.},
                         {'date':DateTime()-12, 'inventory':-118.5},
                         {'date':DateTime(),    'inventory':-118.5},]
      },
      {'id':3, 'values':[{'date':DateTime()-28, 'inventory':0.},
                         {'date':DateTime()-20, 'inventory':0.},
                         {'date':DateTime()-12, 'inventory':0.},
                         {'date':DateTime(),    'inventory':-33.5},]
      },
      {'id':6, 'values':[{'date':DateTime()-28, 'inventory':-280.5},
                         {'date':DateTime()-20, 'inventory':-426.5},
                         {'date':DateTime()-12, 'inventory':-426.5},
                         {'date':DateTime(),    'inventory':-426.5},]
      },
      {'id':9, 'values':[{'date':DateTime()-28, 'inventory':0.},
                         {'date':DateTime()-20, 'inventory':0.},
                         {'date':DateTime()-12, 'inventory':0.},
                         {'date':DateTime(),    'inventory':0.},]
      },
    ]

    for expected_values in expected_values_list:
      organisation = organisation_list[expected_values['id']]
      url = organisation.getRelativeUrl()
      values = expected_values['values']
      for value in values:
        date = value['date']
        e_inventory = value['inventory']
        self._testGetInventory(expected=e_inventory,
                               at_date=date,
                               node=url,
                               omit_input=1)


  def stepTestGetInventoryOnSectionCategory(self, sequence=None,
                                            sequence_list=None, **kw):
    """
      Test getInventory with a section_category argument
    """
    organisation_list = sequence.get('organisation_list')
    expected_values_list = [
      {'id':'testing_category/a/aa', 'values':[{'inventory':274.5},] },
      {'id':'testing_category/z/zc', 'values':[{'inventory':152.},] },
      {'id':'testing_category/z', 'values':[{'inventory':-274.5},] },
      {'id':'testing_category/o', 'values':[{'inventory':0.},] },
    ]

    for expected_values in expected_values_list:
      category = expected_values['id']
      values = expected_values['values']
      for value in values:
        e_inventory = value['inventory']
        self._testGetInventory(expected=e_inventory,
                               section_category=category)


  def stepTestGetInventoryOnPaymentCategory(self, sequence=None,
                                            sequence_list=None, **kw):
    """
      Test getInventory with a payment_category argument
    """
    organisation_list = sequence.get('organisation_list')
    expected_values_list = [
      {'id':'testing_category/a/aa', 'values':[{'inventory':274.5},] },
      {'id':'testing_category/z/zc', 'values':[{'inventory':-426.5},] },
      {'id':'testing_category/a/ab', 'values':[{'inventory':152.},] },
      {'id':'testing_category/a', 'values':[{'inventory':426.5},] },
    ]

    for expected_values in expected_values_list:
      category = expected_values['id']
      values = expected_values['values']
      for value in values:
        e_inventory = value['inventory']
        self._testGetInventory(expected=e_inventory,
                               payment_category=category)


  def stepTestGetInventoryOnNodeCategory(self, sequence=None,
                                         sequence_list=None, **kw):
    """
      Test getInventory with a node_category argument
    """
    organisation_list = sequence.get('organisation_list')
    expected_values_list = [
      {'id':'testing_category/z/zb/zba', 'values':[{'inventory':162.},] },
      {'id':'testing_category/z/zb/zbb', 'values':[{'inventory':112.5},] },
      {'id':'testing_category/a/ab', 'values':[{'inventory':-426.5},] },
      {'id':'testing_category/a', 'values':[{'inventory':0.},] },
      {'id':'testing_category/z', 'values':[{'inventory':0.},] },
    ]

    for expected_values in expected_values_list:
      category = expected_values['id']
      values = expected_values['values']
      for value in values:
        e_inventory = value['inventory']
        self._testGetInventory(expected=e_inventory, node_category=category)


  def stepTestGetInventoryOnMirrorSectionCategory(self, sequence=None, sequence_list=None, **kw):
    """
      Test getInventory with a section_category argument
    """
    organisation_list = sequence.get('organisation_list')
    expected_values_list = [
      {'id':'testing_category/a/aa', 'values':[{'inventory':-274.5},] },
      {'id':'testing_category/z/zc', 'values':[{'inventory':-152.},] },
      {'id':'testing_category/z', 'values':[{'inventory':274.5},] },
      {'id':'testing_category/o', 'values':[{'inventory':0.},] },
    ]

    for expected_values in expected_values_list:
      category = expected_values['id']
      values = expected_values['values']
      for value in values:
        e_inventory = value['inventory']
        self._testGetInventory(expected=e_inventory, mirror_section_category=category)


  def stepTestGetInventoryOnResourceCategory(self, sequence=None, sequence_list=None, **kw):
    """
      Test getInventory with a resource_category argument
    """
    organisation_list = sequence.get('organisation_list')
    expected_values_list = [
      {'id':'testing_category/a/aa', 'values':[{'inventory':274.5},] },
      {'id':'testing_category/o', 'values':[{'inventory':18.5},] },
      {'id':'testing_category/z/za', 'values':[{'inventory':25.5},] },
      {'id':'testing_category/z', 'values':[{'inventory':256.},] },
    ]

    for expected_values in expected_values_list:
      category = expected_values['id']
      values = expected_values['values']
      for value in values:
        e_inventory = value['inventory']
        self._testGetInventory(expected=e_inventory,
                               resource_category=category,
                               section=organisation_list[0].getRelativeUrl())


  def _testGetInventory(self, expected, **kw):
    """
      Shared testing method
    """
    simulation = self.getPortal().portal_simulation
    e_inventory = expected
    LOG('Testing inventory with args :', 0, kw)
    a_inventory = simulation.getInventory(**kw)
    if e_inventory != a_inventory:
      msg = 'Inventory differs between expected (%s) and real (%s) quantities'\
             % (repr(e_inventory), repr(a_inventory))
      LOG('TestInventory._testGetInventory', 0, msg)
      LOG('SQL Query was : ', 0, str(simulation.getInventory(src__=1, **kw)))
      self.assertEquals(e_inventory, a_inventory, msg)


  def stepTestGetInventoryOnSimulationState(self, sequence=None,
                                            sequence_list=None, **kw):
    """
      Test getInventory with some simulation states, by using
      methods getCurrentInventory, getAvailableInventory and getFutureInventory
    """
    packing_list_workflow = 'packing_list_workflow'
    state_variable = 'simulation_state'
    packing_list_list = sequence.get('packing_list_list')
    workflow_tool = self.getPortal().portal_workflow
    simulation = self.getPortal().portal_simulation
    transit_simulation_state = ['started']

    transition_list = [
       {'id':0, 'action':'confirm_action'}, # a
       {'id':0, 'action':'set_ready_action'}, # b
              {'id':1, 'action':'confirm_action'}, # c
       {'id':0, 'action':'start_action'}, # d
                     {'id':2, 'action':'confirm_action'}, # e
       {'id':0, 'action':'stop_action'}, # f
                     {'id':2, 'action':'set_ready_action'}, # g
                     {'id':2, 'action':'start_action'}, # h
                            {'id':3, 'action':'confirm_action'}, # i
                            {'id':3, 'action':'set_ready_action'}, # j
                            {'id':3, 'action':'start_action'}, # k
                            {'id':3, 'action':'stop_action'}, # l
    ]

    expected_values_list = [
     #( without omit_transit, with omit_transit)
      ({'Current':  0.  , 'Available': 0.  , 'Future':  0.  },
       {'Current':  0.  , 'Available': 0.  , 'Future':  0.  }),
      ({'Current':  0.  , 'Available': 0.  , 'Future':280.5 }, # a
       {'Current':  0.  , 'Available': 0.  , 'Future':280.5 }),
      ({'Current':  0.  , 'Available': 0.  , 'Future':280.5 }, # b
       {'Current':  0.  , 'Available': 0.  , 'Future':280.5 }),
      ({'Current':  0.  , 'Available': 0.  , 'Future':426.5 }, # c
       {'Current':  0.  , 'Available': 0.  , 'Future':426.5 }),
      ({'Current':280.5 , 'Available': 280.5  , 'Future':426.5 }, # d
       {'Current':  0.  , 'Available': 0.  , 'Future':146.  }),
      ({'Current':280.5 , 'Available': 162.  , 'Future':308.  }, # e
       {'Current':  0.  , 'Available': -118.5  , 'Future': 27.5 }),
      ({'Current':280.5 , 'Available': 162.  , 'Future':308.  }, # f
       {'Current':280.5 , 'Available': 162.  , 'Future':308.  }),
      ({'Current':280.5 , 'Available': 162.  , 'Future':308.  }, # g
       {'Current':280.5 , 'Available': 162.  , 'Future':308.  }),
      ({'Current':162.  , 'Available': 162.  , 'Future':308.  }, # h
       {'Current':162.  , 'Available': 162.  , 'Future':308.  }),
      ({'Current':162.  , 'Available': 128.5  , 'Future':274.5 }, # i
       {'Current':162.  , 'Available': 128.5  , 'Future':274.5 }),
      ({'Current':162.  , 'Available': 128.5   , 'Future':274.5 }, # j
       {'Current':162.  , 'Available': 128.5  , 'Future':274.5 }),
      ({'Current':128.5 , 'Available': 128.5  , 'Future':274.5 }, # k
       {'Current':128.5 , 'Available': 128.5  , 'Future':274.5 }),
      ({'Current':128.5 , 'Available': 128.5  , 'Future':274.5 }, # l
       {'Current':128.5 , 'Available': 128.5  , 'Future':274.5 }),
    ]

    organisation_list = sequence.get('organisation_list')
    organisation_url = organisation_list[0].getRelativeUrl()
    date = DateTime()

    def _testWithState(expected_values, omit_transit):
      # Get current workflow states to add it to the log
      state_list = []
      for packing_list in packing_list_list:
        state_list.append(workflow_tool.getStatusOf(
                packing_list_workflow, packing_list)[state_variable])

      LOG('Testing with these workflow states :', 0, state_list)
      for name, e_inventory in expected_values.items():
        method_name = 'get%sInventory' % name
        method = getattr(simulation, method_name, None)
        if method is None:
          LOG('TEST ERROR : Simulation Tool has no %s method'
              % method_name, 0, '')
          self.failUnless(0)
        a_inventory = method(section=organisation_url,
                             omit_transit=omit_transit,
                             transit_simulation_state=transit_simulation_state,
                             at_date=date)
        if a_inventory != e_inventory:
          LOG('TEST ERROR : Inventory quantity differs between expected (%s) and real (%s) quantities' % (repr(e_inventory), repr(a_inventory)), 0, 'with method %s and omit_transit=%s' % (method_name, omit_transit))
          LOG('SQL Query was :', 0, method(section=organisation_url,
                             omit_transit=omit_transit,
                             transit_simulation_state=transit_simulation_state,
                             at_date=date, src__=1))
          self.assertEquals(a_inventory, e_inventory)

    # First, test with draft state everywhere
    LOG('Testing Inventory with every Packing List in draft state...', 0, '')
    for omit_transit in (0,1):
      _testWithState(expected_values_list[0][omit_transit], omit_transit)

    i = 0
    for expected_values in expected_values_list[1:]:
      self.tic() # acceptable here because this is not the job
                 # of the test to check if can do all transition
                 # without processing messages
      transition_step = transition_list[i]
      transited_pl = packing_list_list[transition_step['id']]
      action = transition_step['action']
      LOG("Transiting '%s' on packing list %s" % (action, transition_step['id']), 0, '')
      workflow_tool.doActionFor(transited_pl, action, packing_list_workflow)
      transited_pl.recursiveImmediateReindexObject() # XXX
      transaction.commit()
      self.stepTic()

      for omit_transit in (0,1):
        values = expected_values[omit_transit]
        _testWithState(values, omit_transit)

      i += 1


  def stepTestGetInventoryWithSelectionReport(self, sequence=None, sequence_list=None, **kw):
    """
    """
    organisation_list = sequence.get('organisation_list')
    expected_values_list = [
      {'id':2, 'values':[{'date':DateTime()-28, 'inventory':280.5},
                         {'date':DateTime()-20, 'inventory':280.5},
                         {'date':DateTime()-12, 'inventory':162.},
                         {'date':DateTime(),    'inventory':162.},]
      },
      {'id':3, 'values':[{'date':DateTime()-28, 'inventory':0.},
                         {'date':DateTime()-20, 'inventory':146.},
                         {'date':DateTime()-12, 'inventory':146.},
                         {'date':DateTime(),    'inventory':112.5},]
      },
      {'id':6, 'values':[{'date':DateTime()-28, 'inventory':-280.5},
                         {'date':DateTime()-20, 'inventory':-426.5},
                         {'date':DateTime()-12, 'inventory':-426.5},
                         {'date':DateTime(),    'inventory':-426.5},]
      },
      {'id':9, 'values':[{'date':DateTime()-28, 'inventory':0.},
                         {'date':DateTime()-20, 'inventory':0.},
                         {'date':DateTime()-12, 'inventory':118.5},
                         {'date':DateTime(),    'inventory':152.},]
      },
    ]

    for expected_values in expected_values_list:
      selection_domain = DomainSelection(domain_dict = {'destination_section':organisation_list[expected_values['id']],
                                                        'source_section':organisation_list[expected_values['id']]})
      values = expected_values['values']
      for value in values:
        date = value['date']
        e_inventory = value['inventory']
        self._testGetInventory(expected=e_inventory, at_date=date, selection_domain=selection_domain)


  def stepTestGetInventoryListOnSection(self, sequence=None, sequence_list=None, **kw):
    """
      Test getInventoryList on a section
    """
    organisation_list = sequence.get('organisation_list')
    resource_list = sequence.get('resource_list')

    # Build expected list
    expected_list = []
    for i in range(1, 31):
      quantity = (i + 0.) / 2
      expected_list.append({ 'node_relative_url': 2,
                             'section_relative_url': 0,
                             'resource_relative_url': 0,
                             'inventory': quantity })
    for i in range(31, 33):
      quantity = (i + 0.) / 2
      expected_list.append({ 'node_relative_url': 2,
                             'section_relative_url': 0,
                             'resource_relative_url': 1,
                             'inventory': quantity })
    for i in range(33, 34):
      quantity = (i + 0.) / 2
      expected_list.append({ 'node_relative_url': 2,
                             'section_relative_url': 0,
                             'resource_relative_url': 2,
                             'inventory': quantity })
    for i in range(33, 40):
      quantity = (i + 0.) / 2
      expected_list.append({ 'node_relative_url': 3,
                             'section_relative_url': 0,
                             'resource_relative_url': 0,
                             'inventory': quantity })
    for i in range(40, 41):
      quantity = (i + 0.) / 2
      expected_list.append({ 'node_relative_url': 3,
                             'section_relative_url': 0,
                             'resource_relative_url': 2,
                             'inventory': quantity })
    for i in range(1, 24):
      quantity = (i + 0.) / 4
      expected_list.append({ 'node_relative_url': 2,
                             'section_relative_url': 0,
                             'resource_relative_url': 0,
                             'inventory': - quantity })
    for i in range(12, 18):
      quantity = (i + 0.) / 2
      expected_list.append({ 'node_relative_url': 2,
                             'section_relative_url': 0,
                             'resource_relative_url': 0,
                             'inventory': - quantity })
    for i in range(12, 13):
      quantity = (i + 0.) / 2
      expected_list.append({ 'node_relative_url': 2,
                             'section_relative_url': 0,
                             'resource_relative_url': 1,
                             'inventory': - quantity })
    for i in [7.5, 5, 3]:
      quantity = (i + 0.)
      expected_list.append({ 'node_relative_url': 3,
                             'section_relative_url': 0,
                             'resource_relative_url': 0,
                             'inventory': - quantity })
    for i in [18]:
      quantity = (i + 0.)
      expected_list.append({ 'node_relative_url': 3,
                             'section_relative_url': 0,
                             'resource_relative_url': 2,
                             'inventory': - quantity })

    for i in [ [2,0,0], [2,0,1], [2,0,2], [3,0,0], [3,0,2],
               [2,0,0], [2,0,1], [3,0,0], [3,0,2] ]:
      expected_list.append({ 'node_relative_url': i[0],
                             'section_relative_url': i[1],
                             'resource_relative_url': i[2],
                             'inventory':0. })

    item_dict = { 'node': organisation_list,
                  'section': organisation_list,
                  'resource': resource_list }
    expected_l = expected_list[:]
    for expected in expected_l:
      for attribute in [x for x in expected.keys()
                          if x.endswith('_relative_url')]:
        attr_name = attribute.split('_')[0]
        expected[attribute] = item_dict[attr_name]\
                                  [expected[attribute]].getRelativeUrl()
    self._testGetInventoryList(expected=expected_l,
                               section=organisation_list[0].getRelativeUrl(),
                               omit_simulation=1)

  def stepTestGetInventoryListOnNode(self, sequence=None,
                                     sequence_list=None, **kw):
    """
      Test getInventoryList on a Node
    """
    organisation_list = sequence.get('organisation_list')
    resource_list = sequence.get('resource_list')

    # Build expected list
    expected_list = []
    for i in range(1, 31):
      quantity = (i + 0.) / 2
      expected_list.append({ 'node_relative_url': 2,
                             'section_relative_url': 0,
                             'resource_relative_url': 0,
                             'inventory': quantity })
    for i in range(31, 33):
      quantity = (i + 0.) / 2
      expected_list.append({ 'node_relative_url': 2,
                             'section_relative_url': 0,
                             'resource_relative_url': 1,
                             'inventory': quantity })
    for i in range(33, 34):
      quantity = (i + 0.) / 2
      expected_list.append({ 'node_relative_url': 2,
                             'section_relative_url': 0,
                             'resource_relative_url': 2,
                             'inventory': quantity })
    for i in range(1, 24):
      quantity = (i + 0.) / 4
      expected_list.append({ 'node_relative_url': 2,
                             'section_relative_url': 0,
                             'resource_relative_url': 0,
                             'inventory': - quantity })
    for i in range(12, 18):
      quantity = (i + 0.) / 2
      expected_list.append({ 'node_relative_url': 2,
                             'section_relative_url': 0,
                             'resource_relative_url': 0,
                             'inventory': - quantity })
    for i in range(12, 13):
      quantity = (i + 0.) / 2
      expected_list.append({ 'node_relative_url': 2,
                             'section_relative_url': 0,
                             'resource_relative_url': 1,
                             'inventory': - quantity })

    for i in [ [2,0,0], [2,0,1], [2,0,2], [2,0,0], [2,0,1] ]:
      expected_list.append({ 'node_relative_url': i[0],
                             'section_relative_url': i[1],
                             'resource_relative_url': i[2],
                             'inventory':0. })

    item_dict = { 'node': organisation_list,
                  'section': organisation_list,
                  'resource': resource_list }
    expected_l = expected_list[:]
    for expected in expected_l:
      for attribute in [x for x in expected.keys()
                            if x.endswith('_relative_url')]:
        attr_name = attribute.split('_')[0]
        expected[attribute] = item_dict[attr_name]\
                                [expected[attribute]].getRelativeUrl()
    self._testGetInventoryList( expected=expected_l,
                                node=organisation_list[2].getRelativeUrl(),
                                omit_simulation=1)


  def stepTestGetInventoryListWithOmitInput(self, sequence=None, sequence_list=None, **kw):
    """
      Test getInventoryList on a section with omit_input
    """
    organisation_list = sequence.get('organisation_list')
    resource_list = sequence.get('resource_list')

    # Build expected list
    expected_list = []
    for i in range(1, 24):
      quantity = (i + 0.) / 4
      expected_list.append({ 'node_relative_url': 2, 'section_relative_url':0, 'resource_relative_url':0, 'inventory':-quantity })
    for i in range(12, 18):
      quantity = (i + 0.) / 2
      expected_list.append({ 'node_relative_url': 2, 'section_relative_url':0, 'resource_relative_url':0, 'inventory':-quantity })
    for i in range(12, 13):
      quantity = (i + 0.) / 2
      expected_list.append({ 'node_relative_url': 2, 'section_relative_url':0, 'resource_relative_url':1, 'inventory':-quantity })
    for i in [7.5, 5, 3]:
      quantity = (i + 0.)
      expected_list.append({ 'node_relative_url': 3, 'section_relative_url':0, 'resource_relative_url':0, 'inventory':-quantity })
    for i in [18]:
      quantity = (i + 0.)
      expected_list.append({ 'node_relative_url': 3, 'section_relative_url':0, 'resource_relative_url':2, 'inventory':-quantity })

    item_dict = {'node':organisation_list, 'section':organisation_list, 'resource':resource_list}
    expected_l = expected_list[:]
    for expected in expected_l:
      for attribute in [x for x in expected.keys() if x.endswith('_relative_url')]:
        attr_name = attribute.split('_')[0]
        expected[attribute] = item_dict[attr_name][expected[attribute]].getRelativeUrl()
    self._testGetInventoryList(expected=expected_l, section=organisation_list[0].getRelativeUrl(), omit_simulation=1, omit_input=1)


  def stepTestGetInventoryListWithOmitOutput(self, sequence=None, sequence_list=None, **kw):
    """
      Test getInventoryList on a section with omit_output
    """
    organisation_list = sequence.get('organisation_list')
    resource_list = sequence.get('resource_list')

    # Build expected list
    expected_list = []
    for i in range(1, 31):
      quantity = (i + 0.) / 2
      expected_list.append({ 'node_relative_url': 2, 'section_relative_url':0, 'resource_relative_url':0, 'inventory':quantity })
    for i in range(31, 33):
      quantity = (i + 0.) / 2
      expected_list.append({ 'node_relative_url': 2, 'section_relative_url':0, 'resource_relative_url':1, 'inventory':quantity })
    for i in range(33, 34):
      quantity = (i + 0.) / 2
      expected_list.append({ 'node_relative_url': 2, 'section_relative_url':0, 'resource_relative_url':2, 'inventory':quantity })
    for i in range(33, 40):
      quantity = (i + 0.) / 2
      expected_list.append({ 'node_relative_url': 3, 'section_relative_url':0, 'resource_relative_url':0, 'inventory':quantity })
    for i in range(40, 41):
      quantity = (i + 0.) / 2
      expected_list.append({ 'node_relative_url': 3, 'section_relative_url':0, 'resource_relative_url':2, 'inventory':quantity })

    item_dict = {'node':organisation_list, 'section':organisation_list, 'resource':resource_list}
    expected_l = expected_list[:]
    for expected in expected_l:
      for attribute in [x for x in expected.keys() if x.endswith('_relative_url')]:
        attr_name = attribute.split('_')[0]
        expected[attribute] = item_dict[attr_name][expected[attribute]].getRelativeUrl()
    self._testGetInventoryList(expected=expected_l, section=organisation_list[0].getRelativeUrl(), omit_simulation=1, omit_output=1)


  def stepTestGetInventoryListWithGroupBy(self, sequence=None, sequence_list=None, **kw):
    """
      Test getInventoryList by using group_by_*
    """
    organisation_list = sequence.get('organisation_list')
    resource_list = sequence.get('resource_list')

    # Build expected list
    expected_list_list = [
      ({'group_by_node':1}, [
        {'node_relative_url': 2, 'section_relative_url':0, 'resource_relative_url':0, 'inventory':120. },
        {'node_relative_url': 2, 'section_relative_url':0, 'resource_relative_url':1, 'inventory':25.5 },
        {'node_relative_url': 2, 'section_relative_url':0, 'resource_relative_url':2, 'inventory':16.5 },
        {'node_relative_url': 3, 'section_relative_url':0, 'resource_relative_url':0, 'inventory':110.5 },
        {'node_relative_url': 3, 'section_relative_url':0, 'resource_relative_url':2, 'inventory':2. },
        {'node_relative_url': 6, 'section_relative_url':4, 'resource_relative_url':0, 'inventory':-358.5 },
        {'node_relative_url': 6, 'section_relative_url':4, 'resource_relative_url':1, 'inventory':-31.5 },
        {'node_relative_url': 6, 'section_relative_url':4, 'resource_relative_url':2, 'inventory':-36.5 },
        {'node_relative_url': 9, 'section_relative_url':7, 'resource_relative_url':0, 'inventory':128. },
        {'node_relative_url': 9, 'section_relative_url':7, 'resource_relative_url':1, 'inventory':6. },
        {'node_relative_url': 9, 'section_relative_url':7, 'resource_relative_url':2, 'inventory':18. },
      ]),
      ({'group_by_variation':1, 'section':organisation_list[0].getRelativeUrl()}, [
        {'resource_relative_url':0, 'inventory':17. },    # Baby
        {'resource_relative_url':0, 'inventory':17.75 },
        {'resource_relative_url':0, 'inventory':18.5 },
        {'resource_relative_url':0, 'inventory':11.75 },
        {'resource_relative_url':0, 'inventory':15. },
        {'resource_relative_url':0, 'inventory':17.75 },
        {'resource_relative_url':0, 'inventory':2. },     # 32
        {'resource_relative_url':0, 'inventory':2.25 },
        {'resource_relative_url':0, 'inventory':2.5 },
        {'resource_relative_url':0, 'inventory':2.75 },
        {'resource_relative_url':0, 'inventory':3. },
        {'resource_relative_url':0, 'inventory':3.25 },
        {'resource_relative_url':0, 'inventory':3.5 },    # 34
        {'resource_relative_url':0, 'inventory':3.75 },
        {'resource_relative_url':0, 'inventory':4. },
        {'resource_relative_url':0, 'inventory':4.25 },
        {'resource_relative_url':0, 'inventory':4.5 },
        {'resource_relative_url':0, 'inventory':4.75 },
        {'resource_relative_url':0, 'inventory':5. },     # Man
        {'resource_relative_url':0, 'inventory':5.25 },
        {'resource_relative_url':0, 'inventory':5.5 },
        {'resource_relative_url':0, 'inventory':5.75 },
        {'resource_relative_url':0, 'inventory':6. },
        {'resource_relative_url':0, 'inventory':6.25 },
        {'resource_relative_url':0, 'inventory':6.5 },    # Woman
        {'resource_relative_url':0, 'inventory':26. },
        {'resource_relative_url':0, 'inventory':6.5 },
        {'resource_relative_url':0, 'inventory':6.5 },
        {'resource_relative_url':0, 'inventory':6.5 },
        {'resource_relative_url':0, 'inventory':6.5 },
        {'resource_relative_url':0, 'inventory':0.}, #None }, # Sum of lines (quantity of lines is NULL)

        {'resource_relative_url':1, 'inventory':15.5 },
        {'resource_relative_url':1, 'inventory':10. },
        {'resource_relative_url':1, 'inventory':0. }, #None }, # Sum of lines (quantity of lines is ULL)

        {'resource_relative_url':2, 'inventory':18.5 },
        {'resource_relative_url':2, 'inventory':0. }, #None }, # Sum of lines (quantity of lines is NULL)
      ]),
    ]

    item_dict = {'node':organisation_list, 'section':organisation_list, 'resource':resource_list}
    for expected_tuple in expected_list_list:
      param, expected_list = expected_tuple
      expected_l = expected_list[:]
      for expected in expected_l:
        for attribute in [x for x in expected.keys() if x.endswith('_relative_url')]:
          attr_name = attribute.split('_')[0]
          expected[attribute] = item_dict[attr_name][expected[attribute]].getRelativeUrl()
      LOG('Testing getInventoryList with', 0, param)
      self._testGetInventoryList(expected=expected_l, omit_simulation=1, **param)


  def _testGetInventoryList(self, expected, **kw):
    """
      Shared testing method
      expected is a list of dictionaries containing identifying keys and 'inventory'
    """
    simulation = self.getPortal().portal_simulation
    expected = expected[:]
    if len(expected) > 0:
      attribute_list = [x for x in expected[0].keys() if x != 'inventory']
    else:
      attribute_list = []

    LOG('Testing getInventoryList with args :', 0, kw)
    inventory_list = simulation.getInventoryList(**kw)
    for inventory in inventory_list:
      a_attributes = {}
      for attr in attribute_list:
        if not hasattr(inventory, attr):
          LOG('TEST ERROR : Result of getInventoryList has no %s attribute' % attr, 0, '')
          LOG('SQL Query was : ', 0, repr(simulation.getInventoryList(src__=1, **kw)))
          self.failUnless(0)
        a_attributes[attr] = getattr(inventory, attr)
      a_inventory = inventory.inventory
      # Build a function to filter on attributes
      def cmpfunction(item):
        for (key, value) in a_attributes.items():
          if item[key] != value:
            return 0
        return 1
      # Look for lines with the same attributes in expected list
      expected_list = []
      for i in range(len(expected)):
        exp = expected[i]
        if cmpfunction(exp):
          expected_list.append(dict(exp))
          expected_list[-1].update({'id':i})
      # Now, look in these lines for one which has the same inventory
      found_list = filter(lambda x:x['inventory'] == a_inventory, expected_list)
      if len(found_list) == 0:
        LOG('TEST ERROR : Found a line with getInventoryList which is not expected.', 0, 'Found line : %s (inventory : %s) ; expected values with these attributes : %s' % (a_attributes, a_inventory, expected_list))
        LOG('SQL Query was : ', 0, repr(simulation.getInventoryList(src__=1, **kw)))
        self.assertNotEquals(len(found_list), 0)
      found = found_list[0]
      LOG('found a line with inventory =', 0, repr(found['inventory']))
      del expected[found['id']]
    # All inventory lines were found. Now check if some expected values remain
    if len(expected) > 0:
      LOG('TEST ERROR : Not all expected values were matched. Remaining =', 0, expected)
      LOG('SQL Query was : ', 0, str(simulation.getInventoryList(src__=1, **kw)))
      self.failUnless(len(expected), 0)


  def stepTestGetNextNegativeInventoryDate(self, sequence=None, sequence_list=None, **kw):
    """
      Test getNextNegativeInventoryDate
    """
    expected_negative_date = addToDate(DateTime())
    base_category_list = ['size', 'colour', 'morphology']
    variation_categories = ['size/Baby', '1', '5'] # size, colour, morphology
    node = 3
    # Set some new deliveries to reach a negative inventory
    # Resource and variation MUST be the same on each new delivery
    data_list = [
      { 'source':node, 'destination':9, 'source_section':0, 'destination_section':7,
        'source_payment':1, 'destination_payment':8, 'start_date':expected_negative_date, 'lines':[
           {'resource':0, 'cells': [
               {'variation':variation_categories, 'quantity':100000.},
             ]
           }, # line end
        ]
      }, # packing list end
      { 'source':6, 'destination':node, 'source_section':4, 'destination_section':0,
        'source_payment':5, 'destination_payment':1, 'start_date':expected_negative_date+5, 'lines':[
           {'resource':0, 'cells': [
               {'variation':variation_categories, 'quantity':100000.},
             ]
           }, # line end
        ]
      }, # packing list end
    ]

    portal = self.getPortal()
    simulation = portal.portal_simulation
    packing_list_module = portal.getDefaultModule(self.packing_list_portal_type)
    packing_list_list = sequence.get('packing_list_list')
    organisation_list = sequence.get('organisation_list')
    resource_list = sequence.get('resource_list')
    delivery_line_list = []

    for data in data_list:
      # Create Packing List
      packing_list = packing_list_module.newContent(portal_type=self.packing_list_portal_type)
      packing_list_list.append(packing_list)
      # Add properties
      property_list = [x for x in data.items() if x[0] not in ('lines','start_date')]
      property_list = [(x[0], organisation_list[x[1]].getRelativeUrl()) for x in property_list] + \
                      [x for x in data.items() if x[0] in ('start_date',)]
      property_dict = {}
      for (id, value) in property_list: property_dict[id] = value
      packing_list.edit(**property_dict)
      for line in data['lines']:
        # Create Packing List Line
        packing_list_line = packing_list.newContent(portal_type=self.packing_list_line_portal_type)
        delivery_line_list.append(packing_list_line)
        resource_value = resource_list[line['resource']]
        resource_value.setVariationBaseCategoryList(base_category_list)
        category_list = packing_list_line.getCategoryList()
        variation_category_list = resource_value.getVariationRangeCategoryList(base_category_list=['size']) + \
            ['colour/' + x.getRelativeUrl() for x in resource_value.objectValues(portal_type='Apparel Model Colour Variation')] + \
            ['morphology/' + x.getRelativeUrl() for x in resource_value.objectValues(portal_type='Apparel Model Morphology Variation')]

        packing_list_line.edit(
            resource_value=resource_value,
            variation_category_list=variation_category_list,
        )

        # Set cell range
        base_category_dict = {}
        for i in range(len(base_category_list)):
          base_category_dict[base_category_list[i]] = i

        # Set cells
        for cell in line['cells']:
          variation = cell['variation']
          for i in range(len(variation)):
            c = variation[i]
            if len(c.split('/')) == 1:
              variation[i] = '%s/%s' % (base_category_list[i], resource_value[c].getRelativeUrl())
          new_variation = []
          for bc in packing_list_line.getVariationBaseCategoryList():
            new_variation.append(variation[base_category_dict[bc]])
          variation = new_variation
          packing_list_cell = packing_list_line.newCell(base_id='movement', *variation)
          packing_list_cell.edit(
              quantity = cell['quantity'],
              predicate_category_list = variation,
              variation_category_list = variation,
              mapped_value_property_list = ['quantity'],
              )
      sequence.edit(packing_list_list = packing_list_list)

    transaction.commit()
    self.stepTic()
    transaction.commit()

    # Then test the next negative date
    next_date = simulation.getNextNegativeInventoryDate(
                      resource=resource_value.getRelativeUrl(),
                      node=organisation_list[node].getRelativeUrl(),
                      variation_category=variation_categories)

    if type(next_date) == type(''):
      next_date = DateTime(next_date)
    next_date = next_date.strftime('%Y-%m-%d %H:%M:%S')
    expected_negative_date = '%.4d-%.2d-%.2d %.2d:%.2d:%.2d' % (
                            expected_negative_date.year(),
                            expected_negative_date.month(),
                            expected_negative_date.day(),
                            expected_negative_date.hour(),
                            expected_negative_date.minute(),
                            expected_negative_date.second())
    if next_date != expected_negative_date:
      LOG('TEST ERROR : Next negative date is not the expected one.', 0,
          'calculated : %s, expected : %s' % (
           repr(next_date), repr(expected_negative_date)))
      LOG('SQL Query was ', 0,
          simulation.getNextNegativeInventoryDate(
                    resource=resource_value.getRelativeUrl(),
                    node=organisation_list[node].getRelativeUrl(),
                    variation_category=variation_categories, src__=1))
    self.assertEquals(next_date, expected_negative_date)


  def checkVariatedInventory(self, sequence=None, sequence_list=None,
                             variation_category_list=None,
                             quantity=None,**kw):
    """
    """
    simulation = self.getPortal().portal_simulation
    variation_category_list = copy(variation_category_list)
    variation_category_list.sort()
    variation_text = '\n'.join(variation_category_list)
    inventory = simulation.getCurrentInventory(
                    section=sequence.get('section').getRelativeUrl(),
                    node=sequence.get('node').getRelativeUrl(),
                    variation_text=variation_text
                )
    self.assertEquals(inventory, quantity)

  def stepTestInitialVariatedInventory(self, sequence=None, sequence_list=None, **kw):
    """
      Test Inventory Module behavior
    """
    resource = sequence.get('resource')
    variation_category_list = sequence.get('variation_1')
    quantity = 1
    self.checkVariatedInventory(variation_category_list=variation_category_list,
                                quantity=quantity,sequence=sequence)
    variation_category_list = sequence.get('variation_2')
    quantity = 3
    self.checkVariatedInventory(variation_category_list=variation_category_list,
                                quantity=quantity,sequence=sequence)

  def stepTestInitialVariatedNonDefaultQuantityUnitInventory(self, sequence=None, sequence_list=None, **kw):
    """
      Test Inventory Module behavior
    """
    resource = sequence.get('resource')
    variation_category_list = sequence.get('variation_1')
    quantity = 100
    self.checkVariatedInventory(variation_category_list=variation_category_list,
                                quantity=quantity,sequence=sequence)
    variation_category_list = sequence.get('variation_2')
    quantity = 300
    self.checkVariatedInventory(variation_category_list=variation_category_list,
                                quantity=quantity,sequence=sequence)

  def stepTestVariatedInventoryAfterInventory(self, sequence=None, sequence_list=None, **kw):
    """
      Test Inventory Module behavior
    """
    resource = sequence.get('resource')
    variation_category_list = sequence.get('variation_1')
    quantity = 5
    self.checkVariatedInventory(variation_category_list=variation_category_list,
                                quantity=quantity,sequence=sequence)
    variation_category_list = sequence.get('variation_2')
    quantity = 0
    self.checkVariatedInventory(variation_category_list=variation_category_list,
                                quantity=quantity,sequence=sequence)

  def stepTestInventoryModule(self, sequence=None, sequence_list=None, **kw):
    """
      Test Inventory Module behavior
    """
    step = sequence.get('step')
    inventory_list = sequence.get('inventory_list')
    simulation = self.getPortal().portal_simulation
    if step is None:
      step = 0
    expected = [(40.,0), (24.,1), (80.,0)]
    inventory = simulation.getCurrentInventory(
                    section=sequence.get('section').getRelativeUrl(),
                    node=sequence.get('node').getRelativeUrl(),
                    at_date=inventory_list[expected[step][1]].getStartDate()
                )
    self.assertEquals(inventory, expected[step][0],
                    'section=%s, node=%s' % (
                    sequence.get('section').getRelativeUrl(),
                    sequence.get('node').getRelativeUrl()))
    step += 1
    sequence.edit(step=step)

  def stepModifyFirstInventory(self, sequence=None, sequence_list=None, **kw):
    """
      Modify the first entered Inventory, to test the quantity change
    """
    inventory = sequence.get('inventory_list')[0]
    inventory_line = inventory['1']
    item_list = sequence.get('item_list')
    aggregate_value_list = [item_list[0],item_list[1], item_list[4]]
    inventory_line.edit(
        aggregate_value_list=aggregate_value_list,
        quantity=sum([x.getQuantity() for x in aggregate_value_list]))


  def test_01_getInventory(self, quiet=0, run=run_all_test):
    """
      Test the getInventory methods
    """
    if not run: return
    sequence_list = SequenceList()

    get_inventory_test_sequence= 'stepTestInventoryListBrainGetQuantity \
                                   stepTestGetInventoryOnNode \
                                   stepTestGetInventoryOnVariationCategory \
                                   stepTestGetInventoryOnPayment \
                                   stepTestGetInventoryOnSection \
                                   stepTestGetInventoryOnMirrorSection \
                                   stepTestGetInventoryOnResource \
                                   stepTestGetInventoryWithOmitInput \
                                   stepTestGetInventoryWithOmitOutput \
                                   stepTestGetInventoryOnSimulationState \
                                   stepTestGetInventoryOnSectionCategory \
                                   stepTestGetInventoryOnPaymentCategory \
                                   stepTestGetInventoryOnNodeCategory \
                                   stepTestGetInventoryOnMirrorSectionCategory \
                                   stepTestGetInventoryOnResourceCategory \
                                   stepTestGetInventoryOnVariationText \
                                   '
                                   #TestGetInventoryWithSelectionReport \
    get_inventory_test_sequence += 'stepTestGetInventoryListOnSection \
                                   stepTestGetInventoryListOnNode \
                                   stepTestGetInventoryListWithOmitInput \
                                   stepTestGetInventoryListWithOmitOutput \
                                   stepTestGetInventoryListWithGroupBy \
                                   stepTestGetNextNegativeInventoryDate \
                                  '

    sequence_string = 'stepCreateOrganisationList \
                       stepCreateOrder \
                       stepCreateVariatedResourceList \
                       stepCreatePackingListList \
                       stepTic \
                       stepCreateTestingCategories \
                       stepTic \
                       ' + get_inventory_test_sequence
    sequence_list.addSequenceString(sequence_string)

    sequence_list.play(self)


  def test_02_InventoryModule(self, quiet=0, run=run_all_test):
    """
      Test the InventoryModule behavior
    """
    if not run: return
    sequence_list = SequenceList()

    sequence_string = 'stepCreateOrganisationsForModule \
                       stepCreateVariatedResource \
                       stepCreateItemList \
                       stepCreatePackingListForModule \
                       stepTic \
                       stepCreatePackingListLine \
                       stepTic \
                       stepDeliverPackingList \
                       stepTic \
                       stepCreateAggregatingInventory \
                       stepTic \
                       stepTestInventoryModule \
                       stepCreateSingleInventory \
                       stepTic \
                       stepTestInventoryModule \
                       stepModifyFirstInventory \
                       stepTic \
                       stepTestInventoryModule \
                       '
    sequence_list.addSequenceString(sequence_string)

    sequence_list.play(self)

  def test_03_InventoryModuleWithVariation(self, quiet=0, run=run_all_test):
    """
      Test the InventoryModule behavior
    """
    if not run: return
    sequence_list = SequenceList()

    sequence_string = 'stepCreateOrganisationsForModule \
                       stepCreateVariatedResource \
                       stepTic \
                       stepCreatePackingListForModule \
                       stepTic \
                       stepCreateVariatedPackingListLine \
                       stepTic \
                       stepDeliverPackingList \
                       stepTic \
                       stepTestInitialVariatedInventory \
                       stepCreateSingleVariatedInventory \
                       stepTic \
                       stepTestVariatedInventoryAfterInventory \
                       '
    sequence_list.addSequenceString(sequence_string)

    sequence_list.play(self)

  def test_04_InventoryModuleWithVariationAndMultiQuantityUnit(self, quiet=0, run=run_all_test):
    """
      Test InventoryModule behavior with product which has
      variation and multiple quantity units.
    """
    if not run: return
    sequence_list = SequenceList()

    sequence_string = 'stepCreateOrganisationsForModule \
                       stepCreateVariatedMultipleQuantityUnitResource \
                       stepTic \
                       stepCreatePackingListForModule \
                       stepTic \
                       stepCreateVariatedNonDefaultQuantityUnitPackingListLine \
                       stepTic \
                       stepDeliverPackingList \
                       stepTic \
                       stepTestInitialVariatedNonDefaultQuantityUnitInventory \
                       stepCreateSingleVariatedInventory \
                       stepTic \
                       stepTestVariatedInventoryAfterInventory \
                       '
    sequence_list.addSequenceString(sequence_string)
    sequence_list.play(self)

def test_suite():
  suite = unittest.TestSuite()
  suite.addTest(unittest.makeSuite(TestInventory))
  return suite