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