diff --git a/product/ERP5/Document/GeneratedDeliveryBuilder.py b/product/ERP5/Document/GeneratedDeliveryBuilder.py
index 7c785357753cea7ca784d66846c1b77cae10965f..3596e7460e2f27e8495d599ac0bdd7f330de85ca 100644
--- a/product/ERP5/Document/GeneratedDeliveryBuilder.py
+++ b/product/ERP5/Document/GeneratedDeliveryBuilder.py
@@ -89,4 +89,21 @@ class GeneratedDeliveryBuilder(BuilderMixin):
                     , PropertySheet.Amount
                     , PropertySheet.Comment
                     , PropertySheet.DeliveryBuilder
-                    )
\ No newline at end of file
+                    )
+
+  def _setDeliveryMovementProperties(self, delivery_movement,
+                                     simulation_movement, property_dict,
+                                     update_existing_movement=0,
+                                     force_update=0, activate_kw=None):
+    """
+    Initialize or update delivery movement properties.
+    """
+    if getattr(simulation_movement, 'getMappedProperty', None) is not None:
+      property_dict['quantity'] = simulation_movement.getMappedProperty('quantity')
+    else:
+      property_dict['quantity'] = simulation_movement.getQuantity()
+    property_dict['price'] = simulation_movement.getPrice()
+    if update_existing_movement:
+      property_dict['quantity'] = (delivery_movement.getQuantity() or 0.0) + property_dict['quantity']
+    # Update properties on object (quantity, price...)
+    delivery_movement._edit(force_update=1, **property_dict)
diff --git a/product/ERP5/mixin/builder.py b/product/ERP5/mixin/builder.py
index 336e469d9f1db9f02e18f09f4e78c099d6af9a04..fae25d57ecce9ec949b02be747312fa3ca62a259 100644
--- a/product/ERP5/mixin/builder.py
+++ b/product/ERP5/mixin/builder.py
@@ -182,7 +182,6 @@ class BuilderMixin(XMLObject, Amount, Predicate):
                                                    group_by_node=1,
                                                    group_by_section=0,
                                                    **kw)
-    id_count = 0
     # min_flow and max_delay are stored on a supply line. By default
     # we can get them through a method having the right supply type prefix
     # like getPurchaseSupplyLineMinFlow. So we need to guess the supply prefix
@@ -195,25 +194,30 @@ class BuilderMixin(XMLObject, Amount, Predicate):
       supply_prefix = 'sale'
     else:
       supply_prefix = 'internal'
+
+    resource_portal_type_list = self.getResourcePortalTypeList()
+    def newMovement(inventory_item, resource):
+      # Create temporary movement
+      movement = newTempMovement(self.getPortalObject(), "temp")
+      dumb_movement = inventory_item.getObject()
+      resource_portal_type = resource.getPortalType()
+      assert resource_portal_type in (resource_portal_type_list), \
+        "Builder %r does not support resource of type : %r" % (
+        self.getRelativeUrl(), resource_portal_type)
+      movement.edit(
+          resource=inventory_item.resource_relative_url,
+          # XXX FIXME define on a supply line
+          # quantity_unit
+          quantity_unit=resource.getQuantityUnit(),
+          variation_category_list=dumb_movement.getVariationCategoryList(),
+          destination_value=self.getDestinationValue(),
+          resource_portal_type=resource_portal_type,
+          destination_section_value=self.getDestinationSectionValue())
+      return movement
+
     for inventory_item in sql_list:
       if (inventory_item.inventory is not None):
-        dumb_movement = inventory_item.getObject()
-        # Create temporary movement
-        movement = newTempMovement(self.getPortalObject(),
-                                   str(id_count))
-        id_count += 1
-        resource_portal_type_list = self.getResourcePortalTypeList()
         resource = portal.portal_catalog.getObject(inventory_item.resource_uid)
-        resource_portal_type = resource.getPortalType()
-        assert resource_portal_type in (resource_portal_type_list), \
-          "Builder %r does not support resource of type : %r" % (
-          self.getRelativeUrl(), resource_portal_type)
-        movement.edit(
-            resource=inventory_item.resource_relative_url,
-            variation_category_list=dumb_movement.getVariationCategoryList(),
-            destination_value=self.getDestinationValue(),
-            resource_portal_type=resource_portal_type,
-            destination_section_value=self.getDestinationSectionValue())
         # Get min_flow, max_delay on supply line
         min_flow = 0
         max_delay = 0
@@ -225,20 +229,38 @@ class BuilderMixin(XMLObject, Amount, Predicate):
         if round(inventory_item.inventory, 5) < min_stock:
           stop_date = resource.getNextAlertInventoryDate(
                                reference_quantity=min_stock,
-                               variation_text=movement.getVariationText(),
+                               variation_text=inventory_item.variation_text,
                                from_date=DateTime(),
                                **kw)
           if stop_date != None:
+            movement = newMovement(inventory_item, resource)
             max_delay = resource.getMaxDelay(0)
             movement.edit(
-              start_date=DateTime(((stop_date-max_delay).Date())),
-              stop_date=DateTime(stop_date.Date()),
+              start_date=stop_date-max_delay,
+              stop_date=stop_date,
               quantity=max(min_flow, -inventory_item.inventory),
-              quantity_unit=resource.getQuantityUnit()
-              # XXX FIXME define on a supply line
-              # quantity_unit
             )
             movement_list.append(movement)
+        # We could need to cancel automated stock optimization if for some reasons
+        # previous optimisations are obsolete
+        elif round(inventory_item.inventory, 5) > min_stock:
+          delta = inventory_item.inventory - min_stock
+          optimized_inventory_list = portal.portal_simulation.getInventoryList(
+                               resource_uid=inventory_item.resource_uid,
+                               node_uid=inventory_item.node_uid,
+                               variation_text=inventory_item.variation_text,
+                               simulation_state="auto_planned",
+                               sort_on=[("date", "descending")],
+                               )
+          for optimized_inventory in optimized_inventory_list:
+            movement = newMovement(inventory_item, resource)
+            quantity = min(delta, optimized_inventory.inventory)
+            delta = delta - quantity
+            movement.edit(start_date=optimized_inventory.date,
+                          quantity=-quantity)
+            movement_list.append(movement)
+            if delta <= 0:
+              break
     return movement_list
 
   def _searchMovementList(self, **kw):
diff --git a/product/ERP5/tests/testOrderBuilder.py b/product/ERP5/tests/testOrderBuilder.py
index 73a26ed7f27c32f8b75b1ac8c283918bfb58fd1b..66780709a50f5fa5dbd8e4fdde48ebf5a280c4b1 100644
--- a/product/ERP5/tests/testOrderBuilder.py
+++ b/product/ERP5/tests/testOrderBuilder.py
@@ -64,6 +64,10 @@ class TestOrderBuilderMixin(TestOrderMixin):
     self.createCategories()
     self.validateRules()
 
+  def assertDateAlmostEquals(self, first_date, second_date):
+    self.assertTrue(abs(first_date - second_date) < 1.0/86400,
+                    "%r != %r" % (first_date, second_date))
+
   def stepSetMaxDelayOnResource(self, sequence):
     """
     Sets max_delay on resource
@@ -137,8 +141,8 @@ class TestOrderBuilderMixin(TestOrderMixin):
     # XXX: add support for more generated documents
     order, = sequence.get('generated_document_list')
     self.assertEqual(order.getDestinationValue(), organisation)
-    self.assertEqual(order.getStartDate(), self.wanted_start_date)
-    self.assertEqual(order.getStopDate(), self.wanted_stop_date)
+    self.assertDateAlmostEquals(order.getStartDate(), self.wanted_start_date)
+    self.assertDateAlmostEquals(order.getStopDate(), self.wanted_stop_date)
 
     # XXX: ... and for more lines/cells too
     order_line, = order.contentValues(portal_type=self.order_line_portal_type)
@@ -163,8 +167,8 @@ class TestOrderBuilderMixin(TestOrderMixin):
     # XXX: add support for more generated documents
     order, = sequence.get('generated_document_list')
     self.assertEqual(order.getDestinationValue(), organisation)
-    self.assertEqual(order.getStartDate(), self.wanted_start_date)
-    self.assertEqual(order.getStopDate(), self.wanted_stop_date)
+    self.assertDateAlmostEquals(self.wanted_start_date, order.getStartDate())
+    self.assertDateAlmostEquals(self.wanted_stop_date, order.getStopDate())
 
     # XXX: ... and for more lines/cells too
     order_line, = order.contentValues(portal_type=self.order_line_portal_type)
@@ -322,8 +326,7 @@ class TestOrderBuilder(TestOrderBuilderMixin, ERP5TypeTestCase):
 
     self.wanted_quantity = 1.0
     self.wanted_start_date = DateTime(
-      str(self.datetime.earliestTime()
-          + self.order_builder_hardcoded_time_diff))
+      str(self.datetime + self.order_builder_hardcoded_time_diff))
 
     self.wanted_stop_date = self.wanted_start_date
 
@@ -355,7 +358,7 @@ class TestOrderBuilder(TestOrderBuilderMixin, ERP5TypeTestCase):
 
     self.wanted_quantity = 1.0
     self.wanted_start_date = DateTime(
-      str(self.datetime.earliestTime() +
+      str(self.datetime +
           self.order_builder_hardcoded_time_diff))
 
     self.wanted_stop_date = self.wanted_start_date
@@ -374,13 +377,11 @@ class TestOrderBuilder(TestOrderBuilderMixin, ERP5TypeTestCase):
 
     self.wanted_quantity = 1.0
     self.wanted_start_date = DateTime(
-      str(self.datetime.earliestTime()
-          - self.max_delay
+      str(self.datetime - self.max_delay
           + self.order_builder_hardcoded_time_diff))
 
     self.wanted_stop_date = DateTime(
-      str(self.datetime.earliestTime()
-          + self.order_builder_hardcoded_time_diff))
+      str(self.datetime + self.order_builder_hardcoded_time_diff))
 
     sequence_list = SequenceList()
     sequence_list.addSequenceString(self.common_sequence_string)
@@ -394,8 +395,7 @@ class TestOrderBuilder(TestOrderBuilderMixin, ERP5TypeTestCase):
 
     self.wanted_quantity = 1.0
     self.wanted_start_date = DateTime(
-      str(self.datetime.earliestTime()
-          + self.order_builder_hardcoded_time_diff))
+      str(self.datetime + self.order_builder_hardcoded_time_diff))
 
     self.wanted_stop_date = self.wanted_start_date