Index: main/kofacustom.dspg/trunk/src/kofacustom/dspg/applicants/applicant.py
===================================================================
--- main/kofacustom.dspg/trunk/src/kofacustom/dspg/applicants/applicant.py	(revision 14718)
+++ main/kofacustom.dspg/trunk/src/kofacustom/dspg/applicants/applicant.py	(revision 14721)
@@ -31,4 +31,13 @@
     grok.provides(ICustomApplicant)
 
+    @property
+    def is_nd(self):
+        if self.applicant_id.startswith('nd') \
+            or self.applicant_id.startswith('rmd') \
+            or self.applicant_id.startswith('prend') \
+            or self.applicant_id.startswith('prermd'):
+            return True
+        return False
+
 # Set all attributes of CustomApplicant required in ICustomApplicant as field
 # properties. Doing this, we do not have to set initial attributes
Index: main/kofacustom.dspg/trunk/src/kofacustom/dspg/applicants/browser.py
===================================================================
--- main/kofacustom.dspg/trunk/src/kofacustom/dspg/applicants/browser.py	(revision 14718)
+++ main/kofacustom.dspg/trunk/src/kofacustom/dspg/applicants/browser.py	(revision 14721)
@@ -19,10 +19,179 @@
 """
 import grok
-from waeup.kofa.applicants.browser import (
-    ApplicantRegistrationPage, ApplicantsContainerPage)
-from kofacustom.nigeria.applicants.browser import (
-    NigeriaApplicantDisplayFormPage,
-    NigeriaPDFApplicationSlip)
+from zope.component import getUtility
+from zope.i18n import translate
+from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
+from zope.formlib.textwidgets import BytesDisplayWidget
+from waeup.kofa.applicants.interfaces import (
+    IApplicant, IApplicantEdit, ISpecialApplicant)
+from waeup.kofa.applicants.browser import (ApplicantDisplayFormPage,
+    ApplicantManageFormPage, ApplicantEditFormPage,
+    ApplicantsContainerPage)
+from waeup.kofa.applicants.viewlets import (
+    PaymentReceiptActionButton, PDFActionButton)
+from waeup.kofa.applicants.pdf import PDFApplicationSlip
+from kofacustom.nigeria.applicants.interfaces import (
+    UG_OMIT_DISPLAY_FIELDS,
+    UG_OMIT_PDF_FIELDS,
+    UG_OMIT_MANAGE_FIELDS,
+    UG_OMIT_EDIT_FIELDS
+    )
+from kofacustom.dspg.applicants.interfaces import (
+    ICustomUGApplicant, ICustomUGApplicantEdit,
+    ND_OMIT_DISPLAY_FIELDS,
+    ND_OMIT_PDF_FIELDS,
+    ND_OMIT_MANAGE_FIELDS,
+    ND_OMIT_EDIT_FIELDS
+    )
 
-from kofacustom.dspg.interfaces import MessageFactory as _
+UG_OMIT_EDIT_FIELDS = [
+    value for value in UG_OMIT_EDIT_FIELDS
+        if not value in ('jamb_subjects', 'jamb_score', 'jamb_reg_number')]
 
+PRE_OMIT_EDIT_FIELDS = UG_OMIT_EDIT_FIELDS + [
+    'firstname',
+    'middlename',
+    'lastname',
+    #'sex',
+    'jamb_score'
+    ]
+
+class CustomApplicantsContainerPage(ApplicantsContainerPage):
+    """The standard view for regular applicant containers.
+    """
+
+    @property
+    def form_fields(self):
+        form_fields = super(CustomApplicantsContainerPage, self).form_fields
+        if self.request.principal.id == 'zope.anybody':
+            return form_fields.omit('application_fee')
+        return form_fields
+
+class CustomApplicantDisplayFormPage(ApplicantDisplayFormPage):
+    """A display view for applicant data.
+    """
+
+    @property
+    def form_fields(self):
+        if self.context.special:
+            return grok.AutoFields(ISpecialApplicant)
+        form_fields = grok.AutoFields(ICustomUGApplicant)
+        if self.context.is_nd:
+            for field in ND_OMIT_DISPLAY_FIELDS:
+                form_fields = form_fields.omit(field)
+        else:
+            form_fields = grok.AutoFields(ICustomUGApplicant)
+            for field in UG_OMIT_DISPLAY_FIELDS:
+                form_fields = form_fields.omit(field)
+        form_fields['notice'].custom_widget = BytesDisplayWidget
+        form_fields['jamb_subjects'].custom_widget = BytesDisplayWidget
+        if not getattr(self.context, 'student_id'):
+            form_fields = form_fields.omit('student_id')
+        if not getattr(self.context, 'screening_score'):
+            form_fields = form_fields.omit('screening_score')
+        if not getattr(self.context, 'screening_venue'):
+            form_fields = form_fields.omit('screening_venue')
+        if not getattr(self.context, 'screening_date'):
+            form_fields = form_fields.omit('screening_date')
+        return form_fields
+
+class CustomPDFApplicationSlip(PDFApplicationSlip):
+
+    def _reduced_slip(self):
+        return getattr(self.context, 'result_uploaded', False)
+
+    @property
+    def note(self):
+        note = getattr(self.context.__parent__, 'application_slip_notice', None)
+        if note:
+            return '<br /><br />' + note
+        pronoun = 'S/he'
+        if self.context.sex == 'm':
+            pronoun = 'He'
+        else:
+            pronoun = 'She'
+        return '''<br /><br />
+The applicant has declared that:
+
+a) %s is not a member of any secret cult and will not join any.
+b) %s will not engage in any cult activities.
+c) %s will not be involved in any acts of terrorism, rape, robbery, fighting, illegal gathering and
+any activities that could disrupt peace on campus.
+d) %s does not have and will not acquire any form of weapon, fire arms, gun knife or any weapon
+that can cause damage to life and property.
+e) %s will strive to be worthy in character and learning at all times.
+
+The applicant has acknowledged that offences will automatically lead to the expulsion from the
+Polytechnic and also be dealt with in accordance with the law of the land.
+
+The applicant promises to abide by all the Rules and Regulations of the Polytechnic if offered
+admission.
+''' % (
+    pronoun, pronoun, pronoun, pronoun, pronoun)
+
+    @property
+    def form_fields(self):
+        form_fields = grok.AutoFields(ICustomUGApplicant)
+        if self.context.is_nd:
+            for field in ND_OMIT_PDF_FIELDS:
+                form_fields = form_fields.omit(field)
+        else:
+            form_fields = grok.AutoFields(ICustomUGApplicant)
+            for field in UG_OMIT_PDF_FIELDS:
+                form_fields = form_fields.omit(field)
+        if not getattr(self.context, 'student_id'):
+            form_fields = form_fields.omit('student_id')
+        if not getattr(self.context, 'screening_score'):
+            form_fields = form_fields.omit('screening_score')
+        if not getattr(self.context, 'screening_venue'):
+            form_fields = form_fields.omit('screening_venue')
+        if not getattr(self.context, 'screening_date'):
+            form_fields = form_fields.omit('screening_date')
+        return form_fields
+
+class CustomApplicantManageFormPage(ApplicantManageFormPage):
+    """A full edit view for applicant data.
+    """
+
+    @property
+    def form_fields(self):
+        if self.context.special:
+            form_fields = grok.AutoFields(ISpecialApplicant)
+            form_fields['applicant_id'].for_display = True
+            return form_fields
+        form_fields = grok.AutoFields(ICustomUGApplicant)
+        if self.context.is_nd:
+            for field in ND_OMIT_MANAGE_FIELDS:
+                form_fields = form_fields.omit(field)
+        else:
+            for field in UG_OMIT_MANAGE_FIELDS:
+                form_fields = form_fields.omit(field)
+        form_fields['student_id'].for_display = True
+        form_fields['applicant_id'].for_display = True
+        return form_fields
+
+class CustomApplicantEditFormPage(ApplicantEditFormPage):
+    """An applicant-centered edit view for applicant data.
+    """
+
+    @property
+    def form_fields(self):
+
+        if self.context.special:
+            form_fields = grok.AutoFields(ISpecialApplicant).omit(
+                'locked', 'suspended')
+            form_fields['applicant_id'].for_display = True
+            return form_fields
+        form_fields = grok.AutoFields(ICustomUGApplicantEdit)
+        if self.context.is_nd:
+            for field in ND_OMIT_EDIT_FIELDS:
+                form_fields = form_fields.omit(field)
+        elif self.target is not None and self.target.startswith('pre'):
+            for field in PRE_OMIT_EDIT_FIELDS:
+                form_fields = form_fields.omit(field)
+        else:
+            for field in UG_OMIT_EDIT_FIELDS:
+                form_fields = form_fields.omit(field)
+        form_fields['applicant_id'].for_display = True
+        form_fields['reg_number'].for_display = True
+        return form_fields
Index: main/kofacustom.dspg/trunk/src/kofacustom/dspg/applicants/interfaces.py
===================================================================
--- main/kofacustom.dspg/trunk/src/kofacustom/dspg/applicants/interfaces.py	(revision 14718)
+++ main/kofacustom.dspg/trunk/src/kofacustom/dspg/applicants/interfaces.py	(revision 14721)
@@ -26,9 +26,10 @@
 from waeup.kofa.interfaces import (
     SimpleKofaVocabulary, academic_sessions_vocab, validate_email)
-from waeup.kofa.schema import FormattedDate, TextLineChoice
+from waeup.kofa.schema import FormattedDate, TextLineChoice, PhoneNumber
 from waeup.kofa.students.vocabularies import nats_vocab, GenderSource
 from waeup.kofa.applicants.interfaces import contextual_reg_num_source
 from kofacustom.nigeria.applicants.interfaces import (
     LGASource, high_qual, high_grade, exam_types,
+    OMIT_DISPLAY_FIELDS,
     INigeriaUGApplicant, INigeriaPGApplicant,
     INigeriaApplicantOnlinePayment,
@@ -40,5 +41,25 @@
 from kofacustom.dspg.payments.interfaces import ICustomOnlinePayment
 
-class ICustomUGApplicant(INigeriaUGApplicant):
+ND_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
+    'hq_type',
+    'hq_matric_no',
+    'hq_degree',
+    'hq_school',
+    'hq_session',
+    'hq_disc',
+    'hq_type')
+ND_OMIT_PDF_FIELDS = ND_OMIT_DISPLAY_FIELDS + ('phone',)
+ND_OMIT_MANAGE_FIELDS = ('special_application',)
+ND_OMIT_EDIT_FIELDS = ND_OMIT_MANAGE_FIELDS + ND_OMIT_DISPLAY_FIELDS + (
+    'student_id', 'notice',
+    'screening_score',
+    'screening_venue',
+    'screening_date',
+    'jamb_age',
+    'jamb_subjects',
+    'jamb_score',
+    'aggregate')
+
+class ICustomUGApplicant(IApplicantBaseData):
     """An undergraduate applicant.
 
@@ -47,4 +68,208 @@
     adding them to the UG_OMIT* tuples.
     """
+    sex = schema.Choice(
+        title = _(u'Sex'),
+        source = GenderSource(),
+        required = False,
+        )
+    nationality = schema.Choice(
+        source = nats_vocab,
+        title = _(u'Nationality'),
+        required = False,
+        )
+    lga = schema.Choice(
+        source = LGASource(),
+        title = _(u'State/LGA (Nigerians only)'),
+        required = False,
+        )
+    #perm_address = schema.Text(
+    #    title = _(u'Permanent Address'),
+    #    required = False,
+    #    )
+    next_kin_address = schema.Text(
+        title = _(u'Next of Kin Address'),
+        required = False,
+        )
+    jamb_reg_number = schema.TextLine(
+        title = _(u'JAMB Registration Number'),
+        required = False,
+        )
+    course1 = schema.Choice(
+        title = _(u'1st Choice Course of Study'),
+        source = AppCatCertificateSource(),
+        required = False,
+        )
+    course2 = schema.Choice(
+        title = _(u'2nd Choice Course of Study'),
+        source = AppCatCertificateSource(),
+        required = False,
+        )
+    olevel_type = schema.Choice(
+        title = _(u'Qualification Obtained'),
+        required = False,
+        readonly = False,
+        vocabulary = exam_types,
+        )
+    olevel_school = schema.TextLine(
+        title = _(u'Institution Attended'),
+        required = False,
+        readonly = False,
+        )
+    olevel_exam_number = schema.TextLine(
+        title = _(u'Exam Number'),
+        required = False,
+        readonly = False,
+        )
+    olevel_exam_date = FormattedDate(
+        title = _(u'Exam Date'),
+        required = False,
+        readonly = False,
+        show_year = True,
+        )
+    olevel_results = schema.List(
+        title = _(u'Exam Results'),
+        value_type = ResultEntryField(),
+        required = False,
+        readonly = False,
+        defaultFactory=list,
+        )
+    olevel_pin = schema.TextLine(
+        title = _(u'Result Checking PIN'),
+        required = False,
+        readonly = False,
+        )
+    olevel_pin_serial = schema.TextLine(
+        title = _(u'PIN Serial Number'),
+        required = False,
+        readonly = False,
+        )
+    olevel_type2 = schema.Choice(
+        title = _(u'2nd Qualification Obtained'),
+        required = False,
+        readonly = False,
+        vocabulary = exam_types,
+        )
+    olevel_school2 = schema.TextLine(
+        title = _(u'2nd Institution Attended'),
+        required = False,
+        readonly = False,
+        )
+    olevel_exam_number2 = schema.TextLine(
+        title = _(u'2nd Exam Number'),
+        required = False,
+        readonly = False,
+        )
+    olevel_exam_date2 = FormattedDate(
+        title = _(u'2nd Exam Date'),
+        required = False,
+        readonly = False,
+        show_year = True,
+        )
+    olevel_results2 = schema.List(
+        title = _(u'2nd Exam Results'),
+        value_type = ResultEntryField(),
+        required = False,
+        readonly = False,
+        defaultFactory=list,
+        )
+    olevel_pin2 = schema.TextLine(
+        title = _(u'2nd Result Checking PIN'),
+        required = False,
+        readonly = False,
+        )
+    olevel_pin_serial2 = schema.TextLine(
+        title = _(u'2nd PIN Serial Number'),
+        required = False,
+        readonly = False,
+        )
+    hq_type = schema.Choice(
+        title = _(u'Qualification Obtained'),
+        required = False,
+        readonly = False,
+        vocabulary = high_qual,
+        )
+    hq_matric_no = schema.TextLine(
+        title = _(u'Former Matric Number'),
+        required = False,
+        readonly = False,
+        )
+    hq_degree = schema.Choice(
+        title = _(u'Class of Degree'),
+        required = False,
+        readonly = False,
+        vocabulary = high_grade,
+        )
+    hq_school = schema.TextLine(
+        title = _(u'Institution Attended'),
+        required = False,
+        readonly = False,
+        )
+    hq_session = schema.TextLine(
+        title = _(u'Years Attended'),
+        required = False,
+        readonly = False,
+        )
+    hq_disc = schema.TextLine(
+        title = _(u'Discipline'),
+        required = False,
+        readonly = False,
+        )
+    jamb_subjects = schema.Text(
+        title = _(u'Subjects and Scores'),
+        description = _(u'(one subject with score per line)'),
+        required = False,
+        )
+    jamb_score = schema.Int(
+        title = _(u'Total JAMB Score'),
+        required = False,
+        )
+    jamb_age = schema.Int(
+        title = _(u'Age (provided by JAMB)'),
+        required = False,
+        )
+    notice = schema.Text(
+        title = _(u'Notice'),
+        required = False,
+        )
+    screening_venue = schema.TextLine(
+        title = _(u'Screening Venue'),
+        required = False,
+        )
+    screening_date = schema.TextLine(
+        title = _(u'Screening Date'),
+        required = False,
+        )
+    screening_score = schema.Int(
+        title = _(u'Screening Score (%)'),
+        required = False,
+        )
+    aggregate = schema.Int(
+        title = _(u'Aggregate Score (%)'),
+        description = _(u'(average of relative JAMB and PUTME scores)'),
+        required = False,
+        )
+    result_uploaded = schema.Bool(
+        title = _(u'Result uploaded'),
+        default = False,
+        required = False,
+        )
+    student_id = schema.TextLine(
+        title = _(u'Student Id'),
+        required = False,
+        readonly = False,
+        )
+    course_admitted = schema.Choice(
+        title = _(u'Admitted Course of Study'),
+        source = CertificateSource(),
+        required = False,
+        )
+    locked = schema.Bool(
+        title = _(u'Form locked'),
+        default = False,
+        required = False,
+        )
+
+ICustomUGApplicant[
+    'sex'].order =  IApplicantBaseData['sex'].order
 
 class ICustomPGApplicant(INigeriaPGApplicant):
@@ -55,5 +280,4 @@
     adding them to the PG_OMIT* tuples.
     """
-
 
 class ICustomApplicant(ICustomUGApplicant, ICustomPGApplicant):
@@ -76,5 +300,5 @@
         """
 
-class ICustomUGApplicantEdit(INigeriaUGApplicantEdit):
+class ICustomUGApplicantEdit(ICustomUGApplicant):
     """An undergraduate applicant interface for edit forms.
 
@@ -87,4 +311,68 @@
     respective form page.
     """
+    email = schema.ASCIILine(
+        title = _(u'Email Address'),
+        required = True,
+        constraint=validate_email,
+        )
+    phone = PhoneNumber(
+        title = _(u'Phone'),
+        description = u'',
+        required = True,
+        )
+    date_of_birth = FormattedDate(
+        title = _(u'Date of Birth'),
+        required = True,
+        show_year = True,
+        )
+    sex = schema.Choice(
+        title = _(u'Sex'),
+        source = GenderSource(),
+        required = True,
+        )
+    nationality = schema.Choice(
+        source = nats_vocab,
+        title = _(u'Nationality'),
+        required = True,
+        )
+    course1 = schema.Choice(
+        title = _(u'1st Choice Course of Study'),
+        source = AppCatCertificateSource(),
+        required = True,
+        )
+    olevel_type = schema.Choice(
+        title = _(u'Qualification Obtained'),
+        required = True,
+        readonly = False,
+        vocabulary = exam_types,
+        )
+    jamb_subjects = schema.Text(
+        title = _(u'Subjects and Scores'),
+        description = _(u'(one subject with score per line)'),
+        required = True,
+        )
+    jamb_reg_number = schema.TextLine(
+        title = _(u'JAMB Registration Number'),
+        required = True,
+        )
+
+ICustomUGApplicantEdit[
+    'nationality'].order =  ICustomUGApplicant['nationality'].order
+ICustomUGApplicantEdit[
+    'email'].order =  ICustomUGApplicant['email'].order
+ICustomUGApplicantEdit[
+    'phone'].order =  ICustomUGApplicant['phone'].order
+ICustomUGApplicantEdit[
+    'course1'].order =  ICustomUGApplicant['course1'].order
+ICustomUGApplicantEdit[
+    'date_of_birth'].order =  ICustomUGApplicant['date_of_birth'].order
+ICustomUGApplicantEdit[
+    'sex'].order =  ICustomUGApplicant['sex'].order
+ICustomUGApplicantEdit[
+    'olevel_type'].order =  ICustomUGApplicant['olevel_type'].order
+ICustomUGApplicantEdit[
+    'jamb_subjects'].order =  ICustomUGApplicant['jamb_subjects'].order
+ICustomUGApplicantEdit[
+    'jamb_reg_number'].order =  ICustomUGApplicant['jamb_reg_number'].order
 
 class ICustomPGApplicantEdit(INigeriaPGApplicantEdit):
@@ -105,16 +393,4 @@
     """
 
-class IPUTMEApplicantEdit(IPUTMEApplicantEdit):
-    """An undergraduate applicant interface for editing.
-
-    Here we can repeat the fields from base data and set the
-    `required` and `readonly` attributes to True to further restrict
-    the data access. Or we can allow only certain certificates to be
-    selected by choosing the appropriate source.
-
-    We cannot omit fields here. This has to be done in the
-    respective form page.
-    """
-
 class ICustomApplicantUpdateByRegNo(INigeriaApplicantUpdateByRegNo):
     """Representation of an applicant.
Index: main/kofacustom.dspg/trunk/src/kofacustom/dspg/applicants/tests/test_browser.py
===================================================================
--- main/kofacustom.dspg/trunk/src/kofacustom/dspg/applicants/tests/test_browser.py	(revision 14718)
+++ main/kofacustom.dspg/trunk/src/kofacustom/dspg/applicants/tests/test_browser.py	(revision 14721)
@@ -19,21 +19,136 @@
 Test the applicant-related UI components.
 """
+import shutil
+import tempfile
+import datetime
+import pytz
 import os
-import datetime
+from zope.component.hooks import setSite, clearSite
 from zope.component import createObject, getUtility
 from zope.catalog.interfaces import ICatalog
 from zope.intid.interfaces import IIntIds
