Index: main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/applicant.py
===================================================================
--- main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/applicant.py	(revision 9166)
+++ main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/applicant.py	(revision 9209)
@@ -27,5 +27,5 @@
 from zope.securitypolicy.interfaces import IPrincipalRoleManager
 from zope.interface import implementedBy
-from zope.schema.interfaces import RequiredMissing
+from zope.schema.interfaces import RequiredMissing, ConstraintNotSatisfied
 from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState
 from waeup.kofa.image import KofaImageFile
@@ -36,4 +36,5 @@
 from waeup.kofa.interfaces import MessageFactory as _
 from waeup.kofa.students.vocabularies import RegNumNotInSource
+from waeup.kofa.students.studycourse import StudentStudyCourse
 from waeup.kofa.utils.helpers import attrs_to_fields
 from waeup.kofa.applicants.interfaces import IApplicant, IApplicantEdit
@@ -118,19 +119,27 @@
         if self.course_admitted is None:
             return False, _('No course admitted provided.')
-        # Add student object
+        # Set student attributes
         try:
             for name in self.create_names:
                 setattr(student, name, getattr(self, name, None))
         except RequiredMissing, err:
-            return False, _('RequiredMissing: %s' % err)
+            return False, 'RequiredMissing: %s' % err
+        except:
+            return False, 'Error: %s' % err
+        # Finally prove if the certificate still exists
+        try:
+            StudentStudyCourse().certificate = self.course_admitted
+        except ConstraintNotSatisfied, err:
+            return False, 'ConstraintNotSatisfied: %s' % self.course_admitted.code
+        # Add student
         site = grok.getSite()
         site['students'].addStudent(student)
+        # Save student_id
         self.student_id = student.student_id
+        # Fire transitions
         IWorkflowInfo(self).fireTransition('create')
         IWorkflowInfo(student).fireTransition('admit')
-
         # Set password
         IUserAccount(student).setPassword(self.application_number)
-
         # Save the certificate and set session attributes
         student['studycourse'].certificate = self.course_admitted
@@ -142,5 +151,4 @@
         # Update the catalog
         notify(grok.ObjectModifiedEvent(student))
-
         # Save application slip
         self._createApplicationPDF(student, view=view)
Index: main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/batching.py
===================================================================
--- main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/batching.py	(revision 9166)
+++ main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/batching.py	(revision 9209)
@@ -40,5 +40,5 @@
     grok.provides(IBatchProcessor)
     grok.context(Interface)
-    util_name = 'applicants container processor'
+    util_name = 'applicantscontainerprocessor'
     grok.name(util_name)
 
Index: main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/browser.py
===================================================================
--- main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/browser.py	(revision 9166)
+++ main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/browser.py	(revision 9209)
@@ -309,10 +309,17 @@
     pnav = 3
 
-    form_fields = grok.AutoFields(IApplicantsContainer).omit('title')
-    form_fields['description'].custom_widget = HTMLDisplayWidget
-    form_fields[
-        'startdate'].custom_widget = FriendlyDatetimeDisplayWidget('le')
-    form_fields[
-        'enddate'].custom_widget = FriendlyDatetimeDisplayWidget('le')
+    @property
+    def form_fields(self):
+        form_fields = grok.AutoFields(IApplicantsContainer).omit('title')
+        form_fields['description'].custom_widget = HTMLDisplayWidget
+        form_fields[
+            'startdate'].custom_widget = FriendlyDatetimeDisplayWidget('le')
+        form_fields[
+            'enddate'].custom_widget = FriendlyDatetimeDisplayWidget('le')
+        if self.request.principal.id == 'zope.anybody':
+            form_fields = form_fields.omit(
+                'code', 'prefix', 'year', 'mode',
+                'strict_deadline', 'application_category')
+        return form_fields
 
     @property
@@ -494,7 +501,8 @@
     grok.template('applicantdisplaypage')
     form_fields = grok.AutoFields(IApplicant).omit(
-        'locked', 'course_admitted', 'password')
+        'locked', 'course_admitted', 'password', 'suspended')
     label = _('Applicant')
     pnav = 3
+    hide_hint = False
 
     @property
