Index: main/kofacustom.pcn/trunk/src/kofacustom/pcn/applicants/browser.py
===================================================================
--- main/kofacustom.pcn/trunk/src/kofacustom/pcn/applicants/browser.py	(revision 11841)
+++ main/kofacustom.pcn/trunk/src/kofacustom/pcn/applicants/browser.py	(revision 11843)
@@ -20,9 +20,15 @@
 import grok
 from waeup.kofa.applicants.browser import (
-    ApplicantRegistrationPage, ApplicantsContainerPage)
+    ApplicantRegistrationPage,
+    ApplicantsContainerPage,
+    ApplicantDisplayFormPage,
+    ApplicantManageFormPage,
+    ApplicantEditFormPage)
 from waeup.kofa.applicants.viewlets import (
     StudentCreateActionButton,
-    ApplicantsRootCreateStudentsActionButton
+    ApplicantsRootCreateStudentsActionButton,
     )
+from kofacustom.pcn.applicants.interfaces import (
+    ICustomApplicant, ICustomApplicantEdit)
 from kofacustom.pcn.interfaces import MessageFactory as _
 
@@ -42,2 +48,39 @@
         """
         return
+
+class CustomApplicantDisplayFormPage(ApplicantDisplayFormPage):
+    """A display view for applicant data.
+    """
+    grok.template('applicantdisplaypage')
+
+    @property
+    def form_fields(self):
+        form_fields = grok.AutoFields(ICustomApplicant).omit(
+            'locked', 'course_admitted', 'password', 'suspended')
+        return form_fields
+
+class CustomApplicantManageFormPage(ApplicantManageFormPage):
+    """A full edit view for applicant data.
+    """
+    grok.template('applicanteditpage')
+
+    @property
+    def form_fields(self):
+        form_fields = grok.AutoFields(ICustomApplicant)
+        form_fields['applicant_id'].for_display = True
+        return form_fields
+
+class CustomApplicantEditFormPage(ApplicantEditFormPage):
+    """An applicant-centered edit view for applicant data.
+    """
+    grok.template('applicanteditpage')
+
+    @property
+    def form_fields(self):
+        form_fields = grok.AutoFields(ICustomApplicantEdit).omit(
+            'locked', 'course_admitted',
+            'suspended'
+            )
+        form_fields['applicant_id'].for_display = True
+        form_fields['reg_number'].for_display = True
+        return form_fields
Index: main/kofacustom.pcn/trunk/src/kofacustom/pcn/applicants/browser_templates/applicantdisplaypage.pt
===================================================================
--- main/kofacustom.pcn/trunk/src/kofacustom/pcn/applicants/browser_templates/applicantdisplaypage.pt	(revision 11843)
+++ main/kofacustom.pcn/trunk/src/kofacustom/pcn/applicants/browser_templates/applicantdisplaypage.pt	(revision 11843)
@@ -0,0 +1,65 @@
+<h2 i18n:domain="waeup.kofa">
+  ...
+  <span tal:replace="context/translated_state">APPLICATIONSTATE
+  </span>
+  <span tal:omit-tag=""
+    i18n:translate="" tal:condition="context/suspended">(account suspended)
+  </span>
+  ...
+</h2>
+
+<div class="workflow">
+  <div tal:repeat="msg context/history/messages">
+    <span tal:replace="msg">MESSAGE</span><br />
+  </div>
+</div>
+
+<img src="" height="180px" tal:attributes="src view/passport_url" />
+
+<table i18n:domain="waeup.kofa" class="form-table">
+  <tbody>
+    <tal:widgets content="structure provider:widgets" />
+    <tr tal:condition="view/getCourseAdmitted">
+      <td class="fieldname" i18n:translate="">
+          Admitted Course of Study:
+      </td>
+      <td>
+        <span tal:replace="structure view/getCourseAdmitted" />
+      </td>
+    </tr>
+    <tr>
+      <td class="fieldname" i18n:translate="">
+          Password:
+      </td>
+      <td>
+          <tal:password replace="view/hasPassword" />
+      </td>
+    <tr>
+  </tbody>
+</table>
+<h3 i18n:domain="waeup.kofa" i18n:translate="">
+    Payment Tickets
+</h3>
+<table i18n:domain="waeup.kofa" class="table table-condensed">
+  <thead>
+    <tr>
+      <th i18n:translate="">Payment Id</th>
+      <th i18n:translate="">Creation Date</th>
+      <th i18n:translate="">Payment Date</th>
+      <th i18n:translate="">Category</th>
+      <th i18n:translate="">Item</th>
+      <th i18n:translate="">State</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr tal:repeat="value context/values">
+      <td> <a tal:attributes="href python:view.url(value)">
+      <span tal:content="value/p_id">PID</span></a></td>
+      <td tal:content="python: layout.formatDatetime(value.creation_date)">CREATION DATE</td>
+      <td tal:content="python: layout.formatDatetime(value.payment_date)">PAYMENT DATE</td>
+      <td tal:content ="value/category">CATEGORY</td>
+      <td tal:content ="value/display_item">ITEM</td>
+      <td tal:content ="value/p_state_title">STATE</td>
+    </tr>
+  </tbody>
+</table>
Index: main/kofacustom.pcn/trunk/src/kofacustom/pcn/applicants/browser_templates/applicanteditpage.pt
===================================================================
--- main/kofacustom.pcn/trunk/src/kofacustom/pcn/applicants/browser_templates/applicanteditpage.pt	(revision 11843)
+++ main/kofacustom.pcn/trunk/src/kofacustom/pcn/applicants/browser_templates/applicanteditpage.pt	(revision 11843)
@@ -0,0 +1,138 @@
+<form action="." tal:attributes="action request/URL" method="post"
+      i18n:domain="waeup.kofa" enctype="multipart/form-data"
+      autocomplete="off">
+
+  <h2 i18n:domain="waeup.kofa">
+    ...
+    <span tal:replace="context/translated_state">APPLICATIONSTATE
+    </span>
+    <span tal:omit-tag=""
+      i18n:translate="" tal:condition="context/suspended">(account suspended)
+    </span>
+    ...
+  </h2>
+
+  <div class="workflow">
+    <div tal:repeat="msg context/history/messages">
+      <span tal:replace="msg">MESSAGE</span><br />
+    </div>
+  </div>
+
+  <table class="form-table">
+    <tbody>
+      <tal:widgets content="structure provider:widgets" />
+      <tr>
+        <td class="fieldname" i18n:translate="">
+          Passport Photo:
+        </td>
+        <td>
+          <img src="passport.jpg" height="180px" /><br />
+          <br />
+      		<div class="input-group half">
+      			<div class="input-group-btn">
+      				<div class="btn btn-default btn-file">
+                Select&hellip;
+                <input type="file" name="form.passport" />
+              </div>
+      			</div>
+      			<input type="text" class="form-control" readonly>
+          </div>
+          <span i18n:translate="">
+            Max. file size:
+          </span>
+          <span tal:replace="view/max_upload_size">10 KB</span>
+      </tr>
+      <tr tal:condition="view/manage_applications">
+        <td class="fieldname" i18n:translate="">Password:</td>
+        <td>
+          <input class="form-control" name="password" type="password"  />
+        </td>
+      </tr>
+      <tr tal:condition="view/manage_applications">
+        <td class="fieldname" i18n:translate="">Retype Password:</td>
+        <td>
+          <input class="form-control" name="control_password" type="password" />
+        </td>
+      </tr>
+      <tr tal:condition="view/manage_applications">
+        <td class="fieldname" i18n:translate="">Application Transition:</td>
+        <td>
+          <select id="transition" name="transition" class="form-control half">
+            <option tal:repeat="transition view/getTransitions"
+                    tal:attributes="value transition/name">
+              <span tal:replace="transition/title">TRANSITIONTITLE</span>
+            </option>
+          </select>
+        </td>
+      </tr>
+    </tbody>
+  </table>
+
+  <div tal:condition="not: view/manage_applications">
+    <input id="confirm_passport" name="confirm_passport"
+           type="checkbox" value="True"/>
+    <span i18n:translate="">
+    I confirm that the Passport Photograph uploaded on this form is a
+    true picture of me.
+    </span>
+  </div>
+  <br />
+
+  <div tal:condition="view/availableActions">
+    <span tal:repeat="action view/actions"
+          tal:omit-tag="">
+      <input tal:condition="python:action.label in view.display_actions[0]"
+             tal:replace="structure action/render"/>
+    </span>
+  </div>
+
+  <br /><br />
+  <h3 i18n:translate="">
+      Payment Tickets
+  </h3>
+
+  <table i18n:domain="waeup.kofa" class="table table-condensed">
+    <thead>
+    <tr>
+      <th>&nbsp;</th>
+      <th i18n:translate="">Payment Id</th>
+      <th i18n:translate="">Creation Date</th>
+      <th i18n:translate="">Payment Date</th>
+      <th i18n:translate="">Category</th>
+      <th i18n:translate="">Item</th>
+      <th i18n:translate="">State</th>
+    </tr>
+    </thead>
+    <tbody>
+      <tr tal:repeat="cl context/values">
+         <td>
+          <input type="checkbox"
+    		 name="val_id"
+    		 tal:attributes="value cl/__name__"
+         tal:condition="python: not view.unremovable(cl)" />
+        </td>
+        <td> <a tal:attributes="href python:view.url(cl)">
+        <span tal:content="cl/p_id">PID</span></a></td>
+        <td tal:content="python: layout.formatDatetime(cl.creation_date)">CREATION DATE</td>
+        <td tal:content="python: layout.formatDatetime(cl.payment_date)">PAYMENT DATE</td>
+      <td tal:content ="cl/category">CATEGORY</td>
+      <td tal:content ="cl/display_item">ITEM</td>
+      <td tal:content ="cl/p_state_title">STATE</td>
+      </tr>
+    </tbody>
+  </table>
+
+  <div tal:condition="view/availableActions">
+    <span tal:repeat="action view/actions"
+          tal:omit-tag="">
+      <input tal:condition="python:action.label in view.display_actions[1]"
+             tal:replace="structure action/render"/>
+    </span>
+  </div>
+  <br />
+  <p i18n:translate="" tal:condition="context/special">
+    <strong>Notice:</strong> If you need to pay for another service,
+    select the corresponding special application category above,
+    click 'Save' and then 'Add online payment ticket' again.
+  </p>
+</form>
Index: main/kofacustom.pcn/trunk/src/kofacustom/pcn/applicants/interfaces.py
===================================================================
--- main/kofacustom.pcn/trunk/src/kofacustom/pcn/applicants/interfaces.py	(revision 11841)
+++ main/kofacustom.pcn/trunk/src/kofacustom/pcn/applicants/interfaces.py	(revision 11843)
@@ -18,18 +18,127 @@
 """Customized interfaces of the university application package.
 """
-
+from datetime import datetime
+from grokcore.content.interfaces import IContainer
+from zc.sourcefactory.contextual import BasicContextualSourceFactory
+from zope import schema
+from zope.component import queryUtility, getUtility
+from zope.catalog.interfaces import ICatalog
+from zope.interface import Interface, Attribute, implements, directlyProvides
+from zope.schema.interfaces import (
+    ValidationError, ISource, IContextSourceBinder)
+from waeup.kofa.browser.interfaces import IApplicantBase
+from waeup.kofa.schema import TextLineChoice, FormattedDate
+from waeup.kofa.interfaces import (
+    IKofaObject, validate_email,
+    SimpleKofaVocabulary)
+from waeup.kofa.interfaces import MessageFactory as _
+from waeup.kofa.payments.interfaces import IOnlinePayment
+from waeup.kofa.schema import PhoneNumber
+from waeup.kofa.students.vocabularies import GenderSource, RegNumberSource
+from waeup.kofa.university.vocabularies import (
+    AppCatSource, CertificateSource, SpecialApplicationSource)
 from waeup.kofa.applicants.interfaces import (
-    IApplicantBaseData,
-    IApplicantOnlinePayment,
-    IApplicantEdit,
-    )
+    contextual_reg_num_source, AppCatCertificateSource,
+    IApplicantOnlinePayment)
 from kofacustom.pcn.interfaces import MessageFactory as _
 
-class ICustomApplicant(IApplicantBaseData):
-    """A custom applicant.
+class ICustomApplicant(IApplicantBase):
+    """The data for an applicant.
 
+    This is a base interface with no field
+    required. For use with processors, forms, etc., please use one of
+    the derived interfaces below, which set more fields to required
+    state, depending on use-case.
     """
 