-from hurry.workflow.interfaces import IWorkflowState
+from zope.testbrowser.testing import Browser
 from kofacustom.dspg.testing import FunctionalLayer
-from waeup.kofa.browser.tests.test_pdf import samples_dir
-from waeup.kofa.applicants.tests.test_browser import ApplicantsFullSetup
+from waeup.kofa.app import University
+from waeup.kofa.university.faculty import Faculty
+from waeup.kofa.university.department import Department
+from waeup.kofa.testing import FunctionalTestCase
 from waeup.kofa.applicants.tests.test_batching import ApplicantImportExportSetup
-from kofacustom.dspg.applicants.export import CustomApplicantExporter
-from kofacustom.dspg.applicants.batching import CustomApplicantProcessor
+from waeup.kofa.applicants.container import ApplicantsContainer
 
-class CustomApplicantUITests(ApplicantsFullSetup):
-    # Tests for uploading/browsing the passport image of appplicants
+session = datetime.datetime.now().year - 2
+ndftcontainer_name = u'ndft%s' % session
 
+class ApplicantUITest(FunctionalTestCase):
+    """Perform some browser tests.
+    """
     layer = FunctionalLayer
+
+    def setUp(self):
+        super(ApplicantUITest, self).setUp()
+        # Setup a sample site for each test
+        app = University()
+        self.dc_root = tempfile.mkdtemp()
+        app['datacenter'].setStoragePath(self.dc_root)
+
+        # Prepopulate the ZODB...
+        self.getRootFolder()['app'] = app
+        # we add the site immediately after creation to the
+        # ZODB. Catalogs and other local utilities are not setup
+        # before that step.
+        self.app = self.getRootFolder()['app']
+        # Set site here. Some of the following setup code might need
+        # to access grok.getSite() and should get our new app then
+        setSite(app)
+
+        # Add ndft applicants container
+        self.ndftcontainer = ApplicantsContainer()
+        self.ndftcontainer.mode = 'create'
+        self.ndftcontainer.code = ndftcontainer_name
+        self.ndftcontainer.prefix = u'ndft'
+        self.ndftcontainer.application_category = u'ndft'
+        self.ndftcontainer.year = session
+        self.ndftcontainer.application_fee = 300.0
+        #self.ndftcontainer.title = u'This is the %s container' % ndftcontainer_name
+        self.app['applicants'][ndftcontainer_name] = self.ndftcontainer
+
+        delta = datetime.timedelta(days=10)
+        self.ndftcontainer.startdate = datetime.datetime.now(pytz.utc) - delta
+        self.ndftcontainer.enddate = datetime.datetime.now(pytz.utc) + delta
+
+        # Populate university
+        self.certificate = createObject('waeup.Certificate')
+        self.certificate.code = 'CERT1'
+        self.certificate.application_category = 'ndft'
+        self.certificate.start_level = 100
+        self.certificate.end_level = 500
+        self.certificate.study_mode = u'nce_ft'
+        self.app['faculties']['fac1'] = Faculty()
+        self.app['faculties']['fac1']['dep1'] = Department()
+        self.app['faculties']['fac1']['dep1'].certificates.addCertificate(
+            self.certificate)
+
+        # Add (customized) applicants
+        ndftapplicant = createObject(u'waeup.Applicant')
+        ndftapplicant.firstname = u'Anna'
+        ndftapplicant.lastname = u'Post'
+        self.app['applicants'][ndftcontainer_name].addApplicant(ndftapplicant)
+        self.ndftapplication_number = ndftapplicant.application_number
+        self.ndftapplicant = self.app['applicants'][ndftcontainer_name][
+            self.ndftapplication_number]
+        self.ndftapplicant_path = ('http://localhost/app/applicants/%s/%s'
+            % (ndftcontainer_name, self.ndftapplication_number))
+
+        self.browser = Browser()
+        self.browser.handleErrors = False
+
+    def tearDown(self):
+        super(ApplicantUITest, self).tearDown()
+        shutil.rmtree(self.dc_root)
+        clearSite()
+        return
+
+    def fill_correct_values(self):
+        self.browser.getControl(name="form.reg_number").value = '1234'
+        self.browser.getControl(name="form.firstname").value = 'John'
+        self.browser.getControl(name="form.lastname").value = 'Tester'
+        self.browser.getControl(name="form.date_of_birth").value = '09/09/1988'
+        self.browser.getControl(name="form.lga").value = ['foreigner']
+        #self.browser.getControl(name="form.nationality").value = ['NG']
+        #self.browser.getControl(name="form.sex").value = ['m']
+        self.browser.getControl(name="form.email").value = 'xx@yy.zz'
+
+    def test_manage_and_view_applicant(self):
+        # Managers can manage ndft applicants.
+        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+        self.browser.open(self.ndftapplicant_path)
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertTrue("'O' Level" in self.browser.contents)
+        self.assertFalse("Higher" in self.browser.contents)
+        self.browser.open(self.ndftapplicant_path + '/manage')
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertTrue("'O' Level" in self.browser.contents)
+        self.assertTrue("Higher" in self.browser.contents)
+        self.browser.open(self.ndftapplicant_path + '/edit')
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertTrue("'O' Level" in self.browser.contents)
+        self.assertFalse("Higher" in self.browser.contents)
+        self.browser.open(self.ndftapplicant_path + '/application_slip.pdf')
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        # Now we turn the ndft applicant into an hndft applicant.
+        self.ndftapplicant.applicant_id = u'hndft_anything'
+        self.browser.open(self.ndftapplicant_path)
+        self.assertTrue("Higher" in self.browser.contents)
+        self.assertTrue("'O' Level" in self.browser.contents)
+        self.browser.open(self.ndftapplicant_path + '/edit')
+        self.assertTrue("Higher" in self.browser.contents)
+        self.assertTrue("'O' Level" in self.browser.contents)
+
+        self.browser.open(self.ndftapplicant_path + '/manage')
+        # Manager can fill and save the form
+        self.fill_correct_values()
+        self.browser.getControl("Save").click()
+        self.assertMatches('...Form has been saved...', self.browser.contents)
+        return
 
 class ApplicantExporterTest(ApplicantImportExportSetup):
