Commit 619385ce authored by Rafael Monnerat's avatar Rafael Monnerat

Speedup RSS and cleanup for CRM

See merge request nexedi/slapos.core!416
parents fdbc9fc4 95d11f41
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_jio_button</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_jio_button</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>rss_view</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>View</string>
</tuple>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Action Information</string> </value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>30.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>RSS Feed</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/Folder_viewOpenTicketFeedURL</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:rss_feed_image</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -62,7 +62,7 @@
</item>
<item>
<key> <string>title</string> </key>
<value> <string>RSS Monitoring Support Request List</string> </value>
<value> <string>RSS Feed</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
......@@ -79,7 +79,7 @@
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/Folder_viewOpenTicketList?portal_skin=RSS</string> </value>
<value> <string>string:${object_url}/Folder_viewOpenTicketFeedURL</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -62,7 +62,7 @@
</item>
<item>
<key> <string>title</string> </key>
<value> <string>RSS Monitoring Support Request List</string> </value>
<value> <string>RSS Feed</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
......@@ -79,7 +79,7 @@
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/Folder_viewOpenTicketList?portal_skin=RSS</string> </value>
<value> <string>string:${object_url}/Folder_viewOpenTicketFeedURL</string> </value>
</item>
</dictionary>
</pickle>
......
portal = context.getPortalObject()
person = portal.portal_membership.getAuthenticatedMember().getUserValue()
if person is None:
raise ValueError("User Not Found")
request_url = "%s/Folder_viewOpenTicketList" % context.absolute_url()
# XXX - Cannot search in catalog with parameter url_string
access_token = None
for token_item in portal.portal_catalog(
portal_type="Restricted Access Token",
default_agent_uid=person.getUid(),
validation_state='validated'
):
if token_item.getUrlString() == request_url:
access_token = token_item
reference = access_token.getReference()
break
if access_token is None:
access_token = portal.access_token_module.newContent(
portal_type="Restricted Access Token",
url_string=request_url,
url_method="GET",
)
access_token.setAgentValue(person)
reference = access_token.getReference()
access_token.validate()
return "%s?portal_skin=RSS&access_token=%s&access_token_secret=%s" % (
request_url,
access_token.getId(),
reference)
......@@ -54,7 +54,7 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>WebSection_getRSSDateContent</string> </value>
<value> <string>Folder_getTicketFeedUrl</string> </value>
</item>
</dictionary>
</pickle>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5 Form" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_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/>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>action_title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>edit_order</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>enctype</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<list>
<string>bottom</string>
<string>hidden</string>
</list>
</value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<dictionary>
<item>
<key> <string>bottom</string> </key>
<value>
<list>
<string>your_feed_url</string>
</list>
</value>
</item>
<item>
<key> <string>hidden</string> </key>
<value>
<list/>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Folder_viewOpenTicketFeedURL</string> </value>
</item>
<item>
<key> <string>method</string> </key>
<value> <string>POST</string> </value>
</item>
<item>
<key> <string>name</string> </key>
<value> <string>Folder_viewOpenTicketFeedURL</string> </value>
</item>
<item>
<key> <string>pt</string> </key>
<value> <string>form_dialog</string> </value>
</item>
<item>
<key> <string>row_length</string> </key>
<value> <int>4</int> </value>
</item>
<item>
<key> <string>stored_encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>RSS Feed</string> </value>
</item>
<item>
<key> <string>unicode_mode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>update_action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>update_action_title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="LinkField" module="Products.Formulator.StandardFields"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>your_feed_url</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
<item>
<key> <string>not_link</string> </key>
<value> <string>The specified link is broken.</string> </value>
</item>
<item>
<key> <string>required_not_found</string> </key>
<value> <string>Input is required but no input given.</string> </value>
</item>
<item>
<key> <string>too_long</string> </key>
<value> <string>Too much input was given.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>check_link</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>check_timeout</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_maxwidth</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>link_type</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>truncate</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>check_link</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>check_timeout</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_maxwidth</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>link_type</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>truncate</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>check_link</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>check_timeout</string> </key>
<value> <float>7.0</float> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_maxwidth</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>display_width</string> </key>
<value> <int>20</int> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string>text</string> </value>
</item>
<item>
<key> <string>link_type</string> </key>
<value> <string>external</string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Feed URL</string> </value>
</item>
<item>
<key> <string>truncate</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <int>0</int> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>here/Folder_getTicketFeedUrl</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
portal = context.getPortalObject()
return portal.portal_catalog.getResultValue(
follow_up_uid=context.getUid(),
portal_type=portal.getPortalEventTypeList(),
simulation_state=["confirmed", "started", "stopped", "delivered"],
sort_on=(("modification_date", 'DESC'),))
......@@ -29,8 +29,6 @@ from App.Common import rfc1123_date
from Products.ERP5Type.Cache import DEFAULT_CACHE_SCOPE
import json
import feedparser
def getFakeSlapState():
return "destroy_requested"
......@@ -158,119 +156,6 @@ class TestSlapOSSupportRequestModule_getMonitoringUrlList(TestCRMSkinsMixin):
self.tic()
self.assertNotEqual(instance_tree.getSuccessorList(), [])
class TestSlapOSFolder_getOpenTicketList(TestCRMSkinsMixin):
def _test_ticket(self, ticket, expected_amount):
module = ticket.getParentValue()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount-1)
ticket.submit()
ticket.immediateReindexObject()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount)
self.assertEqual(open_ticket_list[0].getUid(), ticket.getUid())
ticket.validate()
ticket.immediateReindexObject()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount)
self.assertEqual(open_ticket_list[0].getUid(), ticket.getUid())
ticket.suspend()
ticket.immediateReindexObject()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount)
self.assertEqual(open_ticket_list[0].getUid(), ticket.getUid())
ticket.invalidate()
ticket.immediateReindexObject()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount)
self.assertEqual(open_ticket_list[0].getUid(), ticket.getUid())
def _test_upgrade_decision(self, ticket, expected_amount):
module = ticket.getParentValue()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount-1)
ticket.plan()
ticket.immediateReindexObject()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount-1)
ticket.confirm()
ticket.immediateReindexObject()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount)
self.assertTrue(ticket.getUid() in [i.getUid() for i in open_ticket_list])
ticket.start()
ticket.immediateReindexObject()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount-1)
ticket.stop()
ticket.immediateReindexObject()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount-1)
ticket.deliver()
ticket.immediateReindexObject()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount)
self.assertTrue(ticket.getUid() in [i.getUid() for i in open_ticket_list])
def test_support_request(self):
def newSupportRequest():
sr = self.portal.support_request_module.newContent(\
title="Test Support Request %s" % self.new_id)
sr.immediateReindexObject()
return sr
ticket = newSupportRequest()
self._test_ticket(ticket, 1)
ticket = newSupportRequest()
self._test_ticket(ticket, 2)
def test_regularisation_request(self):
def newRegularisationRequest():
ticket = self.portal.regularisation_request_module.newContent(
portal_type='Regularisation Request',
title="Test Reg. Req.%s" % self.new_id,
reference="TESTREGREQ-%s" % self.new_id
)
ticket.immediateReindexObject()
return ticket
ticket = newRegularisationRequest()
self._test_ticket(ticket, 1)
ticket = newRegularisationRequest()
self._test_ticket(ticket, 2)
def test_upgrade_decision(self):
def newUpgradeDecision():
ticket = self.portal.upgrade_decision_module.newContent(
portal_type='Upgrade Decision',
title="Upgrade Decision Test %s" % self.new_id,
reference="TESTUD-%s" % self.new_id)
ticket.immediateReindexObject()
return ticket
ticket = newUpgradeDecision()
self._test_upgrade_decision(ticket, 1)
ticket = newUpgradeDecision()
self._test_upgrade_decision(ticket, 2)
class TestSlapOSBase_getOpenRelatedTicketList(TestCRMSkinsMixin):
def test_getOpenRelatedTicketList_support_request_related_to_compute_node(self):
......@@ -453,172 +338,6 @@ class TestSlapOSBase_getOpenRelatedTicketList(TestCRMSkinsMixin):
open_related_ticket_list = document.Base_getOpenRelatedTicketList()
self.assertEqual(len(open_related_ticket_list), 0)
class TestSlapOSTicketEvent(TestCRMSkinsMixin):
def _test_event(self, ticket):
def newEvent(ticket):
event = self.portal.event_module.newContent(
title="Test Event %s" % self.new_id,
portal_type="Web Message",
follow_up_value=ticket)
event.immediateReindexObject()
return event
last_event = ticket.Ticket_getLatestEvent()
self.assertEqual(last_event, None)
event = newEvent(ticket)
last_event = ticket.Ticket_getLatestEvent()
self.assertEqual(last_event, None)
event.plan()
event.immediateReindexObject()
self.assertEqual(last_event, None)
event.confirm()
event.immediateReindexObject()
last_event = ticket.Ticket_getLatestEvent()
self.assertEqual(last_event, event)
event.start()
event.immediateReindexObject()
last_event = ticket.Ticket_getLatestEvent()
self.assertEqual(last_event, event)
event.stop()
event.immediateReindexObject()
last_event = ticket.Ticket_getLatestEvent()
self.assertEqual(last_event, event)
event.deliver()
event.immediateReindexObject()
last_event = ticket.Ticket_getLatestEvent()
self.assertEqual(last_event, event)
# Now we test unwanted cases (deleted and cancelled)
another_event = newEvent(ticket)
last_event = ticket.Ticket_getLatestEvent()
self.assertEqual(last_event, event)
another_event.cancel()
event.immediateReindexObject()
last_event = ticket.Ticket_getLatestEvent()
self.assertEqual(last_event, event)
another_event = newEvent(ticket)
last_event = ticket.Ticket_getLatestEvent()
self.assertEqual(last_event, event)
another_event.delete()
event.immediateReindexObject()
last_event = ticket.Ticket_getLatestEvent()
self.assertEqual(last_event, event)
class TestSlapOSEvent_getRSSTextContent(TestSlapOSTicketEvent):
def test_Event_getRSSTextContent(self):
source = self.person
destination = self.portal.person_module.newContent(
portal_type='Person',
title="Person Destination %s" % self.new_id,
reference="TESTPERSD-%s" % self.new_id,
default_email_text="live_test_%s@example.org" % self.new_id,
)
destination_2 = self.portal.person_module.newContent(
portal_type='Person',
title="Person Destination 2 %s" % self.new_id,
reference="TESTPERSD2-%s" % self.new_id,
default_email_text="live_test_%s@example.org" % self.new_id,
)
event = self.portal.event_module.newContent(
title="Test Event %s" % self.new_id,
portal_type="Web Message",
text_content="Test Event %s" % self.new_id)
text_content = event.Event_getRSSTextContent()
self.assertTrue(event.getTextContent() in text_content)
self.assertTrue("Sender: " in text_content, "Sender: not in %s" % text_content)
self.assertTrue("Recipient: " in text_content, "Recipient: not in %s" % text_content)
self.assertTrue("Content:" in text_content, "Content: not in %s" % text_content)
event.setSourceValue(source)
text_content = event.Event_getRSSTextContent()
self.assertTrue("Sender: %s" % source.getTitle() in text_content,
"Sender: %s not in %s" % (source.getTitle(), text_content))
event.setDestinationValue(destination)
text_content = event.Event_getRSSTextContent()
self.assertTrue("Recipient: %s" % destination.getTitle() in text_content,
"Recipient: %s not in %s" % (destination.getTitle(), text_content))
event.setDestinationValue(destination_2)
text_content = event.Event_getRSSTextContent()
self.assertTrue("Recipient: %s" % destination_2.getTitle() in text_content,
"Recipient: %s not in %s" % (destination.getTitle(), text_content))
event.setDestinationValueList([destination, destination_2])
text_content = event.Event_getRSSTextContent()
self.assertTrue(
"Recipient: %s,%s" % (destination.getTitle(),
destination_2.getTitle()) in text_content,
"Recipient: %s,%s not in %s" % (destination.getTitle(),
destination_2.getTitle(),
text_content)
)
def test_support_request(self):
ticket = self.portal.support_request_module.newContent(\
title="Test Support Request %s" % self.new_id,
resource="service_module/slapos_crm_monitoring",
destination_decision_value=self.person)
ticket.immediateReindexObject()
self._test_event(ticket)
class TestSlapOSTicket_getLatestEvent(TestSlapOSTicketEvent):
def test_support_request(self):
ticket = self.portal.support_request_module.newContent(\
title="Test Support Request %s" % self.new_id,
resource="service_module/slapos_crm_monitoring",
destination_decision_value=self.person)
ticket.immediateReindexObject()
self._test_event(ticket)
def test_regularisation_request(self):
ticket = self.portal.regularisation_request_module.newContent(
portal_type='Regularisation Request',
title="Test Reg. Req.%s" % self.new_id,
reference="TESTREGREQ-%s" % self.new_id
)
ticket.immediateReindexObject()
self._test_event(ticket)
def test_upgrade_decision(self):
ticket = self.portal.upgrade_decision_module.newContent(
portal_type='Upgrade Decision',
title="Upgrade Decision Test %s" % self.new_id,
reference="TESTUD-%s" % self.new_id
)
ticket.immediateReindexObject()
self._test_event(ticket)
class TestSlapOSComputeNode_notifyWrongAllocationScope(TestCRMSkinsMixin):
def afterSetUp(self):
......@@ -1681,43 +1400,28 @@ class TestSupportRequestUpdateMonitoringState(SlapOSTestCaseMixin):
support_request.getSimulationState())
class TestSlapOSSupportRequestRSS(TestCRMSkinsMixin):
def test_WebSection_viewTicketListAsRSS(self):
person = self.makePerson()
class TestSlapOSFolder_getTicketFeedUrl(TestCRMSkinsMixin):
module = self.portal.support_request_module
support_request = module.newContent(
portal_type="Support Request",
title='Help',
destination_decision_value=person,
)
self.portal.event_module.newContent(
portal_type='Web Message',
follow_up_value=support_request,
text_content='I need help !',
source_value=person,
).start()
support_request.validate()
def _test(self, module):
self.assertRaises(ValueError, module.Folder_getTicketFeedUrl)
person = self.makePerson(user=1)
self.tic()
self.login(person.getUserId())
self.portal.portal_skins.changeSkin('RSS')
parsed = feedparser.parse(self.portal.WebSection_viewTicketListAsRSS())
self.assertFalse(parsed.bozo)
first_entry_id = [item.id for item in parsed.entries]
self.assertEqual([item.summary for item in parsed.entries], ['I need help !'])
self.portal.event_module.newContent(
portal_type='Web Message',
follow_up_value=support_request,
text_content='How can I help you ?',
destination_value=person,
).start()
self.tic()
self.portal.portal_skins.changeSkin('RSS')
parsed = feedparser.parse(self.portal.WebSection_viewTicketListAsRSS())
self.assertFalse(parsed.bozo)
self.assertEqual([item.summary for item in parsed.entries], ['How can I help you ?'])
self.assertNotEqual([item.id for item in parsed.entries][0], first_entry_id)
url = module.Folder_getTicketFeedUrl()
self.assertIn('Folder_viewOpenTicketList', url)
self.assertIn(module.absolute_url(), url)
self.assertIn('access_token_secret', url)
self.assertIn('access_token=', url)
self.assertIn('portal_skin=RSS', url)
def test_Folder_getTicketFeedUrl_support_request_module(self):
self._test(self.portal.support_request_module)
def test_Folder_getTicketFeedUrl_regularisation_request_module(self):
self._test(self.portal.regularisation_request_module)
def test_Folder_getTicketFeedUrl_incident_response_module(self):
self._test(self.portal.incident_response_module)
Compute Node Module | slapos_ticket_activity_report
Compute Node | view_related_support_request
Incident Response Module | rss_view
Incident Response Module | view
Incident Response | view
Instance Tree Module | slapos_resilience_usage_report
......
from Products.ERP5Type.Cache import CachingMethod
portal = context.getPortalObject()
def getLastEventRelativeUrl(uid):
portal = context.getPortalObject()
last_event = portal.portal_catalog.getResultValue(
follow_up_uid=context.getUid(),
portal_type=portal.getPortalEventTypeList(),
simulation_state=["confirmed", "started", "stopped", "delivered"],
sort_on=(("modification_date", 'DESC'),))
if last_event is not None:
return last_event.getRelativeUrl()
else:
return last_event
last_event_url = CachingMethod(getLastEventRelativeUrl,
id='Ticket_getLatestEventRelativeUrl',
cache_factory='erp5_content_short')(context.getUid())
if last_event_url is not None:
return portal.restrictedTraverse(last_event_url)
portal = context.getPortalObject()
event = portal.portal_catalog.getResultValue(
follow_up_uid=context.getUid(),
sort_on=[('modification_date', 'DESC')],
)
if event:
return event.getModificationDate()
return context.getModificationDate()
portal = context.getPortalObject()
event = portal.portal_catalog.getResultValue(
follow_up_uid=context.getUid(),
sort_on=[('modification_date', 'DESC')],
)
if event:
return event.getTextContent()
return context.getDescription()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>WebSection_getRSSDescriptionContent</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -154,6 +154,10 @@
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
......@@ -267,7 +271,7 @@
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>cell/WebSection_getRSSDescriptionContent</string> </value>
<value> <string>python: cell.Ticket_getLatestEvent() and cell.Ticket_getLatestEvent().getTextContent() or cell.getDescription()</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -176,6 +176,10 @@
<key> <string>default_now</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default_timezone</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
......@@ -483,7 +487,7 @@
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>cell/WebSection_getRSSDateContent</string> </value>
<value> <string>python: cell.Ticket_getLatestEvent() and cell.Ticket_getLatestEvent().getModificationDate() or cell.getModificationDate()</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -154,6 +154,10 @@
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>input_type</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
......@@ -267,7 +271,7 @@
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>cell/WebSection_getRSSDescriptionContent</string> </value>
<value> <string>python: cell.Ticket_getLatestEvent() and cell.Ticket_getLatestEvent().getTextContent() or cell.getDescription()</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -176,6 +176,10 @@
<key> <string>default_now</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default_timezone</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
......@@ -483,7 +487,7 @@
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>cell/WebSection_getRSSDateContent</string> </value>
<value> <string>python: cell.Ticket_getLatestEvent() and cell.Ticket_getLatestEvent().getModificationDate() or cell.getModificationDate()</string> </value>
</item>
</dictionary>
</pickle>
......
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2013-2019 Nexedi SA and Contributors.
#
# This program is free software: you can Use, Study, Modify and Redistribute
# it under the terms of the GNU General Public License version 3, or (at your
# option) any later version, as published by the Free Software Foundation.
#
# You can also Link and Combine this program with other software covered by
# the terms of any of the Free Software licenses or any of the Open Source
# Initiative approved licenses and Convey the resulting work. Corresponding
# source of such a combination shall include the source code for all other
# software used.
#
# This program is distributed WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See COPYING file for full licensing terms.
# See https://www.nexedi.com/licensing for rationale and options.
#
##############################################################################
import transaction
from erp5.component.test.SlapOSTestCaseMixin import SlapOSTestCaseMixinWithAbort
from DateTime import DateTime
import feedparser
def getFakeSlapState():
return "destroy_requested"
class TestRSSSyleSkinsMixin(SlapOSTestCaseMixinWithAbort):
def afterSetUp(self):
SlapOSTestCaseMixinWithAbort.afterSetUp(self)
self.person = self.makePerson(new_id=self.new_id, index=0, user=0)
self.clearCache()
def _cancelTestSupportRequestList(self, title="%"):
for support_request in self.portal.portal_catalog(
portal_type="Support Request",
title=title,
simulation_state=["validated", "suspended"]):
support_request.invalidate()
self.tic()
def _updatePersonAssignment(self, person, role='role/member'):
for assignment in person.contentValues(portal_type="Assignment"):
assignment.cancel()
assignment = person.newContent(portal_type='Assignment')
assignment.setRole(role)
assignment.setStartDate(DateTime())
assignment.open()
return assignment
def _makeInstanceTree(self):
person = self.portal.person_module.template_member\
.Base_createCloneDocument(batch_mode=1)
instance_tree = self.portal\
.instance_tree_module.template_instance_tree\
.Base_createCloneDocument(batch_mode=1)
instance_tree.validate()
new_id = self.generateNewId()
instance_tree.edit(
title= "Test hosting sub ticket %s" % new_id,
reference="TESTHST-%s" % new_id,
destination_section_value=person
)
return instance_tree
def _makeSoftwareInstance(self, instance_tree, software_url):
kw = dict(
software_release=software_url,
software_type=self.generateNewSoftwareType(),
instance_xml=self.generateSafeXml(),
sla_xml=self.generateSafeXml(),
shared=False,
software_title=instance_tree.getTitle(),
state='started'
)
instance_tree.requestStart(**kw)
instance_tree.requestInstance(**kw)
def _makeSoftwareInstallation(self):
self._makeComputeNode()
software_installation = self.portal\
.software_installation_module.template_software_installation\
.Base_createCloneDocument(batch_mode=1)
software_installation.edit(
url_string=self.generateNewSoftwareReleaseUrl(),
aggregate=self.compute_node.getRelativeUrl(),
reference='TESTSOFTINSTS-%s' % self.generateNewId(),
title='Start requested for %s' % self.compute_node.getUid()
)
software_installation.validate()
software_installation.requestStart()
return software_installation
class TestSlapOSTicketEvent(TestRSSSyleSkinsMixin):
def _test_event(self, ticket):
def newEvent(ticket):
event = self.portal.event_module.newContent(
title="Test Event %s" % self.new_id,
portal_type="Web Message",
follow_up_value=ticket)
event.immediateReindexObject()
return event
self.clearCache()
transaction.commit()
self.portal.portal_skins.changeSkin('RSS')
last_event = ticket.Ticket_getLatestEvent()
self.assertEqual(last_event, None)
event = newEvent(ticket)
self.clearCache()
transaction.commit()
last_event = ticket.Ticket_getLatestEvent()
self.assertEqual(last_event, None)
event.plan()
event.immediateReindexObject()
self.assertEqual(last_event, None)
event.confirm()
event.immediateReindexObject()
self.clearCache()
transaction.commit()
last_event = ticket.Ticket_getLatestEvent()
self.assertEqual(last_event, event)
event.start()
event.immediateReindexObject()
self.clearCache()
transaction.commit()
last_event = ticket.Ticket_getLatestEvent()
self.assertEqual(last_event, event)
event.stop()
event.immediateReindexObject()
self.clearCache()
transaction.commit()
last_event = ticket.Ticket_getLatestEvent()
self.assertEqual(last_event, event)
event.deliver()
event.immediateReindexObject()
self.clearCache()
transaction.commit()
last_event = ticket.Ticket_getLatestEvent()
self.assertEqual(last_event, event)
# Now we test unwanted cases (deleted and cancelled)
another_event = newEvent(ticket)
self.clearCache()
transaction.commit()
last_event = ticket.Ticket_getLatestEvent()
self.assertEqual(last_event, event)
another_event.cancel()
event.immediateReindexObject()
self.clearCache()
transaction.commit()
last_event = ticket.Ticket_getLatestEvent()
self.assertEqual(last_event, event)
another_event = newEvent(ticket)
self.clearCache()
transaction.commit()
last_event = ticket.Ticket_getLatestEvent()
self.assertEqual(last_event, event)
another_event.delete()
event.immediateReindexObject()
self.clearCache()
transaction.commit()
last_event = ticket.Ticket_getLatestEvent()
self.assertEqual(last_event, event)
class TestSlapOSEvent_getRSSTextContent(TestSlapOSTicketEvent):
def test_Event_getRSSTextContent(self):
source = self.person
destination = self.portal.person_module.newContent(
portal_type='Person',
title="Person Destination %s" % self.new_id,
reference="TESTPERSD-%s" % self.new_id,
default_email_text="live_test_%s@example.org" % self.new_id,
)
destination_2 = self.portal.person_module.newContent(
portal_type='Person',
title="Person Destination 2 %s" % self.new_id,
reference="TESTPERSD2-%s" % self.new_id,
default_email_text="live_test_%s@example.org" % self.new_id,
)
event = self.portal.event_module.newContent(
title="Test Event %s" % self.new_id,
portal_type="Web Message",
text_content="Test Event %s" % self.new_id)
self.portal.portal_skins.changeSkin('RSS')
text_content = event.Event_getRSSTextContent()
self.assertTrue(event.getTextContent() in text_content)
self.assertTrue("Sender: " in text_content, "Sender: not in %s" % text_content)
self.assertTrue("Recipient: " in text_content, "Recipient: not in %s" % text_content)
self.assertTrue("Content:" in text_content, "Content: not in %s" % text_content)
event.setSourceValue(source)
text_content = event.Event_getRSSTextContent()
self.assertTrue("Sender: %s" % source.getTitle() in text_content,
"Sender: %s not in %s" % (source.getTitle(), text_content))
event.setDestinationValue(destination)
text_content = event.Event_getRSSTextContent()
self.assertTrue("Recipient: %s" % destination.getTitle() in text_content,
"Recipient: %s not in %s" % (destination.getTitle(), text_content))
event.setDestinationValue(destination_2)
text_content = event.Event_getRSSTextContent()
self.assertTrue("Recipient: %s" % destination_2.getTitle() in text_content,
"Recipient: %s not in %s" % (destination.getTitle(), text_content))
event.setDestinationValueList([destination, destination_2])
text_content = event.Event_getRSSTextContent()
self.assertTrue(
"Recipient: %s,%s" % (destination.getTitle(),
destination_2.getTitle()) in text_content,
"Recipient: %s,%s not in %s" % (destination.getTitle(),
destination_2.getTitle(),
text_content)
)
def test_support_request(self):
ticket = self.portal.support_request_module.newContent(\
title="Test Support Request %s" % self.new_id,
resource="service_module/slapos_crm_monitoring",
destination_decision_value=self.person)
ticket.immediateReindexObject()
self._test_event(ticket)
class TestSlapOSTicket_getLatestEvent(TestSlapOSTicketEvent):
def test_support_request(self):
ticket = self.portal.support_request_module.newContent(\
title="Test Support Request %s" % self.new_id,
resource="service_module/slapos_crm_monitoring",
destination_decision_value=self.person)
ticket.immediateReindexObject()
self._test_event(ticket)
def test_regularisation_request(self):
ticket = self.portal.regularisation_request_module.newContent(
portal_type='Regularisation Request',
title="Test Reg. Req.%s" % self.new_id,
reference="TESTREGREQ-%s" % self.new_id
)
ticket.immediateReindexObject()
self._test_event(ticket)
def test_upgrade_decision(self):
ticket = self.portal.upgrade_decision_module.newContent(
portal_type='Upgrade Decision',
title="Upgrade Decision Test %s" % self.new_id,
reference="TESTUD-%s" % self.new_id
)
ticket.immediateReindexObject()
self._test_event(ticket)
class TestSlapOSSupportRequestRSS(TestRSSSyleSkinsMixin):
def test_WebSection_viewTicketListAsRSS(self):
person = self.makePerson()
module = self.portal.support_request_module
support_request = module.newContent(
portal_type="Support Request",
title='Help',
destination_decision_value=person,
)
self.portal.event_module.newContent(
portal_type='Web Message',
follow_up_value=support_request,
text_content='I need help !',
source_value=person,
).start()
support_request.validate()
self.clearCache()
self.tic()
self.login(person.getUserId())
self.portal.portal_skins.changeSkin('RSS')
self.clearCache()
transaction.commit()
parsed = feedparser.parse(self.portal.WebSection_viewTicketListAsRSS())
self.assertFalse(parsed.bozo)
first_entry_id = [item.id for item in parsed.entries]
self.assertEqual([item.summary for item in parsed.entries], ['I need help !'])
self.portal.event_module.newContent(
portal_type='Web Message',
follow_up_value=support_request,
text_content='How can I help you ?',
destination_value=person,
).start()
self.clearCache()
self.tic()
self.portal.portal_skins.changeSkin('RSS')
self.clearCache()
transaction.commit()
parsed = feedparser.parse(self.portal.WebSection_viewTicketListAsRSS())
self.assertFalse(parsed.bozo)
self.assertEqual([item.summary for item in parsed.entries], ['How can I help you ?'])
self.assertNotEqual([item.id for item in parsed.entries][0], first_entry_id)
def test_WebSection_viewCriticalTicketListAsRSS(self):
person = self.makePerson()
module = self.portal.support_request_module
support_request = module.newContent(
portal_type="Support Request",
title='Help',
destination_decision_value=person,
)
self.portal.event_module.newContent(
portal_type='Web Message',
follow_up_value=support_request,
text_content='I need help !',
source_value=person,
).start()
support_request.validate()
self.clearCache()
self.tic()
self.login(person.getUserId())
self.portal.portal_skins.changeSkin('RSS')
self.clearCache()
transaction.commit()
parsed = feedparser.parse(self.portal.WebSection_viewCriticalTicketListAsRSS())
self.assertFalse(parsed.bozo)
first_entry_id = [item.id for item in parsed.entries]
self.assertEqual([item.summary for item in parsed.entries], ['I need help !'])
self.portal.event_module.newContent(
portal_type='Web Message',
follow_up_value=support_request,
text_content='How can I help you ?',
destination_value=person,
).start()
self.clearCache()
self.tic()
self.portal.portal_skins.changeSkin('RSS')
self.clearCache()
transaction.commit()
parsed = feedparser.parse(self.portal.WebSection_viewCriticalTicketListAsRSS())
self.assertFalse(parsed.bozo)
self.assertEqual([item.summary for item in parsed.entries], ['How can I help you ?'])
self.assertNotEqual([item.id for item in parsed.entries][0], first_entry_id)
class TestSlapOSFolder_getOpenTicketList(TestRSSSyleSkinsMixin):
def _test_ticket(self, ticket, expected_amount):
self.portal.portal_skins.changeSkin('RSS')
module = ticket.getParentValue()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount-1)
ticket.submit()
ticket.immediateReindexObject()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount)
self.assertEqual(open_ticket_list[0].getUid(), ticket.getUid())
ticket.validate()
ticket.immediateReindexObject()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount)
self.assertEqual(open_ticket_list[0].getUid(), ticket.getUid())
ticket.suspend()
ticket.immediateReindexObject()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount)
self.assertEqual(open_ticket_list[0].getUid(), ticket.getUid())
ticket.invalidate()
ticket.immediateReindexObject()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount)
self.assertEqual(open_ticket_list[0].getUid(), ticket.getUid())
def _test_upgrade_decision(self, ticket, expected_amount):
self.portal.portal_skins.changeSkin('RSS')
module = ticket.getParentValue()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount-1)
ticket.plan()
ticket.immediateReindexObject()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount-1)
ticket.confirm()
ticket.immediateReindexObject()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount)
self.assertTrue(ticket.getUid() in [i.getUid() for i in open_ticket_list])
ticket.start()
ticket.immediateReindexObject()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount-1)
ticket.stop()
ticket.immediateReindexObject()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount-1)
ticket.deliver()
ticket.immediateReindexObject()
open_ticket_list = module.Folder_getOpenTicketList(title=ticket.getTitle())
self.assertEqual(len(open_ticket_list), expected_amount)
self.assertTrue(ticket.getUid() in [i.getUid() for i in open_ticket_list])
def test_support_request(self):
def newSupportRequest():
sr = self.portal.support_request_module.newContent(\
title="Test Support Request %s" % self.new_id)
sr.immediateReindexObject()
return sr
ticket = newSupportRequest()
self._test_ticket(ticket, 1)
ticket = newSupportRequest()
self._test_ticket(ticket, 2)
def test_regularisation_request(self):
def newRegularisationRequest():
ticket = self.portal.regularisation_request_module.newContent(
portal_type='Regularisation Request',
title="Test Reg. Req.%s" % self.new_id,
reference="TESTREGREQ-%s" % self.new_id
)
ticket.immediateReindexObject()
return ticket
ticket = newRegularisationRequest()
self._test_ticket(ticket, 1)
ticket = newRegularisationRequest()
self._test_ticket(ticket, 2)
def test_upgrade_decision(self):
def newUpgradeDecision():
ticket = self.portal.upgrade_decision_module.newContent(
portal_type='Upgrade Decision',
title="Upgrade Decision Test %s" % self.new_id,
reference="TESTUD-%s" % self.new_id)
ticket.immediateReindexObject()
return ticket
ticket = newUpgradeDecision()
self._test_upgrade_decision(ticket, 1)
ticket = newUpgradeDecision()
self._test_upgrade_decision(ticket, 2)
<?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>default_reference</string> </key>
<value> <string>testSlapOSRSSStyleSkins</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.testSlapOSRSSStyleSkins</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">AAAAAAAAAAI=</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>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<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>
slapos_web
erp5_rss_style
\ No newline at end of file
erp5_rss_style
slapos_crm
\ No newline at end of file
test.erp5.testSlapOSRSSStyleSkins
\ 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