Commit 28838e29 authored by Rafael Monnerat's avatar Rafael Monnerat

slapos_crm: Introduce ticket_slap_interface_workflow

   This introduce API for request support and add events on Support Requests
parent 55fc2d9f
...@@ -7,4 +7,8 @@ ...@@ -7,4 +7,8 @@
<type>Regularisation Request</type> <type>Regularisation Request</type>
<workflow>edit_workflow, pricing_interaction_workflow, ticket_interaction_workflow, ticket_workflow</workflow> <workflow>edit_workflow, pricing_interaction_workflow, ticket_interaction_workflow, ticket_workflow</workflow>
</chain> </chain>
<chain>
<type>Support Request</type>
<workflow>ticket_slap_interface_workflow</workflow>
</chain>
</workflow_chain> </workflow_chain>
\ No newline at end of file
from DateTime import DateTime
portal = context.getPortalObject()
aggregate_value = portal.restrictedTraverse(source_relative_url)
if aggregate_value.getPortalType() == "Compute Node":
destination_decision = aggregate_value.getSourceAdministration()
elif aggregate_value.getPortalType() == "Software Instance":
destination_decision = aggregate_value.getSpecialiseValue().getDestinationSection()
elif aggregate_value.getPortalType() == "Instance Tree":
destination_decision = aggregate_value.getDestinationSection()
elif aggregate_value.getPortalType() == "Software Installation":
destination_decision = aggregate_value.getDestinationSection()
else:
destination_decision = None
if portal.ERP5Site_isSupportRequestCreationClosed(destination_decision):
# Stop ticket creation
return
support_request_in_progress = portal.portal_catalog.getResultValue(
portal_type = 'Support Request',
title = title,
simulation_state = ["validated", "submitted", "suspended"],
default_aggregate_uid = aggregate_value.getUid(),
)
if support_request_in_progress is not None:
return support_request_in_progress
support_request_in_progress = context.REQUEST.get("support_request_in_progress", None)
if support_request_in_progress is not None:
support_request = portal.restrictedTraverse(support_request_in_progress, None)
if support_request and support_request.getTitle() == title and \
support_request.getAggregateUid() == aggregate_value.getUid():
return portal.restrictedTraverse(support_request_in_progress)
# Ensure resoure is Monitoring
resource = portal.service_module.\
slapos_crm_monitoring.getRelativeUrl()
support_request = portal.restrictedTraverse(
portal.portal_preferences.getPreferredSupportRequestTemplate())\
.Base_createCloneDocument(batch_mode=1)
support_request.edit(
title = title,
description = description,
start_date = DateTime(),
destination_decision=destination_decision,
aggregate_value = aggregate_value,
resource=resource
)
support_request.validate()
context.REQUEST.set("support_request_in_progress", support_request.getRelativeUrl())
return support_request
...@@ -29,11 +29,12 @@ request_title = 'Allocation scope of %s changed to %s' % (compute_node_reference ...@@ -29,11 +29,12 @@ request_title = 'Allocation scope of %s changed to %s' % (compute_node_reference
request_description = 'Allocation scope has been changed to ' \ request_description = 'Allocation scope has been changed to ' \
'%s for %s' % (target_allocation_scope, compute_node_reference) '%s for %s' % (target_allocation_scope, compute_node_reference)
support_request = context.Base_generateSupportRequestForSlapOS( person.notify(support_request_title=request_title,
request_title, support_request_description=request_description,
request_description, aggregate=context.getRelativeUrl())
compute_node.getRelativeUrl()
) support_request_relative_url = context.REQUEST.get("support_request_relative_url")
support_request = portal.restrictedTraverse(support_request_relative_url)
if support_request is not None: if support_request is not None:
if support_request.getSimulationState() != "validated": if support_request.getSimulationState() != "validated":
...@@ -53,8 +54,8 @@ if support_request is not None: ...@@ -53,8 +54,8 @@ if support_request is not None:
message = notification_message.asText( message = notification_message.asText(
substitution_method_parameter_dict={'mapping_dict': mapping_dict}) substitution_method_parameter_dict={'mapping_dict': mapping_dict})
event = support_request.SupportRequest_trySendNotificationMessage( support_request.notify(message_title=request_title, message=message)
request_title, message, person.getRelativeUrl()) event = support_request.REQUEST.get("ticket_notified_item")
if event is not None: if event is not None:
# event added, suspend ticket # event added, suspend ticket
......
from DateTime import DateTime from DateTime import DateTime
portal = context.getPortalObject() portal = context.getPortalObject()
if portal.ERP5Site_isSupportRequestCreationClosed(): person = context.getSourceAdministrationValue(portal_type="Person")
# Stop ticket creation if not person or \
return context.getMonitorScope() == "disabled" or \
portal.ERP5Site_isSupportRequestCreationClosed():
if context.getMonitorScope() == "disabled":
return return
software_installation_list = portal.portal_catalog( software_installation_list = portal.portal_catalog(
...@@ -50,15 +49,13 @@ for software_installation in software_installation_list: ...@@ -50,15 +49,13 @@ for software_installation in software_installation_list:
(software_installation.getUrlString(), compute_node_title, software_installation.getCreationDate()) (software_installation.getUrlString(), compute_node_title, software_installation.getCreationDate())
if should_notify: if should_notify:
support_request = context.Base_generateSupportRequestForSlapOS( person.notify(support_request_title=ticket_title,
ticket_title, support_request_description=description,
description, aggregate=software_installation.getRelativeUrl())
software_installation.getRelativeUrl()
)
person = context.getSourceAdministrationValue(portal_type="Person") support_request = context.REQUEST.get("support_request_relative_url")
if not person: if support_request is None:
return support_request return
# Send Notification message # Send Notification message
notification_reference = 'slapos-crm-compute_node_software_installation_state.notification' notification_reference = 'slapos-crm-compute_node_software_installation_state.notification'
...@@ -75,10 +72,7 @@ for software_installation in software_installation_list: ...@@ -75,10 +72,7 @@ for software_installation in software_installation_list:
message = notification_message.asText( message = notification_message.asText(
substitution_method_parameter_dict={'mapping_dict':mapping_dict}) substitution_method_parameter_dict={'mapping_dict':mapping_dict})
support_request.SupportRequest_trySendNotificationMessage( support_request.notify(message_title=ticket_title, message=message)
ticket_title,
message, person.getRelativeUrl())
support_request_list.append(support_request) support_request_list.append(support_request)
return support_request_list return support_request_list
from DateTime import DateTime from DateTime import DateTime
portal = context.getPortalObject() portal = context.getPortalObject()
if portal.ERP5Site_isSupportRequestCreationClosed(): person = context.getSourceAdministrationValue(portal_type="Person")
# Stop ticket creation if not person or \
return context.getMonitorScope() == "disabled" or \
portal.ERP5Site_isSupportRequestCreationClosed():
if context.getMonitorScope() == "disabled":
return return
if context.getAllocationScope("open").startswith("close"): if context.getAllocationScope("open").startswith("close"):
...@@ -18,7 +17,6 @@ ticket_title = "[MONITORING] Lost contact with compute_node %s" % reference ...@@ -18,7 +17,6 @@ ticket_title = "[MONITORING] Lost contact with compute_node %s" % reference
description = "" description = ""
last_contact = "No Contact Information" last_contact = "No Contact Information"
d = context.getAccessStatus() d = context.getAccessStatus()
# Ignore if data isn't present. # Ignore if data isn't present.
if d.get("no_data") == 1: if d.get("no_data") == 1:
...@@ -33,20 +31,19 @@ else: ...@@ -33,20 +31,19 @@ else:
# Nothing to notify. # Nothing to notify.
return return
support_request = context.Base_generateSupportRequestForSlapOS( person.notify(support_request_title=ticket_title,
ticket_title, support_request_description=description,
description, aggregate=context.getRelativeUrl())
context.getRelativeUrl()
)
person = context.getSourceAdministrationValue(portal_type="Person") support_request_relative_url = context.REQUEST.get("support_request_relative_url")
if not person: if support_request_relative_url is None:
return support_request return
support_request = portal.restrictedTraverse(support_request_relative_url)
# Send Notification message # Send Notification message
notification_reference = 'slapos-crm-compute_node_check_state.notification'
notification_message = portal.portal_notifications.getDocumentValue( notification_message = portal.portal_notifications.getDocumentValue(
reference=notification_reference) reference='slapos-crm-compute_node_check_state.notification')
if notification_message is None: if notification_message is None:
message = """%s""" % description message = """%s""" % description
...@@ -55,10 +52,8 @@ else: ...@@ -55,10 +52,8 @@ else:
'compute_node_id':reference, 'compute_node_id':reference,
'last_contact':last_contact} 'last_contact':last_contact}
message = notification_message.asText( message = notification_message.asText(
substitution_method_parameter_dict={'mapping_dict':mapping_dict}) substitution_method_parameter_dict={'mapping_dict': mapping_dict})
support_request.SupportRequest_trySendNotificationMessage( support_request.notify(message_title=ticket_title, message=message)
ticket_title,
message, person.getRelativeUrl())
return support_request return support_request
portal = context.getPortalObject() portal = context.getPortalObject()
person = context.getDestinationSectionValue()
if person is None or portal.ERP5Site_isSupportRequestCreationClosed(person.getRelativeUrl()):
# Stop ticket creation
return
ticket_title = "Instance Tree %s is failing." % context.getTitle() ticket_title = "Instance Tree %s is failing." % context.getTitle()
error_message = instance.SoftwareInstance_hasReportedError(include_message=True) error_message = instance.SoftwareInstance_hasReportedError(include_message=True)
...@@ -10,27 +16,23 @@ if error_message: ...@@ -10,27 +16,23 @@ if error_message:
else: else:
error_message = "No message!" error_message = "No message!"
support_request = context.Base_generateSupportRequestForSlapOS( person.notify(support_request_title=ticket_title,
ticket_title, support_request_description=description,
description, aggregate=context.getRelativeUrl())
context.getRelativeUrl())
if support_request is None: support_request_relative_url = context.REQUEST.get("support_request_relative_url")
if support_request_relative_url is None:
return return
person = context.getDestinationSectionValue(portal_type="Person") support_request = portal.restrictedTraverse(support_request_relative_url)
if not person:
return
if support_request.getSimulationState() not in ["validated", "suspended"]: if support_request.getSimulationState() not in ["validated", "suspended"]:
support_request.validate() support_request.validate()
# Send Notification message # Send Notification message
message = description message = description
notification_reference = notification_message_reference
notification_message = portal.portal_notifications.getDocumentValue( notification_message = portal.portal_notifications.getDocumentValue(
reference=notification_reference) reference=notification_message_reference)
if notification_message is not None: if notification_message is not None:
mapping_dict = {'instance_tree_title':context.getTitle(), mapping_dict = {'instance_tree_title':context.getTitle(),
'instance': instance.getTitle(), 'instance': instance.getTitle(),
...@@ -39,5 +41,5 @@ if notification_message is not None: ...@@ -39,5 +41,5 @@ if notification_message is not None:
message = notification_message.asText( message = notification_message.asText(
substitution_method_parameter_dict={'mapping_dict':mapping_dict}) substitution_method_parameter_dict={'mapping_dict':mapping_dict})
return support_request.SupportRequest_trySendNotificationMessage( support_request.notify(message_title=ticket_title, message=message)
ticket_title, message, person.getRelativeUrl()) return context.REQUEST.get("ticket_notified_item")
""" Close Support Request which are related to a Destroy Requested Instance. """ """ Close Support Request which are related to a Destroy Requested Instance. """
portal = context.getPortalObject()
if context.getSimulationState() == "invalidated": if context.getSimulationState() == "invalidated":
return return
document = context.getAggregateValue() document = context.getAggregateValue()
if document is not None and document.getSlapState() == "destroy_requested": if document is not None and document.getSlapState() == "destroy_requested":
person = context.getDestinationDecision(portal_type="Person") person = context.getDestinationDecision(portal_type="Person")
if not person: if not person:
return return
if context.getSimulationState() != "invalidated":
context.invalidate()
# Send Notification message # Send Notification message
message = """ Closing this ticket as the Instance Tree was destroyed by the user. message = """ Closing this ticket as the Instance Tree was destroyed by the user.
""" """
notification_reference = "slapos-crm-support-request-close-destroyed-notification"
portal = context.getPortalObject()
notification_message = portal.portal_notifications.getDocumentValue( notification_message = portal.portal_notifications.getDocumentValue(
reference=notification_reference) reference="slapos-crm-support-request-close-destroyed-notification")
if notification_message is not None: if notification_message is not None:
mapping_dict = {'instance_tree_title':document.getTitle()} mapping_dict = {'instance_tree_title': document.getTitle()}
message = notification_message.asText( message = notification_message.asText(
substitution_method_parameter_dict={'mapping_dict':mapping_dict}) substitution_method_parameter_dict={'mapping_dict':mapping_dict})
return context.SupportRequest_trySendNotificationMessage( context.notify(message_title="Instance Tree was destroyed was destroyed by the user",
"Instance Tree was destroyed was destroyed by the user", message, person) message=message)
context.invalidate()
return context.REQUEST.get("ticket_notified_item")
...@@ -2,7 +2,6 @@ if context.getSimulationState() == "invalidated": ...@@ -2,7 +2,6 @@ if context.getSimulationState() == "invalidated":
return return
document = context.getAggregateValue(portal_type="Instance Tree") document = context.getAggregateValue(portal_type="Instance Tree")
if document is None: if document is None:
return return
......
...@@ -27,8 +27,6 @@ from erp5.component.test.SlapOSTestCaseMixin import \ ...@@ -27,8 +27,6 @@ from erp5.component.test.SlapOSTestCaseMixin import \
from DateTime import DateTime from DateTime import DateTime
from App.Common import rfc1123_date from App.Common import rfc1123_date
from Products.ERP5Type.Cache import DEFAULT_CACHE_SCOPE from Products.ERP5Type.Cache import DEFAULT_CACHE_SCOPE
from Products.ERP5Type.tests.utils import createZODBPythonScript
import json import json
import feedparser import feedparser
...@@ -655,13 +653,6 @@ class TestSlapOSComputeNode_notifyWrongAllocationScope(TestCRMSkinsMixin): ...@@ -655,13 +653,6 @@ class TestSlapOSComputeNode_notifyWrongAllocationScope(TestCRMSkinsMixin):
'assert reference == "slapos-crm-compute_node_allocation_scope.notification"\n' \ 'assert reference == "slapos-crm-compute_node_allocation_scope.notification"\n' \
'return context.restrictedTraverse(' \ 'return context.restrictedTraverse(' \
'context.REQUEST["test_ComputeNodeNotAllowedAllocationScope_OpenPublic"])') 'context.REQUEST["test_ComputeNodeNotAllowedAllocationScope_OpenPublic"])')
@simulate('SupportRequest_trySendNotificationMessage',
'message_title, message, destination_relative_url',
'context.portal_workflow.doActionFor(' \
'context, action="edit_action", ' \
'comment="Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s" % (message_title, message, destination_relative_url))\n' \
'return 1')
def test_ComputeNodeNotAllowedAllocationScope_OpenPublic(self): def test_ComputeNodeNotAllowedAllocationScope_OpenPublic(self):
compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0] compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0]
person = compute_node.getSourceAdministrationValue() person = compute_node.getSourceAdministrationValue()
...@@ -677,13 +668,14 @@ class TestSlapOSComputeNode_notifyWrongAllocationScope(TestCRMSkinsMixin): ...@@ -677,13 +668,14 @@ class TestSlapOSComputeNode_notifyWrongAllocationScope(TestCRMSkinsMixin):
self.assertNotEqual(None, ticket) self.assertNotEqual(None, ticket)
self.assertEqual(ticket.getSimulationState(), 'suspended') self.assertEqual(ticket.getSimulationState(), 'suspended')
self.assertEqual('Visited by SupportRequest_trySendNotificationMessage ' \ event_list = ticket.getFollowUpRelatedValueList()
'%s %s %s' % \ self.assertEqual(len(event_list), 1)
('Allocation scope of %s changed to %s' % (compute_node.getReference(), event = event_list[0]
'open/personal'),
'Test NM content\n%s\n' % compute_node.getReference(), person.getRelativeUrl()),
ticket.workflow_history['edit_workflow'][-1]['comment'])
self.assertEqual(event.getTitle(),
'Allocation scope of %s changed to %s' % (compute_node.getReference(), 'open/personal'))
self.assertIn(compute_node.getReference(), event.getTextContent())
self.assertEqual(event.getDestination(), person.getRelativeUrl())
@simulate('ERP5Site_isSupportRequestCreationClosed', '*args, **kwargs','return 0') @simulate('ERP5Site_isSupportRequestCreationClosed', '*args, **kwargs','return 0')
@simulate('NotificationTool_getDocumentValue', @simulate('NotificationTool_getDocumentValue',
...@@ -691,13 +683,6 @@ class TestSlapOSComputeNode_notifyWrongAllocationScope(TestCRMSkinsMixin): ...@@ -691,13 +683,6 @@ class TestSlapOSComputeNode_notifyWrongAllocationScope(TestCRMSkinsMixin):
'assert reference == "slapos-crm-compute_node_allocation_scope.notification"\n' \ 'assert reference == "slapos-crm-compute_node_allocation_scope.notification"\n' \
'return context.restrictedTraverse(' \ 'return context.restrictedTraverse(' \
'context.REQUEST["test_ComputeNodeNotAllowedAllocationScope_OpenFriend"])') 'context.REQUEST["test_ComputeNodeNotAllowedAllocationScope_OpenFriend"])')
@simulate('SupportRequest_trySendNotificationMessage',
'message_title, message, destination_relative_url',
'context.portal_workflow.doActionFor(' \
'context, action="edit_action", ' \
'comment="Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s" % (message_title, message, destination_relative_url))\n' \
'return 1')
def test_ComputeNodeNotAllowedAllocationScope_OpenFriend(self): def test_ComputeNodeNotAllowedAllocationScope_OpenFriend(self):
compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0] compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0]
person = compute_node.getSourceAdministrationValue() person = compute_node.getSourceAdministrationValue()
...@@ -712,12 +697,15 @@ class TestSlapOSComputeNode_notifyWrongAllocationScope(TestCRMSkinsMixin): ...@@ -712,12 +697,15 @@ class TestSlapOSComputeNode_notifyWrongAllocationScope(TestCRMSkinsMixin):
self.tic() self.tic()
self.assertEqual(compute_node.getAllocationScope(), 'open/personal') self.assertEqual(compute_node.getAllocationScope(), 'open/personal')
self.assertEqual(ticket.getSimulationState(), 'suspended') self.assertEqual(ticket.getSimulationState(), 'suspended')
self.assertEqual('Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s' % \ event_list = ticket.getFollowUpRelatedValueList()
('Allocation scope of %s changed to %s' % (compute_node.getReference(), self.assertEqual(len(event_list), 1)
'open/personal'), event = event_list[0]
'Test NM content\n%s\n' % compute_node.getReference(), person.getRelativeUrl()),
ticket.workflow_history['edit_workflow'][-1]['comment']) self.assertEqual(event.getTitle(),
'Allocation scope of %s changed to %s' % (compute_node.getReference(), 'open/personal'))
self.assertIn(compute_node.getReference(), event.getTextContent())
self.assertEqual(event.getDestination(), person.getRelativeUrl())
@simulate('ERP5Site_isSupportRequestCreationClosed', '*args, **kwargs','return 0') @simulate('ERP5Site_isSupportRequestCreationClosed', '*args, **kwargs','return 0')
@simulate('ComputeNode_hasContactedRecently', '*args, **kwargs','return False') @simulate('ComputeNode_hasContactedRecently', '*args, **kwargs','return False')
...@@ -726,13 +714,6 @@ class TestSlapOSComputeNode_notifyWrongAllocationScope(TestCRMSkinsMixin): ...@@ -726,13 +714,6 @@ class TestSlapOSComputeNode_notifyWrongAllocationScope(TestCRMSkinsMixin):
'assert reference == "slapos-crm-compute-node-allocation-scope-closed.notification"\n' \ 'assert reference == "slapos-crm-compute-node-allocation-scope-closed.notification"\n' \
'return context.restrictedTraverse(' \ 'return context.restrictedTraverse(' \
'context.REQUEST["test_ComputeNodeToCloseAllocationScope_OpenPersonal"])') 'context.REQUEST["test_ComputeNodeToCloseAllocationScope_OpenPersonal"])')
@simulate('SupportRequest_trySendNotificationMessage',
'message_title, message, destination_relative_url',
'context.portal_workflow.doActionFor(' \
'context, action="edit_action", ' \
'comment="Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s" % (message_title, message, destination_relative_url))\n' \
'return 1')
def test_ComputeNodeToCloseAllocationScope_OpenPersonal(self): def test_ComputeNodeToCloseAllocationScope_OpenPersonal(self):
compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0] compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0]
person = compute_node.getSourceAdministrationValue() person = compute_node.getSourceAdministrationValue()
...@@ -747,12 +728,16 @@ class TestSlapOSComputeNode_notifyWrongAllocationScope(TestCRMSkinsMixin): ...@@ -747,12 +728,16 @@ class TestSlapOSComputeNode_notifyWrongAllocationScope(TestCRMSkinsMixin):
self.assertEqual('suspended', support_request.getSimulationState()) self.assertEqual('suspended', support_request.getSimulationState())
self.assertEqual(compute_node.getAllocationScope(), target_allocation_scope) self.assertEqual(compute_node.getAllocationScope(), target_allocation_scope)
self.assertEqual('Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s' % \ event_list = support_request.getFollowUpRelatedValueList()
('Allocation scope of %s changed to %s' % (compute_node.getReference(), self.assertEqual(len(event_list), 1)
target_allocation_scope), event = event_list[0]
'Test NM content\n%s\n' % compute_node.getReference(), person.getRelativeUrl()),
support_request.workflow_history['edit_workflow'][-1]['comment']) self.assertEqual(event.getTitle(),
'Allocation scope of %s changed to %s' % \
(compute_node.getReference(), target_allocation_scope))
self.assertIn(compute_node.getReference(), event.getTextContent())
self.assertEqual(event.getDestination(), person.getRelativeUrl())
def test_ComputeNodeNormalAllocationScope_OpenPersonal(self): def test_ComputeNodeNormalAllocationScope_OpenPersonal(self):
compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0] compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0]
...@@ -988,189 +973,6 @@ class TestSlapOSisSupportRequestCreationClosed(TestCRMSkinsMixin): ...@@ -988,189 +973,6 @@ class TestSlapOSisSupportRequestCreationClosed(TestCRMSkinsMixin):
self.assertFalse(self.portal.ERP5Site_isSupportRequestCreationClosed()) self.assertFalse(self.portal.ERP5Site_isSupportRequestCreationClosed())
class TestSlapOSGenerateSupportRequestForSlapOS(TestCRMSkinsMixin):
def afterSetUp(self):
TestCRMSkinsMixin.afterSetUp(self)
self.tic()
self._cancelTestSupportRequestList()
def test_compute_node_Base_generateSupportRequestForSlapOS(self):
self._makeComputeNode()
title = "Test Support Request %s" % self.compute_node.getReference()
support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl()
)
self.tic()
self.assertNotEqual(support_request, None)
self.assertEqual(support_request.getSimulationState(), "validated")
self.assertEqual(support_request.getRelativeUrl(),
self.portal.REQUEST.get("support_request_in_progress", None))
# The support request is added to compute_node owner.
self.assertEqual(support_request.getDestinationDecision(),
self.compute_node.getSourceAdministration())
self.assertEqual(support_request.getTitle(), title)
self.assertEqual(support_request.getDescription(), title)
self.assertEqual(support_request.getAggregateValue(),
self.compute_node)
def test_software_instance_Base_generateSupportRequestForSlapOS(self):
instance_tree = self._makeInstanceTree()
self._makeSoftwareInstance(instance_tree,
self.generateNewSoftwareReleaseUrl())
instance = instance_tree.getSuccessorValue()
title = "Test Support Request %s" % instance.getReference()
support_request = instance.Base_generateSupportRequestForSlapOS(
title, title, instance.getRelativeUrl()
)
self.tic()
self.assertNotEqual(support_request, None)
self.assertEqual(support_request.getSimulationState(), "validated")
self.assertEqual(support_request.getRelativeUrl(),
self.portal.REQUEST.get("support_request_in_progress", None))
# The support request is added to compute_node owner.
self.assertEqual(support_request.getDestinationDecision(),
instance_tree.getDestinationSection())
self.assertEqual(support_request.getTitle(), title)
self.assertEqual(support_request.getDescription(), title)
self.assertEqual(support_request.getAggregateValue(),
instance)
def test_instance_tree_Base_generateSupportRequestForSlapOS(self):
instance_tree = self._makeInstanceTree()
title = "Test Support Request %s" % instance_tree.getReference()
support_request = instance_tree.Base_generateSupportRequestForSlapOS(
title, title, instance_tree.getRelativeUrl()
)
self.tic()
self.assertNotEqual(support_request, None)
self.assertEqual(support_request.getSimulationState(), "validated")
self.assertEqual(support_request.getRelativeUrl(),
self.portal.REQUEST.get("support_request_in_progress", None))
# The support request is added to compute_node owner.
self.assertEqual(support_request.getDestinationDecision(),
instance_tree.getDestinationSection())
self.assertEqual(support_request.getTitle(), title)
self.assertEqual(support_request.getDescription(), title)
self.assertEqual(support_request.getAggregateValue(),
instance_tree)
def test_software_installation_Base_generateSupportRequestForSlapOS(self):
software_installation = self._makeSoftwareInstallation()
title = "Test Support Request %s" % software_installation.generateNewId()
support_request = software_installation.Base_generateSupportRequestForSlapOS(
title, title, software_installation.getRelativeUrl()
)
self.tic()
self.assertNotEqual(support_request, None)
self.assertEqual(support_request.getSimulationState(), "validated")
self.assertEqual(support_request.getRelativeUrl(),
self.portal.REQUEST.get("support_request_in_progress", None))
# The support request is added to compute_node owner.
self.assertEqual(support_request.getDestinationDecision(),
software_installation.getDestinationSection())
self.assertEqual(support_request.getTitle(), title)
self.assertEqual(support_request.getDescription(), title)
self.assertEqual(support_request.getAggregateValue(),
software_installation)
def test_Base_generateSupportRequestForSlapOS_do_not_recreate_if_open(self):
self._makeComputeNode(owner=self.makePerson(user=0))
title = "Test Support Request %s" % self.compute_node.getReference()
support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl()
)
self.tic()
self.portal.REQUEST.set("support_request_in_progress", None)
same_support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl()
)
self.assertEqual(support_request, same_support_request)
def test_Base_generateSupportRequestForSlapOS_do_not_recreate_if_suspended(self):
self._makeComputeNode(owner=self.makePerson(user=0))
title = "Test Support Request %s" % self.compute_node.getReference()
support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl()
)
support_request.suspend()
self.tic()
self.portal.REQUEST.set("support_request_in_progress", None)
same_support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl()
)
self.assertEqual(support_request, same_support_request)
def test_Base_generateSupportRequestForSlapOS_recreate_if_closed(self):
self._makeComputeNode(owner=self.makePerson(user=0))
title = "Test Support Request %s" % self.compute_node.getReference()
support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl())
self.tic()
support_request.invalidate()
self.tic()
self.portal.REQUEST.set("support_request_in_progress", None)
support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl()
)
self.tic()
self.assertNotEqual(support_request, None)
def test_Base_generateSupportRequestForSlapOS_recreate(self):
self._makeComputeNode(owner=self.makePerson(user=0))
title = "Test Support Request %s" % self.compute_node.getRelativeUrl()
support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl())
same_support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl()
)
self.assertEqual(support_request, same_support_request)
def test_Base_generateSupportRequestForSlapOS_inprogress(self):
self._makeComputeNode(owner=self.makePerson(user=0))
title = "Test Support Request %s" % self.compute_node.getRelativeUrl()
support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl())
in_progress = support_request.getRelativeUrl()
self.portal.REQUEST.set("support_request_in_progress", in_progress)
title = "Test Support Request %s" % self.compute_node.getRelativeUrl()
support_request = self.compute_node.Base_generateSupportRequestForSlapOS(
title, title, self.compute_node.getRelativeUrl())
self.assertEqual(support_request.getRelativeUrl(), in_progress)
class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin): class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin):
def beforeTearDown(self): def beforeTearDown(self):
...@@ -1181,11 +983,6 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin): ...@@ -1181,11 +983,6 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin):
TestCRMSkinsMixin.afterSetUp(self) TestCRMSkinsMixin.afterSetUp(self)
self._cancelTestSupportRequestList("% TESTCOMPT-%") self._cancelTestSupportRequestList("% TESTCOMPT-%")
def _makeSupportRequest(self):
return self.portal.restrictedTraverse(
self.portal.portal_preferences.getPreferredSupportRequestTemplate()).\
Base_createCloneDocument(batch_mode=1)
def _makeNotificationMessage(self, reference): def _makeNotificationMessage(self, reference):
notification_message = self.portal.notification_message_module.newContent( notification_message = self.portal.notification_message_module.newContent(
portal_type="Notification Message", portal_type="Notification Message",
...@@ -1205,56 +1002,36 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin): ...@@ -1205,56 +1002,36 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin):
) )
return support_request return support_request
def _simulateBase_generateSupportRequestForSlapOS(self):
script_name = 'Base_generateSupportRequestForSlapOS'
if script_name in self.portal.portal_skins.custom.objectIds():
raise ValueError('Precondition failed: %s exists in custom' % script_name)
createZODBPythonScript(self.portal.portal_skins.custom,
script_name,
'*args, **kw',
'# Script body\n'
"""return context.getPortalObject().REQUEST['_simulateBase_generateSupportRequestForSlapOS']""")
transaction.commit()
@simulate('ERP5Site_isSupportRequestCreationClosed', '*args, **kwargs','return 0') @simulate('ERP5Site_isSupportRequestCreationClosed', '*args, **kwargs','return 0')
def test_ComputeNode_checkState_call_support_request(self): def test_ComputeNode_checkState_call_support_request(self):
compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0] compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0]
try: try:
self.pinDateTime(DateTime()-1.1) d = DateTime() - 1.1
self.pinDateTime(d)
compute_node.setAccessStatus("#access ") compute_node.setAccessStatus("#access ")
finally: finally:
self.unpinDateTime() self.unpinDateTime()
self._simulateBase_generateSupportRequestForSlapOS()
support_request = self._makeSupportRequest()
self.portal.REQUEST.set('_simulateBase_generateSupportRequestForSlapOS',
support_request)
try:
compute_node_support_request = compute_node.ComputeNode_checkState() compute_node_support_request = compute_node.ComputeNode_checkState()
finally: self.assertNotEqual(compute_node_support_request, None)
self._dropScript("Base_generateSupportRequestForSlapOS") self.assertIn("[MONITORING] Lost contact with compute_node",
compute_node_support_request.getTitle())
self.assertEqual(support_request, self.assertIn("has not contacted the server for more than 30 minutes",
compute_node_support_request) compute_node_support_request.getDescription())
self.assertIn(d.strftime("%Y/%m/%d %H:%M:%S"),
compute_node_support_request.getDescription())
@simulate('ERP5Site_isSupportRequestCreationClosed', '*args, **kwargs','return 0') @simulate('ERP5Site_isSupportRequestCreationClosed', '*args, **kwargs','return 0')
def test_ComputeNode_checkState_empty_cache(self): def test_ComputeNode_checkState_empty_cache(self):
compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0] compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0]
self._simulateBase_generateSupportRequestForSlapOS()
support_request = self._makeSupportRequest()
self.portal.REQUEST.set('_simulateBase_generateSupportRequestForSlapOS',
support_request)
try:
compute_node_support_request = compute_node.ComputeNode_checkState() compute_node_support_request = compute_node.ComputeNode_checkState()
finally:
self._dropScript("Base_generateSupportRequestForSlapOS")
self.assertEqual(support_request, compute_node_support_request = compute_node.ComputeNode_checkState()
compute_node_support_request) self.assertNotEqual(compute_node_support_request, None)
self.assertIn("[MONITORING] Lost contact with compute_node",
compute_node_support_request.getTitle())
self.assertIn("has not contacted the server (No Contact Information)",
compute_node_support_request.getDescription())
@simulate('ERP5Site_isSupportRequestCreationClosed', '*args, **kwargs','return 0') @simulate('ERP5Site_isSupportRequestCreationClosed', '*args, **kwargs','return 0')
@simulate('NotificationTool_getDocumentValue', @simulate('NotificationTool_getDocumentValue',
...@@ -1262,12 +1039,6 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin): ...@@ -1262,12 +1039,6 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin):
'assert reference == "slapos-crm-compute_node_check_state.notification"\n' \ 'assert reference == "slapos-crm-compute_node_check_state.notification"\n' \
'return context.restrictedTraverse(' \ 'return context.restrictedTraverse(' \
'context.REQUEST["test_ComputeNode_checkState_notify"])') 'context.REQUEST["test_ComputeNode_checkState_notify"])')
@simulate('SupportRequest_trySendNotificationMessage',
'message_title, message, destination_relative_url',
'context.portal_workflow.doActionFor(' \
'context, action="edit_action", ' \
'comment="Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s" % (message_title, message, destination_relative_url))')
def test_ComputeNode_checkState_notify(self): def test_ComputeNode_checkState_notify(self):
compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0] compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0]
person = compute_node.getSourceAdministrationValue() person = compute_node.getSourceAdministrationValue()
...@@ -1286,14 +1057,15 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin): ...@@ -1286,14 +1057,15 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin):
ticket_title = "[MONITORING] Lost contact with compute_node %s" % compute_node.getReference() ticket_title = "[MONITORING] Lost contact with compute_node %s" % compute_node.getReference()
ticket = self._getGeneratedSupportRequest(compute_node.getUid(), ticket_title) ticket = self._getGeneratedSupportRequest(compute_node.getUid(), ticket_title)
self.assertNotEqual(ticket, None) self.assertNotEqual(ticket, None)
self.assertEqual('Visited by SupportRequest_trySendNotificationMessage ' \ event_list = ticket.getFollowUpRelatedValueList()
'%s %s %s' % ( \ self.assertEqual(len(event_list), 1)
ticket_title, event = event_list[0]
'Test NM content\n%s\n' % compute_node.getReference(),
person.getRelativeUrl()),
ticket.workflow_history['edit_workflow'][-1]['comment'])
self.assertEqual(event.getTitle(), ticket.getTitle())
self.assertIn(compute_node.getReference(), event.getTextContent())
self.assertEqual(event.getDestination(), person.getRelativeUrl())
@simulate('ERP5Site_isSupportRequestCreationClosed', '*args, **kwargs','return 0') @simulate('ERP5Site_isSupportRequestCreationClosed', '*args, **kwargs','return 0')
@simulate('NotificationTool_getDocumentValue', @simulate('NotificationTool_getDocumentValue',
...@@ -1301,12 +1073,6 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin): ...@@ -1301,12 +1073,6 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin):
'assert reference == "slapos-crm-compute_node_check_state.notification"\n' \ 'assert reference == "slapos-crm-compute_node_check_state.notification"\n' \
'return context.restrictedTraverse(' \ 'return context.restrictedTraverse(' \
'context.REQUEST["test_ComputeNode_checkState_empty_cache_notify"])') 'context.REQUEST["test_ComputeNode_checkState_empty_cache_notify"])')
@simulate('SupportRequest_trySendNotificationMessage',
'message_title, message, destination_relative_url',
'context.portal_workflow.doActionFor(' \
'context, action="edit_action", ' \
'comment="Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s" % (message_title, message, destination_relative_url))')
def test_ComputeNode_checkState_empty_cache_notify(self): def test_ComputeNode_checkState_empty_cache_notify(self):
compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0] compute_node = self._makeComputeNode(owner=self.makePerson(user=0))[0]
person = compute_node.getSourceAdministrationValue() person = compute_node.getSourceAdministrationValue()
...@@ -1320,13 +1086,13 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin): ...@@ -1320,13 +1086,13 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin):
ticket_title = "[MONITORING] Lost contact with compute_node %s" % compute_node.getReference() ticket_title = "[MONITORING] Lost contact with compute_node %s" % compute_node.getReference()
ticket = self._getGeneratedSupportRequest(compute_node.getUid(), ticket_title) ticket = self._getGeneratedSupportRequest(compute_node.getUid(), ticket_title)
self.assertNotEqual(ticket, None) self.assertNotEqual(ticket, None)
self.assertEqual('Visited by SupportRequest_trySendNotificationMessage ' \ event_list = ticket.getFollowUpRelatedValueList()
'%s %s %s' % ( \ self.assertEqual(len(event_list), 1)
ticket_title, event = event_list[0]
'Test NM content\n%s\n' % compute_node.getReference(),
person.getRelativeUrl()),
ticket.workflow_history['edit_workflow'][-1]['comment'])
self.assertEqual(event.getTitle(), ticket.getTitle())
self.assertIn(compute_node.getReference(), event.getTextContent())
self.assertEqual(event.getDestination(), person.getRelativeUrl())
class TestSlapOSInstanceTree_createSupportRequestEvent(SlapOSTestCaseMixin): class TestSlapOSInstanceTree_createSupportRequestEvent(SlapOSTestCaseMixin):
...@@ -1341,8 +1107,7 @@ class TestSlapOSInstanceTree_createSupportRequestEvent(SlapOSTestCaseMixin): ...@@ -1341,8 +1107,7 @@ class TestSlapOSInstanceTree_createSupportRequestEvent(SlapOSTestCaseMixin):
return notification_message.getRelativeUrl() return notification_message.getRelativeUrl()
def _makeInstanceTree(self): def _makeInstanceTree(self):
person = self.portal.person_module.template_member\ person = self.makePerson(user=1)
.Base_createCloneDocument(batch_mode=1)
instance_tree = self.portal\ instance_tree = self.portal\
.instance_tree_module.template_instance_tree\ .instance_tree_module.template_instance_tree\
.Base_createCloneDocument(batch_mode=1) .Base_createCloneDocument(batch_mode=1)
...@@ -1371,12 +1136,6 @@ class TestSlapOSInstanceTree_createSupportRequestEvent(SlapOSTestCaseMixin): ...@@ -1371,12 +1136,6 @@ class TestSlapOSInstanceTree_createSupportRequestEvent(SlapOSTestCaseMixin):
'assert reference == "test-slapos-crm-check.notification"\n' \ 'assert reference == "test-slapos-crm-check.notification"\n' \
'return context.restrictedTraverse(' \ 'return context.restrictedTraverse(' \
'context.REQUEST["testInstanceTree_createSupportRequestEvent"])') 'context.REQUEST["testInstanceTree_createSupportRequestEvent"])')
@simulate('SupportRequest_trySendNotificationMessage',
'message_title, message, destination_relative_url',
'context.portal_workflow.doActionFor(' \
'context, action="edit_action", ' \
'comment="Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s" % (message_title, message, destination_relative_url))')
def testInstanceTree_createSupportRequestEvent(self): def testInstanceTree_createSupportRequestEvent(self):
instance_tree = self._makeInstanceTree() instance_tree = self._makeInstanceTree()
person = instance_tree.getDestinationSectionValue() person = instance_tree.getDestinationSectionValue()
...@@ -1392,12 +1151,14 @@ class TestSlapOSInstanceTree_createSupportRequestEvent(SlapOSTestCaseMixin): ...@@ -1392,12 +1151,14 @@ class TestSlapOSInstanceTree_createSupportRequestEvent(SlapOSTestCaseMixin):
instance_tree.getUid()) instance_tree.getUid())
self.assertNotEqual(ticket, None) self.assertNotEqual(ticket, None)
self.assertEqual(ticket.getSimulationState(), "validated") self.assertEqual(ticket.getSimulationState(), "validated")
self.assertEqual('Visited by SupportRequest_trySendNotificationMessage ' \ self.assertNotEqual(ticket, None)
'%s %s %s' % ( \ event_list = ticket.getFollowUpRelatedValueList()
ticket_title, self.assertEqual(len(event_list), 1)
'Test NM content\n%s\n' % instance_tree.getReference(), event = event_list[0]
person.getRelativeUrl()),
ticket.workflow_history['edit_workflow'][-1]['comment']) self.assertEqual(event.getTitle(), ticket_title)
self.assertIn(instance_tree.getReference(), event.getTextContent())
self.assertEqual(event.getDestination(), person.getRelativeUrl())
ticket.suspend() ticket.suspend()
self.tic() self.tic()
...@@ -1734,95 +1495,6 @@ class TestSlapOSHasError(SlapOSTestCaseMixin): ...@@ -1734,95 +1495,6 @@ class TestSlapOSHasError(SlapOSTestCaseMixin):
None, None,
instance_tree.InstanceTree_checkSoftwareInstanceState()) instance_tree.InstanceTree_checkSoftwareInstanceState())
class TestSupportRequestTrySendNotificationMessage(SlapOSTestCaseMixin):
def test_SupportRequest_trySendNotificationMessage(self):
self._makeComputeNode(owner=self.makePerson(user=0))
person = self.compute_node.getSourceAdministrationValue()
title = "Test Support Request %s" % self.compute_node.getReference()
text_content='Test NM content<br/>%s<br/>' % self.compute_node.getReference()
support_request = self.portal.support_request_module.newContent(\
title=title, description=title,
destination_decision=self.compute_node.getSourceAdministration(),
aggregate_value=self.compute_node.getRelativeUrl())
support_request.validate()
self.tic()
first_event = support_request.SupportRequest_trySendNotificationMessage(
message_title=title, message=text_content,
destination_relative_url=person.getRelativeUrl()
)
self.assertNotEqual(first_event, None)
self.tic()
self.assertEqual(
support_request.getFollowUpRelatedList(),
[first_event.getRelativeUrl()])
self.assertEqual(title, first_event.getTitle())
self.assertEqual(text_content, first_event.getTextContent())
self.assertNotEqual(None, first_event.getStartDate())
self.assertEqual("service_module/slapos_crm_information",
first_event.getResource())
self.assertEqual(first_event.getDestination(), person.getRelativeUrl())
self.assertEqual(first_event.getFollowUp(), support_request.getRelativeUrl())
event = support_request.SupportRequest_trySendNotificationMessage(
message_title=title, message=text_content,
destination_relative_url=person.getRelativeUrl()
)
self.assertEqual(event, first_event)
self.assertEqual(title, event.getTitle())
self.assertEqual(text_content, event.getTextContent())
self.assertNotEqual(None, event.getStartDate())
self.assertEqual("service_module/slapos_crm_information",
event.getResource())
self.assertEqual(event.getDestination(), person.getRelativeUrl())
title += "__zz"
event = support_request.SupportRequest_trySendNotificationMessage(
message_title=title, message=text_content,
destination_relative_url=person.getRelativeUrl(),
)
self.assertEqual(event.getTitle(), title)
self.assertEqual(text_content, event.getTextContent())
self.assertNotEqual(None, event.getStartDate())
self.assertEqual("service_module/slapos_crm_information",
event.getResource())
self.assertEqual(event.getDestination(), person.getRelativeUrl())
another_support_request = self.portal.support_request_module.newContent(\
title=title, description=title,
destination_decision=self.compute_node.getSourceAdministration(),
aggregate_value=self.compute_node.getRelativeUrl())
another_support_request.validate()
self.tic()
another_first_event = \
another_support_request.SupportRequest_trySendNotificationMessage(
message_title=title, message=text_content,
destination_relative_url=person.getRelativeUrl())
self.assertNotEqual(another_first_event, None)
self.tic()
self.assertEqual(
another_support_request.getFollowUpRelatedList(),
[another_first_event.getRelativeUrl()])
self.assertEqual(title, another_first_event.getTitle())
self.assertEqual(text_content, another_first_event.getTextContent())
self.assertNotEqual(None, another_first_event.getStartDate())
self.assertEqual("service_module/slapos_crm_information",
another_first_event.getResource())
self.assertEqual(another_first_event.getDestination(), person.getRelativeUrl())
self.assertEqual(another_first_event.getFollowUp(),
another_support_request.getRelativeUrl())
class TestSupportRequestUpdateMonitoringState(SlapOSTestCaseMixin): class TestSupportRequestUpdateMonitoringState(SlapOSTestCaseMixin):
def _makeInstanceTree(self): def _makeInstanceTree(self):
...@@ -1873,10 +1545,6 @@ class TestSupportRequestUpdateMonitoringState(SlapOSTestCaseMixin): ...@@ -1873,10 +1545,6 @@ class TestSupportRequestUpdateMonitoringState(SlapOSTestCaseMixin):
support_request.SupportRequest_updateMonitoringState()) support_request.SupportRequest_updateMonitoringState())
@simulate('ERP5Site_isSupportRequestCreationClosed', '','return 0') @simulate('ERP5Site_isSupportRequestCreationClosed', '','return 0')
@simulate('SupportRequest_trySendNotificationMessage',
"message_title, message, source_relative_url",
"""assert "destroyed" in message
return "Visited by SupportRequest_trySendNotificationMessage %s %s" % (message_title, source_relative_url)""")
def testSupportRequest_updateMonitoringDestroyRequestedState(self): def testSupportRequest_updateMonitoringDestroyRequestedState(self):
support_request = self._makeSupportRequest() support_request = self._makeSupportRequest()
self.assertEqual(None, self.assertEqual(None,
...@@ -1887,20 +1555,29 @@ return "Visited by SupportRequest_trySendNotificationMessage %s %s" % (message_t ...@@ -1887,20 +1555,29 @@ return "Visited by SupportRequest_trySendNotificationMessage %s %s" % (message_t
support_request.setAggregateValue( support_request.setAggregateValue(
self._makeComputeNode(owner=self.makePerson(user=0))[0]) self._makeComputeNode(owner=self.makePerson(user=0))[0])
support_request.setDestinationDecisionValue(self.makePerson(user=0))
self.assertEqual(None, self.assertEqual(None,
support_request.SupportRequest_updateMonitoringDestroyRequestedState()) support_request.SupportRequest_updateMonitoringDestroyRequestedState())
hs = self._makeInstanceTree() hs = self._makeInstanceTree()
support_request.setAggregateValue(hs) support_request.setAggregateValue(hs)
self.tic()
hs.getSlapState = getFakeSlapState hs.getSlapState = getFakeSlapState
self.commit() self.commit()
support_request.setDestinationDecisionValue(self.makePerson(user=0)) self.assertNotEqual(None,
expected_text = """Visited by SupportRequest_trySendNotificationMessage Instance Tree was destroyed was destroyed by the user %s""" % support_request.getDestinationDecision()
self.assertEqual(expected_text,
support_request.SupportRequest_updateMonitoringDestroyRequestedState()) support_request.SupportRequest_updateMonitoringDestroyRequestedState())
self.tic()
event_list = support_request.getFollowUpRelatedValueList()
self.assertEqual(len(event_list), 1)
event = event_list[0]
self.assertEqual(event.getTitle(), 'Instance Tree was destroyed was destroyed by the user')
self.assertEqual(event.getDestination(), support_request.getDestinationDecision())
self.assertEqual("invalidated", self.assertEqual("invalidated",
support_request.getSimulationState()) support_request.getSimulationState())
......
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2002-2012 Nexedi SA and Contributors. All Rights Reserved.
#
# 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.
#
##############################################################################
from erp5.component.test.SlapOSTestCaseMixin import SlapOSTestCaseMixin #, simulate
import transaction
class TestSlapOSCoreTicketSlapInterfaceWorkflow(SlapOSTestCaseMixin):
def afterSetUp(self):
SlapOSTestCaseMixin.afterSetUp(self)
portal = self.getPortalObject()
self.ticket_trade_condition = portal.sale_trade_condition_module.slapos_ticket_trade_condition
person_user = self.makePerson()
self.tic()
# Login as new user
self.login(person_user.getUserId())
new_person = self.portal.portal_membership.getAuthenticatedMember().getUserValue()
self.assertEqual(person_user.getRelativeUrl(), new_person.getRelativeUrl())
self.support_request = portal.support_request_module.newContent(
portal_type="Support Request",
destination_decision=person_user.getRelativeUrl(),
specialise=self.ticket_trade_condition.getRelativeUrl()
)
# Value set by the init
self.assertTrue(self.support_request.getReference().startswith("SR-"),
"Reference don't start with SR- : %s" % self.support_request.getReference())
def beforeTearDown(self):
transaction.abort()
def test_SupportRequest_approveRegistration_no_reference(self):
self.support_request.setReference(None)
self.assertRaises(ValueError, self.support_request.approveRegistration)
def test_SupportRequest_approveRegistration_already_validated(self):
# Login as admin since user cannot re-approve a validated project
self.login()
self.support_request.validate()
# Don't raise if support request is validated
self.assertEqual(self.support_request.approveRegistration(), None)
def test_SupportRequest_approveRegistration(self):
person = self.portal.portal_membership.getAuthenticatedMember().getUserValue()
self.support_request.approveRegistration()
self.tic()
self.logout()
self.login(person.getUserId())
self.assertEqual(self.support_request.getSimulationState(),
'validated')
self.assertEqual(self.support_request.getSourceSection(),
self.ticket_trade_condition.getSourceSection())
self.assertEqual(self.support_request.getSourceTrade(),
self.ticket_trade_condition.getSourceSection())
self.assertEqual(self.support_request.getSource(),
self.ticket_trade_condition.getSource())
self.assertNotEqual(self.support_request.getStartDate(),
None)
event = self.support_request.getCausalityValue()
self.assertNotEqual(event, None)
event_relative_url = self.support_request.REQUEST.get("event_relative_url")
self.assertEqual(event.getRelativeUrl(), event_relative_url)
self.assertEqual(event.getTitle(), self.support_request.getTitle())
def test_SupportRequest_requestEvent_noParameter(self):
self.assertRaises(TypeError, self.support_request.requestEvent)
self.assertRaises(TypeError, self.support_request.requestEvent, event_title="A")
self.assertRaises(TypeError, self.support_request.requestEvent, event_content="A")
def test_SupportRequest_requestEvent(self):
person = self.portal.portal_membership.getAuthenticatedMember().getUserValue()
self.support_request.approveRegistration()
self.tic()
self.logout()
self.login(person.getUserId())
self.support_request.requestEvent(
event_title="A",
event_content="B"
)
self.tic()
event_relative_url = self.support_request.REQUEST.get("event_relative_url")
event = self.portal.restrictedTraverse(event_relative_url)
self.assertEqual(event.getSimulationState(), "stopped")
self.assertEqual(self.support_request.getSimulationState(),
'validated')
self.assertEqual(self.support_request.getDestinationDecision(),
event.getSource())
self.assertEqual(person, event.getSourceValue())
self.assertEqual(self.support_request.getResource(),
event.getResource())
self.assertEqual(self.support_request,
event.getFollowUpValue())
self.assertEqual(event.getTitle(), "A")
self.assertEqual(event.getTextContent(), "B")
self.assertEqual(event.getContentType(), "text/plain")
self.assertEqual(event.getPortalType(), "Web Message")
self.assertEqual(event.getDestination(),
self.support_request.getSource())
def test_SupportRequest_notify_noParameter(self):
self.assertRaises(TypeError, self.support_request.notify)
self.assertRaises(TypeError, self.support_request.notify, message_title="A")
self.assertRaises(TypeError, self.support_request.notify, message="A")
self.assertRaises(TypeError, self.support_request.notify, destination_relative_url="A")
def test_SupportRequest_notify(self):
person = self.portal.portal_membership.getAuthenticatedMember().getUserValue()
self.support_request.approveRegistration()
self.tic()
self.logout()
self.login()
self.support_request.notify(
message_title="A",
message="B")
event = self.support_request.REQUEST.get("ticket_notified_item")
self.assertEqual(event.getSimulationState(), "delivered")
self.assertEqual(self.support_request.getSimulationState(),
'validated')
self.assertEqual(self.support_request.getDestinationDecision(),
event.getDestination())
self.assertEqual(person, event.getDestinationValue())
self.assertEqual("service_module/slapos_crm_information",
event.getResource())
self.assertEqual(self.support_request,
event.getFollowUpValue())
self.assertEqual(event.getTitle(), "A")
self.assertEqual(event.getTextContent(), "B")
self.assertEqual(event.getContentType(), "text/html")
self.assertEqual(event.getPortalType(), "Web Message")
self.assertEqual(event.getSource(),
self.support_request.getSource())
# Retry now to see if doesn't create a new message
self.support_request.notify(
message_title="A",
message="B")
self.tic()
self.assertEqual(event,
self.support_request.REQUEST.get("ticket_notified_item"))
# Retry, now it must create a new one
self.support_request.notify(
message_title="C",
message="B")
self.tic()
self.assertNotEqual(event,
self.support_request.REQUEST.get("ticket_notified_item"))
# Remove completly the ticket_notified_item and try to create a new one
# It should find it anyway from catalog.
self.support_request.REQUEST.set("ticket_notified_item", None)
self.commit()
# Retry, now it must create a new one
self.support_request.notify(
message_title="A",
message="B")
self.tic()
self.assertEqual(event,
self.support_request.REQUEST.get("ticket_notified_item"))
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Test Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>testSlapOSCloudTicketSlapInterfaceWorkflow</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>test.erp5.testSlapOSCloudTicketSlapInterfaceWorkflow</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Test Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_count</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>source/portal_workflow/ticket_slap_interface_workflow/state_draft</string>
</tuple>
</value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>person_slap_interface_workflow</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ticket_slap_interface_workflow</string> </value>
</item>
<item>
<key> <string>language</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>manager_bypass</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow</string> </value>
</item>
<item>
<key> <string>state_variable</string> </key>
<value> <string>slap_state</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Ticket Slap Interface Workflow</string> </value>
</item>
<item>
<key> <string>workflow_managed_permission</string> </key>
<value>
<tuple/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Length" module="BTrees.Length"/>
</pickle>
<pickle> <int>0</int> </pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
</ZopeData>
ticket = state_change["object"]
from DateTime import DateTime
portal = context.getPortalObject()
if ticket.getSimulationState() != "draft":
return
if ticket.getReference() in [None, ""]:
raise ValueError("Reference is missing on the Ticket")
# Get the user id of the context owner.
local_role_list = ticket.get_local_roles()
for group, role_list in local_role_list:
if 'Owner' in role_list:
user_id = group
break
person = portal.portal_catalog.getResultValue(user_id=user_id)
if person is None:
# Value was created by super user, so there isn't a point on continue
return
# XXX unhardcode the trade condition, by adding a preference
if ticket.getSpecialise() != "sale_trade_condition_module/slapos_ticket_trade_condition":
return
trade_condition = portal.sale_trade_condition_module.slapos_ticket_trade_condition
ticket.edit(
source_section=trade_condition.getSourceSection(),
source_trade=trade_condition.getSourceSection(),
source=trade_condition.getSource())
ticket.setStartDate(DateTime())
ticket.requestEvent(
event_title=ticket.getTitle(),
event_content=ticket.getDescription()
)
event_relative_url = context.REQUEST.get("event_relative_url")
ticket.setCausality(event_relative_url)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Script" module="erp5.portal_type"/>
</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>state_change</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>script_Ticket_approveRegistration</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Script</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Ticket_approveRegistration</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/> <global name="Workflow Script" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
...@@ -50,11 +50,27 @@ ...@@ -50,11 +50,27 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>title, description, source_relative_url</string> </value> <value> <string>state_change</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>Base_generateSupportRequestForSlapOS</string> </value> <value> <string>script_Ticket_checkConsistency</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Script</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
support_request = context ticket = state_change["object"]
portal = context.getPortalObject() from DateTime import DateTime
portal = ticket.getPortalObject()
# Get required arguments
kwargs = state_change.kwargs
# Required args
# Raise TypeError if all parameters are not provided
try:
message_title = kwargs['message_title']
message = kwargs['message']
except KeyError:
raise TypeError("Ticket_notify takes exactly 2 arguments")
resource = portal.service_module.slapos_crm_information.getRelativeUrl() resource = portal.service_module.slapos_crm_information.getRelativeUrl()
# create Web message if needed for this ticket # create Web message if needed for this ticket
last_event = context.portal_catalog.getResultValue( last_event = ticket.portal_catalog.getResultValue(
title=message_title, title=message_title,
follow_up_uid=support_request.getUid(), follow_up_uid=ticket.getUid(),
sort_on=[('delivery.start_date', 'DESC')], sort_on=[('delivery.start_date', 'DESC')],
) )
if last_event: if last_event:
# User has already been notified for this problem. # User has already been notified for this problem.
return last_event ticket.REQUEST.set("ticket_notified_item", last_event)
return
transactional_event = context.REQUEST.get("support_request_notified_item", None) transactional_event = ticket.REQUEST.get("ticket_notified_item", None)
if transactional_event is not None: if transactional_event is not None:
if (transactional_event.getFollowUpUid() == support_request.getUid()) and \ if (transactional_event.getFollowUpUid() == ticket.getUid()) and \
(transactional_event.getTitle() == message_title): (transactional_event.getTitle() == message_title):
return transactional_event ticket.REQUEST.set("ticket_notified_item", transactional_event)
return
template = portal.restrictedTraverse( template = portal.restrictedTraverse(
portal.portal_preferences.getPreferredWebMessageTemplate()) portal.portal_preferences.getPreferredWebMessageTemplate())
...@@ -28,14 +43,12 @@ event.edit( ...@@ -28,14 +43,12 @@ event.edit(
text_content=message, text_content=message,
start_date = DateTime(), start_date = DateTime(),
resource = resource, resource = resource,
source=support_request.getSource(), source=ticket.getSource(),
destination=destination_relative_url, destination=ticket.getDestinationDecision(),
follow_up=support_request.getRelativeUrl(), follow_up=ticket.getRelativeUrl(),
) )
event.stop() event.stop()
event.deliver() event.deliver()
support_request.serialize() ticket.serialize()
context.REQUEST.set("support_request_notified_item", event) ticket.REQUEST.set("ticket_notified_item", event)
return event
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/> <global name="Workflow Script" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
...@@ -50,11 +50,33 @@ ...@@ -50,11 +50,33 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>message_title, message, destination_relative_url</string> </value> <value> <string>state_change</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>SupportRequest_trySendNotificationMessage</string> </value> <value> <string>script_Ticket_notify</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Script</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Ticket_notify</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
ticket = state_change["object"]
from DateTime import DateTime
portal = context.getPortalObject()
# Get required arguments
kwargs = state_change.kwargs
# Required args
# Raise TypeError if all parameters are not provided
try:
title = kwargs['event_title']
text_content = kwargs['event_content']
except KeyError:
raise TypeError, "Ticket_requestEvent takes exactly 2 argument"
web_message = portal.event_module.newContent(
portal_type="Web Message",
title=title,
text_content=text_content,
source=ticket.getDestinationDecision(),
content_type="text/plain",
destination=ticket.getSource(),
resource=ticket.getResource(),
follow_up=ticket.getRelativeUrl()
)
web_message.stop(comment="Submitted from the renderjs app")
if portal.portal_workflow.isTransitionPossible(ticket, "validate"):
ticket.validate(comment="See %s" % web_message.getRelativeUrl())
ticket.REQUEST.set("event_relative_url", web_message.getRelativeUrl())
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Script" module="erp5.portal_type"/>
</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>state_change</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>script_Ticket_requestEvent</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Script</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Ticket_requestEvent</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow State" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>acquire_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>destination/portal_workflow/ticket_slap_interface_workflow/transition_approve_registration</string>
<string>destination/portal_workflow/ticket_slap_interface_workflow/transition_notify</string>
<string>destination/portal_workflow/ticket_slap_interface_workflow/transition_request_event</string>
</tuple>
</value>
</item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>state_draft</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow State</string> </value>
</item>
<item>
<key> <string>state_permission_role_list_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>state_type</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Draft</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Transition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>action_name</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/workflow</string>
<string>before_script/portal_workflow/ticket_slap_interface_workflow/script_Ticket_checkConsistency</string>
<string>after_script/portal_workflow/ticket_slap_interface_workflow/script_Ticket_approveRegistration</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>guard_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>transition_approve_registration</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Transition</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Approve Registration</string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Transition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>action_name</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/workflow</string>
<string>before_script/portal_workflow/ticket_slap_interface_workflow/script_Ticket_checkConsistency</string>
<string>after_script/portal_workflow/ticket_slap_interface_workflow/script_Ticket_notify</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>guard_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>transition_notify</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Transition</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Notify</string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Transition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>action_name</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/workflow</string>
<string>before_script/portal_workflow/ticket_slap_interface_workflow/script_Ticket_checkConsistency</string>
<string>after_script/portal_workflow/ticket_slap_interface_workflow/script_Ticket_requestEvent</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>guard_permission</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>transition_request_event</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Transition</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Request Event</string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>The last transition</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_action</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>variable_default_expression</string> </key>
<value> <string>transition/getReference|nothing</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>The name of the user who performed the last transition</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_actor</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>variable_default_expression</string> </key>
<value> <string>user/getUserName</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Comments about the last transition</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_comment</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>variable_default_expression</string> </key>
<value> <string>python:state_change.kwargs.get(\'comment\', \'\')</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Error message if validation failed</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_error_message</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Provides access to workflow history</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_history</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>variable_default_expression</string> </key>
<value> <string>state_change/getHistory</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>portal type (use as filter for worklists)</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_portal_type</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Workflow Variable" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>automatic_update</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Time of the last transition</string> </value>
</item>
<item>
<key> <string>for_catalog</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>variable_time</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Workflow Variable</string> </value>
</item>
<item>
<key> <string>status_included</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>variable_default_expression</string> </key>
<value> <string>state_change/getDateTime</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -32,6 +32,12 @@ ...@@ -32,6 +32,12 @@
</tuple> </tuple>
</value> </value>
</item> </item>
<item>
<key> <string>comment</string> </key>
<value>
<none/>
</value>
</item>
<item> <item>
<key> <string>default_reference</string> </key> <key> <string>default_reference</string> </key>
<value> <string>ticket_workflow</string> </value> <value> <string>ticket_workflow</string> </value>
......
...@@ -4,3 +4,4 @@ Regularisation Request | edit_workflow ...@@ -4,3 +4,4 @@ Regularisation Request | edit_workflow
Regularisation Request | pricing_interaction_workflow Regularisation Request | pricing_interaction_workflow
Regularisation Request | ticket_interaction_workflow Regularisation Request | ticket_interaction_workflow
Regularisation Request | ticket_workflow Regularisation Request | ticket_workflow
Support Request | ticket_slap_interface_workflow
\ No newline at end of file
test.erp5.testSlapOSCRMSkins test.erp5.testSlapOSCRMSkins
test.erp5.testSlapOSCRMRegularisationRequestSkins test.erp5.testSlapOSCRMRegularisationRequestSkins
test.erp5.testSlapOSCRMAlarm test.erp5.testSlapOSCRMAlarm
test.erp5.testSlapOSCloudTicketSlapInterfaceWorkflow
\ No newline at end of file
ticket_slap_interface_workflow
ticket_workflow ticket_workflow
\ No newline at end of file
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