Commit cc8ae8bf authored by Romain Courteaud's avatar Romain Courteaud

slapos_crm:

* drop preferred_support_request_template_property
* drop slapos_crm_support_request_template
* fixup slapos_crm_create_regularisation_request tests
* reactivate slapos_crm_create_regularisation_request
* test slapos_crm_invalidate_suspended_regularisation_request is ok
* test slapos_crm_check_software_installation_state
* test slapos_crm_check_instance_in_error
* test slapos_crm_update_support_request_state
* desactivate Person_getSubscriptionRequestFirstUnpaidInvoiceList
* drop Person_getSubscriptionRequestFirstUnpaidInvoiceList
* do not count all Support Requests
  limit parameter with count is meaningless, as count return 1 result
* update Base_getSupportRequestInProgress usage
* XXX disable ticket.notify and ticket.requestEvent
* wip script to create Support Request and Event
* search a matching Trade Condition to generate a Support Request
* update ComputeNode_checkState to use new scripts
* test ComputeNode_checkSoftwareInstallationState
* deliver outgoing events
* test InstanceTree_checkSoftwareInstanceState
* Project_createSupportRequestWithCausality already checks if Support Request exists
* no need to check twice the object portal type
* test SupportRequest_updateMonitoringState
* activate one more alarm
* revert  Send Mail on pending tickets
  nexedi/slapos.core!417
  Virtual Master's manager are responsible to handle the tickets through their worklist.
  Not user.
  Virtual Master's manager can send email from the Ticket to directly ping a user.
* drop ticket_slap_interface_workflow
* test ComputeNode_hasContactedRecently
  Do not check if there is a packing list. It is unrelated to the contact.
* Base_getOpenRelatedTicketList was dropped
* ComputeNode_checkAndUpdateAllocationScope was dropped
* test: simplify
* set comment in the event workflow history
* send Mail Message
* unify event creation
  Reuse Ticket_createProjectEvent
* do not pass a empty list of node_uid
* no need to manually handle the notification message
* create the Regularisation Request from a Trade Condition instead of a template
* use notification message title instead of the ticket title
* use Entity_hasOutstandingAmount
  Entity_getOutstandingAmount is meaningless in case of multiple source_section and multiple currencies.
  Entity_hasOutstandingAmount will only report True or False.
