Index: main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/browser.py
===================================================================
--- main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/browser.py	(revision 9169)
+++ main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/browser.py	(revision 9208)
@@ -361,4 +361,26 @@
         return
 
+class ExportPDFAdmissionSlipPage(UtilityView, grok.View):
+    """Deliver a PDF Admission slip.
+    """
+    grok.context(IStudent)
+    grok.name('admission_slip.pdf')
+    grok.require('waeup.viewStudent')
+    prefix = 'form'
+
+    form_fields = grok.AutoFields(IStudentBase).select('student_id', 'reg_number')
+
+    @property
+    def label(self):
+        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
+        return translate(_('Admission Letter of'),
+            'waeup.kofa', target_language=portal_language) \
+            + ' %s' % self.context.display_fullname
+
+    def render(self):
+        students_utils = getUtility(IStudentsUtils)
+        return students_utils.renderPDFAdmissionLetter(self,
+            self.context.student)
+
 class StudentBaseManageFormPage(KofaEditFormPage):
     """ View to manage student base data
@@ -1234,5 +1256,5 @@
         if error is not None:
             self.flash(error)
-            if 'Would you like' in error:
+            if 'previous session' in error:
                 self.redirect(self.url(self.context) + '/@@addpp')
                 return
@@ -1409,4 +1431,5 @@
     buttonname = _('Create bed ticket')
     notice = ''
+    with_ac = True
 
     def update(self, SUBMIT=None):
@@ -1449,13 +1472,15 @@
             self.redirect(self.url(self.context))
             return
-        self.ac_series = self.request.form.get('ac_series', None)
-        self.ac_number = self.request.form.get('ac_number', None)
+        if self.with_ac:
+            self.ac_series = self.request.form.get('ac_series', None)
+            self.ac_number = self.request.form.get('ac_number', None)
         if SUBMIT is None:
             return
-        pin = '%s-%s-%s' % (self.ac_prefix, self.ac_series, self.ac_number)
-        code = get_access_code(pin)
-        if not code:
-            self.flash(_('Activation code is invalid.'))
-            return
+        if self.with_ac:
+            pin = '%s-%s-%s' % (self.ac_prefix, self.ac_series, self.ac_number)
+            code = get_access_code(pin)
+            if not code:
+                self.flash(_('Activation code is invalid.'))
+                return
         # Search and book bed
         cat = queryUtility(ICatalog, name='beds_catalog', default=None)
@@ -1463,5 +1488,5 @@
             owner=(student.student_id,student.student_id))
         if len(entries):
-            # If bed space has bee manually allocated use this bed
+            # If bed space has been manually allocated use this bed
             bed = [entry for entry in entries][0]
         else:
@@ -1479,24 +1504,26 @@
                     mapping = {'a':acc_details['bt']}))
                 return
-        # Mark pin as used (this also fires a pin related transition)
-        if code.state == USED:
-            self.flash(_('Activation code has already been used.'))
-            return
-        else:
-            comment = _(u'invalidated')
-            # Here we know that the ac is in state initialized so we do not
-            # expect an exception, but the owner might be different
-            if not invalidate_accesscode(
-                pin,comment,self.context.student.student_id):
-                self.flash(_('You are not the owner of this access code.'))
+        if self.with_ac:
+            # Mark pin as used (this also fires a pin related transition)
+            if code.state == USED:
+                self.flash(_('Activation code has already been used.'))
                 return
+            else:
+                comment = _(u'invalidated')
+                # Here we know that the ac is in state initialized so we do not
+                # expect an exception, but the owner might be different
+                if not invalidate_accesscode(
+                    pin,comment,self.context.student.student_id):
+                    self.flash(_('You are not the owner of this access code.'))
+                    return
         # Create bed ticket
         bedticket = createObject(u'waeup.BedTicket')
-        bedticket.booking_code = pin
+        if self.with_ac:
+            bedticket.booking_code = pin
         bedticket.booking_session = acc_details['booking_session']
         bedticket.bed_type = acc_details['bt']
         bedticket.bed = bed
         hall_title = bed.__parent__.hostel_name
-        coordinates = bed.getBedCoordinates()[1:]
+        coordinates = bed.coordinates[1:]
         block, room_nr, bed_nr = coordinates
         bc = _('${a}, Block ${b}, Room ${c}, Bed ${d} (${e})', mapping = {
@@ -1521,4 +1548,5 @@
     grok.require('waeup.handleAccommodation')
     form_fields = grok.AutoFields(IBedTicket)
+    form_fields['booking_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
     pnav = 4
 
@@ -1547,7 +1575,10 @@
     def label(self):
         portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
-        return translate(_('Bed Allocation: '),
+        #return translate(_('Bed Allocation: '),
+        #    'waeup.kofa', target_language=portal_language) \
+        #    + ' %s' % self.context.bed_coordinates
+        return translate(_('Bed Allocation Slip'),
             'waeup.kofa', target_language=portal_language) \
-            + ' %s' % self.context.bed_coordinates
+            + ' %s' % self.context.getSessionString()
 
     def render(self):
@@ -1614,5 +1645,5 @@
         self.context.bed = new_bed
         hall_title = new_bed.__parent__.hostel_name
-        coordinates = new_bed.getBedCoordinates()[1:]
+        coordinates = new_bed.coordinates[1:]
         block, room_nr, bed_nr = coordinates
         bc = _('${a}, Block ${b}, Room ${c}, Bed ${d} (${e})', mapping = {
Index: main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/browser_templates/basepage.pt
===================================================================
--- main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/browser_templates/basepage.pt	(revision 9169)
+++ main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/browser_templates/basepage.pt	(revision 9208)
@@ -18,5 +18,5 @@
           <tal:password replace="view/hasPassword" />
       </td>
-    <tr>
+    </tr>
     <tal:files content="structure provider:files" />
   </tbody>
Index: main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/interfaces.py
===================================================================
--- main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/interfaces.py	(revision 9169)
+++ main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/interfaces.py	(revision 9208)
@@ -156,4 +156,5 @@
     current_level = Attribute('The current level of the student')
     current_mode = Attribute('The current mode of the student')
+    current_verdict = Attribute('The current verdict of the student')
     fullname = Attribute('All name parts separated by hyphens')
     display_fullname = Attribute('The fullname of an applicant')
Index: main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/student.py
===================================================================
--- main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/student.py	(revision 9169)
+++ main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/student.py	(revision 9208)
@@ -134,4 +134,10 @@
         level = getattr(
             self.get('studycourse', None), 'current_level', None)
+        return level
+
+    @property
+    def current_verdict(self):
+        level = getattr(
+            self.get('studycourse', None), 'current_verdict', None)
         return level
 
Index: main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/tests/test_browser.py
===================================================================
--- main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/tests/test_browser.py	(revision 9169)
+++ main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/tests/test_browser.py	(revision 9208)
@@ -403,4 +403,13 @@
 
     layer = FunctionalLayer
+
+    def test_student_properties(self):
+        self.student['studycourse'].current_level = 100
+        self.assertEqual(self.student.current_level, 100)
+        self.student['studycourse'].current_session = 2011
+        self.assertEqual(self.student.current_session, 2011)
+        self.student['studycourse'].current_verdict = 'A'
+        self.assertEqual(self.student.current_verdict, 'A')
+        return
 
     def test_basic_auth(self):
@@ -1183,5 +1192,5 @@
         self.assertTrue(
             'You logged in.' in self.browser.contents)
-        # Student can upload a passport picture
+        # Admitted student can upload a passport picture
         self.browser.open(self.student_path + '/change_portrait')
         ctrl = self.browser.getControl(name='passportuploadedit')
@@ -1194,5 +1203,11 @@
             '<img align="middle" height="125px" src="passport.jpg" />'
             in self.browser.contents)
+        # Students can open admission letter
+        self.browser.getLink("Base Data").click()
+        self.browser.getLink("Download admission letter").click()
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
         # Student can view the clearance data
+        self.browser.open(self.student_path)
         self.browser.getLink("Clearance Data").click()
         # Student can't open clearance edit form before starting clearance
@@ -1584,4 +1599,16 @@
 
     def test_student_previous_payments(self):
+        configuration = createObject('waeup.SessionConfiguration')
+        configuration.academic_session = 2000
+        configuration.clearance_fee = 3456.0
+        configuration.booking_fee = 123.4
+        self.student['studycourse'].entry_session = 2002
+        self.app['configuration'].addSessionConfiguration(configuration)
+        configuration2 = createObject('waeup.SessionConfiguration')
+        configuration2.academic_session = 2003
+        configuration2.clearance_fee = 3456.0
+        configuration2.booking_fee = 123.4
+        self.student['studycourse'].entry_session = 2002
+        self.app['configuration'].addSessionConfiguration(configuration2)
         # Login
         self.browser.open(self.login_path)
@@ -1606,5 +1633,17 @@
         # Previous session payment form is provided
         self.browser.getControl(name="form.p_category").value = ['schoolfee']
+        self.browser.getControl(name="form.p_session").value = ['2000']
+        self.browser.getControl(name="form.p_level").value = ['300']
+        self.browser.getControl("Create ticket").click()
+        self.assertMatches('...The previous session must not fall below...',
+                           self.browser.contents)
+        self.browser.getControl(name="form.p_category").value = ['schoolfee']
         self.browser.getControl(name="form.p_session").value = ['2004']
+        self.browser.getControl(name="form.p_level").value = ['300']
+        self.browser.getControl("Create ticket").click()
+        self.assertMatches('...This is not a previous session...',
+                           self.browser.contents)
+        self.browser.getControl(name="form.p_category").value = ['schoolfee']
+        self.browser.getControl(name="form.p_session").value = ['2003']
         self.browser.getControl(name="form.p_level").value = ['300']
         self.browser.getControl("Create ticket").click()
@@ -1619,5 +1658,5 @@
 
         # Payment session is properly set
-        self.assertEqual(self.student['payments'][value].p_session, 2004)
+        self.assertEqual(self.student['payments'][value].p_session, 2003)
         self.assertEqual(self.student['payments'][value].p_level, 300)
 
@@ -1954,5 +1993,5 @@
         self.browser.getControl(name="form.identifier").value = '123'
         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' in self.browser.contents)
 
Index: main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/utils.py
===================================================================
--- main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/utils.py	(revision 9169)
+++ main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/utils.py	(revision 9208)
@@ -138,5 +138,24 @@
         f_label = formatted_label(size=12) % _('Study Course')
         f_label = Paragraph(f_label, style["Normal"])
-        f_text = formatted_text(studentview.context.certcode, size=12)
+        f_text = formatted_text(
+            studentview.context['studycourse'].certificate.longtitle(), size=12)
+        f_text = Paragraph(f_text, style["Normal"])
+        data_right.append([f_label,f_text])
+
+        f_label = formatted_label(size=12) % _('Department')
+        f_label = Paragraph(f_label, style["Normal"])
+        f_text = formatted_text(
+            studentview.context[
+            'studycourse'].certificate.__parent__.__parent__.longtitle(),
+            size=12)
+        f_text = Paragraph(f_text, style["Normal"])
+        data_right.append([f_label,f_text])
+
+        f_label = formatted_label(size=12) % _('Faculty')
+        f_label = Paragraph(f_label, style["Normal"])
+        f_text = formatted_text(
+            studentview.context[
+            'studycourse'].certificate.__parent__.__parent__.__parent__.longtitle(),
+            size=12)
         f_text = Paragraph(f_text, style["Normal"])
         data_right.append([f_label,f_text])
@@ -309,4 +328,9 @@
                 return _('Study course data are incomplete.'), None
             if previous_session:
+                if previous_session < student['studycourse'].entry_session:
+                    return _('The previous session must not fall below '
+                             'your entry session.'), None
+                if previous_session > student['studycourse'].current_session - 1:
+                    return _('This is not a previous session.'), None
                 if previous_level == 100:
                     amount = getattr(certificate, 'school_fee_1', 0.0)
@@ -328,5 +352,8 @@
                     amount = getattr(certificate, 'school_fee_2', 0.0)
         elif category == 'clearance':
-            p_item = student['studycourse'].certificate.code
+            try:
+                p_item = student['studycourse'].certificate.code
+            except (AttributeError, TypeError):
+                return _('Study course data are incomplete.'), None
             amount = academic_session.clearance_fee
         elif category == 'bed_allocation':
@@ -371,6 +398,6 @@
         entry_session = studycourse.entry_session
         current_level = studycourse.current_level
-        if not (entry_session and current_level and certificate):
-            return
+        if None in (entry_session, current_level, certificate):
+            return d
         end_level = certificate.end_level
         if current_level == 10:
@@ -398,4 +425,55 @@
         return available_beds[0]
 
+    def renderPDFAdmissionLetter(self, view, student=None):
+        """Render pdf admission letter.
+        """
+        # XXX: we have to fix the import problems here.
+        from waeup.kofa.browser.interfaces import IPDFCreator
+        from waeup.kofa.browser.pdf import format_html, NOTE_STYLE
+        if student is None:
+            return
+        style = getSampleStyleSheet()
+        creator = getUtility(IPDFCreator)
+        data = []
+        doc_title = view.label
+        author = '%s (%s)' % (view.request.principal.title,
+                              view.request.principal.id)
+        footer_text = view.label
+        if getattr(student, 'student_id', None) is not None:
+            footer_text = "%s - %s - " % (student.student_id, footer_text)
+
+        # Admission text
+        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
+        inst_name = grok.getSite()['configuration'].name
+        text = trans(_(
+            'This is to inform you that you have been provisionally'
+            ' admitted into ${a} as follows:', mapping = {'a': inst_name}),
+            portal_language)
+        html = format_html(text)
+        data.append(Paragraph(html, NOTE_STYLE))
+        data.append(Spacer(1, 20))
+
+        # Student data
+        data.append(render_student_data(view))
+
+        # Insert history
+        data.append(Spacer(1, 20))
+        datelist = student.history.messages[0].split()[0].split('-')
+        creation_date = u'%s/%s/%s' % (datelist[2], datelist[1], datelist[0])
+        text = trans(_(
+            'Your Kofa student record was created on ${a}.',
+            mapping = {'a': creation_date}),
+            portal_language)
+        html = format_html(text)
+        data.append(Paragraph(html, NOTE_STYLE))
+
+        # Create pdf stream
+        view.response.setHeader(
+            'Content-Type', 'application/pdf')
+        pdf_stream = creator.create_pdf(
+            data, None, doc_title, author=author, footer=footer_text,
+            note=None)
+        return pdf_stream
+
     def renderPDF(self, view, filename='slip.pdf', student=None,
                   studentview=None, tableheader=None, tabledata=None,
@@ -428,11 +506,12 @@
 
         # Insert widgets
-        data.append(Paragraph(view.title, style["Heading3"]))
-        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
-        separators = getattr(self, 'SEPARATORS_DICT', {})
-        table = creator.getWidgetsTable(
-            view.form_fields, view.context, None, lang=portal_language,
-            separators=separators)
-        data.append(table)
+        if view.form_fields:
+            data.append(Paragraph(view.title, style["Heading3"]))
+            portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
+            separators = getattr(self, 'SEPARATORS_DICT', {})
+            table = creator.getWidgetsTable(
+                view.form_fields, view.context, None, lang=portal_language,
+                separators=separators)
+            data.append(table)
 
         # Insert scanned docs
Index: main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/viewlets.py
===================================================================
--- main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/viewlets.py	(revision 9169)
+++ main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/viewlets.py	(revision 9208)
@@ -150,5 +150,5 @@
 
 class ContactActionButton(ManageActionButton):
-    grok.order(4)
+    grok.order(5)
     grok.context(IStudent)
     grok.view(StudentBaseDisplayFormPage)
@@ -166,6 +166,15 @@
     target = 'manage_base'
 
+class AdmissionSlipActionButton(ManageActionButton):
+    grok.order(4)
+    grok.context(IStudent)
+    grok.view(StudentBaseDisplayFormPage)
+    grok.require('waeup.viewStudent')
+    icon = 'actionicon_pdf.png'
+    text = _('Download admission letter')
+    target = 'admission_slip.pdf'
+
 class StudentTransfernButton(ManageActionButton):
-    grok.order(5)
+    grok.order(6)
     grok.context(IStudent)
     grok.view(StudentBaseDisplayFormPage)
@@ -176,5 +185,5 @@
 
 class StudentDeactivateActionButton(ManageActionButton):
-    grok.order(6)
+    grok.order(7)
     grok.context(IStudent)
     grok.view(StudentBaseDisplayFormPage)
@@ -196,5 +205,5 @@
 
 class StudentActivateActionButton(ManageActionButton):
-    grok.order(6)
+    grok.order(7)
     grok.context(IStudent)
     grok.view(StudentBaseDisplayFormPage)
@@ -624,11 +633,11 @@
     @property
     def targets(self):
-        student_url = self.view.application_url() + (
-            '/students/%s' % self.request.principal.id)
-        #app_slip = getUtility(IExtFileStore).getFileByContext(
-        #    self.context.student, 'application_slip')
+        student = grok.getSite()['students'][self.request.principal.id]
+        student_url = self.view.url(student)
+        app_slip = getUtility(IExtFileStore).getFileByContext(
+            student, 'application_slip')
         targets = []
-        #if app_slip:
-        #    targets = [{'url':student_url + '/application_slip', 'title':'Application Slip'},]
+        if app_slip:
+            targets = [{'url':student_url + '/application_slip', 'title':'Application Slip'},]
         targets += [
             {'url':student_url, 'title':'Base Data'},
