Ignore:
Timestamp:
3 Feb 2015, 16:54:56 (10 years ago)
Author:
Henrik Bettermann
Message:

Notify customer by email after customer and contract transitions.

Location:
main/waeup.ikoba/trunk/src/waeup/ikoba
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.ikoba/trunk/src/waeup/ikoba/customers/customer.py

    r12398 r12553  
    110110
    111111    @property
     112    def title(self):
     113        return self.display_fullname
     114
     115    @property
    112116    def fullname(self):
    113117        firstname = getattr(self, 'firstname', None)
  • main/waeup.ikoba/trunk/src/waeup/ikoba/customers/interfaces.py

    r12537 r12553  
    7878    fullname = Attribute('All name parts separated by hyphens')
    7979    display_fullname = Attribute('The fullname of an applicant')
     80    title = Attribute('A title used for email notifications only')
    8081
    8182    suspended = schema.Bool(
  • main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_browser.py

    r12540 r12553  
    2121import shutil
    2222import tempfile
     23import logging
    2324import pytz
    2425import base64
     
    301302    # Tests for Customer class views and pages
    302303
     304
     305    def setup_logging(self):
     306        # setup a log-handler that catches all fake mailer output
     307        self.stream = StringIO()
     308        handler = logging.StreamHandler(self.stream)
     309        logger = logging.getLogger('test.smtp')
     310        logger.addHandler(handler)
     311        logger.setLevel(logging.INFO)
     312        return
     313
     314    def get_fake_smtp_output(self):
     315        # get output generated by fake mailer
     316        self.stream.flush()
     317        self.stream.seek(0)
     318        return self.stream.read()
     319
     320    def teardown_logging(self):
     321        # remove the log handler for fake mailer output
     322        logger = logging.getLogger('test.smtp')
     323        handlers = [x for x in logger.handlers]
     324        for handler in handlers:
     325            logger.removeHandler(handler)
     326        return
     327
    303328    def test_basic_auth(self):
    304329        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
     
    386411
    387412
    388     def test_manage_workflow(self):
     413    def test_manage_workflow_send_transition_information(self):
    389414        # Managers can pass through the whole workflow
     415        config = grok.getSite()['configuration']
     416        config.email_notification = True
     417        self.setup_logging()
    390418        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
    391419        customer = self.app['customers'][self.customer_id]
     
    399427        self.browser.getControl(name="transition").value = ['reject']
    400428        self.browser.getControl("Apply").click()
     429        # The customer is being notified by email after rejection
     430        expected = [
     431            u'Sending email from no-reply@waeup.org to aa@aa.ng:',
     432            u'Message:', u'msg: MIME-Version: 1.0',
     433            u'msg: Content-Type: text/plain; charset="us-ascii"',
     434            u'msg: Content-Transfer-Encoding: 7bit',
     435            u'msg: From: Administrator <no-reply@waeup.org>',
     436            u'msg: To: Anna Tester <aa@aa.ng>',
     437            u'msg: Reply-To: Administrator <contact@waeup.org>',
     438            u'msg: Subject: Ikoba status change information',
     439            u'msg: ',
     440            u'msg: Dear Anna Tester,',
     441            u'msg: ',
     442            u'msg: The status of the following object has been changed:',
     443            u'msg: ', u'msg: Object Id: K1000000',
     444            u'msg: Title: Anna Tester',
     445            u'msg: Transition: customer registration rejected',
     446            u'msg: New state: started',
     447            u'msg: ',
     448            u'msg: Regards,',
     449            u'msg: ',
     450            u'msg: Manager',
     451            u'msg: ',
     452            u'msg: --',
     453            u'msg: Sample Company',
     454            u'msg: ',
     455            u'']
     456        self.assertEqual(expected, self.get_fake_smtp_output().split('\n'))
    401457        self.browser.open(self.trigtrans_path)
    402458        self.browser.getControl(name="transition").value = ['request']
     
    411467        self.browser.getControl(name="transition").value = ['reset1']
    412468        self.browser.getControl("Apply").click()
     469        self.teardown_logging()
    413470        return
    414471
  • main/waeup.ikoba/trunk/src/waeup/ikoba/customers/workflow.py

    r12526 r12553  
    2121from datetime import datetime
    2222from zope.component import getUtility
     23from zope.i18n import translate
    2324from hurry.workflow.workflow import Transition, WorkflowState, NullCondition
    2425from hurry.workflow.interfaces import (
    2526    IWorkflowState, IWorkflowTransitionEvent, InvalidTransitionError)
    2627from waeup.ikoba.interfaces import (
    27     IObjectHistory, IIkobaWorkflowInfo, IIkobaUtils,
     28    IObjectHistory, IIkobaWorkflowInfo, IIkobaUtils, IUserAccount,
    2829    STARTED, CREATED, REQUESTED, PROVISIONALLY, APPROVED,
    2930    SUBMITTED, VERIFIED, REJECTED, EXPIRED)
     
    159160def handle_customer_transition_event(obj, event):
    160161    """Append message to customer history and log file when transition happened.
     162
     163    Notify customer by email.
    161164    """
    162165
     
    164167    history = IObjectHistory(obj)
    165168    history.addMessage(msg)
     169    if event.transition.transition_id not in ('create', 'start', 'request'):
     170        ikoba_utils = getUtility(IIkobaUtils)
     171        ikoba_utils.sendTransitionInfo(IUserAccount(obj), obj, msg)
    166172    try:
    167173        customers_container = grok.getSite()['customers']
     
    280286    history = IObjectHistory(obj)
    281287    history.addMessage(msg)
     288    if event.transition.transition_id not in ('create', 'submit') \
     289        and obj.customer:
     290        ikoba_utils = getUtility(IIkobaUtils)
     291        ikoba_utils.sendTransitionInfo(IUserAccount(obj.customer), obj, msg)
    282292    try:
    283293        customers_container = grok.getSite()['customers']
  • main/waeup.ikoba/trunk/src/waeup/ikoba/interfaces.py

    r12526 r12553  
    611611        )
    612612
     613    email_notification = schema.Bool(
     614        title = _(u'Notify customers by email'),
     615        default = False,
     616        )
     617
    613618    captcha = schema.Choice(
    614619        title = _(u'Captcha used for public registration pages'),
  • main/waeup.ikoba/trunk/src/waeup/ikoba/utils/utils.py

    r12545 r12553  
    2727from waeup.ikoba.interfaces import MessageFactory as _
    2828from waeup.ikoba.smtp import send_mail as send_mail_internally
    29 from waeup.ikoba.utils.helpers import get_sorted_preferred
     29from waeup.ikoba.utils.helpers import (
     30    get_sorted_preferred, get_current_principal)
    3031from waeup.ikoba.payments.currencies import ISO_4217_CURRENCIES
    3132
     
    241242            subject, body, config)
    242243
    243     def getPaymentItem(self, payment):
    244         """Return payment item.
    245 
    246         This method can be used to customize the display_item property method.
    247         """
    248         return payment.p_item
     244    def sendTransitionInfo(self, customer, obj, msg=None):
     245        """Send transition information as email.
     246
     247        Input is the customer for which credentials are sent and the object
     248        which was transitioned.
     249
     250        Returns True or False to indicate successful operation.
     251        """
     252        config = grok.getSite()['configuration']
     253        if not config.email_notification:
     254            return
     255        subject = 'Ikoba status change information'
     256        text = _(u"""Dear ${a},
     257
     258The status of the following object has been changed:
     259
     260Object Id: ${c}
     261Title: ${d}
     262Transition: ${e}
     263New state: ${f}
     264
     265Regards,
     266
     267${b}
     268
     269--
     270${g}
     271""")
     272        from_name = config.name_admin
     273        from_addr = config.email_admin
     274        rcpt_name = customer.title
     275        rcpt_addr = customer.email
     276
     277        user = get_current_principal()
     278        if user is None:
     279            usertitle = 'system'
     280        elif user.id == 'zope.anybody':
     281            usertitle = 'Anonymous'
     282        else:
     283            usertitle = getattr(user, 'public_name', None)
     284            if not usertitle:
     285                usertitle = user.title
     286
     287        msg = translate(msg,'waeup.ikoba', target_language=self.PORTAL_LANGUAGE)
     288        new_state = translate(obj.translated_state,'waeup.ikoba',
     289            target_language=self.PORTAL_LANGUAGE)
     290
     291        text = _(text, mapping={
     292            'a': rcpt_name,
     293            'b': usertitle,
     294            'c': obj.__name__,
     295            'd': obj.title,
     296            'e': msg.lower(),
     297            'f': new_state,
     298            'g': config.name})
     299
     300        body = translate(text, 'waeup.ikoba',
     301            target_language=self.PORTAL_LANGUAGE)
     302
     303        return send_mail(
     304            from_name, from_addr, rcpt_name, rcpt_addr,
     305            subject, body, config)
    249306
    250307    def expensive_actions_allowed(self, type=None, request=None):
Note: See TracChangeset for help on using the changeset viewer.