@@ -539,5 +547,5 @@
     grok.name('base')
     form_fields = grok.AutoFields(IApplicant).select(
-        'applicant_id', 'firstname', 'lastname','email', 'course1')
+        'applicant_id','email', 'course1')
 
 class CreateStudentPage(UtilityView, grok.View):
@@ -708,7 +716,7 @@
 
     def update(self):
-        if self.context.state in ('initialized', 'started'):
+        if self.context.state in ('initialized', 'started', 'paid'):
             self.flash(
-                _('Please pay before trying to download the application slip.'))
+                _('Please pay and submit before trying to download the application slip.'))
             return self.redirect(self.url(self.context))
         return
@@ -882,5 +890,5 @@
     form_fields = grok.AutoFields(IApplicantEdit).omit(
         'locked', 'course_admitted', 'student_id',
-        'screening_score',
+        'suspended'
         )
     form_fields['applicant_id'].for_display = True
@@ -1034,5 +1042,5 @@
         return
 
-    @action(_('Get login credentials'), style='primary')
+    @action(_('Send login credentials to email address'), style='primary')
     def register(self, **data):
         if not self.captcha_result.is_valid:
@@ -1085,7 +1093,8 @@
         # Send email with credentials
         login_url = self.url(grok.getSite(), 'login')
+        url_info = u'Login: %s' % login_url
         msg = _('You have successfully been registered for the')
         if kofa_utils.sendCredentials(IUserAccount(applicant),
-            password, login_url, msg):
+            password, url_info, msg):
             email_sent = applicant.email
         else:
Index: main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/browser_templates/applicantdisplaypage.pt
===================================================================
--- main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/browser_templates/applicantdisplaypage.pt	(revision 9166)
+++ main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/browser_templates/applicantdisplaypage.pt	(revision 9209)
@@ -1,4 +1,10 @@
-<h2>
-... <span tal:replace="context/translated_state">APPLICATIONSTATE</span> ...
+<h2 i18n:domain="waeup.kofa">
+  ...
+  <span tal:replace="context/translated_state">APPLICATIONSTATE
+  </span>
+  <span tal:omit-tag=""
+    i18n:translate="" tal:condition="context/suspended">(account suspended)
+  </span>
+  ...
 </h2>
 
@@ -14,5 +20,5 @@
   <tbody>
     <tal:widgets content="structure provider:widgets" />
-    <tr>
+    <tr tal:condition="view/getCourseAdmitted">
       <td class="fieldname" i18n:translate="">
           Admitted Course of Study:
Index: main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/browser_templates/applicanteditpage.pt
===================================================================
--- main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/browser_templates/applicanteditpage.pt	(revision 9166)
+++ main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/browser_templates/applicanteditpage.pt	(revision 9209)
@@ -3,6 +3,12 @@
       autocomplete="off">
 
-  <h2>
-  ... <span tal:replace="context/translated_state">APPLICATIONSTATE</span> ...
+  <h2 i18n:domain="waeup.kofa">
+    ...
+    <span tal:replace="context/translated_state">APPLICATIONSTATE
+    </span>
+    <span tal:omit-tag=""
+      i18n:translate="" tal:condition="context/suspended">(account suspended)
+    </span>
+    ...
   </h2>
 
Index: main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/browser_templates/applicantregemailsent.pt
===================================================================
--- main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/browser_templates/applicantregemailsent.pt	(revision 9166)
+++ main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/browser_templates/applicantregemailsent.pt	(revision 9209)
@@ -29,9 +29,10 @@
     <tr>
   </table>
-  <p i18n:translate="">
-    Print this page and proceed to the
+  <p>
+    <span i18n:translate="">Print this page and proceed to the</span>
     <a tal:attributes="href python: view.url(layout.site, 'login')">login form</a>.
-    Please note that passwords are case-sensitive,
+    <span i18n:translate="">Please note that passwords are case-sensitive,
     <br />when entering your credentials, and keep your password secret!
+    </span>
   </p>
   <p tal:condition = "view/email">
Index: main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/browser_templates/applicantscontainerpage.pt
===================================================================
--- main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/browser_templates/applicantscontainerpage.pt	(revision 9166)
+++ main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/browser_templates/applicantscontainerpage.pt	(revision 9209)
@@ -1,7 +1,3 @@
-<span tal:condition="view/introduction" tal:omit-tag="">
-  <p tal:content="structure view/introduction">INTRODUCTION</p>
-</span>
-
-<table class="form-table" tal:condition="layout/isAuthenticated">
+<table class="form-table">
   <tbody>
     <tal:block repeat="widget view/widgets">
