Commit cf6e3e2b authored by Xiaowu Zhang's avatar Xiaowu Zhang

erp5_project: add action to update quantity/unit from tasks

parent 6f038296
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_jio_action</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_jio_action</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>calculate_quantity_and_unit_from_task</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>Modify portal content</string>
</tuple>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Action Information</string> </value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>26.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Calculate Quantity And Unit From Tasks</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/Project_updateQuantityAndUnitDialog</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_jio_action</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_jio_action</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>calculate_quantity_and_unit_from_constraint</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>Modify portal content</string>
</tuple>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Action Information</string> </value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>10.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Calculate Quantity And Unit From Constraints</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/ProjectMilestone_updateQuantityAndUnitDialog</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_jio_action</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_jio_action</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>calculate_quantity_and_unit_from_task</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>Modify portal content</string>
</tuple>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Action Information</string> </value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>26.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Calculate Quantity And Unit From Tasks</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/Project_updateQuantityAndUnitDialog</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
task_list = context.getPredecessorValueList(portal_type='Task')
default_unit = 'time/day'
unit_dict = {}
default_unit = 'time/day'
quantity = 0
for task in task_list:
quantity_unit = task.getTaskLineQuantityUnit()
quantity += task.getTaskLineQuantity()
if quantity_unit:
if quantity_unit not in unit_dict:
unit_dict[quantity_unit] = []
unit_dict[quantity_unit].append(task.getRelativeUrl())
unit_list = unit_dict.keys()
if len(unit_list) > 1:
for key, value_list in unit_dict.iteritems():
if key != default_unit:
if batch:
return value_list
else:
return context.Base_redirect('view', keep_items={'portal_status_message': 'Impossible to compute totals as %s has as unit' % ' '.join(value_list)})
elif len(unit_list) == 0:
quantity_unit = default_unit
else:
quantity_unit = unit_list[0]
context.edit(
quantity=quantity,
quantity_unit=quantity_unit)
if not batch:
return context.Base_redirect('view', keep_items={'portal_status_message': 'Quantity/Unit updated'})
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>batch=0, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ProjectMilestone_updateQuantityAndUnit</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5 Form" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>action</string> </key>
<value> <string>ProjectMilestone_updateQuantityAndUnit</string> </value>
</item>
<item>
<key> <string>action_title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>edit_order</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>enctype</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<list>
<string>left</string>
<string>right</string>
<string>center</string>
<string>bottom</string>
<string>hidden</string>
</list>
</value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<dictionary>
<item>
<key> <string>bottom</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>center</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>hidden</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>left</string> </key>
<value>
<list>
<string>your_message</string>
</list>
</value>
</item>
<item>
<key> <string>right</string> </key>
<value>
<list/>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ProjectMilestone_updateQuantityAndUnitDialog</string> </value>
</item>
<item>
<key> <string>method</string> </key>
<value> <string>POST</string> </value>
</item>
<item>
<key> <string>name</string> </key>
<value> <string>Project_updateQuantityAndUnitDialog</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>ERP5 Form</string> </value>
</item>
<item>
<key> <string>pt</string> </key>
<value> <string>form_dialog</string> </value>
</item>
<item>
<key> <string>row_length</string> </key>
<value> <int>4</int> </value>
</item>
<item>
<key> <string>stored_encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Calculate Quantity And Unit From Tasks</string> </value>
</item>
<item>
<key> <string>unicode_mode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>update_action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>update_action_title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
relation_dict = {}
uid_list = [context.getUid()]
def iterate(container):
relative_url = container.getRelativeUrl()
relation_dict[relative_url] = []
for project_line in container.objectValues(portal_type='Project Line'):
relation_dict[relative_url].append(project_line.getRelativeUrl())
uid_list.append(project_line.getUid())
iterate(project_line)
iterate(context)
task_list = context.portal_catalog(source_project_uid=uid_list, portal_type='Task')
task_by_project = {}
default_unit = 'time/day'
unit_dict = {}
for task in task_list:
source_project = task.getSourceProject()
if source_project not in task_by_project:
task_by_project[source_project] = []
task_by_project[source_project].append(task)
quantity_unit = task.getTaskLineQuantityUnit()
if quantity_unit:
if quantity_unit not in unit_dict:
unit_dict[quantity_unit] = []
unit_dict[quantity_unit].append(task.getRelativeUrl())
unit_list = unit_dict.keys()
if len(unit_list) > 1:
for key, value_list in unit_dict.iteritems():
if key != default_unit:
if batch:
return value_list
else:
return context.Base_redirect('view', keep_items={'portal_status_message': 'Impossible to compute totals as %s has as unit' % ' '.join(value_list)})
elif len(unit_list) == 0:
quantity_unit = default_unit
else:
quantity_unit = unit_list[0]
def calculateQuantity(relative_url):
quantity = 0
for task in task_by_project[relative_url]:
quantity += task.getTaskLineQuantity()
for project_line in relation_dict[relative_url]:
quantity += calculateQuantity(project_line)
return quantity
# skip for project since it has no quantity and unit field
if context.getPortalType() == 'Project':
relation_dict.pop(context.getRelativeUrl())
for relative_url in relation_dict.keys():
context.restrictedTraverse(relative_url).edit(
quantity=calculateQuantity(relative_url),
quantity_unit = quantity_unit)
if not batch:
return context.Base_redirect('view', keep_items={'portal_status_message': 'Quantity/Unit updated'})
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>batch=0, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Project_updateQuantityAndUnit</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5 Form" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>action</string> </key>
<value> <string>Project_updateQuantityAndUnit</string> </value>
</item>
<item>
<key> <string>action_title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>edit_order</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>enctype</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<list>
<string>left</string>
<string>right</string>
<string>center</string>
<string>bottom</string>
<string>hidden</string>
</list>
</value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<dictionary>
<item>
<key> <string>bottom</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>center</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>hidden</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>left</string> </key>
<value>
<list>
<string>your_message</string>
</list>
</value>
</item>
<item>
<key> <string>right</string> </key>
<value>
<list/>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Project_updateQuantityAndUnitDialog</string> </value>
</item>
<item>
<key> <string>method</string> </key>
<value> <string>POST</string> </value>
</item>
<item>
<key> <string>name</string> </key>
<value> <string>Project_updateQuantityAndUnitDialog</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>ERP5 Form</string> </value>
</item>
<item>
<key> <string>pt</string> </key>
<value> <string>form_dialog</string> </value>
</item>
<item>
<key> <string>row_length</string> </key>
<value> <int>4</int> </value>
</item>
<item>
<key> <string>stored_encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Calculate Quantity And Unit From Tasks</string> </value>
</item>
<item>
<key> <string>unicode_mode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>update_action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>update_action_title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -87,6 +87,12 @@ class TestProject(ERP5TypeTestCase): ...@@ -87,6 +87,12 @@ class TestProject(ERP5TypeTestCase):
title='Project_2', title='Project_2',
id='Project_2') id='Project_2')
if not self.portal.project_module.has_key('Project_3'):
self.portal.project_module.newContent(
portal_type='Project',
reference='Project_3',
title='Project_3',
id='Project_3')
# Create resources # Create resources
module = self.portal.product_module module = self.portal.product_module
if not module.has_key('development'): if not module.has_key('development'):
...@@ -214,6 +220,91 @@ class TestProject(ERP5TypeTestCase): ...@@ -214,6 +220,91 @@ class TestProject(ERP5TypeTestCase):
self.assertEqual(project.getStartDate(), task3.getStartDate()) self.assertEqual(project.getStartDate(), task3.getStartDate())
self.assertEqual(project.getStopDate(), task3.getStopDate()) self.assertEqual(project.getStopDate(), task3.getStopDate())
def testProject_updateQuantityAndUnit(self):
# Create Tasks
task_module = self.getPortalObject().task_module
project = self.getPortalObject().project_module.Project_3
for key in ['1', '2']:
if not project.has_key('project_line_%s' % key):
project.newContent(portal_type='Project Line', id='project_line_%s' % key)
if not project.project_line_1.has_key('project_line_1_1'):
project.project_line_1.newContent(portal_type='Project Line', id='project_line_1_1')
task_list = []
for i in ['Project_3', 'Project_3/project_line_1', 'Project_3/project_line_2', 'Project_3/project_line_1/project_line_1_1']:
task_list.append(task_module.newContent(
portal_type='Task',
title='Task',
specialise=self.business_process,
task_line_quantity=3,
resource='product_module/enterprise_support',
task_line_quantity_unit='time/day',
source='organisation_module/Organisation_1',
source_section='organisation_module/Organisation_1',
destination='organisation_module/Organisation_2',
destination_section='organisation_module/Organisation_2',
source_project='project_module/%s' % i))
task_list[0].edit(task_line_quantity_unit='time/hours')
self.tic()
value_list = project.Project_updateQuantityAndUnit(batch=1)
self.assertEqual(len(value_list), 1)
self.assertEqual(value_list[0], task_list[0].getRelativeUrl())
task_list[0].edit(task_line_quantity_unit='time/day')
self.tic()
value_list = project.Project_updateQuantityAndUnit(batch=1)
self.assertEqual(value_list, None)
self.assertEqual(project.project_line_1.getQuantity(), 6)
self.assertEqual(project.project_line_1.getQuantityUnit(),'time/day')
self.assertEqual(project.project_line_2.getQuantity(), 3)
self.assertEqual(project.project_line_2.getQuantityUnit(),'time/day')
self.assertEqual(project.project_line_1.project_line_1_1.getQuantity(), 3)
self.assertEqual(project.project_line_1.project_line_1_1.getQuantityUnit(),'time/day')
self.assertEqual(project.getQuantity(), 0)
self.assertEqual(project.getQuantityUnit(), None)
# Call on project line
project.project_line_1.edit(quantity=0, quantity_unit='')
self.tic()
value_list = project.project_line_1.Project_updateQuantityAndUnit(batch=1)
self.assertEqual(value_list, None)
self.assertEqual(project.project_line_1.getQuantity(), 6)
self.assertEqual(project.project_line_1.getQuantityUnit(),'time/day')
def testProjectMilstone_updateQuantityAndUnit(self):
# Create Tasks
task_module = self.getPortalObject().task_module
project = self.getPortalObject().project_module.Project_3
if not project.has_key('project_milestone_1'):
project.newContent(portal_type='Project Milestone', id='project_milestone_1')
task_list = []
for _ in range(2):
task_list.append(task_module.newContent(
portal_type='Task',
title='Task',
specialise=self.business_process,
task_line_quantity=3,
resource='product_module/enterprise_support',
task_line_quantity_unit='time/day',
source='organisation_module/Organisation_1',
source_section='organisation_module/Organisation_1',
destination='organisation_module/Organisation_2',
destination_section='organisation_module/Organisation_2'))
project.project_milestone_1.edit(predecessor_value_list=task_list)
task_list[0].edit(task_line_quantity_unit='time/hours')
self.tic()
value_list = project.project_milestone_1.ProjectMilestone_updateQuantityAndUnit(batch=1)
self.assertEqual(len(value_list), 1)
self.assertEqual(value_list[0], task_list[0].getRelativeUrl())
task_list[0].edit(task_line_quantity_unit='time/day')
self.tic()
value_list = project.project_milestone_1.ProjectMilestone_updateQuantityAndUnit(batch=1)
self.assertEqual(value_list, None)
self.assertEqual(project.project_milestone_1.getQuantity(), 6)
self.assertEqual(project.project_milestone_1.getQuantityUnit(),'time/day')
self.tic()
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestProject)) suite.addTest(unittest.makeSuite(TestProject))
......
...@@ -3,6 +3,7 @@ Person | jump_to_task_report ...@@ -3,6 +3,7 @@ Person | jump_to_task_report
Project Cell | view Project Cell | view
Project Line | add_task_related Project Line | add_task_related
Project Line | bug_list Project Line | bug_list
Project Line | calculate_quantity_and_unit_from_task
Project Line | constraint Project Line | constraint
Project Line | contents Project Line | contents
Project Line | create_new_file Project Line | create_new_file
...@@ -18,6 +19,7 @@ Project Line | task_list ...@@ -18,6 +19,7 @@ Project Line | task_list
Project Line | task_report_list Project Line | task_report_list
Project Line | update_date Project Line | update_date
Project Line | view Project Line | view
Project Milestone | calculate_quantity_and_unit_from_constraint
Project Milestone | create_new_file Project Milestone | create_new_file
Project Milestone | document_list Project Milestone | document_list
Project Milestone | jump_to_document Project Milestone | jump_to_document
...@@ -27,6 +29,7 @@ Project Module | view ...@@ -27,6 +29,7 @@ Project Module | view
Project Module | worker_monthly_report Project Module | worker_monthly_report
Project | add_task_related Project | add_task_related
Project | bug_list Project | bug_list
Project | calculate_quantity_and_unit_from_task
Project | content Project | content
Project | create_new_file Project | create_new_file
Project | detailed_report Project | detailed_report
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment