Index: /main/kofacustom.edocons/trunk/src/kofacustom/edocons/applicants/browser.py
===================================================================
--- /main/kofacustom.edocons/trunk/src/kofacustom/edocons/applicants/browser.py	(revision 16617)
+++ /main/kofacustom.edocons/trunk/src/kofacustom/edocons/applicants/browser.py	(revision 16618)
@@ -19,10 +19,124 @@
 """
 import grok
-from waeup.kofa.applicants.browser import (
-    ApplicantRegistrationPage, ApplicantsContainerPage)
+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.students.interfaces import IStudentsUtils
+from waeup.kofa.applicants.browser import (ApplicantDisplayFormPage,
+    ApplicantManageFormPage, ApplicantEditFormPage,
+    ApplicantRegistrationPage,
+    OnlinePaymentDisplayFormPage,
+    OnlinePaymentBreadcrumb, ExportPDFPaymentSlipPage,
+    )
+from waeup.kofa.applicants.viewlets import (
+    PDFActionButton, PaymentReceiptActionButton)
+from waeup.kofa.applicants.pdf import PDFApplicationSlip
 from kofacustom.nigeria.applicants.browser import (
     NigeriaApplicantDisplayFormPage,
+    NigeriaApplicantManageFormPage,
+    NigeriaApplicantEditFormPage,
     NigeriaPDFApplicationSlip)
+from kofacustom.nigeria.applicants.interfaces import (
+    INigeriaPGApplicant, INigeriaUGApplicant,
+    INigeriaPGApplicantEdit, INigeriaUGApplicantEdit,
+    INigeriaApplicantOnlinePayment,
+    UG_OMIT_DISPLAY_FIELDS,
+    UG_OMIT_PDF_FIELDS,
+    UG_OMIT_MANAGE_FIELDS,
+    UG_OMIT_EDIT_FIELDS,
+    PG_OMIT_DISPLAY_FIELDS,
+    PG_OMIT_PDF_FIELDS,
+    PG_OMIT_MANAGE_FIELDS,
+    PG_OMIT_EDIT_FIELDS,
+    )
+from kofacustom.edocons.applicants.interfaces import (
+    ICustomPGApplicant, ICustomUGApplicant, ICustomApplicant,
+    ICustomPGApplicantEdit, ICustomUGApplicantEdit,
+    ICustomApplicantOnlinePayment,
+    )
+from kofacustom.nigeria.interfaces import MessageFactory as _
 
-from kofacustom.edocons.interfaces import MessageFactory as _
+class CustomApplicantDisplayFormPage(NigeriaApplicantDisplayFormPage):
+    """A display view for applicant data.
+    """
 
+    @property
+    def form_fields(self):
+        if self.target is not None and self.target.startswith('pg'):
+            form_fields = grok.AutoFields(ICustomPGApplicant)
+            for field in PG_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['perm_address'].custom_widget = BytesDisplayWidget
+        form_fields['notice'].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') or self._not_paid():
+            form_fields = form_fields.omit('screening_venue')
+        if not getattr(self.context, 'screening_date') or self._not_paid():
+            form_fields = form_fields.omit('screening_date')
+        return form_fields
+
+class CustomPDFApplicationSlip(NigeriaPDFApplicationSlip):
+
+    @property
+    def form_fields(self):
+        if self.target is not None and self.target.startswith('pg'):
+            form_fields = grok.AutoFields(ICustomPGApplicant)
+            for field in PG_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(NigeriaApplicantManageFormPage):
+    """A full edit view for applicant data.
+    """
+
+    @property
+    def form_fields(self):
+        if self.target is not None and self.target.startswith('pg'):
+            form_fields = grok.AutoFields(ICustomPGApplicant)
+            for field in PG_OMIT_MANAGE_FIELDS:
+                form_fields = form_fields.omit(field)
+        else:
+            form_fields = grok.AutoFields(ICustomUGApplicant)
+            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(NigeriaApplicantEditFormPage):
+    """An applicant-centered edit view for applicant data.
+    """
+
+    @property
+    def form_fields(self):
+        if self.target is not None and self.target.startswith('pg'):
+            form_fields = grok.AutoFields(ICustomPGApplicantEdit)
+            for field in PG_OMIT_EDIT_FIELDS:
+                form_fields = form_fields.omit(field)
+        else:
+            form_fields = grok.AutoFields(ICustomUGApplicantEdit)
+            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.edocons/trunk/src/kofacustom/edocons/applicants/interfaces.py
===================================================================
--- /main/kofacustom.edocons/trunk/src/kofacustom/edocons/applicants/interfaces.py	(revision 16617)
+++ /main/kofacustom.edocons/trunk/src/kofacustom/edocons/applicants/interfaces.py	(revision 16618)
@@ -28,7 +28,10 @@
 from waeup.kofa.schema import FormattedDate, TextLineChoice
 from waeup.kofa.students.vocabularies import nats_vocab, GenderSource
-from waeup.kofa.applicants.interfaces import contextual_reg_num_source
+from waeup.kofa.applicants.interfaces import (
+    contextual_reg_num_source,
+    IApplicantBaseData)
 from kofacustom.nigeria.applicants.interfaces import (
     LGASource, high_qual, high_grade, exam_types,
+    jambsubjects,
     INigeriaUGApplicant, INigeriaPGApplicant,
     INigeriaApplicantOnlinePayment,
@@ -37,14 +40,249 @@
     IPUTMEApplicantEdit,
     )
+from kofacustom.nigeria.interfaces import (
+    LGASource, DisabilitiesSource,
+    high_qual, high_grade, exam_types, validate_jamb_reg_number)
+
 from kofacustom.edocons.interfaces import MessageFactory as _
 from kofacustom.edocons.payments.interfaces import ICustomOnlinePayment
 
+programme_types_vocab = SimpleKofaVocabulary(
+    (_('Post UTME'), 'putme'),
+    (_('Post DE'), 'pude'),
+    (_('Admission Screening Exercise'), 'ase'),
+    (_('not applicable'), 'na'),
+    )
+
 class ICustomUGApplicant(INigeriaUGApplicant):
     """An undergraduate applicant.