@@ -19,2 +15,6 @@
   </tbody>
 </table>
+
+<span tal:condition="view/introduction" tal:omit-tag="">
+  <p tal:content="structure view/introduction">INTRODUCTION</p>
+</span>
Index: main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/browser_templates/applicantsrootpage.pt
===================================================================
--- main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/browser_templates/applicantsrootpage.pt	(revision 9166)
+++ main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/browser_templates/applicantsrootpage.pt	(revision 9209)
@@ -25,7 +25,7 @@
       </td>
       <td>
-      <span tal:content="python: layout.formatDate(entry.startdate)">START</span>
+      <span tal:content="python: layout.formatTZDate(entry.startdate)">START</span>
       -
-      <span tal:content="python: layout.formatDate(entry.enddate)">END</span>
+      <span tal:content="python: layout.formatTZDate(entry.enddate)">END</span>
       </td>
     </tr>
Index: main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/container.py
===================================================================
--- main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/container.py	(revision 9166)
+++ main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/container.py	(revision 9209)
@@ -51,7 +51,5 @@
     description_dict = {}
 
-    @property
-    def local_roles(self):
-        return []
+    local_roles = []
 
     def archive(self, app_ids=None):
Index: main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/dynamicroles.py
===================================================================
--- main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/dynamicroles.py	(revision 9166)
+++ main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/dynamicroles.py	(revision 9209)
@@ -24,17 +24,16 @@
 import grok
 from zope.securitypolicy.interfaces import IPrincipalRoleManager
+from zope.securitypolicy.principalrole import AnnotationPrincipalRoleManager
 from waeup.kofa.applicants.interfaces import IApplicant
-from waeup.kofa.students.dynamicroles import StudentPrincipalRoleManager
 
 # All components in here have the same context: Applicant instances
 grok.context(IApplicant)
 
-class ApplicantPrincipalRoleManager(StudentPrincipalRoleManager):
-
+class ApplicantPrincipalRoleManager(AnnotationPrincipalRoleManager,
+                                    grok.Adapter):
     grok.provides(IPrincipalRoleManager)
 
     #: The attribute name to lookup for additional roles
     extra_attrib = 'course1'
-    subcontainer = None
 
     # Role name mapping:
@@ -45,2 +44,62 @@
         'waeup.local.ClearanceOfficer':'waeup.ApplicationsOfficer',
         }
+
+    def getRolesForPrincipal(self, principal_id):
+        """Get roles for principal with id `principal_id`.
+
+        Different to the default implementation, this method also
+        takes into account local roles set on any department connected
+        to the context student.
+
+        If the given principal has at least one of the
+        `external_rolenames` roles granted for the external object, it
+        additionally gets `additional_rolename` role for the context
+        student.
+
+        For the additional roles the `extra_attrib` and all its parent
+        objects are looked up, because 'role inheritance' does not
+        work on that basic level of permission handling.
+
+        Some advantages of this approach:
+
+        - we don't have to store extra local roles for clearance
+          officers in ZODB for each student
+
+        - when local roles on a department change, we don't have to
+          update thousands of students; the local role is assigned
+          dynamically.
+
+        Disadvantage:
+
+        - More expensive role lookups when a clearance officer wants
+          to see an student form.
+
+        This implementation is designed to be usable also for other
+        contexts than students. You can inherit from it and set
+        different role names to lookup/set easily via the static class
+        attributes.
+        """
+        apr_manager = AnnotationPrincipalRoleManager(self._context)
+        result = apr_manager.getRolesForPrincipal(principal_id)
+        if result != []:
+            # If there are local roles defined here, no additional
+            # lookup is done.
+            return result
+        # The principal has no local roles yet. Let's lookup the
+        # connected course, dept, etc.
+        obj = getattr(self._context, self.extra_attrib, None)
+        # Lookup local roles for connected course and all parent
+        # objects. This way we fake 'role inheritance'.
+        while obj is not None:
+            extra_roles = IPrincipalRoleManager(obj).getRolesForPrincipal(
+                principal_id)
+            for role_id, setting in extra_roles:
+                if role_id in self.rolename_mapping.keys():
+                    # Grant additional role
+                    # permissions (allow, deny or unset)
+                    # according to the rolename mapping above.
+                    result.append(
+                        (self.rolename_mapping[role_id], setting))
+                    return result
+            obj = getattr(obj, '__parent__', None)
+        return result
Index: main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/export.py
===================================================================
--- main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/export.py	(revision 9166)
+++ main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/export.py	(revision 9209)
@@ -83,4 +83,8 @@
         elif name == 'history':
             value = value.messages
