Commit 6bcb0fc4 authored by Romain Courteaud's avatar Romain Courteaud

New alarm to automatically create registration request.

This alarm send the first invoice reminder to the user.
parent df8f5b58
<?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_createRegularisationRequest</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>slapos_crm_create_regularisation_request</string> </value>
</item>
<item>
<key> <string>periodicity_hour</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_hour_frequency</string> </key>
<value> <int>2</int> </value>
</item>
<item>
<key> <string>periodicity_minute</string> </key>
<value>
<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="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<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>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>Create regularisation request</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>portal = context.getPortalObject()\n
from Products.ZSQLCatalog.SQLCatalog import SimpleQuery, NegatedQuery\n
\n
# XXX TODO: use getInventory to directly fetch user with a wrong balance\n
portal.portal_catalog.searchAndActivate(\n
portal_type="Person", \n
validation_state="validated",\n
reference=NegatedQuery(SimpleQuery(reference=None)),\n
default_email_text=NegatedQuery(SimpleQuery(default_email_text=None)),\n
method_id=\'Person_checkToCreateRegularisationRequest\',\n
activate_kw={\'tag\': tag}\n
)\n
context.activate(after_tag=tag).getId()\n
</string> </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_createRegularisationRequest</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string encoding="cdata"><![CDATA[
from zExceptions import Unauthorized\n
if REQUEST is not None:\n
raise Unauthorized\n
\n
portal = context.getPortalObject()\n
person = context\n
ticket_portal_type = "Regularisation Request"\n
\n
# XXX TODO\n
# # Prevent to create 2 tickets during the same transaction\n
# transactional_variable = getTransactionalVariable()\n
# if tag in transactional_variable:\n
# raise RuntimeError, \'ticket %s already exist\' % tag\n
# else:\n
# transactional_variable[tag] = None\n
\n
ticket = portal.portal_catalog.getResultValue(\n
portal_type=ticket_portal_type,\n
default_source_project_uid=person.getUid(),\n
simulation_state=[\'suspended\', \'validated\'],\n
)\n
if (ticket is None) and int(person.Entity_statBalance()) > 0:\n
\n
tag = "%s_addRegularisationRequest_inProgress" % person.getUid()\n
if (portal.portal_activities.countMessageWithTag(tag) > 0):\n
# The regularisation request is already under creation but can not be fetched from catalog\n
# As it is not possible to fetch informations, it is better to raise an error\n
return None, None\n
\n
# Prevent concurrent transaction to create 2 tickets for the same person\n
person.serialize()\n
\n
# Time to create the ticket\n
regularisation_request_template = portal.restrictedTraverse(\n
portal.portal_preferences.getPreferredRegularisationRequestTemplate())\n
ticket = regularisation_request_template.Base_createCloneDocument(batch_mode=1)\n
ticket.edit(\n
source_project_value=context,\n
title=\'Account regularisation expected for "%s"\' % context.getTitle(),\n
destination_decision_value=context,\n
start_date=DateTime(),\n
resource=portal.portal_preferences.getPreferredRegularisationRequestResource(),\n
)\n
ticket.validate(comment=\'New automatic ticket for %s\' % context.getTitle())\n
ticket.suspend(comment=\'New automatic ticket for %s\' % context.getTitle())\n
\n
ticket.reindexObject(activate_kw={\'tag\': tag})\n
\n
# Inform user that the ticket has been created.\n
mail_message = portal.event_module.newContent(\n
portal_type=\'Mail Message\',\n
start_date=DateTime(),\n
destination_value=person,\n
follow_up=ticket.getRelativeUrl(),\n
source_value=ticket.getSourceValue(),\n
title=\'Invoice payment requested\',\n
resource=ticket.getResource(),\n
text_content="""\n
Dear user,\n
\n
A new invoice has been generated. \n
You can access it in your invoice section at %s.\n
\n
Do not hesitate to visit the web forum (http://community.slapos.org/forum) in case of question.\n
\n
Regards,\n
The slapos team\n
""" % portal.portal_preferences.getPreferredSlaposWebSiteUrl())\n
portal.portal_workflow.doActionFor(mail_message, \'start_action\', send_mail=True, comment=\'Requested manual payment.\')\n
mail_message.stop(comment=\'Requested manual payment.\')\n
mail_message.deliver(comment=\'Requested manual payment.\')\n
\n
return ticket, mail_message\n
\n
return ticket, None\n
]]></string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Person_checkToCreateRegularisationRequest</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
# Copyright (c) 2013 Nexedi SA and Contributors. All Rights Reserved.
import transaction
from Products.SlapOS.tests.testSlapOSMixin import \
testSlapOSMixin
from Products.ERP5Type.tests.utils import createZODBPythonScript
class TestSlapOSCRMCreateRegularisationRequest(testSlapOSMixin):
def _simulatePerson_checkToCreateRegularisationRequest(self):
script_name = 'Person_checkToCreateRegularisationRequest'
if script_name in self.portal.portal_skins.custom.objectIds():
raise ValueError('Precondition failed: %s exists in custom' % script_name)
createZODBPythonScript(self.portal.portal_skins.custom,
script_name,
'*args, **kwargs',
'# Script body\n'
"""portal_workflow = context.portal_workflow
portal_workflow.doActionFor(context, action='edit_action', comment='Visited by Person_checkToCreateRegularisationRequest') """ )
transaction.commit()
def _dropPerson_checkToCreateRegularisationRequest(self):
script_name = 'Person_checkToCreateRegularisationRequest'
if script_name in self.portal.portal_skins.custom.objectIds():
self.portal.portal_skins.custom.manage_delObjects(script_name)
transaction.commit()
def test_alarm_expected_person(self):
new_id = self.generateNewId()
person = self.portal.person_module.newContent(
portal_type='Person',
title="Test person %s" % new_id,
reference="TESTPERS_%s" % new_id,
default_email_text="%s@example.org" % new_id,
)
person.validate()
self.tic()
self._simulatePerson_checkToCreateRegularisationRequest()
try:
self.portal.portal_alarms.\
slapos_crm_create_regularisation_request.activeSense()
self.tic()
finally:
self._dropPerson_checkToCreateRegularisationRequest()
self.assertEqual(
'Visited by Person_checkToCreateRegularisationRequest',
person.workflow_history['edit_workflow'][-1]['comment'])
def test_alarm_no_email(self):
new_id = self.generateNewId()
person = self.portal.person_module.newContent(
portal_type='Person',
title="Test person %s" % new_id,
reference="TESTPERS_%s" % new_id,
)
person.validate()
self.tic()
self._simulatePerson_checkToCreateRegularisationRequest()
try:
self.portal.portal_alarms.\
slapos_crm_create_regularisation_request.activeSense()
self.tic()
finally:
self._dropPerson_checkToCreateRegularisationRequest()
self.assertNotEqual(
'Visited by Person_checkToCreateRegularisationRequest',
person.workflow_history['edit_workflow'][-1]['comment'])
def test_alarm_no_reference(self):
new_id = self.generateNewId()
person = self.portal.person_module.newContent(
portal_type='Person',
title="Test person %s" % new_id,
default_email_text="%s@example.org" % new_id,
)
person.validate()
self.tic()
self._simulatePerson_checkToCreateRegularisationRequest()
try:
self.portal.portal_alarms.\
slapos_crm_create_regularisation_request.activeSense()
self.tic()
finally:
self._dropPerson_checkToCreateRegularisationRequest()
self.assertNotEqual(
'Visited by Person_checkToCreateRegularisationRequest',
person.workflow_history['edit_workflow'][-1]['comment'])
def test_alarm_not_validated(self):
new_id = self.generateNewId()
person = self.portal.person_module.newContent(
portal_type='Person',
title="Test person %s" % new_id,
reference="TESTPERS_%s" % new_id,
default_email_text="%s@example.org" % new_id,
)
person.validate()
person.invalidate()
self.tic()
self._simulatePerson_checkToCreateRegularisationRequest()
try:
self.portal.portal_alarms.\
slapos_crm_create_regularisation_request.activeSense()
self.tic()
finally:
self._dropPerson_checkToCreateRegularisationRequest()
self.assertNotEqual(
'Visited by Person_checkToCreateRegularisationRequest',
person.workflow_history['edit_workflow'][-1]['comment'])
# def test_alarm_not_suspended_support_request(self):
# new_id = self.generateNewId()
# payment = self.portal.accounting_module.newContent(
# portal_type='Payment Transaction',
# title="Payment %s" % new_id,
# reference="TESTPAY-%s" % new_id,
# )
# new_id = self.generateNewId()
# ticket = self.portal.support_request_module.newContent(
# portal_type='Support Request',
# title="Ticket %s" % new_id,
# reference="TESTSUPREQ-%s" % new_id,
# source_project_value=payment,
# )
# ticket.validate()
#
# self.tic()
# self._simulatePerson_checkToCreateRegularisationRequest()
# try:
# self.portal.portal_alarms.\
# slapos_payzen_update_suspended_support_request.activeSense()
# self.tic()
# finally:
# self._dropPerson_checkToCreateRegularisationRequest()
# self.assertNotEqual(
# 'Visited by Person_checkToCreateRegularisationRequest',
# ticket.workflow_history['edit_workflow'][-1]['comment'])
#
# def test_alarm_suspended_support_request(self):
# new_id = self.generateNewId()
# payment = self.portal.accounting_module.newContent(
# portal_type='Payment Transaction',
# title="Payment %s" % new_id,
# reference="TESTPAY-%s" % new_id,
# )
# new_id = self.generateNewId()
# ticket = self.portal.support_request_module.newContent(
# portal_type='Support Request',
# title="Ticket %s" % new_id,
# reference="TESTSUPREQ-%s" % new_id,
# source_project_value=payment,
# )
# ticket.validate()
# ticket.suspend()
#
# self.tic()
# self._simulatePerson_checkToCreateRegularisationRequest()
# try:
# self.portal.portal_alarms.\
# slapos_payzen_update_suspended_support_request.activeSense()
# self.tic()
# finally:
# self._dropPerson_checkToCreateRegularisationRequest()
# self.assertEqual(
# 'Visited by Person_checkToCreateRegularisationRequest',
# ticket.workflow_history['edit_workflow'][-1]['comment'])
# Copyright (c) 2013 Nexedi SA and Contributors. All Rights Reserved.
import transaction
from Products.SlapOS.tests.testSlapOSMixin import \
testSlapOSMixin
from zExceptions import Unauthorized
from DateTime import DateTime
from functools import wraps
from Products.ERP5Type.tests.utils import createZODBPythonScript
import difflib
def simulate(script_id, params_string, code_string):
def upperWrap(f):
@wraps(f)
def decorated(self, *args, **kw):
if script_id in self.portal.portal_skins.custom.objectIds():
raise ValueError('Precondition failed: %s exists in custom' % script_id)
createZODBPythonScript(self.portal.portal_skins.custom,
script_id, params_string, code_string)
try:
result = f(self, *args, **kw)
finally:
if script_id in self.portal.portal_skins.custom.objectIds():
self.portal.portal_skins.custom.manage_delObjects(script_id)
transaction.commit()
return result
return decorated
return upperWrap
class TestSlapOSPerson_checkToCreateRegularisationRequest(testSlapOSMixin):
def beforeTearDown(self):
transaction.abort()
def createPerson(self):
new_id = self.generateNewId()
return self.portal.person_module.newContent(
portal_type='Person',
title="Person %s" % new_id,
reference="TESTPERS-%s" % new_id,
)
@simulate('Entity_statBalance', '*args, **kwargs', 'return "1"')
def test_addRegularisationRequest_payment_requested(self):
for preference in \
self.portal.portal_catalog(portal_type="System Preference"):
preference = preference.getObject()
if preference.getPreferenceState() == 'global':
preference.setPreferredSlaposWebSiteUrl('http://foobar.org/')
person = self.createPerson()
before_date = DateTime()
ticket, event = person.Person_checkToCreateRegularisationRequest()
after_date = DateTime()
self.assertEquals(ticket.getPortalType(), 'Regularisation Request')
self.assertEquals(ticket.getSimulationState(), 'suspended')
self.assertEquals(ticket.getSourceProject(), person.getRelativeUrl())
self.assertEquals(ticket.getTitle(),
'Account regularisation expected for "%s"' % person.getTitle())
self.assertEquals(event.getPortalType(), 'Mail Message')
self.assertTrue(event.getStartDate() >= before_date)
self.assertTrue(event.getStopDate() <= after_date)
self.assertEquals(event.getTitle(), "Invoice payment requested")
self.assertEquals(event.getDestination(),
person.getRelativeUrl())
self.assertEquals(event.getSource(),
ticket.getSource())
expected_text_content = """
Dear user,
A new invoice has been generated.
You can access it in your invoice section at http://foobar.org/.
Do not hesitate to visit the web forum (http://community.slapos.org/forum) in case of question.
Regards,
The slapos team
"""
self.assertEquals(event.getTextContent(), expected_text_content,
'\n'.join([x for x in difflib.unified_diff(
event.getTextContent().splitlines(),
expected_text_content.splitlines())]))
self.assertEquals(event.getSimulationState(), 'delivered')
# def test_addRegularisationRequest_do_not_duplicate_ticket(self):
# person = self.createPerson()
# ticket = person.Person_checkToCreateRegularisationRequest()
# ticket2 = person.Person_checkToCreateRegularisationRequest()
# self.assertEquals(ticket.getRelativeUrl(), ticket2.getRelativeUrl())
@simulate('Entity_statBalance', '*args, **kwargs', 'return "1"')
def test_addRegularisationRequest_do_not_duplicate_ticket_if_not_reindexed(self):
person = self.createPerson()
ticket, event = person.Person_checkToCreateRegularisationRequest()
transaction.commit()
ticket2, event2 = person.Person_checkToCreateRegularisationRequest()
self.assertNotEquals(ticket, None)
self.assertNotEquals(event, None)
self.assertEquals(ticket2, None)
self.assertEquals(event2, None)
@simulate('Entity_statBalance', '*args, **kwargs', 'return "0"')
def test_addRegularisationRequest_balance_ok(self):
person = self.createPerson()
ticket, event = person.Person_checkToCreateRegularisationRequest()
self.assertEquals(ticket, None)
self.assertEquals(event, None)
@simulate('Entity_statBalance', '*args, **kwargs', 'return "1"')
def test_addRegularisationRequest_existing_suspended_ticket(self):
person = self.createPerson()
ticket, event = person.Person_checkToCreateRegularisationRequest()
transaction.commit()
self.tic()
ticket2, event2 = person.Person_checkToCreateRegularisationRequest()
self.assertNotEquals(ticket, None)
self.assertNotEquals(event, None)
self.assertEquals(ticket2.getRelativeUrl(), ticket.getRelativeUrl())
self.assertEquals(event2, None)
@simulate('Entity_statBalance', '*args, **kwargs', 'return "1"')
def test_addRegularisationRequest_existing_validated_ticket(self):
person = self.createPerson()
ticket, event = person.Person_checkToCreateRegularisationRequest()
ticket.validate()
transaction.commit()
self.tic()
ticket2, event2 = person.Person_checkToCreateRegularisationRequest()
self.assertNotEquals(ticket, None)
self.assertNotEquals(event, None)
self.assertEquals(ticket2.getRelativeUrl(), ticket.getRelativeUrl())
self.assertEquals(event2, None)
@simulate('Entity_statBalance', '*args, **kwargs', 'return "1"')
def test_addRegularisationRequest_existing_invalidated_ticket(self):
person = self.createPerson()
ticket, event = person.Person_checkToCreateRegularisationRequest()
ticket.invalidate()
transaction.commit()
self.tic()
ticket2, event2 = person.Person_checkToCreateRegularisationRequest()
self.assertNotEquals(ticket2.getRelativeUrl(), ticket.getRelativeUrl())
self.assertNotEquals(event2, None)
def test_addRegularisationRequest_REQUEST_disallowed(self):
date = DateTime()
person = self.createPerson()
self.assertRaises(
Unauthorized,
person.Person_checkToCreateRegularisationRequest,
REQUEST={})
9
\ No newline at end of file
10
\ No newline at end of file
event_module/slapos_crm_web_message_template
portal_alarms/slapos_crm_create_regularisation_request
regularisation_request_module/slapos_crm_regularisation_request_template
service_module/slapos_crm_acknowledgement
service_module/slapos_crm_complaint
......
testSlapOSCRMSkins
testSlapOSCRMAlarm
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment