Index: main/waeup.uniben/trunk/src/waeup/uniben/students/browser.py
===================================================================
--- main/waeup.uniben/trunk/src/waeup/uniben/students/browser.py	(revision 9379)
+++ main/waeup.uniben/trunk/src/waeup/uniben/students/browser.py	(revision 9380)
@@ -19,6 +19,7 @@
 from zope.i18n import translate
 from zope.schema.interfaces import ConstraintNotSatisfied
+from zope.component import getUtility
 from hurry.workflow.interfaces import IWorkflowInfo
-from waeup.kofa.interfaces import REQUESTED
+from waeup.kofa.interfaces import REQUESTED, IExtFileStore
 from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
 from waeup.kofa.browser.layout import KofaEditFormPage
@@ -34,4 +35,5 @@
     NigeriaOnlinePaymentDisplayFormPage,
     NigeriaStudentBaseManageFormPage,
+    NigeriaStudentClearanceEditFormPage,
     NigeriaOnlinePaymentAddFormPage,
     NigeriaExportPDFPaymentSlipPage,
@@ -73,4 +75,24 @@
         'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
 
+class CustomStudentClearanceEditFormPage(NigeriaStudentClearanceEditFormPage):
+    """ View to edit student clearance data by student
+    """
+
+    def dataNotComplete(self):
+        store = getUtility(IExtFileStore)
+        if not store.getFileByContext(self.context, attr=u'birth_certificate.jpg'):
+            return _('No birth certificate uploaded.')
+        if not store.getFileByContext(self.context, attr=u'ref_let.jpg'):
+            return _('No guarantor/referee letter uploaded.')
+        if not store.getFileByContext(self.context, attr=u'acc_let.jpg'):
+            return _('No acceptance letter uploaded.')
+        if not store.getFileByContext(self.context, attr=u'fst_sit_scan.jpg'):
+            return _('No first sitting result uploaded.')
+        if not store.getFileByContext(self.context, attr=u'scd_sit_scan.jpg'):
+            return _('No second sitting result uploaded.')
+        if not store.getFileByContext(self.context, attr=u'secr_cults.jpg'):
+            return _('No affidavit of non-menbership of secret cults uploaded.')
+        return False
+
 class CustomOnlinePaymentAddFormPage(NigeriaOnlinePaymentAddFormPage):
     """ Page to add an online payment ticket
Index: main/waeup.uniben/trunk/src/waeup/uniben/students/tests/test_browser.py
===================================================================
--- main/waeup.uniben/trunk/src/waeup/uniben/students/tests/test_browser.py	(revision 9379)
+++ main/waeup.uniben/trunk/src/waeup/uniben/students/tests/test_browser.py	(revision 9380)
@@ -116,4 +116,76 @@
                            self.browser.contents)
 
+    def test_student_access(self):
+        # Students can edit clearance data
+        IWorkflowState(self.student).setState('clearance started')
+        self.student.clearance_locked = False
+        self.student.nationality = u'NG'
+        file_store = getUtility(IExtFileStore)
+        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.browser.open(self.edit_clearance_path)
+
+        # Clearance can only be requested if all required documents
+        # have been uploaded.
+        self.browser.getControl("Save and request clearance").click()
+        self.assertTrue('No birth certificate uploaded'
+            in self.browser.contents)
+        birth_certificate = 'My birth certificate'
+        file_id = IFileStoreNameChooser(self.student).chooseName(
+            attr="birth_certificate.jpg")
+        file_store.createFile(file_id, StringIO(birth_certificate))
+        self.browser.open(self.edit_clearance_path)
+        self.browser.getControl("Save and request clearance").click()
+
+        self.assertTrue('No guarantor/referee letter uploaded'
+            in self.browser.contents)
+        ref_let = 'My ref let'
+        file_id = IFileStoreNameChooser(self.student).chooseName(
+            attr="ref_let.jpg")
+        file_store.createFile(file_id, StringIO(ref_let))
+        self.browser.open(self.edit_clearance_path)
+        self.browser.getControl("Save and request clearance").click()
+
+        self.assertTrue('No acceptance letter uploaded'
+            in self.browser.contents)
+        acc_let = 'My acc let'
+        file_id = IFileStoreNameChooser(self.student).chooseName(
+            attr="acc_let.jpg")
+        file_store.createFile(file_id, StringIO(acc_let))
+        self.browser.open(self.edit_clearance_path)
+        self.browser.getControl("Save and request clearance").click()
+
+        self.assertTrue('No first sitting result uploaded'
+            in self.browser.contents)
+        fst_sit_scan = 'My first sitting result'
+        file_id = IFileStoreNameChooser(self.student).chooseName(
+            attr="fst_sit_scan.jpg")
+        file_store.createFile(file_id, StringIO(fst_sit_scan))
+        self.browser.open(self.edit_clearance_path)
+        self.browser.getControl("Save and request clearance").click()
+
+        self.assertTrue('No second sitting result uploaded'
+            in self.browser.contents)
+        scd_sit_scan = 'My second sitting result'
+        file_id = IFileStoreNameChooser(self.student).chooseName(
+            attr="scd_sit_scan.jpg")
+        file_store.createFile(file_id, StringIO(scd_sit_scan))
+        self.browser.open(self.edit_clearance_path)
+        self.browser.getControl("Save and request clearance").click()
+
+        self.assertTrue('No affidavit of non-menbership of secret cults uploaded'
+            in self.browser.contents)
+        secr_cults = 'My non-membership scan'
+        file_id = IFileStoreNameChooser(self.student).chooseName(
+            attr="secr_cults.jpg")
+        file_store.createFile(file_id, StringIO(secr_cults))
+        self.browser.open(self.edit_clearance_path)
+        self.browser.getControl("Save and request clearance").click()
+
+        self.assertTrue('Clearance has been requested'
+            in self.browser.contents)
+
     def test_manage_payments(self):
         # Add missing configuration data