+        elif name == 'phone' and value is not None:
+            # Append hash '#' to phone numbers to circumvent
+            # unwanted excel automatic
+            value = str('%s#' % value)
         return super(
             ApplicantsExporter, self).mangle_value(
Index: main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/interfaces.py
===================================================================
--- main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/interfaces.py	(revision 9166)
+++ main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/interfaces.py	(revision 9209)
@@ -18,4 +18,5 @@
 """Interfaces of the university application package.
 """
+from datetime import datetime
 from grokcore.content.interfaces import IContainer
 from zc.sourcefactory.contextual import BasicContextualSourceFactory
@@ -29,5 +30,5 @@
 from waeup.kofa.schema import TextLineChoice, FormattedDate
 from waeup.kofa.interfaces import (
-    IKofaObject, year_range, validate_email,
+    IKofaObject, validate_email,
     SimpleKofaVocabulary)
 from waeup.kofa.interfaces import MessageFactory as _
@@ -41,4 +42,8 @@
 
 _marker = object() # a marker different from None
+
+def year_range():
+    curr_year = datetime.now().year
+    return range(curr_year - 2, curr_year + 5)
 
 class RegNumInSource(ValidationError):
@@ -323,4 +328,10 @@
     application_number = Attribute('The key under which the record is stored')
 
+    suspended = schema.Bool(
+        title = _(u'Account suspended'),
+        default = False,
+        required = False,
+        )
+
     applicant_id = schema.TextLine(
         title = _(u'Applicant Id'),
@@ -393,12 +404,4 @@
         required = False,
         )
-    screening_venue = schema.TextLine(
-        title = _(u'Screening Venue'),
-        required = False,
-        )
-    screening_score = schema.Int(
-        title = _(u'Screening Score'),
-        required = False,
-        )
     student_id = schema.TextLine(
         title = _(u'Student Id'),
@@ -460,14 +463,4 @@
         required = False,
         )
-    screening_score = schema.Int(
-        title = _(u'Screening Score'),
-        required = False,
-        readonly = True,
-        )
-    screening_venue = schema.TextLine(
-        title = _(u'Screening Venue'),
-        required = False,
-        readonly = True,
-        )
     course_admitted = schema.Choice(
         title = _(u'Admitted Course of Study'),
Index: main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/tests/test_applicantcopier.py
===================================================================
--- main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/tests/test_applicantcopier.py	(revision 9166)
+++ main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/tests/test_applicantcopier.py	(revision 9209)
@@ -21,4 +21,5 @@
 import os
 import grok
+from datetime import datetime
 from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState
 from zope.event import notify
@@ -28,4 +29,6 @@
 from waeup.kofa.interfaces import IExtFileStore, IFileStoreNameChooser
 from waeup.kofa.applicants.tests.test_browser import ApplicantsFullSetup
+
+session = datetime.now().year - 2
 
 class ApplicantCopierFunctionalTests(ApplicantsFullSetup):
@@ -67,4 +70,12 @@
         self.browser.getControl(name="form.course_admitted").value = ['CERT1']
         self.browser.getControl("Save").click()
+        # Maybe the certificate has meanwhile been removed
+        del self.app['faculties']['fac1']['dep1'].certificates['CERT1']
+        (success, msg) = self.applicant.createStudent()
+        self.assertFalse(success)
+        self.assertTrue('ConstraintNotSatisfied: CERT1' in msg)
+        # Ok, lets add the certificate and try again
+        self.app['faculties']['fac1']['dep1'].certificates.addCertificate(
+            self.certificate)
         (success, msg) = self.applicant.createStudent()
         self.assertTrue('created' in msg)
@@ -82,4 +93,6 @@
         self.assertEqual(student.firstname, 'John')
         self.assertEqual(student.lastname, 'Tester')
+        # student_id set in application record?
+        self.assertEqual(self.applicant.student_id, student.student_id)
         # Check if passport image has been copied
         storage = getUtility(IExtFileStore)
@@ -110,7 +123,7 @@
         # Has the student studycourse the correct attributes?
         self.assertEqual(student['studycourse'].certificate.code, 'CERT1')
-        self.assertEqual(student['studycourse'].entry_session, 2009)
+        self.assertEqual(student['studycourse'].entry_session, session)
         self.assertEqual(student['studycourse'].entry_mode, 'ug_ft')
-        self.assertEqual(student['studycourse'].current_session, 2009)
+        self.assertEqual(student['studycourse'].current_session, session)
         self.assertEqual(student['studycourse'].current_level, 100)
 
Index: main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/tests/test_authentication.py
===================================================================
--- main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/tests/test_authentication.py	(revision 9166)
+++ main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/tests/test_authentication.py	(revision 9209)
@@ -64,4 +64,5 @@
     email = None
     phone = None
+    suspended = False
 
 
Index: main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/tests/test_browser.py
===================================================================
--- main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/tests/test_browser.py	(revision 9166)
+++ main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/tests/test_browser.py	(revision 9209)
@@ -23,4 +23,5 @@
 import tempfile
 import grok
+from datetime import datetime
 from StringIO import StringIO
 from datetime import datetime, date, timedelta
@@ -46,4 +47,9 @@
 PH_LEN = 2059  # Length of placeholder file
 
+session_1 = datetime.now().year - 2
+container_name_1 = u'app%s' % session_1
+session_2 = datetime.now().year - 1
+container_name_2 = u'app%s' % session_2
+
 class ApplicantsFullSetup(FunctionalTestCase):
     # A test case that only contains a setup and teardown
@@ -80,13 +86,13 @@
         self.manage_root_path = self.root_path + '/@@manage'
         self.add_container_path = self.root_path + '/@@add'
-        self.container_path = 'http://localhost/app/applicants/app2009'
+        self.container_path = 'http://localhost/app/applicants/%s' % container_name_1
         self.manage_container_path = self.container_path + '/@@manage'
 
         # Add an applicants container
         applicantscontainer = ApplicantsContainer()
-        applicantscontainer.code = u'app2009'
+        applicantscontainer.code = container_name_1
         applicantscontainer.prefix = 'app'
-        applicantscontainer.year = 2009
-        applicantscontainer.title = u'This is the app2009 container'
+        applicantscontainer.year = session_1
+        applicantscontainer.title = u'This is the %s container' % container_name_1
         applicantscontainer.application_category = 'basic'
         applicantscontainer.mode = 'create'
@@ -95,6 +101,6 @@
         applicantscontainer.startdate = datetime.now(pytz.utc) - delta
         applicantscontainer.enddate = datetime.now(pytz.utc) + delta
-        self.app['applicants']['app2009'] = applicantscontainer
-        self.applicantscontainer = self.app['applicants']['app2009']
+        self.app['applicants'][container_name_1] = applicantscontainer
+        self.applicantscontainer = self.app['applicants'][container_name_1]
 
         # Populate university
@@ -135,14 +141,14 @@
         self.applicant.reg_number = u'1234'
         self.applicant.course1 = certificate
-        app['applicants']['app2009'].addApplicant(self.applicant)
+        app['applicants'][container_name_1].addApplicant(self.applicant)
         IUserAccount(
-            self.app['applicants']['app2009'][
+            self.app['applicants'][container_name_1][
             self.applicant.application_number]).setPassword('apwd')
         self.manage_path = 'http://localhost/app/applicants/%s/%s/%s' % (
-            'app2009', self.applicant.application_number, 'manage')
+            container_name_1, self.applicant.application_number, 'manage')
         self.edit_path = 'http://localhost/app/applicants/%s/%s/%s' % (
-            'app2009', self.applicant.application_number, 'edit')
+            container_name_1, self.applicant.application_number, 'edit')
         self.view_path = 'http://localhost/app/applicants/%s/%s' % (
-            'app2009', self.applicant.application_number)
+            container_name_1, self.applicant.application_number)
 
     def login(self):