-class ICustomApplicantEdit(IApplicantEdit):
+    def writeLogMessage(view, comment):
+        """Adds an INFO message to the log file
+        """
+
+    def createStudent():
+        """Create a student object from applicatnt data
+        and copy applicant object.
+        """
+
+    history = Attribute('Object history, a list of messages')
+    state = Attribute('The application state of an applicant')
+    display_fullname = Attribute('The fullname of an applicant')
+    application_date = Attribute('UTC datetime of submission, used for export only')
+    password = Attribute('Encrypted password of a applicant')
+    application_number = Attribute('The key under which the record is stored')
+
+    suspended = schema.Bool(
+        title = _(u'Account suspended'),
+        default = False,
+        required = False,
+        )
+
+    applicant_id = schema.TextLine(
+        title = _(u'Applicant Id'),
+        required = False,
+        readonly = False,
+        )
+    reg_number = TextLineChoice(
+        title = _(u'Registration Number'),
+        readonly = False,
+        required = True,
+        source = contextual_reg_num_source,
+        )
+    firstname = schema.TextLine(
+        title = _(u'First Name'),
+        required = True,
+        )
+    middlename = schema.TextLine(
+        title = _(u'Middle Name'),
+        required = False,
+        )
+    lastname = schema.TextLine(
+        title = _(u'Last Name (Surname)'),
+        required = True,
+        )
+    date_of_birth = FormattedDate(
+        title = _(u'Date of Birth'),
+        required = False,
+        #date_format = u'%d/%m/%Y', # Use grok-instance-wide default
+        show_year = True,
+        )
+    sex = schema.Choice(
+        title = _(u'Sex'),
+        source = GenderSource(),
+        required = True,
+        )
+    email = schema.ASCIILine(
+        title = _(u'Email Address'),
+        required = False,
+        constraint=validate_email,
+        )
+    phone = PhoneNumber(
+        title = _(u'Phone'),
+        description = u'',
+        required = False,
+        )
+    course1 = schema.Choice(
+        title = _(u'1st Choice Course of Study'),
+        source = AppCatCertificateSource(),
+        required = True,
+        )
+
+    notice = schema.Text(
+        title = _(u'Notice'),
+        required = 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 ICustomApplicantEdit(ICustomApplicant):
     """A custom applicant interface for editing.
 
@@ -41,5 +150,28 @@
     We cannot omit fields here. This has to be done in the
     respective form page.
+
     """
+
+    email = schema.ASCIILine(
+        title = _(u'Email Address'),
+        required = True,
+        constraint=validate_email,
+        )
+    course1 = schema.Choice(
+        title = _(u'1st Choice Course of Study'),
+        source = AppCatCertificateSource(),
+        required = True,
+        )
+    course_admitted = schema.Choice(
+        title = _(u'Admitted Course of Study'),
+        source = CertificateSource(),
+        required = False,
+        readonly = True,
+        )
+    notice = schema.Text(
+        title = _(u'Notice'),
+        required = False,
+        readonly = True,
+        )
 
 class ICustomApplicantOnlinePayment(IApplicantOnlinePayment):
