diff --git a/product/ERP5/tests/testInteractionWorkflow.py b/product/ERP5/tests/testInteractionWorkflow.py index d4edd8a8c816a7441d9791f2bf704506975dd891..9e07b9e266ebc64b1fe20c21ba6e23a64cbcbbe5 100644 --- a/product/ERP5/tests/testInteractionWorkflow.py +++ b/product/ERP5/tests/testInteractionWorkflow.py @@ -560,6 +560,75 @@ context.setTitle('Bar') self.tic() self.assertEquals(organisation.getTitle(), 'Bar') + def test_18_no_temp_object(self, quiet=0, run=run_all_test): + if not run: return + if not quiet: + self.logMessage('Skips Temp Objects') + self.createInteractionWorkflow() + self.interaction.setProperties( + 'editObject', + temporary_document_disallowed=False, + method_id='_setGroup.*', + after_script_name=('afterEdit',)) + params = 'sci, **kw' + body = """\ +context = sci['object'] +context.setTitle('Bar') +""" + self.script.ZPythonScript_edit(params, body) + self.createData() + organisation = self.organisation + temp = organisation.asContext() + temp.setTitle('Foo') + # interaction workflows can affect temp objects + temp.setGroupValue(organisation) + self.assertEqual(temp.getTitle(), 'Bar') + # but not if it has been forbidden + temp.setTitle('Foo') + self.interaction.setProperties( + 'editObject', + temporary_document_disallowed=True, + method_id='_setGroup.*', + after_script_name=('afterEdit',)) + temp.setGroupValue(None) + self.assertEqual(temp.getTitle(), 'Foo') + + def test_19_temp_object_doesnt_skip_normal(self, quiet=0, run=run_all_test): + if not run: return + if not quiet: + self.logMessage('Skips Temp Objects, but run in normal objects in the same transaction') + self.createInteractionWorkflow() + self.interaction.setProperties( + 'editObject', + once_per_transaction=True, + temporary_document_disallowed=True, + method_id='_setGroup.*', + after_script_name=('afterEdit',)) + params = 'sci, **kw' + body = """\ +context = sci['object'] +context.setTitle('Bar') +""" + self.script.ZPythonScript_edit(params, body) + self.createData() + organisation = self.organisation + organisation.setTitle('Foo') + temp = organisation.asContext() + # temp and organisation have the same path + self.assertEqual(temp.getPath(), organisation.getPath()) + # which means that a transactional variable key based on path would + # match both the organisation and the temp object, but triggering the + # workflow on the temp object should not change it: + temp.setGroupValue(organisation) + self.assertEquals(temp.getTitle(), 'Foo') + # nor should it change the normal object + self.assertEquals(organisation.getTitle(), 'Foo') + # however, it should allow triggering the normal object later on the same + # transaction + organisation.setGroupValue(organisation) + self.assertEquals(organisation.getTitle(), 'Bar') + # while still not changing the temp object + self.assertEquals(temp.getTitle(), 'Foo') def test_regular_expression(self): # test that we can add an interaction by defining methods using regular diff --git a/product/ERP5Type/Base.py b/product/ERP5Type/Base.py index b4ab7de463b497d2f35f4e92151c834a24284442..9492007e9e6da904ae8246f165813fbf922005a9 100644 --- a/product/ERP5Type/Base.py +++ b/product/ERP5Type/Base.py @@ -181,17 +181,14 @@ class WorkflowMethod(Method): invoke_once_dict = self._invoke_once.get(portal_type, {}) valid_invoke_once_item_list = [] # Only keep those transitions which were never invoked + once_transition_dict = {} for wf_id, transition_list in invoke_once_dict.iteritems(): valid_transition_list = [] for transition_id in transition_list: once_transition_key = ('Products.ERP5Type.Base.WorkflowMethod.__call__', wf_id, transition_id, instance_path) - try: - already_called_transition = transactional_variable[once_transition_key] - except KeyError: - already_called_transition = 0 - transactional_variable[once_transition_key] = 1 - if not already_called_transition: + once_transition_dict[(wf_id, transition_id)] = once_transition_key + if once_transition_key not in transactional_variable: valid_transition_list.append(transition_id) if valid_transition_list: valid_invoke_once_item_list.append((wf_id, valid_transition_list)) @@ -216,6 +213,12 @@ class WorkflowMethod(Method): for transition_id in transition_list: if candidate_workflow.isWorkflowMethodSupported(instance, transition_id): valid_list.append(transition_id) + once_transition_key = once_transition_dict.get((wf_id, transition_id), + None) + if once_transition_key is not None: + # a run-once transiction, prevent it from running in the + # same transaction again + transactional_variable[once_transition_key] = 1 elif candidate_workflow.__class__.__name__ == 'DCWorkflowDefinition': raise UnsupportedWorkflowMethod(instance, wf_id, transition_id) # XXX Keep the log for projects that needs to comment out