@@ -303,5 +309,5 @@
             'There were errors' in self.browser.contents)
         self.browser.getControl(name="form.prefix").value = ['app']
-        self.browser.getControl(name="form.year").value = ['2010']
+        self.browser.getControl(name="form.year").value = [str(session_2)]
         self.browser.getControl(name="form.mode").value = ['create']
         self.browser.getControl(
@@ -317,5 +323,5 @@
         self.browser.open(self.add_container_path)
         self.browser.getControl(name="form.prefix").value = ['app']
-        self.browser.getControl(name="form.year").value = ['2010']
+        self.browser.getControl(name="form.year").value = [str(session_2)]
         self.browser.getControl(name="form.mode").value = ['create']
         self.browser.getControl(
@@ -326,10 +332,10 @@
         self.browser.open(self.manage_root_path)
         ctrl = self.browser.getControl(name='val_id')
-        ctrl.getControl(value='app2010').selected = True
+        ctrl.getControl(value=container_name_2).selected = True
         self.browser.getControl("Remove selected", index=0).click()
         self.assertTrue('Successfully removed:' in self.browser.contents)
         self.browser.open(self.add_container_path)
         self.browser.getControl(name="form.prefix").value = ['app']
-        self.browser.getControl(name="form.year").value = ['2010']
+        self.browser.getControl(name="form.year").value = [str(session_2)]
         self.browser.getControl(name="form.mode").value = ['create']
         #self.browser.getControl(name="form.ac_prefix").value = ['APP']
@@ -337,7 +343,7 @@
             name="form.application_category").value = ['basic']
         self.browser.getControl("Add applicants container").click()
-        del self.app['applicants']['app2010']
+        del self.app['applicants'][container_name_2]
         ctrl = self.browser.getControl(name='val_id')
-        ctrl.getControl(value='app2010').selected = True
+        ctrl.getControl(value=container_name_2).selected = True
         self.browser.getControl("Remove selected", index=0).click()
         self.assertMatches('...Could not delete...', self.browser.contents)
@@ -465,8 +471,8 @@
         self.browser.open(self.slip_path)
         self.assertTrue(
-            'Please pay before trying to download the application slip.'
+            'Please pay and submit before trying to download the application slip.'
             in self.browser.contents)
         # If applicant is in correct state the pdf slip can be opened.
-        IWorkflowState(self.applicant).setState('paid')
+        IWorkflowState(self.applicant).setState('submitted')
         self.browser.open(self.manage_path)
         self.browser.getLink("Download application slip").click()
@@ -493,8 +499,20 @@
             self.browser.headers['content-length'], str(PH_LEN))
 
