diff --git a/product/ERP5/Document/PropertyAssignmentMovementGroup.py b/product/ERP5/Document/PropertyAssignmentMovementGroup.py
new file mode 100644
index 0000000000000000000000000000000000000000..64b740421dcea7dbfd68569a2d84945fd499b935
--- /dev/null
+++ b/product/ERP5/Document/PropertyAssignmentMovementGroup.py
@@ -0,0 +1,96 @@
+##############################################################################
+#
+# Copyright (c) 2008 Nexedi SA and Contributors. All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsibility of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# guarantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+#
+##############################################################################
+
+from Products.ERP5.Document.MovementGroup import MovementGroup
+from Products.ERP5Type import PropertySheet
+
+class PropertyAssignmentMovementGroup(MovementGroup):
+  """
+  This movement group is used to set the value of a property on the delivery,
+  line or cell based on the value of this property on the grouped simulation
+  movements.
+  The are multiple ways of grouping:
+   - min of all property values of simulation movements
+   - max of all property values of simulation movements
+   - average of all property values of simulation movements
+   - "comon": the property value, only if it's the same for all simulation
+     movements, None otherwise.
+  None values are always ignored, even in 'common' mode
+  """
+  meta_type = 'ERP5 Movement Group'
+  portal_type = 'Property Assignment Movement Group'
+  
+  property_sheets = (
+      PropertySheet.PropertyAssignmentMovementGroup, )
+
+  def test(self, movement, property_dict, **kw):
+    # We can always update.
+    return True, property_dict
+
+  def _separate(self, movement_list):
+    property_dict = {}
+
+    for prop in self.getTestedPropertyList():
+      grouping_method = self.getGroupingMethod()
+      if not grouping_method:
+        break
+
+      property_list = [movement.getProperty(prop) for movement in
+             movement_list if movement.getProperty(prop) is not None]
+
+      if grouping_method == 'max':
+        if len(property_list):
+          property_dict[prop] = max(property_list)
+      elif grouping_method == 'min':
+        if len(property_list):
+          property_dict[prop] = min(property_list)
+      elif grouping_method == 'avg':
+        if len(property_list) and self._can_calculate_average(property_list):
+          property_dict[prop] = self._calculate_average(property_list)
+      else:
+        assert grouping_method == 'common'
+        if len(set(property_list)) == 1:
+          property_dict[prop] = property_list[0]
+    return [[movement_list, property_dict]]
+
+  def _can_calculate_average(self, property_list):
+    """Test if we can calculate an average from this property list, only
+    numeric types are supported.
+    """
+    for prop in property_list:
+      try:
+        float(prop)
+      except (TypeError, ValueError):
+        return False
+    return True
+
+  def _calculate_average(self, property_list):
+    """Calculate the average property from the list, only numeric types are
+    supported.
+    """
+    return sum(property_list) / len(property_list)
+
diff --git a/product/ERP5/PropertySheet/PropertyAssignmentMovementGroup.py b/product/ERP5/PropertySheet/PropertyAssignmentMovementGroup.py
new file mode 100644
index 0000000000000000000000000000000000000000..d3f76d4eb6dd1f7297ef72ba8069f312f448ab2a
--- /dev/null
+++ b/product/ERP5/PropertySheet/PropertyAssignmentMovementGroup.py
@@ -0,0 +1,34 @@
+##############################################################################
+#
+# Copyright (c) 2008 Nexedi SA and Contributors. All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsibility of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# guarantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+class PropertyAssignmentMovementGroup:
+  _properties = (
+    {  'id'          : 'grouping_method',
+       'description' : 'Method use to group',
+       'type'        : 'string',
+       'mode'        : 'w' },
+    )
diff --git a/product/ERP5/tests/testMovementGroup.py b/product/ERP5/tests/testMovementGroup.py
index 116d1dbe476fea14e5fb1f8617d8a2ae249f2434..36656503ad8426e4902d299ef3718073f29ef182 100644
--- a/product/ERP5/tests/testMovementGroup.py
+++ b/product/ERP5/tests/testMovementGroup.py
@@ -110,9 +110,109 @@ class TestPropertyMovementGroup(MovementGroupTestCase):
                                        start_date=DateTime(2001, 1, 2))]))
 
 
+class TestPropertyAssignmentMovementGroup(MovementGroupTestCase):
+  def test_property_assignment_movement_group_max(self):
+    movement_list = ( self.folder.newContent(
+                        temp_object=1,
+                        portal_type='Simulation Movement',
+                        start_date=DateTime(2001, 1, 1)),
+                      self.folder.newContent(
+                        temp_object=1,
+                        portal_type='Simulation Movement',
+                        start_date=DateTime(2001, 1, 2)))
+    self.builder.newContent(
+                  portal_type='Property Assignment Movement Group',
+                  collect_order_group='delivery',
+                  tested_property_list=('start_date',),
+                  grouping_method='max',)
+    movement_group_node = self.builder.collectMovement(movement_list)
+    group_list = movement_group_node.getGroupList()
+    self.assertEquals(1, len(group_list))
+    self.assertEquals(dict(start_date=DateTime(2001, 1, 2)),
+                      group_list[0].getGroupEditDict())
+
+  def test_property_assignment_movement_group_min(self):
+    movement_list = ( self.folder.newContent(
+                        temp_object=1,
+                        portal_type='Simulation Movement',
+                        start_date=DateTime(2001, 1, 1)),
+                      self.folder.newContent(
+                        temp_object=1,
+                        portal_type='Simulation Movement',
+                        start_date=DateTime(2001, 1, 2)))
+    self.builder.newContent(
+                  portal_type='Property Assignment Movement Group',
+                  collect_order_group='delivery',
+                  tested_property_list=('start_date',),
+                  grouping_method='min',)
+    movement_group_node = self.builder.collectMovement(movement_list)
+    group_list = movement_group_node.getGroupList()
+    self.assertEquals(1, len(group_list))
+    self.assertEquals(dict(start_date=DateTime(2001, 1, 1)),
+                      group_list[0].getGroupEditDict())
+
+  def test_property_assignment_movement_group_avg(self):
+    movement_list = ( self.folder.newContent(
+                        temp_object=1,
+                        portal_type='Simulation Movement',
+                        int_index=1,),
+                      self.folder.newContent(
+                        temp_object=1,
+                        portal_type='Simulation Movement',
+                        int_index=3,),)
+    self.builder.newContent(
+                  portal_type='Property Assignment Movement Group',
+                  collect_order_group='delivery',
+                  tested_property_list=('int_index',),
+                  grouping_method='avg',)
+    movement_group_node = self.builder.collectMovement(movement_list)
+    group_list = movement_group_node.getGroupList()
+    self.assertEquals(1, len(group_list))
+    self.assertEquals(dict(int_index=2),
+                      group_list[0].getGroupEditDict())
+
+  def test_property_assignment_movement_group_common_match(self):
+    movement_list = ( self.folder.newContent(
+                        temp_object=1,
+                        portal_type='Simulation Movement',
+                        start_date=DateTime(2001, 1, 1)),
+                      self.folder.newContent(
+                        temp_object=1,
+                        portal_type='Simulation Movement',
+                        start_date=DateTime(2001, 1, 1)))
+    self.builder.newContent(
+                  portal_type='Property Assignment Movement Group',
+                  collect_order_group='delivery',
+                  tested_property_list=('start_date',),
+                  grouping_method='common',)
+    movement_group_node = self.builder.collectMovement(movement_list)
+    group_list = movement_group_node.getGroupList()
+    self.assertEquals(1, len(group_list))
+    self.assertEquals(dict(start_date=DateTime(2001, 1, 1)),
+                      group_list[0].getGroupEditDict())
+
+  def test_property_assignment_movement_group_common_doesnot_match(self):
+    movement_list = ( self.folder.newContent(
+                        temp_object=1,
+                        portal_type='Simulation Movement',
+                        start_date=DateTime(2001, 1, 1)),
+                      self.folder.newContent(
+                        temp_object=1,
+                        portal_type='Simulation Movement',
+                        start_date=DateTime(2001, 1, 2)))
+    self.builder.newContent(
+                  portal_type='Property Assignment Movement Group',
+                  collect_order_group='delivery',
+                  tested_property_list=('start_date',),
+                  grouping_method='common',)
+    movement_group_node = self.builder.collectMovement(movement_list)
+    group_list = movement_group_node.getGroupList()
+    self.assertEquals(1, len(group_list))
+    self.assertEquals(dict(), group_list[0].getGroupEditDict())
+
 
 def test_suite():
   suite = unittest.TestSuite()
   suite.addTest(unittest.makeSuite(TestPropertyMovementGroup))
-#  suite.addTest(unittest.makeSuite(TestPropertyAssignementMovementGroup))
+  suite.addTest(unittest.makeSuite(TestPropertyAssignmentMovementGroup))
   return suite