Index: main/kofacustom.iuokada/trunk/src/kofacustom/iuokada/students/browser.py
===================================================================
--- main/kofacustom.iuokada/trunk/src/kofacustom/iuokada/students/browser.py	(revision 16125)
+++ main/kofacustom.iuokada/trunk/src/kofacustom/iuokada/students/browser.py	(revision 16127)
@@ -21,5 +21,6 @@
 from zope.component import getUtility
 from hurry.workflow.interfaces import IWorkflowInfo
-from waeup.kofa.interfaces import REQUESTED, IExtFileStore, IKofaUtils
+from waeup.kofa.interfaces import (REQUESTED, IExtFileStore, IKofaUtils,
+    academic_sessions_vocab)
 from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
 from waeup.kofa.browser.layout import (
@@ -30,7 +31,9 @@
     CourseTicketDisplayFormPage, StudentTriggerTransitionFormPage,
     StartClearancePage, BalancePaymentAddFormPage,
+    ExportPDFAdmissionSlip,
     msave, emit_lock_message)
 from waeup.kofa.students.interfaces import (
     IStudentsUtils, ICourseTicket, IStudent)
+from waeup.kofa.students.vocabularies import StudyLevelSource
 from waeup.kofa.students.workflow import FORBIDDEN_POSTGRAD_TRANS
 from kofacustom.nigeria.students.browser import (
@@ -219,2 +222,85 @@
 class CustomBalancePaymentAddFormPage(BalancePaymentAddFormPage):
     grok.require('waeup.payStudent')
+
+class CustomExportPDFAdmissionSlip(ExportPDFAdmissionSlip):
+    """Deliver a PDF Admission slip.
+    """
+
+    omit_fields = ('date_of_birth', 'current_level', 'current_mode',
+                   'entry_session')
+
+    @property
+    def session(self):
+        return academic_sessions_vocab.getTerm(
+            self.context.entry_session).title
+
+    @property
+    def level(self):
+        studylevelsource = StudyLevelSource()
+        return studylevelsource.factory.getTitle(
+            self.context['studycourse'].certificate, self.context.current_level)
+
+    @property
+    def label(self):
+        return 'OFFER OF PROVISIONAL ADMISSION \nFOR %s SESSION' % self.session
+
+    @property
+    def pre_text(self):
+        return (
+            'Following your performance in the screening exercise '
+            'for the %s academic session, I am pleased to inform '
+            'you that you have been offered provisional admission into the '
+            'Igbinedion University, Okada as follows:' % self.session)
+
+    @property
+    def post_text(self):
+        return """
+Please note that at the point of registration for your programme of study (course), you will be required to present the following documents: Current UTME result slip, WAEC/NECO (0' Level) result, Birth certificate or sworn affidavit of age, and Health certificate from a recognized Medical Centre.
+
+All credentials (orlglnal) will be checked during registration. This admission will be cancelled at any point in time it is found that your claims in the application form are false.
+
+You are required to show evidence of the result / credentials you presented on application for admission.
+
+Fees can be paid using any of the following options
+
+1. Fees can be paid on through you portal page. INSTRUCTIONS can be found below "FEES PAYMENT PROCEDURE" for the options you have to make your payment, as well as instructions on how to use your preferred payment option.
+2. If you choose to use the bank payment option, you can pay at any branch of the following banks through etranzact platform only: Access Bank, First Bank, Zenith Bank, and Keystone Bank
+
+Kindly note the following:
+
+1. Fees indicated on the Fee Structure page are valid for the current session only.
+2. Your Student Id (indicated above) Is your logln to the University portal.
+3. As an indication of your acceptance of this offer of admission, you should pay a non-refundable Acceptance deposit of 200,000. Further note that the 200,000 deposit is part of the tuition fee for the session. Failure to pay after the expiration of two weeks may lead to forfeiture of admission.
+4. 	All fees must be paid in full at the beginning of the session, as basis for accommodation, registration and attendance of lectures. This is the rule for all students at all levels. Install mental payments of not more than two installments, may be allowed under exceptional circumstances
+5. 	Fees once paid are not refundable.
+6. It is advisable that you keep the original receipts of fees paid and present them on demand.
+
+Accommodation: Accommodation in University hostels is compulsory for every student. No student Is allowed to live outside the hostels. Any student who does so will be expelled from the University. For further details, please refer to the Bursary for Information on fees.
+
+Food: Food is available in cafeteria on "pay-as-you-eat" basis.
+
+Resumption Date: The University opens for fresh students on Saturday, 28th September, 2020. All newly admitted students are expected to report on that date.
+
+Registration/Orientation Programme: Orientation programme/registration for fresh students will start on Monday, 30th September 2020. Registration ends on 2020-10-30. A late registration fee of N50,000 will be charged after this date. All credentials, O'Level Results, Birth Certificate/Age Declaration, UTME Result Slip (Original) will be checked during registration. This admission will be cancelled at any point in time it is found that any of your claims in the application form is false.
+
+Transport Facility: The University provides a compulsory shuttle bus service to all students at a fee already included in the other charges.
+
+Kindly note that fresh students are not allowed the use of private vehicles.
+
+Conduct: All students are expected to conduct themselves properly and dress decently on campus, as well as obey all rules and regulations as failure to comply will attract appropriate sanctions.
+
+We wish you a successful academic career In Igbinedion University.
+
+Congratulations!
+
+L.P.E. Jagbedia
+Ag. Registrar
+registrar@iuokada.edo.ng
+08037349527
+"""
+
+    def render(self):
+        students_utils = getUtility(IStudentsUtils)
+        return students_utils.renderPDFAdmissionLetter(self,
+            self.context.student, omit_fields=self.omit_fields,
+            pre_text=self.pre_text, post_text=self.post_text)
Index: main/kofacustom.iuokada/trunk/src/kofacustom/iuokada/students/tests/test_browser.py
===================================================================
--- main/kofacustom.iuokada/trunk/src/kofacustom/iuokada/students/tests/test_browser.py	(revision 16125)
+++ main/kofacustom.iuokada/trunk/src/kofacustom/iuokada/students/tests/test_browser.py	(revision 16127)
@@ -138,2 +138,31 @@
         open(path, 'wb').write(self.browser.contents)
         print "Sample PDF basedata_slip.pdf written to %s" % path
+
+    def test_student_admission_letter(self):
+        # Student cant login if their password is not set
+        IWorkflowInfo(self.student).fireTransition('admit')
+        self.browser.open(self.login_path)
+        self.browser.getControl(name="form.login").value = self.student_id
+        self.browser.getControl(name="form.password").value = 'spwd'
+        self.browser.getControl("Login").click()
+        self.assertMatches(
+            '...You logged in...', self.browser.contents)
+        # Admitted student can upload a passport picture
+        #self.browser.open(self.student_path + '/change_portrait')
+        #ctrl = self.browser.getControl(name='passportuploadedit')
+        #file_obj = open(SAMPLE_IMAGE, 'rb')
+        #file_ctrl = ctrl.mech_control
+        #file_ctrl.add_file(file_obj, filename='my_photo.jpg')
+        #self.browser.getControl(
+        #    name='upload_passportuploadedit').click()
+        #self.assertTrue(
+        #    'src="http://localhost/app/students/K1000000/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')
+        path = os.path.join(samples_dir(), 'admission_slip.pdf')
+        open(path, 'wb').write(self.browser.contents)
+        print "Sample PDF admission_slip.pdf written to %s" % path