+    def test_applicant_login(self):
+        self.applicant.suspended = True
+        self.login()
+        self.assertTrue(
+            'You entered invalid credentials.' in self.browser.contents)
+        self.applicant.suspended = False
+        self.browser.getControl("Login").click()
+        self.assertTrue(
+            'You logged in.' in self.browser.contents)
+
     def test_applicant_access(self):
         # Applicants can edit their record
         self.browser.open(self.login_path)
         self.login()
+        self.assertTrue(
+            'You logged in.' in self.browser.contents)
         self.browser.open(self.edit_path)
         self.assertTrue(self.browser.url != self.login_path)
@@ -699,5 +717,5 @@
             in self.browser.contents)
         configuration = SessionConfiguration()
-        configuration.academic_session = 2009
+        configuration.academic_session = session_1
         configuration.application_fee = 200.0
         self.app['configuration'].addSessionConfiguration(configuration)
@@ -727,6 +745,6 @@
         payment_id = self.applicant.keys()[0]
         payment = self.applicant[payment_id]
-        self.assertEqual(payment.p_item,'This is the app2009 container')
-        self.assertEqual(payment.p_session,2009)
+        self.assertEqual(payment.p_item,'This is the %s container' % container_name_1)
+        self.assertEqual(payment.p_session, session_1)
         self.assertEqual(payment.p_category,'application')
         self.assertEqual(payment.amount_auth,200.0)
@@ -821,5 +839,5 @@
         self.browser.getControl("Final Submit").click()
         self.assertTrue(
-            '... submitted ...' in self.browser.contents)
+            'Application submitted' in self.browser.contents)
         # ... or allow submission after deadline.
         IWorkflowState(self.applicant).setState('paid')
