diff --git a/product/Coramy/skins/coramy_erp5/ActivityTool_postError.py b/product/Coramy/skins/coramy_erp5/ActivityTool_postError.py
new file mode 100755
index 0000000000000000000000000000000000000000..b75c1d3d851018b36cac13559b26c52c7ca48cd3
--- /dev/null
+++ b/product/Coramy/skins/coramy_erp5/ActivityTool_postError.py
@@ -0,0 +1,10 @@
+## Script (Python) "ActivityTool_postError"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters=error
+##title=
+##
+context.portal_activities.setTitle(context.portal_activities.title + '\p' + error)
diff --git a/product/Coramy/skins/coramy_erp5/AppliedRule_cleanOrphanedOrder.py b/product/Coramy/skins/coramy_erp5/AppliedRule_cleanOrphanedOrder.py
new file mode 100755
index 0000000000000000000000000000000000000000..ffd276bbadadb9180cd534c3d62d1982918d8198
--- /dev/null
+++ b/product/Coramy/skins/coramy_erp5/AppliedRule_cleanOrphanedOrder.py
@@ -0,0 +1,49 @@
+## Script (Python) "AppliedRule_cleanOrphanedOrder"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters=
+##title=
+##
+# Use this script to test if simulation state is acceptable
+
+def hasDelivery(ps_item):
+  for m in ps_item.objectValues():
+    if len(m.getCategoryMembershipList('delivery')) > 0:
+      return 1
+    for a in m.objectValues():
+      if hasDelivery(a):
+        return 1
+  return 0
+
+def getDeliveryList(ps_item):
+  result = {}
+  for m in ps_item.objectValues():
+    for d in m.getDeliveryValueList():
+      if d is not None:
+        result[d.getRelativeUrl()] = 1
+    for a in m.objectValues():
+      result.update( getDeliveryList(a))
+  return result
+
+# ----------------------------------------------------------
+# First make sure all simulation movements point to an order
+
+ar = context
+r = ar.getSpecialiseValue() 
+if r is not None:
+ if r.getPortalType() == "Order Rule":
+  if ar.getCausalityValue() is None:
+    # Additional test need to check this is an order rule
+    print "    Applied Rule %s has no order" % ar.getId()
+    print "      Previously was: %s" % ar.getCausality()
+    if hasDelivery(ar):
+         print "      Applied Rule %s has some delivered movements" % ar.getId()
+         print "        deliveries: %s" % ' '.join(getDeliveryList(ar).keys())
+    elif ar.getId() not in ('zero_stock', ):
+         print "      Delete %s" % ar.getId()
+         context.portal_simulation.deleteContent(ar.getId())
+
+return printed
diff --git a/product/Coramy/skins/coramy_erp5/DateTime_getFormattedDate.py b/product/Coramy/skins/coramy_erp5/DateTime_getFormattedDate.py
new file mode 100755
index 0000000000000000000000000000000000000000..08492d117d425a60512b041822f1eb0976633ae2
--- /dev/null
+++ b/product/Coramy/skins/coramy_erp5/DateTime_getFormattedDate.py
@@ -0,0 +1,15 @@
+## Script (Python) "DateTime_getFormattedDate"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters=date_time=None
+##title=
+##
+from DateTime import DateTime
+
+if date_time == None :
+  date_time = DateTime()
+
+return "%2.2d/%2.2d/%s" % (date_time.day(), date_time.month(), date_time.year())
diff --git a/product/Coramy/skins/coramy_erp5/Delivery_reindexAll.py b/product/Coramy/skins/coramy_erp5/Delivery_reindexAll.py
new file mode 100755
index 0000000000000000000000000000000000000000..344d84d944df6ac4e016b35bec308a259e4e8a93
--- /dev/null
+++ b/product/Coramy/skins/coramy_erp5/Delivery_reindexAll.py
@@ -0,0 +1,31 @@
+## Script (Python) "Delivery_reindexAll"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters=
+##title=
+##
+error_list = []
+return_list = []
+
+context.portal_catalog.catalog_object(context.portal_categories,None)
+
+base_url = '/'.join(context.getPhysicalPath())
+
+print "#### Indexing categories ####"
+for id in list(context.portal_categories.objectIds()):
+  context.portal_activities.newMessage('SQLDict', '%s/portal_categories/%s' % (base_url, id), {}, 'recursiveImmediateReindexObject')
+
+# We index simulation first to make sure we can calculate tests
+print "#### Indexing simulation ####"
+for id in list(context.portal_simulation.objectIds()):
+  context.portal_activities.newMessage('SQLDict', '%s/portal_simulation/%s' % (base_url, id), {}, 'immediateReindexObject')
+
+for folder in context.portal_url.getPortalObject().objectValues(("ERP5 Folder",)):
+  print "#### Indexing contents inside folder %s ####" % folder.id
+  for id in list(folder.objectIds()):
+    context.portal_activities.newMessage('SQLDict', '%s/%s/%s' % (base_url, folder.getId(), id), {}, 'recursiveImmediateReindexObject')
+
+return printed
diff --git a/product/Coramy/skins/coramy_erp5/Delivery_rescueOrphanedMovement.py b/product/Coramy/skins/coramy_erp5/Delivery_rescueOrphanedMovement.py
new file mode 100755
index 0000000000000000000000000000000000000000..2fc0aaa54020640252787416c79da8e42c55f67b
--- /dev/null
+++ b/product/Coramy/skins/coramy_erp5/Delivery_rescueOrphanedMovement.py
@@ -0,0 +1,39 @@
+## Script (Python) "Delivery_rescueOrphanedMovement"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters=fix=0
+##title=
+##
+# Example code:
+
+order_uid_list = context.getCausalityUidList()  # XXX We may need to filter portal_type
+
+# Check each existing movement in delivery
+attached_to_movement = []
+for m in context.getMovementList():
+  # simulation_movement = m.getDeliveryRelatedValueList()
+  # Is there any orphaned movement
+  result = context.Delivery_zGetOrphanedMovementList(order_uid_list = order_uid_list,
+                                                  resource_uid = m.getResourceUid(),
+                                                  variation_text = m.getVariationText())
+  if len(result) > 0:
+    for orphaned in result:
+      print "Found orphaned movement %s attached to %s" % (orphaned.relative_url, m.getRelativeUrl())
+      attached_to_movement.append(orphaned.relative_url)
+      if fix:
+        simulation_movement = orphaned.getObject()
+        quantity = simulation_movement.getQuantity()
+        simulation_movement.setDeliveryValue(m)
+        m.setQuantity(quantity)
+        print "  Fixed orphaned movement %s attached to %s with quantity %s" % (orphaned.relative_url, m.getRelativeUrl(), quantity)
+
+# Check each orphaned movement
+result = context.Delivery_zGetOrphanedMovementList(  order_uid_list = order_uid_list )
+for orphaned in result:
+  if orphaned.relative_url not in attached_to_movement:
+    print "Found orphaned movement %s which required new line/cell" % orphaned.relative_url
+
+return printed
diff --git a/product/Coramy/skins/coramy_erp5/Delivery_zGetOrphanedMovementList.zsql b/product/Coramy/skins/coramy_erp5/Delivery_zGetOrphanedMovementList.zsql
new file mode 100755
index 0000000000000000000000000000000000000000..285e2953edf12ea0460d3681979003f7dc650e57
--- /dev/null
+++ b/product/Coramy/skins/coramy_erp5/Delivery_zGetOrphanedMovementList.zsql
@@ -0,0 +1,52 @@
+<dtml-comment>
+title:
+connection_id:MySQL
+max_rows:1000
+max_cache:100
+cache_time:0
+class_name:ZSQLBrain
+class_file:zsqlbrain.py
+</dtml-comment>
+<params>order_uid_list:list
+resource_uid
+variation_text</params>
+SELECT
+	catalog.*,
+        movement.quantity,
+        movement.target_quantity,
+        movement.resource_uid,
+        movement.variation_text,
+        movement.source_uid,
+        movement.destination_uid,
+        movement.start_date,
+        movement.stop_date,
+        movement.target_start_date,
+        movement.target_stop_date
+FROM
+	movement AS related_order_line,
+	movement,
+	catalog AS related_order,
+	category AS movement_c,
+	catalog LEFT JOIN category ON (category.uid=catalog.uid 
+             AND category.base_category_uid = <dtml-var "portal_categories.delivery.getUid()">) 
+                LEFT JOIN catalog as related_delivery ON related_delivery.uid = category.category_uid
+WHERE
+ 	related_delivery.uid is NULL
+AND
+	catalog.portal_type = "Simulation Movement"
+AND
+	catalog.uid = movement_c.uid
+AND
+	movement_c.category_uid = related_order_line.uid
+AND
+	movement_c.base_category_uid = <dtml-var "portal_categories.order.getUid()">
+AND
+	related_order_line.delivery_uid = related_order.uid
+AND
+	catalog.uid = movement.uid
+AND
+	related_order.simulation_state = 'confirmed'
+<dtml-if order_uid_list>AND	<dtml-in order_uid_list>related_order.uid = <dtml-sqlvar sequence-item type="int"> <dtml-if sequence-end><dtml-else> OR </dtml-if> </dtml-in>
+</dtml-if><dtml-if resource_uid>AND	movement.resource_uid = <dtml-sqlvar resource_uid type="int"> 
+</dtml-if><dtml-if variation_text>AND	movement.variation_text = <dtml-sqlvar variation_text type="string"> 
+</dtml-if>
\ No newline at end of file
diff --git a/product/Coramy/skins/coramy_erp5/Delivery_zGetOrphanedProductionMovementList.zsql b/product/Coramy/skins/coramy_erp5/Delivery_zGetOrphanedProductionMovementList.zsql
new file mode 100755
index 0000000000000000000000000000000000000000..4b38a89197c72cb2df180e99aee54272f1a281ac
--- /dev/null
+++ b/product/Coramy/skins/coramy_erp5/Delivery_zGetOrphanedProductionMovementList.zsql
@@ -0,0 +1,54 @@
+<dtml-comment>
+title:
+connection_id:MySQL
+max_rows:10000
+max_cache:100
+cache_time:0
+class_name:ZSQLBrain
+class_file:zsqlbrain.py
+</dtml-comment>
+<params>order_uid_list:list
+resource_uid
+variation_text</params>
+SELECT
+	catalog.*,
+        movement.quantity,
+        movement.target_quantity,
+        movement.resource_uid,
+        movement.variation_text,
+        movement.source_uid,
+        movement.destination_uid,
+        movement.start_date,
+        movement.stop_date,
+        movement.target_start_date,
+        movement.target_stop_date
+FROM
+	movement ,
+	catalog AS related_order,
+	catalog AS resource,
+	catalog AS parent,
+	catalog LEFT JOIN category ON (category.uid=catalog.uid 
+             AND category.base_category_uid = <dtml-var "portal_categories.delivery.getUid()">) 
+                LEFT JOIN catalog as related_delivery ON related_delivery.uid = category.category_uid
+WHERE
+ 	related_delivery.uid is NULL
+AND
+	catalog.portal_type = "Simulation Movement"
+AND
+	movement.delivery_uid = related_order.uid
+AND
+	catalog.uid = movement.uid
+AND
+	related_order.simulation_state = 'confirmed'
+AND
+	movement.resource_uid = resource.uid
+AND
+	catalog.parent_uid = parent.uid
+AND	((parent.id = "default_transformation_sourcing_rule"
+AND	(resource.portal_type = "Composant" OR resource.portal_type = "Tissu"))
+OR	(parent.id = "default_transformation_rule"
+AND	(resource.portal_type = "Modele" OR resource.portal_type = "Composant" OR resource.portal_type = "Tissu" OR resource.portal_type = "Category"))) 
+<dtml-if order_uid_list>AND	<dtml-in order_uid_list>related_order.uid = <dtml-sqlvar sequence-item type="int"> <dtml-if sequence-end><dtml-else> OR </dtml-if> </dtml-in>
+</dtml-if><dtml-if resource_uid>AND	movement.resource_uid = <dtml-sqlvar resource_uid type="int"> 
+</dtml-if><dtml-if variation_text>AND	movement.variation_text = <dtml-sqlvar variation_text type="string"> 
+</dtml-if>
\ No newline at end of file
diff --git a/product/Coramy/skins/coramy_erp5/Movement_search.zsql b/product/Coramy/skins/coramy_erp5/Movement_search.zsql
new file mode 100755
index 0000000000000000000000000000000000000000..15dcc8a1276f0f7160127990192717ad3b1b8d68
--- /dev/null
+++ b/product/Coramy/skins/coramy_erp5/Movement_search.zsql
@@ -0,0 +1,34 @@
+<dtml-comment>
+title:
+connection_id:MySQL
+max_rows:1000
+max_cache:100
+cache_time:0
+class_name:ZSQLBrain
+class_file:zsqlbrain.py
+</dtml-comment>
+<params>resource_uid
+variation_text
+source_uid
+destination_uid
+start_date
+stop_date
+target_start_date
+target_stop_date</params>
+SELECT
+	catalog.*
+FROM
+	catalog, movement
+WHERE
+	catalog.uid = movement.uid
+AND	movement.is_accountable = 1
+AND	catalog.portal_type <> "Simulation Movement"
+<dtml-if resource_uid>AND	movement.resource_uid = <dtml-sqlvar resource_uid type="int">
+</dtml-if><dtml-if variation_text>AND	movement.variation_text = <dtml-sqlvar variation_text type="string">
+</dtml-if><dtml-if source_uid>AND	movement.source_uid = <dtml-sqlvar source_uid type="int">
+</dtml-if><dtml-if destination_uid>AND	movement.destination_uid = <dtml-sqlvar destination_uid type="int">
+</dtml-if><dtml-if start_date>AND	movement.start_date = <dtml-sqlvar start_date type="string">
+</dtml-if><dtml-if stop_date>AND	movement.stop_date = <dtml-sqlvar stop_date type="string">
+</dtml-if><dtml-if target_start_date>AND	movement.start_date = <dtml-sqlvar target_start_date type="string">
+</dtml-if><dtml-if target_stop_date>AND	movement.stop_date = <dtml-sqlvar target_stop_date type="string">
+</dtml-if>
\ No newline at end of file
diff --git a/product/Coramy/skins/coramy_erp5/Order_cleanDuplicates.py b/product/Coramy/skins/coramy_erp5/Order_cleanDuplicates.py
new file mode 100755
index 0000000000000000000000000000000000000000..b98de568d051e0733dd605f86d6d1b1a1844934c
--- /dev/null
+++ b/product/Coramy/skins/coramy_erp5/Order_cleanDuplicates.py
@@ -0,0 +1,73 @@
+## Script (Python) "Order_cleanDuplicates"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters=
+##title=
+##
+# Use this script to test if simulation state is acceptable
+
+def hasDelivery(ps_item):
+  for m in ps_item.objectValues():
+    if len(m.getCategoryMembershipList('delivery')) > 0:
+      return 1
+    for a in m.objectValues():
+      if hasDelivery(a):
+        return 1
+  return 0
+
+def getDeliveryList(ps_item):
+  result = {}
+  for m in ps_item.objectValues():
+    for d in m.getDeliveryValueList():
+      if d is not None:
+        result[d.getRelativeUrl()] = 1
+    for a in m.objectValues():
+      result.update( getDeliveryList(a))
+  return result
+
+of = context
+if of.getSimulationState() not in ('draft', 'cancelled', 'auto_planned'):
+    ps = of.getCausalityRelatedValueList(portal_type="Applied Rule")
+    if len(ps) == 0:
+      print "    Missing PS for Order %s of type %s" % (of.getId(), of.getPortalType())
+      print "      Reexpand order %s" % of.getId()
+      of.edit()
+    elif len(ps) > 1:
+      print "    Too many PS for Order %s of type %s" % (of.getId(), of.getPortalType())
+      no_delivery = []
+      delivery = []
+      for ps_item in ps:
+        if hasDelivery(ps_item):
+          print "      PS %s has some delivered movements" % ps_item.getId()
+          delivery.append(ps_item)
+        else:
+          print "      PS %s has no delivered movements" % ps_item.getId()
+          no_delivery.append(ps_item)
+      # manage_delObjects
+      if len(delivery) > 0:
+        # Only erase no_delivery if one item has delivery
+        for ps_item in no_delivery:
+          print "      Delete PS %s" % ps_item.getId()
+          parent = ps_item.aq_parent
+          parent.deleteContent(ps_item.getId())
+      else:
+        # Keep at least one
+        for ps_item in no_delivery[1:]:
+          print "      Delete PS %s" % ps_item.getId()
+          id = ps_item.getId()
+          parent = ps_item.aq_parent
+          parent.deleteContent(ps_item.getId())
+      if len(delivery) > 1:
+        # We erase the Applied Rule but keep 
+        # some excessive packing lists which may have been generated
+        # THIS BREAKS CONSISTENCY 
+        for ps_item in delivery[1:]:
+          print "      Delete PS %s with BREAKS CONSISTENCY" % ps_item.getId()
+          id = ps_item.getId()
+          parent = ps_item.aq_parent
+          #parent.deleteContent(ps_item.getId())
+
+return printed
diff --git a/product/Coramy/skins/coramy_erp5/PortalSimulation_cleanup.py b/product/Coramy/skins/coramy_erp5/PortalSimulation_cleanup.py
new file mode 100755
index 0000000000000000000000000000000000000000..a0832c7e2919e8012086b29c0e84e2a873e4a49e
--- /dev/null
+++ b/product/Coramy/skins/coramy_erp5/PortalSimulation_cleanup.py
@@ -0,0 +1,36 @@
+## Script (Python) "PortalSimulation_cleanup"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters=
+##title=
+##
+process = context.portal_activities.newActiveProcess()
+base_url = '/'.join(context.portal_url.getPortalObject().getPhysicalPath())
+
+# ----------------------------------------------------------
+# First make sure all simulation movements point to an order
+
+print "-- Checking simulation"
+for id in context.portal_simulation.objectIds():
+  print "  AppliedRule_cleanOrphadedOrder %s" % id
+  context.portal_activities.newMessage('SQLDict', '%s/portal_simulation/%s' % (base_url, id), process, {}, 'AppliedRule_cleanOrphanedOrder')
+
+# ----------------------------------------------------------
+# Next make sure all orders in > planned state have at most one applied rule
+
+for module_id in ('ordre_fabrication','commande_achat','commande_vente',):
+  for id in context[module_id].objectIds():
+    print "  Order_cleanDuplicates %s/%s" % (module_id , id)
+    context.portal_activities.newMessage('SQLDict', '%s/%s/%s' % (base_url, module_id, id), process, {}, 'Order_cleanDuplicates')
+
+# ----------------------------------------------------------
+# Next make sure all movements in a delivery of material point to simulation
+
+
+# ----------------------------------------------------------
+# Next make sure all movements in a delivery of material point to simulation
+
+return printed
diff --git a/product/Coramy/skins/coramy_erp5/PortalSimulation_rescueOrphaned.py b/product/Coramy/skins/coramy_erp5/PortalSimulation_rescueOrphaned.py
new file mode 100755
index 0000000000000000000000000000000000000000..79b148698a93431b12fcc743d62abb4c005603e5
--- /dev/null
+++ b/product/Coramy/skins/coramy_erp5/PortalSimulation_rescueOrphaned.py
@@ -0,0 +1,276 @@
+## Script (Python) "PortalSimulation_rescueOrphaned"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters=
+##title=
+##
+exception_order = ['303',]
+
+orphaned_delivery_related_list = {}
+orphaned_delivery_related_quantity = {}
+exception_order = ['303',]
+
+orphaned_delivery_related_list = {}
+has_delivery_rule_related_list = {}
+orphaned_delivery_related_quantity = {}
+orphaned_delivery_related_target_quantity = {}
+orphaned_delivery_list = {}
+orphaned_delivery_quantity = {}
+orphaned_delivery_target_quantity = {}
+build_delivery_list = []
+
+m_list = list(context.Delivery_zGetOrphanedProductionMovementList()) + list(context.Delivery_zGetOrphanedMovementList())
+#m_list = context.Delivery_zGetOrphanedProductionMovementList()
+#m_list = context.Delivery_zGetOrphanedMovementList()
+for b in m_list:
+  m = b.getObject()
+  if m.getDeliveryValue() is None:
+    # Only process orphaned
+    if m.getNetConvertedTargetQuantity() is None:
+      return "Error for target_quantity on %s" % m.getRelativeUrl()
+    if m.getNetConvertedQuantity() is None:
+      return "Error for quantity on %s" % m.getRelativeUrl()
+    ra = m.getRootAppliedRule()
+    order = ra.getCausalityValue() # Order
+    if order is not None:
+      order_id = order.getId()
+      order_relative_url = order.getRelativeUrl()
+    else:
+      order_id = 'UNKNOWN ORDER'
+      order_relative_url = None
+    if order_id not in exception_order:
+      print "Trying to fix order %s: %s" % (order_relative_url , b.path)
+      candidates = context.Movement_search(resource_uid = b.resource_uid, variation_text = b.variation_text,
+                                        source_uid = m.getSourceUid(), destination_uid = m.getDestinationUid())
+      found_candidate = 0
+      if len(candidates) > 0:
+        for dm in candidates:
+          dm_object = dm.getObject()
+          if dm_object is not None:
+            if order_relative_url in dm_object.getDeliveryValue().getCausalityList():
+              is_orphaned = not dm_object.isSimulated()
+              quantity_difference =  dm_object.getNetConvertedQuantity() -  m.getNetConvertedQuantity()
+              target_quantity_difference =  dm_object.getNetConvertedTargetQuantity() -  m.getNetConvertedTargetQuantity()
+              is_identical = quantity_difference  ==  0
+              # We must test here is this object has a delivery rule attached to
+              # we may have to remove some delivery rules...
+              simulation_m = dm_object.getDeliveryRelatedValueList()
+              if len(simulation_m) == 1:
+                if simulation_m[0].getRootAppliedRule().getDefaultCausalityValue().getPortalType() == "Delivery Rule":
+                  has_delivery_rule = 0
+                else:
+                  has_delivery_rule = 1
+              else:
+                has_delivery_rule = 0
+              print "  found related %s orphaned: %s order: %s identical: %s drule: %s delivery q/t: %s %s simulation q/t: %s %s" % (
+                                                  dm_object.getRelativeUrl(),
+                                                  is_orphaned,
+                                                  dm_object.getCausalityList(),
+                                                  is_identical,
+                                                  has_delivery_rule,
+                                                  dm_object.getNetConvertedQuantity(),
+                                                  dm_object.getNetConvertedTargetQuantity(),
+                                                  m.getNetConvertedQuantity(),
+                                                  m.getNetConvertedTargetQuantity(), )
+              if is_orphaned or has_delivery_rule:
+                # Only orphaned movements are good candidates
+                found_candidate = 1
+                # Build dm_object to m mapping
+                if not orphaned_delivery_related_list.has_key(dm_object):
+                  orphaned_delivery_related_list[dm_object] = []
+                  has_delivery_rule_related_list[dm_object] = []
+                  orphaned_delivery_related_quantity[dm_object] = 0.0
+                  orphaned_delivery_related_target_quantity[dm_object] = 0.0
+                if m not in orphaned_delivery_related_list[dm_object]:
+                  # Do not count twice
+                  orphaned_delivery_related_list[dm_object].append(m)
+                  if has_delivery_rule: has_delivery_rule_related_list[dm_object].append(m)
+                  orphaned_delivery_related_quantity[dm_object] = orphaned_delivery_related_quantity[dm_object] + m.getNetConvertedQuantity()
+                  orphaned_delivery_related_target_quantity[dm_object] = orphaned_delivery_related_target_quantity[dm_object] + \
+                                                                         m.getNetConvertedTargetQuantity()
+                # Build m to dm_object mapping
+                if not orphaned_delivery_list.has_key(m):
+                  orphaned_delivery_list[m] = []
+                  orphaned_delivery_quantity[m] = 0.0
+                  orphaned_delivery_target_quantity[m] = 0.0
+                if dm_object not in orphaned_delivery_list[m]:
+                  # Do not count twice
+                  orphaned_delivery_list[m].append(dm_object)
+                  orphaned_delivery_quantity[m] = orphaned_delivery_quantity[m] + dm_object.getNetConvertedQuantity() # Quantity is likely 0
+                  orphaned_delivery_target_quantity[m] = orphaned_delivery_target_quantity[m] + \
+                                          dm_object.getNetConvertedTargetQuantity() # Quantity is likely 0
+      if not found_candidate:
+        # Best solution is probably to create a new delivery
+        if order is not None:
+          for delivery in order.getCausalityRelatedValueList(portal_type=("Sales Packing List", "Purchase Packing List",
+                            "Production Report", "Production Packing List", "Sale Packing List" )):
+            print "  portential delivery %s" % delivery.getRelativeUrl()
+        else:
+          print "  no order found"
+        build_delivery_list.append(m)
+
+print "======================================================="
+print "N to 1 aggregates"
+for dm_object in orphaned_delivery_related_list.keys():
+  if dm_object.getNetConvertedQuantity() == orphaned_delivery_related_quantity[dm_object]:
+    print "  Found matching N(%s) quantity to 1 quantity aggregate for %s" % (
+              len(orphaned_delivery_related_list[dm_object]), dm_object.getRelativeUrl())
+    for m in orphaned_delivery_related_list[dm_object]:
+      print "  #### attaching %s to %s" % (m.getRelativeUrl() , dm_object.getRelativeUrl())
+      #m.setDeliveryValue(dm_object)
+      del orphaned_delivery_list[m] # Not needed anylonger since we found a solution
+      del orphaned_delivery_quantity[m] # Not needed anylonger since we found a solution
+  elif dm_object.getNetConvertedTargetQuantity() == orphaned_delivery_related_target_quantity[dm_object]:
+    print "  Found matching N(%s) target_quantity to 1 target_quantity aggregate for %s" % (
+                len(orphaned_delivery_related_list[dm_object]), dm_object.getRelativeUrl())
+    print "  #### updating quantity of %s" % dm_object.getRelativeUrl()
+    #dm_object.setNetConvertedQuantity(orphaned_delivery_related_quantity[dm_object]) # Update quantity to meet simulation
+    for m in orphaned_delivery_related_list[dm_object]:
+      print "  #### attaching %s to %s" % (m.getRelativeUrl() , dm_object.getRelativeUrl())
+      #m.setDeliveryValue(dm_object)
+      del orphaned_delivery_list[m] # Not needed anylonger since we found a solution
+      del orphaned_delivery_quantity[m] # Not needed anylonger since we found a solution
+  elif dm_object.getNetConvertedQuantity() == 0 and dm_object.getNetConvertedTargetQuantity() != 0:
+    # Probably delivery relation renamed at some point
+    print "  Found zeroed N(%s) to 1 aggregate for %s" % (
+                len(orphaned_delivery_related_list[dm_object]), dm_object.getRelativeUrl())
+    print "  #### updating quantity of %s" % dm_object.getRelativeUrl()
+    #dm_object.setNetConvertedQuantity(orphaned_delivery_related_quantity[dm_object]) # Update quantity to meet simulation
+    for m in orphaned_delivery_related_list[dm_object]:
+      print "  #### attaching %s to %s" % (m.getRelativeUrl() , dm_object.getRelativeUrl())
+      #m.setDeliveryValue(dm_object)
+      del orphaned_delivery_list[m] # Not needed anylonger since we found a solution
+      del orphaned_delivery_quantity[m] # Not needed anylonger since we found a solution
+  else:
+    print "  Found non matching N(%s) to 1 aggregate for %s delivery q/t: %s %s simulation q/t: %s %s" % (
+                    len(orphaned_delivery_related_list[dm_object]),
+                    dm_object.getRelativeUrl(),
+                    dm_object.getNetConvertedQuantity(), dm_object.getNetConvertedTargetQuantity(),
+                    orphaned_delivery_related_quantity[dm_object], orphaned_delivery_related_target_quantity[dm_object])
+    print "  #### updating quantity of %s" % dm_object.getRelativeUrl()
+    #dm_object.setNetConvertedQuantity(orphaned_delivery_related_quantity[dm_object]) # Update quantity to meet simulation
+    for m in orphaned_delivery_related_list[dm_object]:
+      print "  #### attaching %s to %s" % (m.getRelativeUrl() , dm_object.getRelativeUrl())
+      #m.setDeliveryValue(dm_object)
+      del orphaned_delivery_list[m] # Not needed anylonger since we found a solution
+      del orphaned_delivery_quantity[m] # Not needed anylonger since we found a solution
+
+print "======================================================="
+print "1 to N > 1 aggregates"
+for m in orphaned_delivery_list.keys():
+  if len(orphaned_delivery_list[m]) > 1:
+    # 1 to 1 should be already processed at this point
+    if m.getNetConvertedQuantity() == orphaned_delivery_target_quantity[m]:
+      print "  Found matching 1 to N(%s) aggregate for %s" % (len(orphaned_delivery_list[m]), m.getRelativeUrl())
+      dm_object = orphaned_delivery_list[m][0]
+      print "  #### attaching %s to %s q/t: %s %s" % (m.getRelativeUrl(), dm_object.getRelativeUrl(),
+                                                      dm_object.getNetConvertedQuantity(), dm_object.getNetConvertedTargetQuantity())
+      # XXX What about quantity_unit
+#       m.edit(
+#                target_start_date = dm_object.getTargetStartDate(),
+#                target_stop_date = dm_object.getTargetStopDate(),
+#                start_date = dm_object.getStartDate(),
+#                stop_date = dm_object.getStopDate(),
+#                quantity = dm_object.getQuantity(),
+#                target_quantity = dm_object.getTargetQuantity(),
+#                delivery = dm_object.getRelativeUrl(),
+#        )
+      for i in range(len(orphaned_delivery_list[m]) - 1):
+        new_id = "%s_fixsplit_%s" % (m.getId(), i)
+        dm_object = orphaned_delivery_list[m][i+1]
+        print "  #### creating new simulation movement %s attached to %s q/t: %s %s" % (new_id, dm_object.getRelativeUrl(),
+                                                                         dm_object.getNetConvertedQuantity(),
+                                                                         dm_object.getNetConvertedTargetQuantity())
+        # XXX What about quantity_unit
+#         new_movement = m.aq_parent.newContent(portal_type = "Simulation Movement",
+#                                             id = new_id,
+#                                             efficiency = m.getEfficiency(),
+#                                             target_efficiency = m.getTargetEfficiency(),
+#                                             target_start_date = dm_object.getTargetStartDate(),
+#                                             target_stop_date = dm_object.getTargetStopDate(),
+#                                             start_date = dm_object.getStartDate(),
+#                                             stop_date = dm_object.getStopDate(),
+#                                             quantity = dm_object.getQuantity(),
+#                                             target_quantity = dm_object.getTargetQuantity(),
+#                                             delivery = dm_object.getRelativeUrl(),
+#                                             source = m.getSource(),
+#                                             destination = m.getDestination(),
+#                                             source_section = m.getSourceSection(),
+#                                             destination_section =  m.getDestinationSection(),
+#                                             order = m.getOrder()
+#                                           )
+    else:
+      print "  Found non matching 1 to N(%s) aggregate for %s delivery q/t: %s %s simulation q/t: %s %s" % (
+                      len(orphaned_delivery_list[m]), m.getRelativeUrl(),
+                      orphaned_delivery_quantity[m], orphaned_delivery_target_quantity[m],
+                      m.getNetConvertedQuantity(), m.getNetConvertedTargetQuantity(),
+                      )
+      dm_object = orphaned_delivery_list[m][0]
+      print "  #### attaching %s to %s q/t: %s %s" % (m.getRelativeUrl(), dm_object.getRelativeUrl(),
+                                                      dm_object.getNetConvertedQuantity(), dm_object.getNetConvertedTargetQuantity())
+      # XXX What about quantity_unit
+#       m.edit(
+#                target_start_date = dm_object.getTargetStartDate(),
+#                target_stop_date = dm_object.getTargetStopDate(),
+#                start_date = dm_object.getStartDate(),
+#                stop_date = dm_object.getStopDate(),
+#                quantity = dm_object.getQuantity(),
+#                target_quantity = dm_object.getTargetQuantity(),
+#                delivery = dm_object.getRelativeUrl(),
+#        )
+      for i in range(len(orphaned_delivery_list[m]) - 1):
+        new_id = "%s_fixsplit_%s" % (m.getId(), i)
+        dm_object = orphaned_delivery_list[m][i+1]
+        print "  #### creating new simulation movement %s attached to %s q/t: %s %s" % (new_id, dm_object.getRelativeUrl(),
+                                                                         dm_object.getNetConvertedQuantity(),
+                                                                         dm_object.getNetConvertedTargetQuantity())
+        # XXX What about quantity_unit
+#         new_movement = m.aq_parent.newContent(portal_type = "Simulation Movement",
+#                                             id = new_id,
+#                                             efficiency = m.getEfficiency(),
+#                                             target_efficiency = m.getTargetEfficiency(),
+#                                             target_start_date = dm_object.getTargetStartDate(),
+#                                             target_stop_date = dm_object.getTargetStopDate(),
+#                                             start_date = dm_object.getStartDate(),
+#                                             stop_date = dm_object.getStopDate(),
+#                                             quantity = dm_object.getQuantity(),
+#                                             target_quantity = dm_object.getTargetQuantity(),
+#                                             delivery = dm_object.getRelativeUrl(),
+#                                             source = m.getSource(),
+#                                             destination = m.getDestination(),
+#                                             source_section = m.getSourceSection(),
+#                                             destination_section =  m.getDestinationSection(),
+#                                             order = m.getOrder()
+#                                           )
+
+print "======================================================="
+print "New deliveries"
+
+#root_group = context.portal_simulation.collectMovement(build_delivery_list)
+#delivery_list = context.portal_simulation.buildDeliveryList(root_group)
+#for delivery in delivery_list:
+#  print "New delivery %s for causality %s" % (delivery.getRelativeUrl(), ' '.join(delivery.getCausalityList()))
+
+print '\n'.join(map(lambda x:x.getRelativeUrl(), build_delivery_list))
+
+print "======================================================="
+print "Reexpand delivery rules (and delete duplicate delivery relations)"
+for arb in context.portal_rules.default_delivery_rule.getSpecialiseRelatedValueList():
+  ar = arb.getObject()
+  before = len(ar.objectIds())
+  #ar.expand()
+  after = len(ar.objectIds())
+  print "  reexpand %s before: %s after: %s" % (ar.getRelativeUrl(), before, after)
+
+
+print "======================================================="
+print "TODO"
+
+print "  compare quantities in simulation and deliveries"
+
+
+
+return printed
diff --git a/product/Coramy/skins/coramy_erp5/PortalSimulation_zGetResourceList.zsql b/product/Coramy/skins/coramy_erp5/PortalSimulation_zGetResourceList.zsql
new file mode 100755
index 0000000000000000000000000000000000000000..d5c8a69176a780a9e73af0f5ae1ca9a73a807c4d
--- /dev/null
+++ b/product/Coramy/skins/coramy_erp5/PortalSimulation_zGetResourceList.zsql
@@ -0,0 +1,23 @@
+<dtml-comment>
+title:
+connection_id:MySQL
+max_rows:1000
+max_cache:100
+cache_time:0
+class_name:
+class_file:
+</dtml-comment>
+<params>section
+strict_membership</params>
+SELECT DISTINCT
+	movement.resource_uid,
+	movement.variation_text
+FROM
+	movement, stock, catalog as section, category
+WHERE
+	stock.uid = movement.uid
+AND	stock.section_uid = section.uid
+AND	section.uid = category.category_uid
+AND	category.base_category_uid = <dtml-sqlvar "portal_categories.group.getUid()" type="int">
+AND	section.relative_url = <dtml-sqlvar section type="string">
+<dtml-if strict_membership>AND	category.strict_membership=1</dtml-if>
\ No newline at end of file
diff --git a/product/Coramy/skins/coramy_erp5/base_folder_workflow_action.form b/product/Coramy/skins/coramy_erp5/base_folder_workflow_action.form
new file mode 100755
index 0000000000000000000000000000000000000000..b0b584d3df52026f57fc536711b7ccedc751bac6
--- /dev/null
+++ b/product/Coramy/skins/coramy_erp5/base_folder_workflow_action.form
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+
+<form>
+  <title>Validate</title>
+  <name>base_folder_workflow_action</name>
+  <action>folder_workflow_status_modify</action>
+  <enctype></enctype>
+  <method>POST</method>
+  <pt>form_view_dialog</pt>
+
+  <groups>
+    <group>
+      <title>Default</title>
+      <fields>
+
+      <field><id>my_comment</id> <type>TextAreaField</type>
+        <values>
+          <alternate_name></alternate_name>
+          <css_class></css_class>
+          <default></default>
+          <description></description>
+          <external_validator></external_validator>
+          <extra></extra>
+          <height type="int">5</height>
+          <hidden type="int">0</hidden>
+          <max_length></max_length>
+          <max_linelength></max_linelength>
+          <max_lines></max_lines>
+          <required type="int">0</required>
+          <title>Commentaires</title>
+          <width type="int">40</width>
+        </values>
+        <tales>
+          <default>python:''</default>
+        </tales>
+        <messages>
+          <message name="external_validator_failed">The input failed the external validator.</message>
+          <message name="required_not_found">Input is required but no input given.</message>
+          <message name="too_many_lines">You entered too many lines.</message>
+          <message name="line_too_long">A line was too long.</message>
+          <message name="too_long">You entered too many characters.</message>
+        </messages>
+      </field>
+      </fields>
+    </group>
+    <group>
+      <title>hidden</title>
+      <fields>
+
+      <field><id>my_workflow_action</id> <type>StringField</type>
+        <values>
+          <alternate_name></alternate_name>
+          <css_class></css_class>
+          <default></default>
+          <description></description>
+          <display_maxwidth></display_maxwidth>
+          <display_width type="int">20</display_width>
+          <external_validator></external_validator>
+          <extra></extra>
+          <hidden type="int">1</hidden>
+          <max_length></max_length>
+          <required type="int">0</required>
+          <title>x</title>
+          <truncate type="int">0</truncate>
+        </values>
+        <tales>
+          <default>python:here.REQUEST.workflow_action</default>
+        </tales>
+        <messages>
+          <message name="external_validator_failed">The input failed the external validator.</message>
+          <message name="required_not_found">Input is required but no input given.</message>
+          <message name="too_long">Too much input was given.</message>
+        </messages>
+      </field>
+      <field><id>my_workflow_id</id> <type>StringField</type>
+        <values>
+          <alternate_name></alternate_name>
+          <css_class></css_class>
+          <default></default>
+          <description></description>
+          <display_maxwidth></display_maxwidth>
+          <display_width type="int">20</display_width>
+          <external_validator></external_validator>
+          <extra></extra>
+          <hidden type="int">1</hidden>
+          <max_length></max_length>
+          <required type="int">0</required>
+          <title>x</title>
+          <truncate type="int">0</truncate>
+        </values>
+        <tales>
+          <default>python:here.REQUEST.workflow_id</default>
+        </tales>
+        <messages>
+          <message name="external_validator_failed">The input failed the external validator.</message>
+          <message name="required_not_found">Input is required but no input given.</message>
+          <message name="too_long">Too much input was given.</message>
+        </messages>
+      </field>
+      </fields>
+    </group>
+  </groups>
+</form>
\ No newline at end of file
diff --git a/product/Coramy/skins/coramy_erp5/folder_workflow_status_modify.py b/product/Coramy/skins/coramy_erp5/folder_workflow_status_modify.py
new file mode 100755
index 0000000000000000000000000000000000000000..7d3a65eb85ac87bcd83b5824aabe1c47a1df27a5
--- /dev/null
+++ b/product/Coramy/skins/coramy_erp5/folder_workflow_status_modify.py
@@ -0,0 +1,77 @@
+## Script (Python) "folder_workflow_status_modify"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind subpath=traverse_subpath
+##parameters=form_id,dialog_id,selection_name
+##title=
+##
+from Products.Formulator.Errors import ValidationError, FormValidationError
+
+request=context.REQUEST
+error_message = ''
+
+try:
+  # Validate the form
+  form = getattr(context,dialog_id)
+  form.validate_all_to_request(request)
+  kw = {}
+  for f in form.get_fields():
+    k = f.id
+    k = k[3:]
+    v = getattr(request,k,None)
+    if v is not None:
+      kw[k] = v
+  selection_list = context.portal_selections.callSelectionFor(selection_name, context=context)
+  for selection_item in selection_list:
+    o = selection_item.getObject()
+    workflow_action = kw['workflow_action']
+    action_list = o.portal_workflow.getActionsFor(o)
+    action_list = filter(lambda x:x.has_key('id'), action_list )
+    action_id_list = map(lambda x:x['id'], action_list)
+    if workflow_action in action_id_list:
+      o.portal_workflow.doActionFor(
+          o,
+          workflow_action,
+          wf_id=kw['workflow_id'],
+          **kw)
+
+   # We will check if there's an error_message
+    history_data = None
+    try:
+      history_data = o.portal_workflow.getInfoFor(ob=o, name='history')
+    except:
+      pass
+    redirect_url = None
+    if history_data is not None:
+      last_history_data = history_data[len(history_data)-1]
+      this_error = last_history_data.get('error_message')
+      if this_error != None and this_error != '':
+        error_message += this_error + "-"
+
+except FormValidationError, validation_errors:
+  # Pack errors into the request
+  field_errors = form.ErrorFields(validation_errors)
+  request.set('field_errors', field_errors)
+  return form(request)
+except ValueError, value_error:
+  # Pack errors into the request
+  redirect_url = '%s/%s?%s%s' % ( context.absolute_url(), form_id
+                                  , 'portal_status_message=',value_error
+                                  )
+
+  context.REQUEST[ 'RESPONSE' ].redirect( redirect_url )
+else:
+ 
+  if error_message != None and error_message != '':
+    redirect_url = '%s/%s?%s' % ( context.absolute_url(), form_id
+                                  , 'portal_status_message=%s' % error_message
+                                  )
+    pass
+  if redirect_url is None:
+    redirect_url = '%s/%s?%s' % ( context.absolute_url(), form_id
+                                  , 'portal_status_message=Status+changed.'
+                                  )
+
+  context.REQUEST[ 'RESPONSE' ].redirect( redirect_url )
diff --git a/product/Coramy/skins/coramy_list_method/PieceTissu_searchConsumedList.zsql b/product/Coramy/skins/coramy_list_method/PieceTissu_searchConsumedList.zsql
new file mode 100755
index 0000000000000000000000000000000000000000..c6cb7d4d2bce14bd80159cb02368175aeeaba0f3
--- /dev/null
+++ b/product/Coramy/skins/coramy_list_method/PieceTissu_searchConsumedList.zsql
@@ -0,0 +1,25 @@
+<dtml-comment>
+title:
+connection_id:MySQL
+max_rows:100000
+max_cache:10
+cache_time:60
+class_name:
+class_file:
+</dtml-comment>
+<params></params>
+SELECT DISTINCT
+	distinct item.uid
+FROM
+	catalog AS item
+
+LEFT JOIN category
+ON (category.category_uid=item.uid
+AND category.base_category_uid = <dtml-var "portal_categories.aggregate.getUid()">)
+
+LEFT JOIN stock
+ON (stock.uid = category.uid)
+
+WHERE item.portal_type = "Piece Tissu"
+AND stock.node_uid = <dtml-var "portal_categories.site.Stock_MP.Gravelines.getUid()">
+AND  stock.quantity < 0
\ No newline at end of file
diff --git a/product/Coramy/skins/coramy_list_method/PieceTissu_searchRemainingList.zsql b/product/Coramy/skins/coramy_list_method/PieceTissu_searchRemainingList.zsql
new file mode 100755
index 0000000000000000000000000000000000000000..ad5cc057091e81ee23150f189318ae5991443ae2
--- /dev/null
+++ b/product/Coramy/skins/coramy_list_method/PieceTissu_searchRemainingList.zsql
@@ -0,0 +1,18 @@
+<dtml-comment>
+title:
+connection_id:MySQL
+max_rows:500
+max_cache:100
+cache_time:60
+class_name:ZSQLBrain
+class_file:zsqlbrain.py
+</dtml-comment>
+<params></params>
+SELECT
+	*
+FROM
+	catalog
+WHERE
+portal_type = "Piece Tissu"
+<dtml-in PieceTissu_searchConsumedList>AND uid <> <dtml-sqlvar uid type="int"> 
+</dtml-in>
\ No newline at end of file