def __call__(self):
        '''This script is to be run once every day and sends a reminder
           email to each and every student with a booking on the next day.
           So, if we run Monday, we should be sending for Wednesday's sessions.'''
        catalog = getToolByName(self.context, 'portal_catalog')

        #We want the date two days from now.
        target_date = DateTime().earliestTime()+2

        days = catalog.unrestrictedSearchResults(path=self.context.getPath(),
                                                 portal_type='Day',
                                                 getDate=target_date)
        mail_counter = 0
        mail_error_counter = 0
        for day in days:
            the_day = day.getObject()
            for session in the_day.contentItems():
                for person in session[1].contentItems():
                    try:
                        mail.sendNotificationEmail(context=self.context,
                                         person=person[1],
                                         email_type=config.EHS_REMINDER_EMAIL)
                        mail_counter += 1;
                    except:
                        mail_error_counter += 1;
                        raise

        #Log how many emails were sent.
        self.context.plone_log("EHS Reminders Sent:  We just spammed %s students and had %s errors when sending mail." % (mail_counter, mail_error_counter))
        return
    def cancelBooking(self):
        '''Processing that happens when a user is cancelling a given
           booking for a session.'''
        if self.request.form.get('form.submitted') == '1' and \
           self.request.form.get('form.button.Submit') == \
           'Cancel selected session':

            self.authenticateForm()

            selectedSlots = self.request.get('selectedSlot', None)
            if type(selectedSlots) != list:
                selectedSlots = [selectedSlots]

            if selectedSlots != [None]:
                plone_utils = getToolByName(self.context, 'plone_utils')
                student_details = self.getStudentDetailsFromSdm()
                for slot in selectedSlots:
                    try:
                        booking_session = self.getBookingSessionByUid(slot)
                        login_id = student_details['login_id']
                        person = booking_session[login_id]
                        booking_session.manage_delObjects([login_id,])

                        try:
                            #EMAIL: Send cancellation message to our user
                            mail.sendNotificationEmail(context=self.context,
                                                       person=person,
                                                       email_type=config.EHS_CANCELLATION_EMAIL)
                            notify(PersonCancelledEvent(person))
                            plone_utils.addPortalMessage(_(u'Your selected booking was cancelled successfully.  You have been sent a confirmation email.'), 'info')
                        except:
                            raise
                            plone_utils.addPortalMessage(_(u'Your selected booking was cancelled successfully but a confirmation email could not be sent.'), 'warning')

                        self.has_cancelled = True
                    except:
                        raise
                        plone_utils.addPortalMessage(_(u'Your booking could not be cancelled.  Please contact Enrolment Help.'), 'error')


        view = ViewPageTemplateFile("show-bookings.pt")
        return view(self)
    def handleSend(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        #Otherwise, if no errors on the form, then send our emails
        templating_errors = []
        mail_counter = 0
        for person in data['bookings']:
            for notification in data['notifications']:
                try:
                    if action.value == 'Check Syntax':
                        #Just do the templating, don't send mail
                        mail.performTemplating(self.context,
                                               person,
                                               notification)
                    else:
                        #Actually send the mail and run the whole process
                        mail.sendNotificationEmail(
                            context=self.context,
                            person=person,
                            email_type=notification,
                            log=True,
                        )
                    mail_counter += 1
                except mail.EmailTemplatingException as exception:
                    messages = []
                    for err in exception.error:
                        wrapped = err.getException()[1]

                        #Some errors mightn't have line numbers.
                        pretty_line_output = ''
                        if hasattr(wrapped, 'lineno'):
                            pretty_line_output = ', Line %d' % wrapped.lineno

                        #Produce our nicely formatted template error output
                        pretty_output = "%s error (%s%s): %s" % (
                            exception.type,
                            notification,
                            pretty_line_output,
                            repr(wrapped),
                        )
                        templating_errors += [pretty_output,]


        #Display the errors for the user to peruse
        if templating_errors:
            visual_error = Invalid('<br />\n'.join(templating_errors))
            error = getMultiAdapter((visual_error, self.request, None,
                                     None, self, self.context),
                                    IErrorViewSnippet)
            error.render = lambda: util.render_html(error)
            error.update()
            self.widgets.errors += (error,)
            self.status = self.formErrorsMessage
        else:
            if action.value == 'Check Syntax':
                self.successMessage = u'No errors detected in templates!'
            else:
                self.successMessage = \
                        u'Successfully sent %d mail messages.' % \
                        mail_counter
            self.status = self.successMessage
    def __call__(self, *args, **kwargs):
        #Recall our user's course selection from their session.
        plone_utils = getToolByName(self.context, 'plone_utils')
        self.student_details = self.getStudentDetailsFromSdm()
        self.booked_session_uid = None

        member = self.getAuthenticatedMember()

        #If a user hasn't selected a course yet, then get them to.
        #Administrators are special -- they don't get bumped.
        if self.student_details is None and not self.showEditLinks() and not self.isBookingStaff():
            self.request.response.redirect(self.context.absolute_url()+'/@@select-course')
            return

        #When submitting our form, do the following for validation/processing
        if self.request.form.get('form.submitted') == '1' and \
           self.request.form.get('form.button.Submit') == 'Submit Form':

           self.authenticateForm()

           #Validate our fields from the page
           for field in ExposedPersonSchema.fields():
               field_validation = field.validate(self.request.form.get(field.getName()), self.context)
               if field_validation: self.errors[field.getName()] = field_validation

           #Special case for personal email address
           if "confirmPersonalEmail" not in self.errors and self.request.form.get('pers_email') != self.request.form.get('confirmPersonalEmail'):
               self.errors['confirmPersonalEmail'] = "Confirmation email address does not match.  Please check your input."
           #Special case for advanced standing
           if self.request.form.get('intendToApplyForAdvancedStanding') is '1' and self.request.form.get('submittedApplicationForAdvancedStanding') is None:
               self.errors['submittedApplicationForAdvancedStanding'] = "This field is required."

           #Special checks for our slotSelection; it's not a real field
           timeSlotUid = self.request.form.get('slotSelection')
           timeSlotUid = isinstance(timeSlotUid, basestring) and [timeSlotUid,] or timeSlotUid
           timeSlot = None
           if not timeSlotUid or len(timeSlotUid) != 1:
               self.errors['slotSelection'] = "Please select one enrolment session to book into."
           else:
               timeSlot = self.getBookingSessionByUid(timeSlotUid[0])
               existing = timeSlot.get(self.student_details['login_id'])
               #XXX Need more checks here to make sure the student
               #can sign up for the given slot...
               if not timeSlot \
                  or timeSlot.isClosed() \
                  or timeSlot.isFull() \
                  or timeSlot.isInThePast() \
                  or timeSlot.getFaculty() != self.student_details['faculty_code'] \
                  or self.context.isUserSignedUpForAnySlot(self.student_details):
                   self.errors['slotSelection'] = "Your could not be signed up for your selected session.  It may have been cancelled, closed or become full.  Please select a different session."
               elif existing:
                   self.errors['slotSelection'] = "You are already attending this enrolment session for %s.  Please choose another session." % existing.crs_full_nm

           #If we don't have any errors, we're good.  Otherwise, we just fall through to displaying the form.
           if len(self.errors) == 0:
               try:
                   #need to add/merge request details with student details here
                   #They might have changed phone/email/etc and we need their
                   #responses included.
                   self.student_details.update(self.request.form)
                   person = timeSlot.invokeFactory('Person', self.student_details['login_id'], **self.student_details)

                   try:
                       #EMAIL: Send confirmation email to our user
                       mail.sendNotificationEmail(context=self.context,
                                      person=timeSlot[person],
                                      email_type=config.EHS_CONFIRMATION_EMAIL)
                       plone_utils.addPortalMessage(_(u'Your booking was processed successfully. Your selected session is highlighted below.'), 'success')
                   except:
                       raise
                       plone_utils.addPortalMessage(_(u'Your booking was processed successfully but a confirmation email could not be sent.'), 'warning')

                   self.booked_session_uid = timeSlot.UID()
               except:
                   raise
                   self.errors['slotSelection'] = "Your could not be signed up for your selected session.  The session may have been cancelled or become full.  Please select a different session."


        #We're just loading the form, not submitting
        else:
            #Copy selected exposed schema attributes into the request.form
            #object to inject them onto the page.
            if self.student_details is not None:
                for field_key in ExposedPersonSchema.keys():
                    self.request.form.setdefault(field_key, self.student_details.get(field_key))

        #Data reconfiguration before our page loads
        if self.student_details is not None:
            self.faculty_code = self.student_details['faculty_code']
            self.faculty_name = config.FACULTY_LIST.getValue(self.faculty_code)
        else:
            self.faculty_code = ''
            self.faculty_name = "Administrative overview (all sessions)"

        #Inject our friendly error message if there's errors on the page
        if self.errors:
            plone_utils.addPortalMessage(_(u'Please correct the indicated errors before attempting to book a session.'), 'error')

        #print self.request.form
        return super(ChooseTimeSlot,self).__call__(args, kwargs)