@@ -830,5 +848,5 @@
         self.browser.getControl("Final Submit").click()
         self.assertTrue(
-            '... submitted ...' in self.browser.contents)
+            'Application submitted' in self.browser.contents)
         self.browser.goBack(count=1)
         self.browser.getControl("Save").click()
@@ -917,5 +935,5 @@
         self.browser.getControl(name="form.phone.area").value = '555'
         self.browser.getControl(name="form.phone.ext").value = '6666666'
-        self.browser.getControl("Get login credentials").click()
+        self.browser.getControl("Send login credentials").click()
         self.assertEqual(self.browser.url,
             self.container_path + '/registration_complete?email=xx%40yy.zz')
@@ -944,5 +962,5 @@
         self.browser.getControl(name="form.reg_number").value = 'anynumber'
         self.browser.getControl(name="form.email").value = 'xx@yy.zz'
-        self.browser.getControl("Get login credentials").click()
+        self.browser.getControl("Send login credentials").click()
         self.assertTrue('No application record found.'
             in self.browser.contents)
@@ -954,5 +972,5 @@
         self.browser.getControl(name="form.reg_number").value = '1234'
         self.browser.getControl(name="form.email").value = 'xx@yy.zz'
-        self.browser.getControl("Get login credentials").click()
+        self.browser.getControl("Send login credentials").click()
         self.assertTrue('An error occurred.' in self.browser.contents)
         # Let's set this attribute manually
@@ -963,5 +981,5 @@
         self.browser.getControl(name="form.reg_number").value = '1234'
         self.browser.getControl(name="form.email").value = 'xx@yy.zz'
-        self.browser.getControl("Get login credentials").click()
+        self.browser.getControl("Send login credentials").click()
         # Anonymous is not informed that firstname verification failed.
         # It seems that the record doesn't exist.
@@ -973,9 +991,9 @@
         self.browser.getControl(name="form.firstname").value = 'John'
         self.browser.getControl(name="form.reg_number").value = '1234'
-        self.browser.getControl("Get login credentials").click()
+        self.browser.getControl("Send login credentials").click()
         self.assertTrue('Your password has already been set and used.'
             in self.browser.contents)
         #IUserAccount(
-        #    self.app['applicants']['app2009'][
+        #    self.app['applicants'][container_name_1][
         #    self.applicant.application_number]).context.password = None
         # Even without unsetting the password we can re-register if state
@@ -987,5 +1005,5 @@
         self.browser.getControl(name="form.reg_number").value = '1234'
         self.browser.getControl(name="form.email").value = 'new@yy.zz'
-        self.browser.getControl("Get login credentials").click()
+        self.browser.getControl("Send login credentials").click()
         # Yeah, we succeded ...
         self.assertTrue('Your registration was successful.'
@@ -1003,5 +1021,5 @@
         self.browser.getControl(name="form.identifier").value = '1234'
         self.browser.getControl(name="form.email").value = 'aa@aa.ng'
-        self.browser.getControl("Get login credentials").click()
+        self.browser.getControl("Send login credentials").click()
         self.assertTrue('No record found' in self.browser.contents)
         self.applicant.email = 'aa@aa.ng'
@@ -1011,5 +1029,5 @@
         self.browser.getControl(name="form.identifier").value = '1234'
         self.browser.getControl(name="form.email").value = 'aa@aa.ng'
-        self.browser.getControl("Get login credentials").click()
+        self.browser.getControl("Send login credentials").click()
         self.assertTrue(
             'An email with your user name and password has been sent'
Index: main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/tests/test_export.py
===================================================================
--- main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/tests/test_export.py	(revision 9166)
+++ main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/tests/test_export.py	(revision 9209)
@@ -120,6 +120,4 @@
         applicant.course_admitted = self.certificate
         applicant.notice = u'Some notice\nin lines.'
-        applicant.screening_score = 98
-        applicant.screening_venue = u'Exam Room'
         applicant.password = 'any password'
         result_entry = ResultEntry(
@@ -144,11 +142,11 @@
             'course_admitted,date_of_birth,display_fullname,email,firstname,'
             'history,lastname,locked,middlename,notice,password,phone,'
-            'reg_number,screening_score,screening_venue,sex,state,'
-            'student_id,container_code\r\n'
+            'reg_number,sex,state,'
+            'student_id,suspended,container_code\r\n'
             'dp2011_654321,,654321,,,,,Anna Tester,,Anna,'
             in result)
         self.assertTrue(
             'Application initialized by system\'],Tester,'
-            '0,,,,,,,,,initialized,,dp2011\r\n'
+            '0,,,,,,,initialized,,0,dp2011\r\n'
             in result)
         return
@@ -168,6 +166,6 @@
             'course_admitted,date_of_birth,display_fullname,email,firstname,'
             'history,lastname,locked,middlename,notice,password,phone,'
-            'reg_number,screening_score,screening_venue,sex,state,'
-            'student_id,container_code\r\n'
+            'reg_number,sex,state,'
+            'student_id,suspended,container_code\r\n'
             'dp2011_654321,,654321,CERT1,CERT1,CERT1,1981-02-04#,'
             'Anna M. Tester,anna@sample.com,Anna,'
@@ -176,5 +174,5 @@
             'Application initialized by system\'],'
             'Tester,0,M.,"Some notice\nin lines.",any password,'
-            '+234-123-12345,123456,98,Exam Room,f,initialized,,dp2011\r\n'
+            '+234-123-12345#,123456,f,initialized,,0,dp2011\r\n'
             in result)
 
@@ -192,6 +190,6 @@
             'course_admitted,date_of_birth,display_fullname,email,firstname,'
             'history,lastname,locked,middlename,notice,password,phone,'
-            'reg_number,screening_score,screening_venue,sex,state,'
-            'student_id,container_code\r\n'
+            'reg_number,sex,state,'
+            'student_id,suspended,container_code\r\n'
             'dp2011_654321,,654321,CERT1,CERT1,CERT1,1981-02-04#,'
             'Anna M. Tester,anna@sample.com,Anna,'
@@ -200,5 +198,5 @@
             'Application initialized by system\'],'
             'Tester,0,M.,"Some notice\nin lines.",any password,'
-            '+234-123-12345,123456,98,Exam Room,f,initialized,,dp2011\r\n'
-            in result)
-        return
+            '+234-123-12345#,123456,f,initialized,,0,dp2011\r\n'
+            in result)
+        return
Index: main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/utils.py
===================================================================
--- main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/utils.py	(revision 9166)
+++ main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/utils.py	(revision 9209)
@@ -39,5 +39,5 @@
     SEPARATORS_DICT = {
       'form.course1': _(u'Desired Study Courses'),
-      'form.screening_score': _(u'Process Data'),
+      'form.student_id': _(u'Process Data'),
       }
 
@@ -45,5 +45,5 @@
         """Set the payment data of an applicant.
         """
-        timestamp = "%d" % int(time()*1000)
+        timestamp = ("%d" % int(time()*10000))[1:]
         container_fee = container.application_fee
         if container_fee:
Index: main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/viewlets.py
===================================================================
--- main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/viewlets.py	(revision 9166)
+++ main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/viewlets.py	(revision 9209)
@@ -183,5 +183,5 @@
         """Get a URL to the target...
         """
-        if self.context.state in ('initialized', 'started'):
+        if self.context.state in ('initialized', 'started', 'paid'):
             return
         return self.view.url(self.view.context, self.target)
@@ -204,5 +204,5 @@
 
 class PaymentReceiptActionButton(ManageActionButton):
-    grok.order(1)
+    grok.order(9) # This button should always be the last one.
     grok.context(IApplicantOnlinePayment)
     grok.view(OnlinePaymentDisplayFormPage)
@@ -219,5 +219,5 @@
 
 class ApprovePaymentActionButton(ManageActionButton):
-    grok.order(2)
+    grok.order(8)
     grok.context(IApplicantOnlinePayment)
     grok.view(OnlinePaymentDisplayFormPage)
Index: main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/workflow.py
===================================================================
--- main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/workflow.py	(revision 9166)
+++ main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/workflow.py	(revision 9209)
@@ -150,4 +150,10 @@
         source = PAID,
         destination = STARTED),
+    Transition(
+        transition_id = 'reset7',
+        title = _('Reset application to admitted'),
+        msg = _('Application reset to admitted'),
+        source = CREATED,
+        destination = ADMITTED),
     )
 
