Index: main/waeup.kofa/trunk/CHANGES.txt
===================================================================
--- main/waeup.kofa/trunk/CHANGES.txt	(revision 17863)
+++ main/waeup.kofa/trunk/CHANGES.txt	(revision 17867)
@@ -4,4 +4,6 @@
 1.8.2.dev0 (unreleased)
 =======================
+
+* Implement Final Year Clearance Routing Slip upload (not active in base package).
 
 * Add student's current session to base data block on slips (requested by Uniben)
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py	(revision 17863)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py	(revision 17867)
@@ -659,4 +659,5 @@
     grok.template('basemanagepage')
     label = _('Manage base data')
+    deletion_warning = _('Are you sure?')
     pnav = 4
 
@@ -2993,4 +2994,26 @@
         return
 
+class StudentFinalClearanceUploadPage(KofaPage):
+    """View to upload scanned final clearance routing slip by student. Not active
+    in base package.
+    """
+    grok.context(IStudent)
+    grok.name('routing_slip_upload')
+    grok.require('waeup.uploadStudentFile')
+    grok.template('finalclearanceuploadpage')
+    label = _('Upload final clearance routing slip')
+    deletion_warning = _('Are you sure?')
+    pnav = 4
+
+    def update(self):
+        final_clearance_enabled = getUtility(
+            IStudentsUtils).final_clearance_enabled(self.context)
+        if not final_clearance_enabled:
+            emit_lock_message(self,
+                _('This form is locked.'))
+            return
+        super(StudentFinalClearanceUploadPage, self).update()
+        return
+
 class StartClearancePage(KofaPage):
     grok.context(IStudent)
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/browser_templates/finalclearanceuploadpage.pt
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/browser_templates/finalclearanceuploadpage.pt	(revision 17867)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/browser_templates/finalclearanceuploadpage.pt	(revision 17867)
@@ -0,0 +1,9 @@
+<form action="." tal:attributes="action request/URL" method="post"
+      enctype="multipart/form-data">
+  <p i18n:translate="routing_slip_info">Please download your <a href="https://xyz/documents/routingslip/file.pdf">Final Clearance Routing Slip</a>, collect all signatures, scan the document into a pdf file and re-upload here.</p>
+  <table class="form-table">
+    <tbody>
+      <tal:files content="structure provider:files" />
+    </tbody>
+  </table>
+</form>
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/fileviewlets.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/fileviewlets.py	(revision 17863)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/fileviewlets.py	(revision 17867)
@@ -37,5 +37,6 @@
     StudentBaseDisplayFormPage, StudentBaseManageFormPage,
     StudentClearanceDisplayFormPage, StudentClearanceManageFormPage,
-    ExportPDFClearanceSlip, StudentFilesUploadPage, StudentSignatureUploadPage)
+    ExportPDFClearanceSlip, StudentFilesUploadPage, StudentSignatureUploadPage,
+    StudentFinalClearanceUploadPage)
 
 grok.context(IKofaObject) # Make IKofaObject the default context
@@ -114,4 +115,9 @@
         return kofa_utils.MAX_PASSPORT_SIZE
 
+class PassportUploadEdit(PassportUploadManage):
+    """Passport upload viewlet for students.
+    """
+    grok.view(StudentFilesUploadPage)
+    grok.require('waeup.uploadStudentFile')
 
 class SignatureDisplay(StudentFileDisplay):
@@ -125,5 +131,4 @@
     label = _(u'Scanned Signature')
     download_name = u'signature.jpg'
-
 
 class SignatureUploadManage(StudentFileUpload):
@@ -137,5 +142,4 @@
     label = _(u'Scanned Signature (jpg only)')
     download_name = u'signature.jpg'
-    tab_redirect = '#tab2'
 
     @property
@@ -145,11 +149,4 @@
 
 
-class PassportUploadEdit(PassportUploadManage):
-    """Passport upload viewlet for students.
-    """
-    grok.view(StudentFilesUploadPage)
-    grok.require('waeup.uploadStudentFile')
-
-
 class SignatureUploadEdit(SignatureUploadManage):
     """Signature upload viewlet for students.
@@ -158,4 +155,31 @@
     grok.require('waeup.uploadStudentFile')
 
+
+class FinalClearanceDisplay(StudentFileDisplay):
+    """Final Clearance Routing Slip display viewlet.
+    """
+    grok.order(4)
+    grok.context(IStudent)
+    grok.view(StudentBaseDisplayFormPage)
+    grok.require('waeup.viewStudent')
+    label = _(u'Scanned Final Clearance Routing Slip ')
+    download_name = u'routingslip'
+
+
+class FinalClearanceUploadManage(StudentFileUpload):
+    """Final Clearance Routing Slip upload viewlet for officers.
+    """
+    grok.order(4)
+    grok.context(IStudent)
+    grok.view(StudentBaseManageFormPage)
+    grok.require('waeup.manageStudent')
+    label = _(u'Scanned Final Clearance Routing Slip (pdf preferred)')
+    download_name = u'routingslip'
+
+class FinalClearanceUploadEdit(FinalClearanceUploadManage):
+    """Final Clearance Form upload viewlet for students.
+    """
+    grok.view(StudentFinalClearanceUploadPage)
+    grok.require('waeup.uploadStudentFile')
 
 class BirthCertificateDisplay(StudentFileDisplay):
@@ -196,4 +220,10 @@
     grok.context(IStudent)
 
+class FinalClearance(StudentImage):
+    """Renders pdf slip.
+    """
+    grok.name('routingslip')
+    download_name = u'routingslip'
+
 class ApplicationSlipImage(StudentImage):
     """Renders application slip scan.
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py	(revision 17863)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py	(revision 17867)
@@ -60,4 +60,5 @@
 
 SAMPLE_IMAGE = os.path.join(os.path.dirname(__file__), 'test_image.jpg')
+SAMPLE_PDF = os.path.join(os.path.dirname(__file__), 'test_pdf.pdf')
 SAMPLE_IMAGE_BMP = os.path.join(os.path.dirname(__file__), 'test_image.bmp')
 URL_LECTURER_LANDING = 'http://localhost/app/my_courses'
@@ -711,4 +712,13 @@
         self.assertTrue(
             'src="http://localhost/app/students/K1000000/signature.jpg"'
+            in self.browser.contents)
+        ctrl = self.browser.getControl(name='finalclearanceuploadmanage')
+        file_obj = open(SAMPLE_PDF, 'rb')
+        file_ctrl = ctrl.mech_control
+        file_ctrl.add_file(file_obj, filename='routing_slip.pdf')
+        self.browser.getControl(
+            name='upload_finalclearanceuploadmanage').click()
+        self.assertTrue(
+            'href="http://localhost/app/students/K1000000/routingslip"'
             in self.browser.contents)
         return
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/utils.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/utils.py	(revision 17863)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/utils.py	(revision 17867)
@@ -1267,4 +1267,8 @@
         return number
 
+    def final_clearance_enabled(self, student):
+        # disabled in base package
+        return True
+
     #: A dictionary which maps widget names to headlines. The headline
     #: is rendered in forms and on pdf slips above the respective
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/viewlets.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/viewlets.py	(revision 17863)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/viewlets.py	(revision 17867)
@@ -638,4 +638,21 @@
         return self.view.url(self.view.context, self.target)
 
+class StudentFinalClearanceFormActionButton(ManageActionButton):
+    grok.order(5)
+    grok.context(IStudent)
+    grok.view(StudentBaseDisplayFormPage)
+    grok.require('waeup.handleStudent')
+    icon = 'actionicon_signature.png'
+    text = _('Upload final clearance routing slip')
+    target = 'routing_slip_upload'
+
+    @property
+    def target_url(self):
+        final_clearance_enabled = getUtility(
+            IStudentsUtils).final_clearance_enabled(self.context)
+        if not final_clearance_enabled:
+            return ''
+        return self.view.url(self.view.context, self.target)
+
 
 class StudentClearanceStartActionButton(ManageActionButton):