@@ -69,24 +184,2 @@
         applicant.password = 'any password'
         return applicant
-
-class ApplicantsContainerUITests(ApplicantsFullSetup):
-    # Tests for ApplicantsContainer class views and pages
-
-    layer = FunctionalLayer
-
-    def test_application_slip(self):
-        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
-        self.slip_path = self.view_path + '/application_slip.pdf'
-        self.browser.open(self.manage_path)
-        self.assertEqual(self.browser.headers['Status'], '200 Ok')
-        self.fill_correct_values()
-        self.browser.getControl("Save").click()
-        IWorkflowState(self.applicant).setState('submitted')
-        self.browser.open(self.manage_path)
-        self.browser.getLink("Download application slip").click()
-        self.assertEqual(self.browser.headers['Status'], '200 Ok')
-        self.assertEqual(self.browser.headers['Content-Type'],
-                         'application/pdf')
-        path = os.path.join(samples_dir(), 'application_slip.pdf')
-        open(path, 'wb').write(self.browser.contents)
-        print "Sample application_slip.pdf written to %s" % path
Index: main/kofacustom.dspg/trunk/src/kofacustom/dspg/applicants/utils.py
===================================================================
--- main/kofacustom.dspg/trunk/src/kofacustom/dspg/applicants/utils.py	(revision 14718)
+++ main/kofacustom.dspg/trunk/src/kofacustom/dspg/applicants/utils.py	(revision 14721)
@@ -54,2 +54,13 @@
         'special': ['Supplementary Payment', 'SP'],
         }
+
+    SEPARATORS_DICT = {
+        'form.applicant_id': _(u'Base Data'),
+        'form.course1': _(u'Programmes/Courses Desired'),
+        'form.hq_type': _(u'Higher Education Record'),
+        'form.jamb_subjects': _(u'JAMB Data'),
+        'form.notice': _(u'Application Process Information'),
+        'form.pp_school': _(u'Post Primary School Qualification'),
+        'form.presently_inst': _(u'Presently attending a course or programme'),
+        'form.olevel_type': _(u"'O' Level Record"),
+        }