-
-    This interface defines the least common multiple of all fields
-    in ug application forms. In customized forms, fields can be excluded by
-    adding them to the UG_OMIT* tuples.
-    """
+    """
+
+    disabilities = schema.Choice(
+        title = _(u'Disability'),
+        source = DisabilitiesSource(),
+        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,
+        )
+    course1 = schema.Choice(
+        title = _(u'1st Choice Course of Study'),
+        source = AppCatCertificateSource(),
+        required = True,
+        )
+    course2 = schema.Choice(
+        title = _(u'2nd Choice Course of Study'),
+        source = AppCatCertificateSource(),
+        required = False,
+        )
+
+    fst_sit_fname = schema.TextLine(
+        title = _(u'Full Name'),
+        required = False,
+        readonly = False,
+        )
+
+    fst_sit_no = schema.TextLine(
+        title = _(u'Exam Number'),
+        required = False,
+        readonly = False,
+        )
+
+    fst_sit_sc_pin = schema.TextLine(
+        title = _(u'Scratch Card Pin'),
+        required = False,
+        readonly = False,
+        )
+
+    fst_sit_sc_serial_number = schema.TextLine(
+        title = _(u'Scratch Card Serial Number'),
+        required = False,
+        readonly = False,
+        )
+
+    fst_sit_date = FormattedDate(
+        title = _(u'Exam Date'),
+        required = False,
+        readonly = False,
+        show_year = True,
+        )
+
+    fst_sit_type = schema.Choice(
+        title = _(u'Exam Type'),
+        required = False,
+        readonly = False,
+        vocabulary = exam_types,
+        )
+
+    fst_sit_results = schema.List(
+        title = _(u'Exam Results'),
+        value_type = ResultEntryField(),
+        required = False,
+        readonly = False,
+        defaultFactory=list,
+        )
+
+    scd_sit_fname = schema.TextLine(
+        title = _(u'Full Name'),
+        required = False,
+        readonly = False,
+        )
+
+    scd_sit_no = schema.TextLine(
+        title = _(u'Exam Number'),
+        required = False,
+        readonly = False,
+        )
+
+    scd_sit_sc_pin = schema.TextLine(
+        title = _(u'Scratch Card Pin'),
+        required = False,
+        readonly = False,
+        )
+
+    scd_sit_sc_serial_number = schema.TextLine(
+        title = _(u'Scratch Card Serial Number'),
+        required = False,
+        readonly = False,
+        )
+
+    scd_sit_date = FormattedDate(
+        title = _(u'Exam Date'),
+        required = False,
+        readonly = False,
+        show_year = True,
+        )
+
+    scd_sit_type = schema.Choice(
+        title = _(u'Exam Type'),
+        required = False,
+        readonly = False,
+        vocabulary = exam_types,
+        )
+
+    scd_sit_results = schema.List(
+        title = _(u'Exam Results'),
+        value_type = ResultEntryField(),
+        required = False,
+        readonly = False,
+        defaultFactory=list,
+        )
+
+    programme_type = schema.Choice(
+        title = _(u'Programme Type'),
+        vocabulary = programme_types_vocab,
+        required = 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'),
+        required = False,
+        )
+    jamb_subjects_list = schema.List(
+        title = _(u'JAMB Subjects'),
+        required = False,
+        defaultFactory=list,
+        value_type = schema.Choice(
+            vocabulary = jambsubjects
+            #source = JAMBSubjectSource(),
+            ),
+        )
+    jamb_score = schema.Int(
+        title = _(u'Total JAMB Score'),
+        required = False,
+        )
+    #jamb_age = schema.Int(
+    #    title = _(u'Age (provided by JAMB)'),
+    #    required = False,
+    #    )
+    jamb_reg_number = schema.TextLine(
+        title = _(u'JAMB Registration Number'),
+        required = False,
+        constraint=validate_jamb_reg_number,
+        )
+    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,
+        )
 
 class ICustomPGApplicant(INigeriaPGApplicant):
@@ -76,5 +314,5 @@
         """
 
-class ICustomUGApplicantEdit(INigeriaUGApplicantEdit):
+class ICustomUGApplicantEdit(ICustomUGApplicant):
     """An undergraduate applicant interface for edit forms.
 
