From 488cd5b0351ef0a71610c3ff8cb35b71e4f91279 Mon Sep 17 00:00:00 2001
From: Romain Courteaud <romain@nexedi.com>
Date: Thu, 25 Aug 2005 07:27:31 +0000
Subject: [PATCH] Initial revision.

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@3649 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 product/ERP5/tests/testProductionOrder.py | 573 ++++++++++++++++++++++
 1 file changed, 573 insertions(+)
 create mode 100755 product/ERP5/tests/testProductionOrder.py

diff --git a/product/ERP5/tests/testProductionOrder.py b/product/ERP5/tests/testProductionOrder.py
new file mode 100755
index 0000000000..759ba79680
--- /dev/null
+++ b/product/ERP5/tests/testProductionOrder.py
@@ -0,0 +1,573 @@
+##############################################################################
+#
+# Copyright (c) 2005 Nexedi SARL and Contributors. All Rights Reserved.
+#          Sebastien Robin <seb@nexedi.com>
+#          Romain Courteaud <romain@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+#
+# Skeleton ZopeTestCase
+#
+
+from random import randint
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+# Needed in order to have a log file inside the current folder
+os.environ['EVENT_LOG_FILE'] = os.path.join(os.getcwd(), 'zLOG.log')
+os.environ['EVENT_LOG_SEVERITY'] = '-300'
+
+from Testing import ZopeTestCase
+from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
+from AccessControl.SecurityManagement import newSecurityManager, \
+                                             noSecurityManager
+from DateTime import DateTime
+from Acquisition import aq_base, aq_inner
+from zLOG import LOG
+from Products.ERP5Type.DateUtils import addToDate
+from Products.ERP5Type.tests.Sequence import Sequence, SequenceList
+import time
+import os
+from Products.ERP5Type import product_path
+from Products.CMFCore.utils import getToolByName
+from testOrder import TestOrderMixin
+
+class TestProductionOrder(TestOrderMixin, ERP5TypeTestCase):
+  """
+    Test business template erp5_mrp
+  """
+  run_all_test = 1
+  order_portal_type = 'Production Order'
+  order_line_portal_type = 'Production Order Line'
+  supply_chain_portal_type = 'Supply Chain'
+  supply_node_portal_type = 'Supply Node'
+  supply_link_portal_type = 'Supply Link'
+  component_portal_type = 'Apparel Component'
+  transformation_portal_type = 'Apparel Transformation'
+  transformed_resource_portal_type = \
+                        'Apparel Transformation Transformed Resource'
+  operation_line_portal_type = 'Apparel Transformation Operation'
+  order_workflow_id='production_order_workflow'
+
+  def getTitle(self):
+    return "Production Order"
+
+  def enableLightInstall(self):
+    """
+    You can override this. 
+    Return if we should do a light install (1) or not (0)
+    """
+    return 1
+
+  def enableActivityTool(self):
+    """
+    You can override this.
+    Return if we should create (1) or not (0) an activity tool.
+    """
+    return 1
+
+  def getBusinessTemplateList(self):
+    """
+    """
+    return ('erp5_apparel', 'erp5_trade', 'erp5_mrp')
+
+  def createCategories(self):
+    """ 
+      Light install create only base categories, so we create 
+      some categories for testing them
+    """
+    TestOrderMixin.createCategories(self)
+    operation_category_list = ['operation1', 'operation2']
+    if len(self.category_tool.operation.contentValues()) == 0:
+      for category_id in operation_category_list:
+        o = self.category_tool.operation.newContent(
+                                               portal_type='Category',
+                                               id=category_id)
+
+  def stepCreateProductionOrganisation1(self, sequence=None, sequence_list=None, 
+                                        **kw):
+    """
+      Create a organisation for supply
+    """
+    self.stepCreateOrganisation(sequence=sequence, sequence_list=sequence_list,
+                                title='production_organisation1', **kw)
+
+  # Note: SC means Supply Chain
+  def stepCreateGenericSC(self, sequence=None, sequence_list=None, **kw):
+    """
+      Create a empty Supply Chain
+    """
+    portal = self.getPortal()
+    supply_chain_module = portal.getDefaultModule( \
+                                   portal_type=self.supply_chain_portal_type)
+    supply_chain = supply_chain_module.newContent( \
+                                   portal_type=self.supply_chain_portal_type)
+    supply_chain.edit(
+      title = "Supply Chain Test",
+    )
+    sequence.edit(supply_chain=supply_chain)
+
+  def stepCreateProductionSC(self, sequence=None, sequence_list=None, 
+                             **kw):
+    """
+      Create a empty organisation
+    """
+    # Create supply chain
+    self.stepCreateGenericSC(sequence=sequence, sequence_list=sequence_list,
+                             **kw)
+    supply_chain = sequence.get('supply_chain')
+    # Create production node
+    production_organisation  = sequence.get('production_organisation1')
+    production_node = supply_chain.newContent(
+                         portal_type=self.supply_node_portal_type)
+    production_node.edit(
+      destination_value=production_organisation
+    )
+    sequence.edit(production_node1=production_node)
+    # Create production link
+    production_link = supply_chain.newContent(
+                         portal_type=self.supply_link_portal_type)
+    production_link.edit(
+      destination_value=production_node,
+      destination_section_value=production_organisation,
+      min_delay=5,
+      max_delay=6,
+      deliverable=1,
+      industrial_phase_list=["phase1"]
+    )
+
+  def stepCreateComponent1(self,sequence=None, sequence_list=None, \
+                                    **kw):
+    """
+      Create a resource with no variation
+    """
+    portal = self.getPortal()
+    resource_module = portal.getDefaultModule(self.component_portal_type)
+    resource = resource_module.newContent(
+                                  portal_type=self.component_portal_type)
+    resource.edit(
+      title = "Component1"
+    )
+    sequence.edit(component1=resource)
+
+  def stepCreateTransformation(self, sequence=None, sequence_list=None,
+                               **kw):
+    """
+      Create a transformation
+    """
+    # Create transformation
+    portal = self.getPortal()
+    transformation_module = portal.getDefaultModule(
+                                     self.transformation_portal_type)
+    transformation = transformation_module.newContent(
+                                   portal_type=self.transformation_portal_type)
+    sequence.edit(transformation=transformation)
+    # Set resource
+    resource = sequence.get('resource')
+    transformation.setResourceValue(resource)
+    # Create operation line 1
+    operation_line = transformation.newContent(
+        portal_type=self.operation_line_portal_type)
+    operation_line.edit(
+        # FIXME hardcoded
+        quantity=2,
+        resource_value=portal.portal_categories.resolveCategory(
+                                     'operation/operation1'),
+        industrial_phase_list=['phase1']
+    )
+
+    # Create operation line 2
+    operation_line = transformation.newContent(
+        portal_type=self.operation_line_portal_type)
+    operation_line.edit(
+        # FIXME hardcoded
+        quantity=3,
+        resource_value=portal.portal_categories.resolveCategory(
+                                     'operation/operation2'),
+        industrial_phase_list=['phase2']
+    )
+    # Create transformed resource line 1
+    line = transformation.newContent(
+        portal_type=self.transformed_resource_portal_type)
+    line.edit(
+        # FIXME hardcoded
+        quantity=6,
+        resource_value=sequence.get('component1'),
+        industrial_phase_list=['supply_phase1']
+    )
+
+  def stepCreateOrder(self, sequence=None, sequence_list=None, **kw):
+    """
+      Create a empty order
+    """
+    portal = self.getPortal()
+    order_module = portal.getDefaultModule(portal_type=self.order_portal_type)
+    order = order_module.newContent(portal_type=self.order_portal_type)
+    organisation = sequence.get('organisation')
+    supply_chain = sequence.get('supply_chain')
+    order.edit(
+      title = "Production Order",
+      start_date = self.datetime + 10,
+      stop_date = self.datetime + 20,
+      destination_value=organisation,
+      destination_section_value=organisation,
+      specialise_value=supply_chain
+    )
+    sequence.edit(order=order)
+
+  def stepCreateOrderLine(self, sequence=None, sequence_list=None, **kw):
+    """
+      Create a empty order line
+    """
+    order = sequence.get('order')
+    order_line = order.newContent(portal_type=self.order_line_portal_type)
+    resource = sequence.get('resource')
+    transformation = sequence.get('transformation')
+    order_line.edit(
+      title="Order Line",
+      resource_value=resource,
+      specialise_value=transformation,
+      quantity=5
+    )
+    sequence.edit(order_line=order_line)
+
+  def stepCheckOrderSimulation(self, sequence=None, sequence_list=None, **kw):
+    """
+      Test if simulation is matching order
+    """
+    order = sequence.get('order')
+    related_applied_rule_list = order.getCausalityRelatedValueList( \
+                                   portal_type=self.applied_rule_portal_type)
+    no_applied_rule_state = ('draft', 'auto_planned')
+    order_state = order.getSimulationState()
+    if order_state in no_applied_rule_state:
+      self.assertEquals(0, len(related_applied_rule_list))
+    else:
+      self.assertEquals(1, len(related_applied_rule_list))
+      applied_rule = related_applied_rule_list[0].getObject()
+      sequence.edit(applied_rule=applied_rule)
+      self.failUnless(applied_rule is not None)
+      self.failUnless(order_state, \
+                      applied_rule.getLastExpandSimulationState())
+      # Test if applied rule has a specialise value with default_order_rule
+      portal_rules = getToolByName(order, 'portal_rules')
+      # XXX hardcoded value
+      self.assertEquals(portal_rules.default_production_order_rule, \
+                        applied_rule.getSpecialiseValue())
+      
+      simulation_movement_list = applied_rule.objectValues()
+      sequence.edit(simulation_movement_list=simulation_movement_list)
+
+  def checkObjectAttributes(self, object, attribute_list):
+    for value, attribute in attribute_list:
+      try:
+        self.assertEquals(value,
+                          getattr(object, attribute)())
+      except AssertionError:
+        raise AssertionError, "Attribute: %s, Value: %s, Result: %s" %\
+                    (attribute, value, getattr(object, attribute)())
+
+  def stepCheckProductionSimulation(self, sequence=None, sequence_list=None,
+                                    **kw):
+    """
+      Hardcoded check
+    """
+    self.stepCheckOrderSimulation(sequence=sequence,
+                                  sequence_list=sequence_list, **kw)
+    # Test simulation movement generated related to order line
+    simulation_movement_list = sequence.get('simulation_movement_list')
+    self.assertEquals(1, len(simulation_movement_list))
+    order_line = sequence.get('order_line')
+    related_simulation_movement_list = order_line.getOrderRelatedValueList()
+    self.assertEquals(1, len(related_simulation_movement_list))
+    related_simulation_movement = related_simulation_movement_list[0]
+    self.assertEquals(related_simulation_movement,
+                      simulation_movement_list[0])
+    production_organisation1 = sequence.get('production_organisation1')
+    # XXX FIXME test date
+    self.checkObjectAttributes(
+           related_simulation_movement, (
+             (order_line.getQuantity(), 'getQuantity'),
+             (order_line.getResourceValue(), 'getResourceValue'),
+             (order_line.getVariationCategoryList(), 
+              'getVariationCategoryList'),
+             (order_line.getDestinationValue(), 'getDestinationValue'),
+             (order_line.getDestinationSectionValue(), 
+              'getDestinationSectionValue'),
+             (production_organisation1, 'getSourceValue'),
+             (production_organisation1, 'getSourceSectionValue')))
+    # Test next applied rule
+    applied_rule_list = related_simulation_movement.objectValues()
+    self.assertEquals(1, len(applied_rule_list))
+    applied_rule = applied_rule_list[0]
+    self.assertEquals("Applied Rule", applied_rule.getPortalType())
+    portal_rules = getToolByName(applied_rule, 'portal_rules')
+    self.assertEquals(portal_rules.default_transformation_rule, \
+                      applied_rule.getSpecialiseValue())
+    # Test deeper simulation 
+    simulation_movement_list = applied_rule.objectValues()
+    self.assertEquals(2, len(simulation_movement_list))
+    # Test consumed movement
+    consumed_movement = applied_rule.cr_1
+    operation_resource = consumed_movement.portal_categories.resolveCategory(
+                                              'operation/operation1')
+    # FIXME
+    self.checkObjectAttributes(
+           consumed_movement, (
+             (10, 'getQuantity'),
+             (operation_resource, 'getResourceValue'),
+             ([], 'getVariationCategoryList'),
+             (None, 'getDestinationValue'),
+             (None, 'getDestinationSectionValue'),
+             (production_organisation1, 'getSourceValue'),
+             (production_organisation1, 'getSourceSectionValue')))
+    # Test produced resource
+    produced_movement = applied_rule.pr
+    resource = sequence.get('resource')
+    production_organisation1 = sequence.get('production_organisation1')
+    self.checkObjectAttributes(
+           produced_movement, (
+             (5, 'getQuantity'),
+             (resource, 'getResourceValue'),
+             ([], 'getVariationCategoryList'),
+             (production_organisation1, 'getDestinationValue'),
+             (production_organisation1, 'getDestinationSectionValue'),
+             (None, 'getSourceValue'),
+             (None, 'getSourceSectionValue')))
+
+  def test_01_testProductionSimulationExpand(self, quiet=0, run=run_all_test):
+    """
+      Test generation and update of order applied rule.
+    """
+    if not run: return
+    sequence_list = SequenceList()
+    # Test when order is 
+    sequence_string = '\
+                      CreateProductionOrganisation1 \
+                      CreateProductionSC \
+                      CreateVariatedResource \
+                      CreateComponent1 \
+                      CreateTransformation \
+                      CreateOrganisation \
+                      CreateOrder \
+                      CreateOrderLine \
+                      Tic \
+                      OrderOrder \
+                      Tic \
+                      CheckProductionSimulation \
+                      '
+    sequence_list.addSequenceString(sequence_string)
+    sequence_list.play(self)
+
+  def stepCreateSupplyOrganisation1(self, sequence=None, sequence_list=None, 
+                                        **kw):
+    """
+      Create a organisation for supply
+    """
+    self.stepCreateOrganisation(sequence=sequence, sequence_list=sequence_list,
+                                title='supply_organisation1', **kw)
+
+  def stepCreateSourcingSC(self, sequence=None, sequence_list=None, 
+                             **kw):
+    """
+      Create a empty organisation
+    """
+    # Create supply chain
+    self.stepCreateProductionSC(sequence=sequence, sequence_list=sequence_list,
+                                **kw)
+    supply_chain = sequence.get('supply_chain')
+    # Create supply node
+    supply_organisation  = sequence.get('supply_organisation1')
+    supply_node = supply_chain.newContent(
+                         portal_type=self.supply_node_portal_type)
+    supply_node.edit(
+      destination_value=supply_organisation
+    )
+    # Create sourcing link
+    supply_link = supply_chain.newContent(
+                         portal_type=self.supply_link_portal_type)
+    production_node1 = sequence.get('production_node1')
+    production_organisation1 = sequence.get('production_organisation1')
+    supply_link.edit(
+      source_value=supply_node,
+      source_section_value=supply_organisation,
+      destination_value=production_node1,
+      destination_section_value=production_organisation1,
+      min_delay=5,
+      max_delay=6,
+      deliverable=0,
+      industrial_phase_list=["supply_phase1"]
+    )
+
+  def stepCheckSourcingSimulation(self, sequence=None, sequence_list=None,
+                                  **kw):
+    """
+      Hardcoded check
+    """
+    self.stepCheckOrderSimulation(sequence=sequence,
+                                  sequence_list=sequence_list, **kw)
+    # Test simulation movement generated related to order line
+    simulation_movement_list = sequence.get('simulation_movement_list')
+    self.assertEquals(1, len(simulation_movement_list))
+    order_line = sequence.get('order_line')
+    related_simulation_movement_list = order_line.getOrderRelatedValueList()
+    self.assertEquals(1, len(related_simulation_movement_list))
+    related_simulation_movement = related_simulation_movement_list[0]
+    self.assertEquals(related_simulation_movement,
+                      simulation_movement_list[0])
+    production_organisation1 = sequence.get('production_organisation1')
+    # XXX FIXME test date
+    self.checkObjectAttributes(
+           related_simulation_movement, (
+             (order_line.getQuantity(), 'getQuantity'),
+             (order_line.getResourceValue(), 'getResourceValue'),
+             (order_line.getVariationCategoryList(), 
+              'getVariationCategoryList'),
+             (order_line.getDestinationValue(), 'getDestinationValue'),
+             (order_line.getDestinationSectionValue(), 
+              'getDestinationSectionValue'),
+             (production_organisation1, 'getSourceValue'),
+             (production_organisation1, 'getSourceSectionValue')))
+    # Test next applied rule
+    applied_rule_list = related_simulation_movement.objectValues()
+    self.assertEquals(1, len(applied_rule_list))
+    applied_rule = applied_rule_list[0]
+    self.assertEquals("Applied Rule", applied_rule.getPortalType())
+    portal_rules = getToolByName(applied_rule, 'portal_rules')
+    self.assertEquals(portal_rules.default_transformation_rule, \
+                      applied_rule.getSpecialiseValue())
+    # Test deeper simulation 
+    simulation_movement_list = list(applied_rule.objectValues())
+    # FIXME
+    self.assertEquals(3, len(simulation_movement_list))
+    # Test produced resource
+    produced_movement = applied_rule.pr
+    resource = sequence.get('resource')
+    production_organisation1 = sequence.get('production_organisation1')
+    self.checkObjectAttributes(
+           produced_movement, (
+             (5, 'getQuantity'),
+             (resource, 'getResourceValue'),
+             ([], 'getVariationCategoryList'),
+             (production_organisation1, 'getDestinationValue'),
+             (production_organisation1, 'getDestinationSectionValue'),
+             (None, 'getSourceValue'),
+             (None, 'getSourceSectionValue')))
+    self.assertEquals(0, len(produced_movement.objectValues()))
+
+    simulation_movement_list.remove(produced_movement)
+    # All code before is a stupid copy (except movement count)
+    # Test consumed movement
+    operation_resource = resource.portal_categories.resolveCategory(
+                                              'operation/operation1')
+    component_resource = sequence.get('component1')
+#     for consumed_movement in (applied_rule.cr_1, applied_rule.cr_2):
+    for consumed_movement in simulation_movement_list:
+      if consumed_movement.getResourceValue() == operation_resource:
+        operation_movement = consumed_movement
+      else:
+        component_movement = consumed_movement
+    # Check operation movement
+    self.checkObjectAttributes(
+           operation_movement, (
+             (10, 'getQuantity'),
+             (operation_resource, 'getResourceValue'),
+             ([], 'getVariationCategoryList'),
+             (None, 'getDestinationValue'),
+             (None, 'getDestinationSectionValue'),
+             (production_organisation1, 'getSourceValue'),
+             (production_organisation1, 'getSourceSectionValue')))
+    self.assertEquals(0, len(operation_movement.objectValues()))
+    # Check component movement
+    self.checkObjectAttributes(
+           component_movement, (
+             (30, 'getQuantity'),
+             (component_resource, 'getResourceValue'),
+             ([], 'getVariationCategoryList'),
+             (None, 'getDestinationValue'),
+             (None, 'getDestinationSectionValue'),
+             (production_organisation1, 'getSourceValue'),
+             (production_organisation1, 'getSourceSectionValue')))
+    self.assertEquals(1, len(component_movement.objectValues()))
+    # Test supply applied rule
+    applied_rule = component_movement.objectValues()[0]
+    self.assertEquals("Applied Rule", applied_rule.getPortalType())
+    portal_rules = getToolByName(applied_rule, 'portal_rules')
+    self.assertEquals(portal_rules.default_transformation_sourcing_rule, \
+                      applied_rule.getSpecialiseValue())
+    # Test supply movement
+    simulation_movement_list = applied_rule.objectValues()
+    # FIXME
+    self.assertEquals(1, len(simulation_movement_list))
+    # Test supply resource
+    supply_movement = applied_rule.ts
+    supply_organisation1 = sequence.get('supply_organisation1')
+    self.checkObjectAttributes(
+           supply_movement, (
+             (30, 'getQuantity'),
+             (component_resource, 'getResourceValue'),
+             ([], 'getVariationCategoryList'),
+             (production_organisation1, 'getDestinationValue'),
+             (production_organisation1, 'getDestinationSectionValue'),
+             (supply_organisation1, 'getSourceValue'),
+             (supply_organisation1, 'getSourceSectionValue')))
+    self.assertEquals(0, len(supply_movement.objectValues()))
+
+  def test_02_testSourcingSimulationExpand(self, quiet=0, 
+                                                     run=run_all_test):
+    """
+      Test generation and update of order applied rule.
+    """
+    if not run: return
+    sequence_list = SequenceList()
+    # Test when order is 
+    sequence_string = '\
+                      CreateProductionOrganisation1 \
+                      CreateSupplyOrganisation1 \
+                      CreateSourcingSC \
+                      CreateVariatedResource \
+                      CreateComponent1 \
+                      CreateTransformation \
+                      CreateOrganisation \
+                      CreateOrder \
+                      CreateOrderLine \
+                      Tic \
+                      OrderOrder \
+                      Tic \
+                      CheckSourcingSimulation \
+                      '
+    sequence_list.addSequenceString(sequence_string)
+    sequence_list.play(self)
+
+if __name__ == '__main__':
+    framework()
+else:
+    import unittest
+    def test_suite():
+        suite = unittest.TestSuite()
+        suite.addTest(unittest.makeSuite(TestProductionOrder))
+        return suite
-- 
2.30.9