* test RegularisationRequest_invalidateIfPersonBalanceIsOk
* test RegularisationRequest_checkToTriggerNextEscalationStep
* test RegularisationRequest_triggerStopReminderEscalation
* test RegularisationRequest_triggerStopAcknowledgmentEscalation
* test RegularisationRequest_triggerDeleteReminderEscalation
* test RegularisationRequest_stopInstanceTreeList
* test RegularisationRequest_deleteInstanceTreeList
* fixup RegularisationRequest_checkToSendUniqEvent tests
* fixup RegularisationRequest_checkToTriggerNextEscalationStep tests
* fixup InstanceTree_stopFromRegularisationRequest tests
* fixup InstanceTree_deleteFromRegularisationRequest tests
* drop slapos_crm_regularisation_request_template
* drop slapos_crm_web_message_template
* drop preferred_web_message_template_property
* drop slapos_ticket_trade_condition
* drop update_destination_for_slapos
* drop allocation_tester
* drop template_software_installation
* drop template_instance_tree
* drop template_member
* test: fixup person title
* test: fixup: ensure tickets can be created
* test: fixup creation of instance tree
* test: fixup instance tree creation
* test: ComputeNode_getTicketRelatedList was dropped
* test: rss feed will be used by virtual manager production
* test: ticket.approveRegistration was dropped
* ExactMatch
parent d9981cfd
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_jio_action</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_jio_action</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>slapos_user_pending_ticket_report</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>View</string>
</tuple>
</value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>50.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Send Pending Ticket Report</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}/Person_viewSlapOSPendingTicketDialog</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_jio_action</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_jio_action</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>update_destination_for_slapos</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>5.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Update Destination with all Slapos Users</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}/SiteMessage_setSlapOSUserSourceAndDestinatationList</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>python: object.getSimulationState() in (\'draft\',)</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Person" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_View_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>__translation_dict</string> </key>
<value>
<dictionary/>
</value>
</item>
<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>default_reference</string> </key>
<value> <string>allocation_tester</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>first_name</string> </key>
<value> <string>Member</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>allocation_tester</string> </value>
</item>
<item>
<key> <string>last_name</string> </key>
<value> <string>Template</string> </value>
</item>
<item>
<key> <string>password</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Person</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Allocation tester</string> </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>
<record id="5" aka="AAAAAAAAAAU=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>default</string> </key>
<value> <string>{SSHA}f1gAG3A53rfwjkLB/+Ex89MtocZz/4V9K4TZ</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -10,13 +10,17 @@ ...@@ -10,13 +10,17 @@
<key> <string>active_sense_method_id</string> </key> <key> <string>active_sense_method_id</string> </key>
<value> <string>Alarm_checkComputeNodeState</string> </value> <value> <string>Alarm_checkComputeNodeState</string> </value>
</item> </item>
<item>
<key> <string>automatic_solve</string> </key>
<value> <int>0</int> </value>
</item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
<value> <string>Check if a public or a friend compute_node contacted master recently and create a ticket if the compute_node stops to contact master after some time.</string> </value> <value> <string>Check if a public or a friend compute_node contacted master recently and create a ticket if the compute_node stops to contact master after some time.</string> </value>
</item> </item>
<item> <item>
<key> <string>enabled</string> </key> <key> <string>enabled</string> </key>
<value> <int>0</int> </value> <value> <int>1</int> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
</item> </item>
<item> <item>
<key> <string>enabled</string> </key> <key> <string>enabled</string> </key>
<value> <int>0</int> </value> <value> <int>1</int> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
</item> </item>
<item> <item>
<key> <string>enabled</string> </key> <key> <string>enabled</string> </key>
<value> <int>0</int> </value> <value> <int>1</int> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Alarm" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>active_sense_method_id</string> </key>
<value> <string>Alarm_sendPendingTicketReminder</string> </value>
</item>
<item>
<key> <string>automatic_solve</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Send a Mail Message with a Reminder in case the user has Tickets to respond</string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>slapos_crm_send_pending_ticket_reminder</string> </value>
</item>
<item>
<key> <string>periodicity_hour</string> </key>
<value>
<tuple>
<int>6</int>
</tuple>
</value>
</item>
<item>
<key> <string>periodicity_hour_frequency</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>periodicity_minute</string> </key>
<value>
<tuple>
<int>0</int>
</tuple>
</value>
</item>
<item>
<key> <string>periodicity_minute_frequency</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>periodicity_month</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_month_day</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_start_date</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="DateTime" module="DateTime.DateTime"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<tuple>
<float>1288051200.0</float>
<string>GMT</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>periodicity_week</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_week_day</string> </key>
<value>
<tuple>
<string>Tuesday</string>
</tuple>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Alarm</string> </value>
</item>
<item>
<key> <string>sense_method_id</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Check compute_node\'s state</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Sale Trade Condition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_View_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_identity_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_range_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>source/organisation_module/slapos</string>
<string>source_section/organisation_module/slapos</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>slapos_ticket_trade_condition</string> </value>
</item>
<item>
<key> <string>language</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Sale Trade Condition</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>SlapOS Ticket Trade Condition</string> </value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>001</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>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -5,10 +5,6 @@ ...@@ -5,10 +5,6 @@
</chain> </chain>
<chain> <chain>
<type>Regularisation Request</type> <type>Regularisation Request</type>
<workflow>edit_workflow, pricing_interaction_workflow, ticket_interaction_workflow, ticket_slap_interface_workflow, ticket_workflow</workflow> <workflow>edit_workflow, pricing_interaction_workflow, ticket_interaction_workflow, ticket_workflow</workflow>
</chain>
<chain>
<type>Support Request</type>
<workflow>ticket_slap_interface_workflow</workflow>
</chain> </chain>
</workflow_chain> </workflow_chain>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Standard Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>mode</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>elementary_type/string</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>preferred_regularisation_request_template_property</string> </value>
</item>
<item>
<key> <string>mode</string> </key>
<value> <string>w</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Standard Property</string> </value>
</item>
<item>
<key> <string>preference</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>property_default</string> </key>
<value> <string>python: \'\'</string> </value>
</item>
<item>
<key> <string>write_permission</string> </key>
<value> <string>Manage properties</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Standard Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>mode</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>elementary_type/string</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>preferred_support_request_template_property</string> </value>
</item>
<item>
<key> <string>mode</string> </key>
<value> <string>w</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Standard Property</string> </value>
</item>
<item>
<key> <string>preference</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>property_default</string> </key>
<value> <string>python: \'\'</string> </value>
</item>
<item>
<key> <string>write_permission</string> </key>
<value> <string>Manage properties</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Standard Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>mode</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>elementary_type/string</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>preferred_web_message_template_property</string> </value>
</item>
<item>
<key> <string>mode</string> </key>
<value> <string>w</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Standard Property</string> </value>
</item>
<item>
<key> <string>preference</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>property_default</string> </key>
<value> <string>python: \'\'</string> </value>
</item>
<item>
<key> <string>write_permission</string> </key>
<value> <string>Manage properties</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -3,24 +3,19 @@ portal = context.getPortalObject() ...@@ -3,24 +3,19 @@ portal = context.getPortalObject()
person_uid_list = [] person_uid_list = []
for (_, brain) in enumerate(portal.portal_simulation.getInventoryList( for (_, brain) in enumerate(portal.portal_simulation.getInventoryList(
simulation_state=('stopped', 'delivered'), simulation_state=('stopped', 'delivered'),
parent_payment_mode_uid = [
portal.portal_categories.payment_mode.payzen.getUid(),
portal.portal_categories.payment_mode.wechat.getUid()],
group_by_mirror_section=True, group_by_mirror_section=True,
portal_type=portal.getPortalAccountingMovementTypeList(), portal_type=portal.getPortalAccountingMovementTypeList(),
node_uid=[x.uid for x in context.Base_getReceivableAccountList()], node_uid=[x.uid for x in context.Base_getReceivableAccountList()] or -1,
grouping_reference=None)): parent__ledger__uid=portal.portal_categories.ledger.automated.getUid(),
grouping_reference=None
)):
payment_request_uid = brain.payment_request_uid section_uid = brain.getDestinationSectionUid(portal_type="Person")
if not payment_request_uid:
payment_request_uid = brain.getObject().getExplanationUid()
payment_request = portal.portal_catalog.getObject(uid=payment_request_uid)
section_uid = payment_request.getDestinationSectionUid(portal_type="Person")
if section_uid is not None: if section_uid is not None:
person_uid_list.append(section_uid) person_uid_list.append(section_uid)
portal.portal_catalog.searchAndActivate( if person_uid_list:
portal.portal_catalog.searchAndActivate(
portal_type="Person", portal_type="Person",
validation_state="validated", validation_state="validated",
uid=person_uid_list, uid=person_uid_list,
......
...@@ -3,7 +3,7 @@ sub_tag = "RegularisationRequest_stopInstanceTreeList" ...@@ -3,7 +3,7 @@ sub_tag = "RegularisationRequest_stopInstanceTreeList"
portal.portal_catalog.searchAndActivate( portal.portal_catalog.searchAndActivate(
portal_type="Regularisation Request", portal_type="Regularisation Request",
simulation_state=["suspended"], simulation_state=["suspended"],
default_resource_uid=[ resource__uid=[
portal.service_module.slapos_crm_stop_acknowledgement.getUid(), portal.service_module.slapos_crm_stop_acknowledgement.getUid(),
portal.service_module.slapos_crm_delete_reminder.getUid(), portal.service_module.slapos_crm_delete_reminder.getUid(),
portal.service_module.slapos_crm_delete_acknowledgement.getUid(), portal.service_module.slapos_crm_delete_acknowledgement.getUid(),
......
...@@ -2,7 +2,7 @@ portal = context.getPortalObject() ...@@ -2,7 +2,7 @@ portal = context.getPortalObject()
portal.portal_catalog.searchAndActivate( portal.portal_catalog.searchAndActivate(
portal_type="Regularisation Request", portal_type="Regularisation Request",
simulation_state=["suspended"], simulation_state=["suspended"],
default_resource_uid=portal.service_module.slapos_crm_acknowledgement.getUid(), resource__uid=portal.service_module.slapos_crm_acknowledgement.getUid(),
method_id='RegularisationRequest_triggerAcknowledgmentEscalation', method_id='RegularisationRequest_triggerAcknowledgmentEscalation',
activate_kw={'tag': tag} activate_kw={'tag': tag}
) )
......
...@@ -2,7 +2,7 @@ portal = context.getPortalObject() ...@@ -2,7 +2,7 @@ portal = context.getPortalObject()
portal.portal_catalog.searchAndActivate( portal.portal_catalog.searchAndActivate(
portal_type="Regularisation Request", portal_type="Regularisation Request",
simulation_state=["suspended"], simulation_state=["suspended"],
default_resource_uid=portal.service_module.slapos_crm_stop_reminder.getUid(), resource__uid=portal.service_module.slapos_crm_stop_reminder.getUid(),
method_id='RegularisationRequest_triggerStopReminderEscalation', method_id='RegularisationRequest_triggerStopReminderEscalation',
activate_kw={'tag': tag} activate_kw={'tag': tag}
) )
......
...@@ -15,7 +15,8 @@ if (slap_state in ['start_requested', 'stop_requested']): ...@@ -15,7 +15,8 @@ if (slap_state in ['start_requested', 'stop_requested']):
software_type=instance_tree.getSourceReference(), software_type=instance_tree.getSourceReference(),
instance_xml=instance_tree.getTextContent(), instance_xml=instance_tree.getTextContent(),
sla_xml=instance_tree.getSlaXml(), sla_xml=instance_tree.getSlaXml(),
shared=instance_tree.isRootSlave() shared=instance_tree.isRootSlave(),
project_reference=instance_tree.getFollowUpReference()
) )
return True return True
return False return False
...@@ -15,7 +15,8 @@ if (slap_state == 'start_requested'): ...@@ -15,7 +15,8 @@ if (slap_state == 'start_requested'):
software_type=instance_tree.getSourceReference(), software_type=instance_tree.getSourceReference(),
instance_xml=instance_tree.getTextContent(), instance_xml=instance_tree.getTextContent(),
sla_xml=instance_tree.getSlaXml(), sla_xml=instance_tree.getSlaXml(),
shared=instance_tree.isRootSlave() shared=instance_tree.isRootSlave(),
project_reference=instance_tree.getFollowUpReference()
) )
return True return True
return False return False
...@@ -16,27 +16,15 @@ ticket_portal_type = "Regularisation Request" ...@@ -16,27 +16,15 @@ ticket_portal_type = "Regularisation Request"
ticket = portal.portal_catalog.getResultValue( ticket = portal.portal_catalog.getResultValue(
portal_type=ticket_portal_type, portal_type=ticket_portal_type,
default_destination_uid=person.getUid(), destination__uid=person.getUid(),
simulation_state=['suspended', 'validated'], simulation_state=['suspended', 'validated'],
) )
if ticket is not None: if ticket is not None:
return ticket, None return ticket, None
outstanding_amount = person.Entity_statSlapOSOutstandingAmount() mail_message = None
if person.Entity_hasOutstandingAmount():
# Amount to be ignored, as it comes from the first invoice generated
# after the subscription. We do not take it into account as no service
# was provided yet.
unpaid_invoice_amount = 0
for invoice in person.Person_getSubscriptionRequestFirstUnpaidInvoiceList():
unpaid_invoice_amount += invoice.getTotalPrice()
# It can't be smaller, we are considernig all open invoices are from unpaid_payment_amount
if round(float(outstanding_amount), 2) == round(float(unpaid_invoice_amount), 2):
return ticket, None
if int(outstanding_amount) > 0:
tag = "%s_addRegularisationRequest_inProgress" % person.getUid() tag = "%s_addRegularisationRequest_inProgress" % person.getUid()
if (portal.portal_activities.countMessageWithTag(tag) > 0): if (portal.portal_activities.countMessageWithTag(tag) > 0):
# The regularisation request is already under creation but can not be fetched from catalog # The regularisation request is already under creation but can not be fetched from catalog
...@@ -47,28 +35,18 @@ if int(outstanding_amount) > 0: ...@@ -47,28 +35,18 @@ if int(outstanding_amount) > 0:
person.serialize() person.serialize()
# Time to create the ticket # Time to create the ticket
regularisation_request_template = portal.restrictedTraverse( comment = 'New automatic ticket for %s' % context.getTitle()
portal.portal_preferences.getPreferredRegularisationRequestTemplate()) ticket = context.Entity_createTicketFromTradeCondition(
ticket = regularisation_request_template.Base_createCloneDocument(batch_mode=1) portal.service_module.slapos_crm_monitoring.getRelativeUrl(),
ticket.edit( 'Account regularisation expected for "%s"' % context.getTitle(),
title='Account regularisation expected for "%s"' % context.getTitle(), '',
destination_decision_value=context, portal_type='Regularisation Request',
destination_value=context, comment=comment
start_date=DateTime(),
resource=portal.portal_preferences.getPreferredRegularisationRequestResource(),
) )
ticket.validate(comment='New automatic ticket for %s' % context.getTitle()) ticket.suspend(comment=comment)
ticket.suspend(comment='New automatic ticket for %s' % context.getTitle())
ticket.reindexObject(activate_kw={'tag': tag}) ticket.reindexObject(activate_kw={'tag': tag})
# Notify using user's language
language = context.getLanguage("en")
notification_message = context.getPortalObject().portal_notifications.getDocumentValue(
reference="slapos-crm.create.regularisation.request",
language=language)
if notification_message is None:
subject = 'Invoice payment requested' subject = 'Invoice payment requested'
body = """Dear %s, body = """Dear %s,
...@@ -78,27 +56,17 @@ You can access it in your invoice section at %s. ...@@ -78,27 +56,17 @@ You can access it in your invoice section at %s.
Regards, Regards,
The slapos team The slapos team
""" % (context.getTitle(), portal.portal_preferences.getPreferredSlaposWebSiteUrl()) """ % (context.getTitle(), portal.portal_preferences.getPreferredSlaposWebSiteUrl())
notification_message_reference = "slapos-crm.create.regularisation.request"
else:
notification_mapping_dict = {
'user_name': context.getTitle()}
subject = notification_message.getTitle()
# Preserve HTML else convert to text
if notification_message.getContentType() == "text/html":
body = notification_message.asEntireHTML(
substitution_method_parameter_dict={'mapping_dict':notification_mapping_dict})
else:
body = notification_message.asText(
substitution_method_parameter_dict={'mapping_dict':notification_mapping_dict})
mail_message = ticket.RegularisationRequest_checkToSendUniqEvent( mail_message = ticket.RegularisationRequest_checkToSendUniqEvent(
portal.portal_preferences.getPreferredRegularisationRequestResource(), portal.portal_preferences.getPreferredRegularisationRequestResource(),
subject, subject,
body, body,
'Requested manual payment.') 'Requested manual payment.',
notification_message=notification_message_reference,
return ticket, mail_message substitution_method_parameter_dict={
'user_name': context.getTitle()
},
)
return ticket, None return ticket, mail_message
portal = context.getPortalObject()
from erp5.component.module.DateUtils import addToDate
from Products.ZSQLCatalog.SQLCatalog import Query
from DateTime import DateTime
unpaid_list = []
subscription_request_list = portal.portal_catalog(
portal_type="Subscription Request",
simulation_state=["ordered", "confirmed"],
default_destination_section_uid=context.getUid(),
# Select "Subscription Request" with most likely unpaid invoices, recently generated.
creation_date=Query(creation_date=addToDate(DateTime(), to_add={'day': -20}), range="min"))
for subscription_request in subscription_request_list:
first_invoice = subscription_request.SubscriptionRequest_verifyPaymentBalanceIsReady()
if first_invoice is not None and not first_invoice.SaleInvoiceTransaction_isLettered():
unpaid_list.append(first_invoice)
return unpaid_list
...@@ -18,8 +18,8 @@ event_portal_type = "Mail Message" ...@@ -18,8 +18,8 @@ event_portal_type = "Mail Message"
event = portal.portal_catalog.getResultValue( event = portal.portal_catalog.getResultValue(
portal_type=event_portal_type, portal_type=event_portal_type,
default_resource_uid=service.getUid(), resource__uid=service.getUid(),
default_follow_up_uid=ticket.getUid(), follow_up__uid=ticket.getUid(),
) )
if (event is None) and (ticket.getSimulationState() == 'suspended'): if (event is None) and (ticket.getSimulationState() == 'suspended'):
...@@ -31,21 +31,15 @@ if (event is None) and (ticket.getSimulationState() == 'suspended'): ...@@ -31,21 +31,15 @@ if (event is None) and (ticket.getSimulationState() == 'suspended'):
# Prevent concurrent transaction to create 2 events for the same ticket # Prevent concurrent transaction to create 2 events for the same ticket
ticket.edit(resource=service_relative_url) ticket.edit(resource=service_relative_url)
event = portal.event_module.newContent( event = ticket.Ticket_createProjectEvent(
portal_type=event_portal_type, title, 'outgoing', 'Mail Message',
start_date=DateTime(), service_relative_url,
destination=ticket.getDestination(),
follow_up=ticket.getRelativeUrl(),
source=context.getSource(),
title=title,
resource=service_relative_url,
text_content=text_content, text_content=text_content,
source_project_value=ticket.getSourceProjectValue(), content_type='text/plain',
notification_message=notification_message,
substitution_method_parameter_dict=substitution_method_parameter_dict,
comment=comment
) )
event.start(send_mail=True, comment=comment)
event.stop(comment=comment)
event.deliver(comment=comment)
event.reindexObject(activate_kw={'tag': tag}) event.reindexObject(activate_kw={'tag': tag})
return event return event
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>service_relative_url, title, text_content, comment, REQUEST=None</string> </value> <value> <string>service_relative_url, title, text_content, comment, notification_message=None, substitution_method_parameter_dict=None, REQUEST=None</string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
...@@ -11,14 +11,16 @@ event_portal_type = "Mail Message" ...@@ -11,14 +11,16 @@ event_portal_type = "Mail Message"
event = portal.portal_catalog.getResultValue( event = portal.portal_catalog.getResultValue(
portal_type=event_portal_type, portal_type=event_portal_type,
default_resource_uid=current_service.getUid(), resource__uid=current_service.getUid(),
default_follow_up_uid=ticket.getUid(), follow_up__uid=ticket.getUid(),
simulation_state="delivered", simulation_state="delivered",
) )
if (ticket.getSimulationState() == 'suspended') and (event is not None) and (ticket.getResource() == current_service_relative_url): if (ticket.getSimulationState() == 'suspended') and (event is not None) and (ticket.getResource() == current_service_relative_url):
if (DateTime() - event.getStartDate()) > delay_period_in_days: if (DateTime() - event.getStartDate()) > delay_period_in_days:
ticket.RegularisationRequest_checkToSendUniqEvent(next_service_relative_url, title, text_content, comment) ticket.RegularisationRequest_checkToSendUniqEvent(next_service_relative_url, title, text_content, comment,
notification_message=notification_message,
substitution_method_parameter_dict=substitution_method_parameter_dict)
return event.getRelativeUrl() return event.getRelativeUrl()
return None return None
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>delay_period_in_days, current_service_relative_url, next_service_relative_url, title, text_content, comment, REQUEST=None</string> </value> <value> <string>delay_period_in_days, current_service_relative_url, next_service_relative_url, title, text_content, comment, notification_message=None, substitution_method_parameter_dict=None, REQUEST=None</string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
...@@ -13,7 +13,7 @@ if (state == 'suspended') and \ ...@@ -13,7 +13,7 @@ if (state == 'suspended') and \
portal.portal_catalog.searchAndActivate( portal.portal_catalog.searchAndActivate(
portal_type="Instance Tree", portal_type="Instance Tree",
validation_state=["validated"], validation_state=["validated"],
default_destination_section_uid=person.getUid(), destination_section__uid=person.getUid(),
method_id='InstanceTree_deleteFromRegularisationRequest', method_id='InstanceTree_deleteFromRegularisationRequest',
method_args=(person.getRelativeUrl(),), method_args=(person.getRelativeUrl(),),
activate_kw={'tag': tag} activate_kw={'tag': tag}
......
...@@ -8,21 +8,5 @@ if (state not in ('suspended', 'validated')) or \ ...@@ -8,21 +8,5 @@ if (state not in ('suspended', 'validated')) or \
(person is None): (person is None):
return return
outstanding_amount = person.Entity_statSlapOSOutstandingAmount() if not person.Entity_hasOutstandingAmount():
context.invalidate(comment="Automatically disabled as balance is ok")
# Amount to be ignored, as it comes from the first invoice generated
# after the subscription. We do not take it into account as no service
# was provided yet.
unpaid_invoice_amount = 0
for invoice in person.Person_getSubscriptionRequestFirstUnpaidInvoiceList():
unpaid_invoice_amount += invoice.getTotalPrice()
# It can't be smaller, we are considernig all open invoices are from unpaid_payment_amount
if round(float(outstanding_amount), 2) == round(float(unpaid_invoice_amount), 2):
context.invalidate(comment="Automatically disabled as balance is %s" % outstanding_amount)
return
if (int(outstanding_amount) > 0):
return
context.invalidate(comment="Automatically disabled as balance is %s" % outstanding_amount)
...@@ -13,7 +13,7 @@ if (state == 'suspended') and \ ...@@ -13,7 +13,7 @@ if (state == 'suspended') and \
portal.portal_catalog.searchAndActivate( portal.portal_catalog.searchAndActivate(
portal_type="Instance Tree", portal_type="Instance Tree",
validation_state=["validated"], validation_state=["validated"],
default_destination_section_uid=person.getUid(), destination_section__uid=person.getUid(),
method_id='InstanceTree_stopFromRegularisationRequest', method_id='InstanceTree_stopFromRegularisationRequest',
method_args=(person.getRelativeUrl(),), method_args=(person.getRelativeUrl(),),
activate_kw={'tag': tag} activate_kw={'tag': tag}
......
...@@ -2,19 +2,10 @@ from zExceptions import Unauthorized ...@@ -2,19 +2,10 @@ from zExceptions import Unauthorized
if REQUEST is not None: if REQUEST is not None:
raise Unauthorized raise Unauthorized
portal = context.getPortalObject()
ndays = 15 ndays = 15
language = "en"
recipient = context.getDestinationSectionValue()
if recipient is not None:
language = recipient.getLanguage("en")
notification_message = portal.portal_notifications.getDocumentValue( subject = 'Reminder: invoice payment requested'
language=language, reference="slapos-crm.acknowledgment.escalation") body = """Dear user,
if notification_message is None:
subject = 'Reminder: invoice payment requested'
body = """Dear user,
We would like to remind you the unpaid invoice you have on %s. We would like to remind you the unpaid invoice you have on %s.
If no payment is done during the coming days, we will stop all your current instances to free some hardware resources. If no payment is done during the coming days, we will stop all your current instances to free some hardware resources.
...@@ -23,21 +14,6 @@ Regards, ...@@ -23,21 +14,6 @@ Regards,
The slapos team The slapos team
""" % context.getPortalObject().portal_preferences.getPreferredSlaposWebSiteUrl() """ % context.getPortalObject().portal_preferences.getPreferredSlaposWebSiteUrl()
else:
notification_mapping_dict = {
'user_name': context.getDestinationSectionTitle(),
'days': ndays}
subject = notification_message.getTitle()
# Preserve HTML else convert to text
if notification_message.getContentType() == "text/html":
body = notification_message.asEntireHTML(
substitution_method_parameter_dict={'mapping_dict':notification_mapping_dict})
else:
body = notification_message.asText(
substitution_method_parameter_dict={'mapping_dict':notification_mapping_dict})
return context.RegularisationRequest_checkToTriggerNextEscalationStep( return context.RegularisationRequest_checkToTriggerNextEscalationStep(
delay_period_in_days=ndays, delay_period_in_days=ndays,
current_service_relative_url='service_module/slapos_crm_acknowledgement', current_service_relative_url='service_module/slapos_crm_acknowledgement',
...@@ -45,4 +21,9 @@ return context.RegularisationRequest_checkToTriggerNextEscalationStep( ...@@ -45,4 +21,9 @@ return context.RegularisationRequest_checkToTriggerNextEscalationStep(
title=subject, title=subject,
text_content=body, text_content=body,
comment='Stopping reminder.', comment='Stopping reminder.',
notification_message="slapos-crm.acknowledgment.escalation",
substitution_method_parameter_dict={
'user_name': context.getDestinationSectionTitle(),
'days': ndays
}
) )
...@@ -2,19 +2,10 @@ from zExceptions import Unauthorized ...@@ -2,19 +2,10 @@ from zExceptions import Unauthorized
if REQUEST is not None: if REQUEST is not None:
raise Unauthorized raise Unauthorized
portal = context.getPortalObject()
ndays = 10 ndays = 10
language = "en"
recipient = context.getDestinationSectionValue()
if recipient is not None:
language = recipient.getLanguage("en")
notification_message = portal.portal_notifications.getDocumentValue( subject = 'Acknowledgment: instances deleted'
language=language, reference="slapos-crm.delete.reminder.escalation") body = """Dear user,
if notification_message is None:
subject = 'Acknowledgment: instances deleted'
body = """Dear user,
Despite our last reminder, you still have an unpaid invoice on %s. Despite our last reminder, you still have an unpaid invoice on %s.
We will now delete all your instances. We will now delete all your instances.
...@@ -22,20 +13,6 @@ We will now delete all your instances. ...@@ -22,20 +13,6 @@ We will now delete all your instances.
Regards, Regards,
The slapos team The slapos team
""" % context.getPortalObject().portal_preferences.getPreferredSlaposWebSiteUrl() """ % context.getPortalObject().portal_preferences.getPreferredSlaposWebSiteUrl()
else:
notification_mapping_dict = {
'user_name': context.getDestinationSectionTitle(),
'days': ndays}
subject = notification_message.getTitle()
# Preserve HTML else convert to text
if notification_message.getContentType() == "text/html":
body = notification_message.asEntireHTML(
substitution_method_parameter_dict={'mapping_dict':notification_mapping_dict})
else:
body = notification_message.asText(
substitution_method_parameter_dict={'mapping_dict':notification_mapping_dict})
return context.RegularisationRequest_checkToTriggerNextEscalationStep( return context.RegularisationRequest_checkToTriggerNextEscalationStep(
delay_period_in_days=ndays, delay_period_in_days=ndays,
...@@ -44,4 +21,9 @@ return context.RegularisationRequest_checkToTriggerNextEscalationStep( ...@@ -44,4 +21,9 @@ return context.RegularisationRequest_checkToTriggerNextEscalationStep(
title=subject, title=subject,
text_content=body, text_content=body,
comment='Deleting acknowledgment.', comment='Deleting acknowledgment.',
notification_message="slapos-crm.delete.reminder.escalation",
substitution_method_parameter_dict={
'user_name': context.getDestinationSectionTitle(),
'days': ndays
}
) )
...@@ -2,19 +2,9 @@ from zExceptions import Unauthorized ...@@ -2,19 +2,9 @@ from zExceptions import Unauthorized
if REQUEST is not None: if REQUEST is not None:
raise Unauthorized raise Unauthorized
portal = context.getPortalObject()
ndays = 7 ndays = 7
language = "en" subject = 'Last reminder: invoice payment requested'
recipient = context.getDestinationSectionValue() body = """Dear user,
if recipient is not None:
language = recipient.getLanguage("en")
notification_message = portal.portal_notifications.getDocumentValue(
language=language, reference="slapos-crm.stop.acknowledgment.escalation")
if notification_message is None:
subject = 'Last reminder: invoice payment requested'
body = """Dear user,
We would like to remind you the unpaid invoice you have on %s. We would like to remind you the unpaid invoice you have on %s.
If no payment is done during the coming days, we will delete all your instances. If no payment is done during the coming days, we will delete all your instances.
...@@ -22,20 +12,6 @@ If no payment is done during the coming days, we will delete all your instances. ...@@ -22,20 +12,6 @@ If no payment is done during the coming days, we will delete all your instances.
Regards, Regards,
The slapos team The slapos team
""" % context.getPortalObject().portal_preferences.getPreferredSlaposWebSiteUrl() """ % context.getPortalObject().portal_preferences.getPreferredSlaposWebSiteUrl()
else:
notification_mapping_dict = {
'user_name': context.getDestinationSectionTitle(),
'days': ndays}
subject = notification_message.getTitle()
# Preserve HTML else convert to text
if notification_message.getContentType() == "text/html":
body = notification_message.asEntireHTML(
substitution_method_parameter_dict={'mapping_dict':notification_mapping_dict})
else:
body = notification_message.asText(
substitution_method_parameter_dict={'mapping_dict':notification_mapping_dict})
return context.RegularisationRequest_checkToTriggerNextEscalationStep( return context.RegularisationRequest_checkToTriggerNextEscalationStep(
delay_period_in_days=ndays, delay_period_in_days=ndays,
...@@ -44,4 +20,9 @@ return context.RegularisationRequest_checkToTriggerNextEscalationStep( ...@@ -44,4 +20,9 @@ return context.RegularisationRequest_checkToTriggerNextEscalationStep(
title=subject, title=subject,
text_content=body, text_content=body,
comment='Deleting reminder.', comment='Deleting reminder.',
notification_message="slapos-crm.stop.acknowledgment.escalation",
substitution_method_parameter_dict={
'user_name': context.getDestinationSectionTitle(),
'days': ndays
}
) )
...@@ -2,19 +2,10 @@ from zExceptions import Unauthorized ...@@ -2,19 +2,10 @@ from zExceptions import Unauthorized
if REQUEST is not None: if REQUEST is not None:
raise Unauthorized raise Unauthorized
portal = context.getPortalObject()
ndays = 7 ndays = 7
language = "en"
recipient = context.getDestinationSectionValue()
if recipient is not None:
language = recipient.getLanguage("en")
notification_message = portal.portal_notifications.getDocumentValue( subject = 'Acknowledgment: instances stopped'
language=language, reference="slapos-crm.stop.reminder.escalation") body = """Dear user,
if notification_message is None:
subject = 'Acknowledgment: instances stopped'
body = """Dear user,
Despite our last reminder, you still have an unpaid invoice on %s. Despite our last reminder, you still have an unpaid invoice on %s.
We will now stop all your current instances to free some hardware resources. We will now stop all your current instances to free some hardware resources.
...@@ -22,20 +13,6 @@ We will now stop all your current instances to free some hardware resources. ...@@ -22,20 +13,6 @@ We will now stop all your current instances to free some hardware resources.
Regards, Regards,
The slapos team The slapos team
""" % context.getPortalObject().portal_preferences.getPreferredSlaposWebSiteUrl() """ % context.getPortalObject().portal_preferences.getPreferredSlaposWebSiteUrl()
else:
notification_mapping_dict = {
'user_name': context.getDestinationSectionTitle(),
'days': ndays}
subject = notification_message.getTitle()
# Preserve HTML else convert to text
if notification_message.getContentType() == "text/html":
body = notification_message.asEntireHTML(
substitution_method_parameter_dict={'mapping_dict':notification_mapping_dict})
else:
body = notification_message.asText(
substitution_method_parameter_dict={'mapping_dict':notification_mapping_dict})
return context.RegularisationRequest_checkToTriggerNextEscalationStep( return context.RegularisationRequest_checkToTriggerNextEscalationStep(
delay_period_in_days=ndays, delay_period_in_days=ndays,
...@@ -44,4 +21,9 @@ return context.RegularisationRequest_checkToTriggerNextEscalationStep( ...@@ -44,4 +21,9 @@ return context.RegularisationRequest_checkToTriggerNextEscalationStep(
title=subject, title=subject,
text_content=body, text_content=body,
comment='Stopping acknowledgment.', comment='Stopping acknowledgment.',
notification_message="slapos-crm.stop.reminder.escalation",
substitution_method_parameter_dict={
'user_name': context.getDestinationSectionTitle(),
'days': ndays
}
) )
...@@ -9,11 +9,11 @@ monitor_enabled_category = portal.restrictedTraverse( ...@@ -9,11 +9,11 @@ monitor_enabled_category = portal.restrictedTraverse(
if monitor_enabled_category is not None: if monitor_enabled_category is not None:
portal.portal_catalog.searchAndActivate( portal.portal_catalog.searchAndActivate(
portal_type = 'Compute Node', portal_type='Compute Node',
validation_state = 'validated', validation_state='validated',
default_monitor_scope_uid = monitor_enabled_category.getUid(), monitor_scope__uid=monitor_enabled_category.getUid(),
method_id = 'ComputeNode_checkState', method_id='ComputeNode_checkState',
activate_kw = {'tag':tag} activate_kw={'tag':tag}
) )
context.activate(after_tag=tag).getId() context.activate(after_tag=tag).getId()
...@@ -9,11 +9,11 @@ monitor_enabled_category = portal.restrictedTraverse( ...@@ -9,11 +9,11 @@ monitor_enabled_category = portal.restrictedTraverse(
if monitor_enabled_category is not None: if monitor_enabled_category is not None:
portal.portal_catalog.searchAndActivate( portal.portal_catalog.searchAndActivate(
portal_type = 'Compute Node', portal_type='Compute Node',
validation_state = 'validated', validation_state='validated',
default_monitor_scope_uid = monitor_enabled_category.getUid(), monitor_scope__uid=monitor_enabled_category.getUid(),
method_id = 'ComputeNode_checkSoftwareInstallationState', method_id='ComputeNode_checkSoftwareInstallationState',
activate_kw = {'tag':tag} activate_kw={'tag':tag}
) )
context.activate(after_tag=tag).getId() context.activate(after_tag=tag).getId()
portal = context.getPortalObject()
portal.portal_catalog.searchAndActivate(
portal_type = 'Person',
method_id = 'Person_sendPendingTicketReminder',
activate_kw = {'tag':tag}
)
context.activate(after_tag=tag).getId()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>tag, fixit, params</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Alarm_sendPendingTicketReminder</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -4,10 +4,10 @@ default_resource_uid = portal.restrictedTraverse("service_module/slapos_crm_moni ...@@ -4,10 +4,10 @@ default_resource_uid = portal.restrictedTraverse("service_module/slapos_crm_moni
portal.portal_catalog.searchAndActivate( portal.portal_catalog.searchAndActivate(
portal_type='Support Request', portal_type='Support Request',
simulation_state=['validated', 'suspended'], simulation_state=['validated', 'suspended'],
default_resource_uid=default_resource_uid, resource__uid=default_resource_uid,
default_aggregate_portal_type=["Instance Tree"], aggregate__portal_type=["Instance Tree"],
method_id='SupportRequest_updateMonitoringState', method_id='SupportRequest_updateMonitoringState',
activate_kw = {'tag':tag} activate_kw={'tag':tag}
) )
context.activate(after_tag=tag).getId() context.activate(after_tag=tag).getId()
from DateTime import DateTime from DateTime import DateTime
portal = context.getPortalObject() portal = context.getPortalObject()
if context.getMonitorScope() == "disabled" or \ if (context.getMonitorScope() == "disabled") or \
portal.ERP5Site_isSupportRequestCreationClosed(): portal.ERP5Site_isSupportRequestCreationClosed():
return return
software_installation_list = portal.portal_catalog( software_installation_list = portal.portal_catalog(
portal_type='Software Installation', portal_type='Software Installation',
default_aggregate_uid=context.getUid(), aggregate__uid=context.getUid(),
validation_state='validated', validation_state='validated',
sort_on=(('creation_date', 'DESC'),) sort_on=(('creation_date', 'DESC'),)
) )
...@@ -24,15 +24,20 @@ for software_installation in software_installation_list: ...@@ -24,15 +24,20 @@ for software_installation in software_installation_list:
# Give it 12 hours to deploy. # Give it 12 hours to deploy.
continue continue
if software_installation.getSlapState() != 'start_requested':
continue
reference = software_installation.getReference() reference = software_installation.getReference()
d = software_installation.getAccessStatus() d = software_installation.getAccessStatus()
if d.get("no_data", None) == 1: if d.get("no_data", None) == 1:
should_notify = True
last_contact = "No Contact Information"
ticket_title = "[MONITORING] No information for %s on %s" % (reference, compute_node_reference) ticket_title = "[MONITORING] No information for %s on %s" % (reference, compute_node_reference)
description = "The software release %s did not started to build on %s since %s" % \ description = "The software release %s did not started to build on %s since %s" % \
(software_installation.getUrlString(), compute_node_title, software_installation.getCreationDate()) (software_installation.getUrlString(), compute_node_title, software_installation.getCreationDate())
else: else:
last_contact = DateTime(d.get('created_at')) last_contact = DateTime(d.get('created_at'))
if d.get("text").startswith("building"): if d.get("text").startswith("#building"):
should_notify = True should_notify = True
ticket_title = "[MONITORING] %s is building for too long on %s" % (reference, compute_node_reference) ticket_title = "[MONITORING] %s is building for too long on %s" % (reference, compute_node_reference)
description = "The software release %s is building for mode them 12 hours on %s, started on %s" % \ description = "The software release %s is building for mode them 12 hours on %s, started on %s" % \
...@@ -48,42 +53,33 @@ for software_installation in software_installation_list: ...@@ -48,42 +53,33 @@ for software_installation in software_installation_list:
if should_notify: if should_notify:
support_request = person.Base_getSupportRequestInProgress( project = context.getFollowUpValue()
title=ticket_title, support_request = project.Project_createSupportRequestWithCausality(
aggregate=context.getRelativeUrl()) ticket_title,
description,
if support_request is None: causality=context.getRelativeUrl(),
person.notify(support_request_title=ticket_title, destination_decision=project.getDestination()
support_request_description=description, )
aggregate=context.getRelativeUrl())
support_request_relative_url = context.REQUEST.get("support_request_relative_url")
if support_request_relative_url is None:
return
support_request = portal.restrictedTraverse(support_request_relative_url)
if support_request is None: if support_request is None:
return return
# Send Notification message notification_message_reference = 'slapos-crm-compute_node_software_installation_state.notification'
notification_reference = 'slapos-crm-compute_node_software_installation_state.notification'
notification_message = portal.portal_notifications.getDocumentValue(
reference=notification_reference)
if notification_message is None:
message = """%s""" % description
else:
mapping_dict = {'compute_node_title':context.getTitle(),
'compute_node_id':reference,
'last_contact':last_contact}
message = notification_message.asText(
substitution_method_parameter_dict={'mapping_dict':mapping_dict})
event = support_request.SupportRequest_getLastEvent(ticket_title) event = support_request.SupportRequest_getLastEvent(ticket_title)
if event is None: if event is None:
support_request.notify(message_title=ticket_title, message=message) support_request.Ticket_createProjectEvent(
ticket_title, 'outgoing', 'Web Message',
portal.service_module.slapos_crm_information.getRelativeUrl(),
text_content=description,
content_type='text/plain',
notification_message=notification_message_reference,
#language=XXX,
substitution_method_parameter_dict={
'compute_node_title':context.getTitle(),
'compute_node_id':reference,
'last_contact':last_contact
}
)
support_request_list.append(support_request) support_request_list.append(support_request)
......
from DateTime import DateTime from DateTime import DateTime
portal = context.getPortalObject() portal = context.getPortalObject()
if context.getMonitorScope() == "disabled" or \ if (context.getMonitorScope() == "disabled") or \
portal.ERP5Site_isSupportRequestCreationClosed(): portal.ERP5Site_isSupportRequestCreationClosed():
return return
...@@ -54,7 +54,7 @@ if not should_notify: ...@@ -54,7 +54,7 @@ if not should_notify:
if compute_partition_uid_list: if compute_partition_uid_list:
instance_list = portal.portal_catalog( instance_list = portal.portal_catalog(
portal_type='Software Instance', portal_type='Software Instance',
default_aggregate_uid=compute_partition_uid_list) aggregate__uid=compute_partition_uid_list)
if instance_list: if instance_list:
should_notify = True should_notify = True
...@@ -76,45 +76,36 @@ if not should_notify: ...@@ -76,45 +76,36 @@ if not should_notify:
context.getTitle(), context.getReference(), last_contact) context.getTitle(), context.getReference(), last_contact)
if should_notify: if should_notify:
support_request = person.Base_getSupportRequestInProgress( support_request = context.Base_getSupportRequestInProgress(
title=node_ticket_title, title=node_ticket_title)
aggregate=context.getRelativeUrl())
if support_request is None: if support_request is None:
support_request = person.Base_getSupportRequestInProgress( project = context.getFollowUpValue()
title=ticket_title, support_request = project.Project_createSupportRequestWithCausality(
aggregate=context.getRelativeUrl()) ticket_title,
description,
if support_request is None: causality=context.getRelativeUrl(),
person.notify(support_request_title=ticket_title, destination_decision=project.getDestination()
support_request_description=description, )
aggregate=context.getRelativeUrl())
support_request_relative_url = context.REQUEST.get("support_request_relative_url")
if support_request_relative_url is None:
return
support_request = portal.restrictedTraverse(support_request_relative_url)
if support_request is None: if support_request is None:
return return
# Send Notification message
notification_message = portal.portal_notifications.getDocumentValue(
reference=notification_message_reference)
if notification_message is None:
message = """%s""" % description
else:
mapping_dict = {'compute_node_title':context.getTitle(),
'compute_node_id':reference,
'last_contact':last_contact,
'issue_document_reference': issue_document_reference}
message = notification_message.asText(
substitution_method_parameter_dict={'mapping_dict': mapping_dict})
event = support_request.SupportRequest_getLastEvent(ticket_title) event = support_request.SupportRequest_getLastEvent(ticket_title)
if event is None: if event is None:
support_request.notify(message_title=ticket_title, message=message) support_request.Ticket_createProjectEvent(
ticket_title, 'outgoing', 'Web Message',
portal.service_module.slapos_crm_information.getRelativeUrl(),
text_content=description,
content_type='text/plain',
notification_message=notification_message_reference,
#language=XXX,
substitution_method_parameter_dict={
'compute_node_title':context.getTitle(),
'compute_node_id':reference,
'last_contact':last_contact,
'issue_document_reference': issue_document_reference
}
)
return support_request return support_request
portal = context.getPortalObject()
compute_node = context compute_node = context
now_date = DateTime() now_date = DateTime()
...@@ -15,13 +14,4 @@ if message_dict.has_key('created_at'): ...@@ -15,13 +14,4 @@ if message_dict.has_key('created_at'):
contact_date = DateTime(message_dict.get('created_at').encode('utf-8')) contact_date = DateTime(message_dict.get('created_at').encode('utf-8'))
return (now_date - contact_date) < maximum_days return (now_date - contact_date) < maximum_days
# If no access status information, check in consumption report
for sale_packing_list in portal.portal_catalog(
portal_type="Sale Packing List Line",
simulation_state="delivered",
default_aggregate_uid=compute_node.getUid(),
sort_on=[('movement.start_date', 'DESC')],
limit=1):
return (now_date - sale_packing_list.getStartDate()) < maximum_days
return False return False
...@@ -96,14 +96,17 @@ ...@@ -96,14 +96,17 @@
<key> <string>left</string> </key> <key> <string>left</string> </key>
<value> <value>
<list> <list>
<string>my_monitor_scope</string> <string>my_title</string>
<string>my_reference</string>
</list> </list>
</value> </value>
</item> </item>
<item> <item>
<key> <string>right</string> </key> <key> <string>right</string> </key>
<value> <value>
<list/> <list>
<string>my_monitor_scope</string>
</list>
</value> </value>
</item> </item>
</dictionary> </dictionary>
......
...@@ -2,19 +2,20 @@ from Products.ERP5Type.Cache import CachingMethod ...@@ -2,19 +2,20 @@ from Products.ERP5Type.Cache import CachingMethod
portal = context.getPortalObject() portal = context.getPortalObject()
def isSupportRequestCreationClosed(destination_decision=None): def isSupportRequestCreationClosed(destination_decision=None):
limit = portal.portal_preferences.getPreferredSupportRequestCreationLimit(5) limit = int(portal.portal_preferences.getPreferredSupportRequestCreationLimit(5))
kw = {} kw = {
kw['limit'] = limit 'limit': limit,
kw['portal_type'] = 'Support Request' 'portal_type': 'Support Request',
kw['simulation_state'] = ["validated","submitted"] 'simulation_state': ["validated", "submitted"],
kw['default_resource_uid'] = portal.service_module.slapos_crm_monitoring.getUid() 'resource__uid': portal.service_module.slapos_crm_monitoring.getUid()
}
if destination_decision: if destination_decision:
kw['default_destination_decision_uid'] = context.restrictedTraverse( kw['destination_decision__uid'] = context.restrictedTraverse(
destination_decision).getUid() destination_decision).getUid()
support_request_amount = context.portal_catalog.countResults(**kw)[0][0] support_request_amount_list = context.portal_catalog(**kw)
return support_request_amount >= int(limit) return limit <= len(support_request_amount_list)
return CachingMethod(isSupportRequestCreationClosed, return CachingMethod(isSupportRequestCreationClosed,
......
portal = context.getPortalObject()
destination_decision_value = context
# Create a temp Sale Order to find the trade condition
now = DateTime()
module = portal.portal_trash
tmp_sale_order = module.newContent(
portal_type='Sale Order',
temp_object=True,
trade_condition_type="ticket",
start_date=now,
destination_value=destination_decision_value,
destination_decision_value=destination_decision_value,
source_project=source_project,
ledger_value=portal.portal_categories.ledger.automated
)
tmp_sale_order.SaleOrder_applySaleTradeCondition(batch_mode=1, force=1)
"""
if tmp_sale_order.getSpecialise(None) is None:
raise AssertionError('Can not find a trade condition to generate the Support Request')
"""
resource = portal.restrictedTraverse(resource)
ticket = portal.getDefaultModule(portal_type).newContent(
portal_type=portal_type,
title=title,
description=text_content,
start_date=tmp_sale_order.getStartDate(),
source=tmp_sale_order.getSource(),
source_section=tmp_sale_order.getSourceSection(),
source_project=tmp_sale_order.getSourceProject(),
destination=tmp_sale_order.getDestination(),
destination_section=tmp_sale_order.getDestinationSection(),
destination_project=tmp_sale_order.getDestinationProject(),
destination_decision=tmp_sale_order.getDestinationDecision(),
specialise=tmp_sale_order.getSpecialise(),
causality=causality,
# Ensure resoure is Monitoring
resource_value=resource,
quantity_unit=resource.getQuantityUnit(),
base_contribution_list=resource.getBaseContributionList(),
use=resource.getUse(),
quantity=1,
price=0
)
ticket.validate(comment=comment)
return ticket
...@@ -50,11 +50,11 @@ ...@@ -50,11 +50,11 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string></string> </value> <value> <string>resource, title, text_content, portal_type=\'Support Request\', source_project=None, causality=None, comment=None</string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>Person_getSubscriptionRequestFirstUnpaidInvoiceList</string> </value> <value> <string>Entity_createTicketFromTradeCondition</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -4,10 +4,6 @@ from erp5.component.module.DateUtils import addToDate ...@@ -4,10 +4,6 @@ from erp5.component.module.DateUtils import addToDate
instance_tree = context instance_tree = context
portal = context.getPortalObject() portal = context.getPortalObject()
if instance_tree.getMonitorScope() == "disabled":
# Don't generate ticket if Monitor Scope is marked to disable
return
if portal.ERP5Site_isSupportRequestCreationClosed(): if portal.ERP5Site_isSupportRequestCreationClosed():
# Stop ticket creation # Stop ticket creation
return return
...@@ -20,14 +16,11 @@ if (date_check_limit - instance_tree.getCreationDate()) < 0: ...@@ -20,14 +16,11 @@ if (date_check_limit - instance_tree.getCreationDate()) < 0:
software_instance_list = context.portal_catalog( software_instance_list = context.portal_catalog(
portal_type=["Software Instance", "Slave Instance"], portal_type=["Software Instance", "Slave Instance"],
specialise_uid=instance_tree.getUid(), specialise__uid=instance_tree.getUid(),
**{"slapos_item.slap_state": ["start_requested"]}) **{"slapos_item.slap_state": ["start_requested"]})
has_newest_allocated_instance = False
has_unallocated_instance = False
failing_instance = None
# Check if at least one software Instance is Allocated # Check if at least one software Instance is Allocated
notification_message_reference = None
for instance in software_instance_list: for instance in software_instance_list:
if (date_check_limit - instance.getCreationDate()) < 0: if (date_check_limit - instance.getCreationDate()) < 0:
continue continue
...@@ -36,19 +29,48 @@ for instance in software_instance_list: ...@@ -36,19 +29,48 @@ for instance in software_instance_list:
continue continue
compute_partition = instance.getAggregateValue() compute_partition = instance.getAggregateValue()
if compute_partition is not None: if compute_partition is None:
has_newest_allocated_instance = True notification_message_reference = 'slapos-crm-instance-tree-instance-allocation.notification'
if instance.getPortalType() == "Software Instance" and \ elif (instance.getPortalType() == "Software Instance") and \
compute_partition.getParentValue().getMonitorScope() == "enabled" and \ (compute_partition.getParentValue().getMonitorScope() == "enabled") and \
instance.SoftwareInstance_hasReportedError(tolerance=30): instance.SoftwareInstance_hasReportedError(tolerance=30):
return context.InstanceTree_createSupportRequestEvent(
instance, 'slapos-crm-instance-tree-instance-state.notification') notification_message_reference = 'slapos-crm-instance-tree-instance-state.notification'
if notification_message_reference is not None:
ticket_title = "Instance Tree %s is failing." % context.getTitle()
error_message = instance.SoftwareInstance_hasReportedError(include_message=True)
description = "%s contains software instances which are unallocated or reporting errors." % (
context.getTitle())
if error_message:
description += "\n\nMessage: %s" % str(error_message)
else: else:
has_unallocated_instance = True error_message = "No message!"
failing_instance = instance
if has_unallocated_instance and has_newest_allocated_instance: project = context.getFollowUpValue()
return context.InstanceTree_createSupportRequestEvent( support_request = project.Project_createSupportRequestWithCausality(
failing_instance, 'slapos-crm-instance-tree-instance-allocation.notification') ticket_title,
description,
causality=context.getRelativeUrl(),
destination_decision=context.getDestinationSectionValue()
)
if support_request is None:
return
return event = support_request.SupportRequest_getLastEvent(ticket_title)
if event is None:
support_request.Ticket_createProjectEvent(
ticket_title, 'outgoing', 'Web Message',
portal.service_module.slapos_crm_information.getRelativeUrl(),
text_content=description,
content_type='text/plain',
notification_message=notification_message_reference,
#language=XXX,
substitution_method_parameter_dict={
'instance_tree_title':context.getTitle(),
'instance': instance.getTitle(),
'error_text': error_message
}
)
return
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()
error_message = instance.SoftwareInstance_hasReportedError(include_message=True)
description = "%s contains software instances which are unallocated or reporting errors." % (
context.getTitle())
if error_message:
description += "\n\nMessage: %s" % error_message
else:
error_message = "No message!"
support_request = person.Base_getSupportRequestInProgress(
title=ticket_title,
aggregate=context.getRelativeUrl())
if support_request is None:
person.notify(support_request_title=ticket_title,
support_request_description=description,
aggregate=context.getRelativeUrl())
support_request_relative_url = context.REQUEST.get("support_request_relative_url")
if support_request_relative_url is None:
return
support_request = portal.restrictedTraverse(support_request_relative_url)
if support_request is None:
return
if support_request.getSimulationState() not in ["validated", "suspended"]:
support_request.validate()
# Send Notification message
message = description
notification_message = portal.portal_notifications.getDocumentValue(
reference=notification_message_reference)
if notification_message is not None:
mapping_dict = {'instance_tree_title':context.getTitle(),
'instance': instance.getTitle(),
'error_text': error_message}
message = notification_message.asText(
substitution_method_parameter_dict={'mapping_dict':mapping_dict})
event = support_request.SupportRequest_getLastEvent(ticket_title)
if event is None:
support_request.notify(message_title=ticket_title, message=message)
return context.REQUEST.get("ticket_notified_item")
from Products.ZSQLCatalog.SQLCatalog import ComplexQuery, SimpleQuery
portal = context.getPortalObject()
person_uid = context.getUid()
query = ComplexQuery(
ComplexQuery(
SimpleQuery(portal_type=["Support Request", "Regularisation Request"]),
SimpleQuery(simulation_state="suspended"),
SimpleQuery(destination_decision_uid=person_uid),
logical_operator='and'),
ComplexQuery(
SimpleQuery(portal_type="Upgrade Decision"),
SimpleQuery(simulation_state="confirmed"),
SimpleQuery(destination_decision_uid=person_uid),
logical_operator='and'),
logical_operator='or')
return portal.portal_catalog(query=query, **kw)
portal = context.getPortalObject()
pending_ticket_list_amount = len(context.Person_getSlapOSPendingTicket())
notification_message = portal.portal_notifications.getDocumentValue(
reference="slapos-crm-person-pending-ticket-notification")
if notification_message is not None:
mapping_dict = {'username': context.getTitle(),
'amount': pending_ticket_list_amount,
'website': portal.portal_preferences.getPreferredSlaposWebSiteUrl()}
return notification_message.getTitle(), notification_message.asText(
substitution_method_parameter_dict={'mapping_dict': mapping_dict})
message = """ You have %s pending tickets """ % pending_ticket_list_amount
return message, message
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>Person_getSlapOSPendingTicketMessageTemplate</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
amount = len(context.Person_getSlapOSPendingTicket())
if amount > 0:
title, reminder_message = context.Person_getSlapOSPendingTicketMessageTemplate()
return context.Person_sendSlapOSPendingTicketNotification(
title,
reminder_message,
batch_mode=1
)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>Person_sendPendingTicketReminder</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
portal = context.getPortalObject()
start_date = DateTime()
# Rely on Trade condition (like in ticket to set the proper sender)
trade_condition = portal.sale_trade_condition_module.slapos_ticket_trade_condition
event_kw = {
'portal_type' : "Mail Message",
'title' : response_event_title,
'resource' : "service_module/slapos_crm_information",
'source' : trade_condition.getSource(),
'destination' : context.getRelativeUrl(),
'start_date' : start_date,
'text_content' : response_event_text_content,
'content_type' : 'text/plain',
}
# Create event
event = portal.event_module.newContent(**event_kw)
event.start(send_mail=True, comment="Sent via Person_sendSlapOSPendingTicketNotification")
if batch_mode:
return event
message = portal.Base_translateString('New event created.')
return event.Base_redirect(keep_items={'portal_status_message': message})
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>response_event_title, response_event_text_content, batch_mode=False, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Person_sendSlapOSPendingTicketNotification</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5 Form" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>Person_sendSlapOSPendingTicketNotification</string> </value>
</item>
<item>
<key> <string>action_title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>edit_order</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>enctype</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<list>
<string>left</string>
<string>right</string>
<string>center</string>
<string>bottom</string>
<string>hidden</string>
</list>
</value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<dictionary>
<item>
<key> <string>bottom</string> </key>
<value>
<list>
<string>listbox</string>
</list>
</value>
</item>
<item>
<key> <string>center</string> </key>
<value>
<list>
<string>your_response_event_title</string>
<string>your_response_event_text_content</string>
</list>
</value>
</item>
<item>
<key> <string>hidden</string> </key>
<value>
<list>
<string>listbox_delivery_start_date</string>
</list>
</value>
</item>
<item>
<key> <string>left</string> </key>
<value>
<list>
<string>my_title</string>
</list>
</value>
</item>
<item>
<key> <string>right</string> </key>
<value>
<list/>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Person_viewSlapOSPendingTicketDialog</string> </value>
</item>
<item>
<key> <string>method</string> </key>
<value> <string>POST</string> </value>
</item>
<item>
<key> <string>name</string> </key>
<value> <string>Person_viewSlapOSPendingTicket</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>Send Pending Ticket Report</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="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>columns</string>
<string>default_params</string>
<string>description</string>
<string>editable</string>
<string>editable_columns</string>
<string>list_method</string>
<string>portal_types</string>
<string>selection_name</string>
<string>sort</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>listbox</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>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>columns</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable_columns</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>list_method</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>portal_types</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>selection_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>sort</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>columns</string> </key>
<value>
<list>
<tuple>
<string>getTitle</string>
<string>Title</string>
</tuple>
<tuple>
<string>translated_portal_type</string>
<string>Event Type</string>
</tuple>
<tuple>
<string>delivery.start_date</string>
<string>Date</string>
</tuple>
<tuple>
<string>translated_simulation_state_title</string>
<string>State</string>
</tuple>
</list>
</value>
</item>
<item>
<key> <string>default_params</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>List of all Support Requests related to the follow up ticket</string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>editable_columns</string> </key>
<value>
<list>
<tuple>
<string>delivery.start_date</string>
<string>Date</string>
</tuple>
</list>
</value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_view_mode_listbox</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>list_method</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>portal_types</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>selection_name</string> </key>
<value> <string>person_pending_ticket_view_selection</string> </value>
</item>
<item>
<key> <string>sort</string> </key>
<value>
<list>
<tuple>
<string>delivery.start_date</string>
<string>asc</string>
</tuple>
</list>
</value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Tickets</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Method" module="Products.Formulator.MethodField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>method_name</string> </key>
<value> <string>Person_getSlapOSPendingTicket</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>editable</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_title</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>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>editable</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_ticket_title</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewCRMFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>default</string>
<string>editable</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>your_response_event_text_content</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>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>default</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_text_content</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewCRMFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Message</string> </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>python: context.Person_getSlapOSPendingTicketMessageTemplate()[1]</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>default</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>your_response_event_title</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>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>default</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_string_field</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Title</string> </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>python: "You have %s pending tickets to take action" % (len(context.Person_getSlapOSPendingTicket()))</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
portal = context.getPortalObject()
project = context
causality_value = portal.restrictedTraverse(causality)
if causality_value.Base_getSupportRequestInProgress(title=title) is not None:
return
destination_decision_value = portal.restrictedTraverse(destination_decision)
return destination_decision_value.Entity_createTicketFromTradeCondition(
portal.service_module.slapos_crm_monitoring.getRelativeUrl(),
title,
text_content,
source_project=project.getRelativeUrl(),
causality=causality
)
...@@ -50,11 +50,11 @@ ...@@ -50,11 +50,11 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>instance, notification_message_reference</string> </value> <value> <string>title, text_content, causality, destination_decision</string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>InstanceTree_createSupportRequestEvent</string> </value> <value> <string>Project_createSupportRequestWithCausality</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
from DateTime import DateTime
portal = context.getPortalObject()
open_sale_order_list = portal.portal_catalog(
portal_type="Open Sale Order",
children_portal_type="Open Sale Order Line",
validation_state="validated")
context.edit(
source=context.organisation_module.slapos,
destination=[i.getDestination() for i in open_sale_order_list])
return context.Base_redirect()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>SiteMessage_setSlapOSUserSourceAndDestinatationList</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
portal = context.getPortalObject() portal = context.getPortalObject()
return portal.portal_catalog.getResultValue( return portal.portal_catalog.getResultValue(
title=title, title={'query': title, 'key': 'ExactMatch'},
follow_up_uid=context.getUid(), follow_up__uid=context.getUid(),
portal_type=portal.getPortalEventTypeList(), portal_type=portal.getPortalEventTypeList(),
sort_on=[('delivery.start_date', 'DESC')]) sort_on=[('delivery.start_date', 'DESC')])
""" Close Support Request which are related to a Destroy Requested Instance. """
portal = context.getPortalObject()
if context.getSimulationState() == "invalidated":
return
document = context.getAggregateValue()
if document is not None and document.getSlapState() == "destroy_requested":
person = context.getDestinationDecision(portal_type="Person")
if not person:
return
# Send Notification message
message = """ Closing this ticket as the Instance Tree was destroyed by the user.
"""
notification_message = portal.portal_notifications.getDocumentValue(
reference="slapos-crm-support-request-close-destroyed-notification")
if notification_message is not None:
mapping_dict = {'instance_tree_title': document.getTitle()}
message = notification_message.asText(
substitution_method_parameter_dict={'mapping_dict':mapping_dict})
ticket_title = "Instance Tree was destroyed was destroyed by the user"
event = context.SupportRequest_getLastEvent(ticket_title)
if event is None:
context.notify(message_title=ticket_title, message=message)
context.invalidate()
return context.REQUEST.get("ticket_notified_item")
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>SupportRequest_updateMonitoringDestroyRequestedState</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
""" 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(portal_type="Instance Tree") document = context.getCausalityValue(portal_type="Instance Tree")
if document is None: if document is None:
return return
if document.getPortalType() == "Instance Tree": if document.getSlapState() == "destroy_requested":
if document.getSlapState() == "destroy_requested":
return context.SupportRequest_updateMonitoringDestroyRequestedState() # Send Notification message
message = """ Closing this ticket as the Instance Tree was destroyed by the user.
"""
ticket_title = "Instance Tree was destroyed was destroyed by the user"
event = context.SupportRequest_getLastEvent(ticket_title)
if event is None:
context.Ticket_createProjectEvent(
ticket_title, 'outgoing', 'Web Message',
portal.service_module.slapos_crm_information.getRelativeUrl(),
text_content=message,
content_type='text/plain',
notification_message="slapos-crm-support-request-close-destroyed-notification",
#language=XXX,
substitution_method_parameter_dict={
'instance_tree_title': document.getTitle()
}
)
context.invalidate()
return event
"""Generic script to add event
It creates new Event for any context which become follow_up of created Event.
"""
portal = context.getPortalObject()
ticket = context
if direction == 'outgoing':
source_relative_url = source or ticket.getSource()
source_section_relative_url = ticket.getSourceSection()
source_project_relative_url = ticket.getSourceProject()
destination_relative_url = destination or ticket.getDestination()
destination_section_relative_url = ticket.getDestinationSection()
destination_project_relative_url = ticket.getDestinationProject()
elif direction == 'incoming':
source_relative_url = source or ticket.getDestination()
source_section_relative_url = ticket.getDestinationSection()
source_project_relative_url = ticket.getDestinationProject()
destination_relative_url = destination or ticket.getSource()
destination_section_relative_url = ticket.getSourceSection()
destination_project_relative_url = ticket.getSourceProject()
else:
raise NotImplementedError('The specified direction is not handled: %r' % (direction,))
event_kw = {
'portal_type': portal_type,
'resource': resource,
'source': source_relative_url,
'source_section': source_section_relative_url,
'source_project': source_project_relative_url,
'destination': destination_relative_url,
'destination_section': destination_section_relative_url,
'destination_project': destination_project_relative_url,
'start_date': DateTime(),
'follow_up_value': ticket,
'language': language,
'text_content': text_content,
'content_type': content_type,
}
# Create event
module = portal.getDefaultModule(portal_type=portal_type)
event = module.newContent(**event_kw)
if notification_message:
event.Event_setTextContentFromNotificationMessage(
notification_message,
language=language,
substitution_method_parameter_dict=substitution_method_parameter_dict
)
# Prefer using the notification message title
# as it will be correctly translated
if not event.hasTitle():
event.edit(title=title)
if not keep_draft:
if direction == 'incoming':
# Support event_workflow and event_simulation_workflow
if portal.portal_workflow.isTransitionPossible(event, 'receive'):
event.receive(comment=comment)
if portal.portal_workflow.isTransitionPossible(event, 'stop'):
event.stop(comment=comment)
else:
event.plan(comment=comment)
event.start(comment=comment, send_mail=(portal_type == 'Mail Message'))
event.stop(comment=comment)
event.deliver(comment=comment)
return event
...@@ -50,11 +50,11 @@ ...@@ -50,11 +50,11 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>**kw</string> </value> <value> <string>title, direction, portal_type, resource, text_content, content_type, notification_message=None, substitution_method_parameter_dict=None, keep_draft=False, source=None, destination=None, language=None, comment=None, **kw</string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>Person_getSlapOSPendingTicket</string> </value> <value> <string>Ticket_createProjectEvent</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
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_source=ticket.getDestinationDecision()
)
event_relative_url = context.REQUEST.get("event_relative_url")
ticket.setCausality(event_relative_url)
ticket = state_change["object"]
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()
# create Web message if needed for this ticket
last_event = ticket.SupportRequest_getLastEvent(message_title)
if last_event:
# User has already been notified for this problem.
ticket.REQUEST.set("ticket_notified_item", last_event)
return
transactional_event = ticket.REQUEST.get("ticket_notified_item", None)
if transactional_event is not None:
if (transactional_event.getFollowUpUid() == ticket.getUid()) and \
(transactional_event.getTitle() == message_title):
ticket.REQUEST.set("ticket_notified_item", transactional_event)
return
template = portal.restrictedTraverse(
portal.portal_preferences.getPreferredWebMessageTemplate())
event = template.Base_createCloneDocument(batch_mode=1)
event.edit(
title=message_title,
text_content=message,
start_date = DateTime(),
resource = resource,
source=ticket.getDestinationDecision(),
destination=ticket.getSource(),
follow_up=ticket.getRelativeUrl(),
)
event.stop()
event.deliver()
ticket.serialize()
ticket.REQUEST.set("ticket_notified_item", event)
This diff is collapsed.
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