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
......
# -*- 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