Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/CHANGES.txt
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/CHANGES.txt	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/CHANGES.txt	(revision 8872)
@@ -0,0 +1,8 @@
+Changes
+*******
+
+0.1dev (unreleased)
+===================
+
+- Initial implementation.
+
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/README.txt
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/README.txt	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/README.txt	(revision 8872)
@@ -0,0 +1,4 @@
+kofacustom.nigeria
+******************
+
+Customizations of the `waeup.kofa` package for the nigerian market.
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/buildout.cfg
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/buildout.cfg	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/buildout.cfg	(revision 8872)
@@ -0,0 +1,189 @@
+[buildout]
+# See http://pypi.python.org/pypi/mr.developer for details
+extensions = mr.developer
+# Install waeup.kofa as develop egg
+auto-checkout = waeup.kofa
+develop = .
+parts =
+    eggbasket
+    app
+    i18n
+    test
+    mkdirs
+    zpasswd
+    zope_conf
+    site_zcml
+    zdaemon_conf
+    deploy_ini
+    debug_ini
+    profile_ini
+# waeupdocs
+    coverage-detect
+    coverage-report
+# kofactl creation must be _after_ app!
+    kofactl
+# For backward compatibility, telling buildout not to throw away
+# the data and log subdirectories from the parts directory.
+    data
+    log
+# newest = false
+
+extends = versions.cfg
+
+# eggs will be installed in the default buildout location
+# (see .buildout/default.cfg in your home directory)
+# unless you specify an eggs-directory option here.
+
+[sources]
+waeup.kofa = svn https://svn.waeup.org/repos/main/waeup.kofa/trunk
+
+[kofa_params]
+## Basic parameters for deployment.
+# default is 127.0.0.1
+host = 0.0.0.0
+# default is 8080
+base_port = 8080
+zeo1_port = 8080
+zeo2_port = 8081
+zeo3_port = 8082
+server_port = 8100
+# default 7. Number of pre-opened ZODB threads/client
+pool_size = 7
+# default 20MB. Cache size of each client (ZEO only)
+client_cache = 20MB
+# default 5000. Number of objects cached.
+object_cache = 5000
+# number of preopened paster threads, default 10
+threadpool_workers = 10
+devel_pkg = kofacustom.nigeria
+
+[app]
+# This creates all scripts in bin/. The kofactl created here is 'faulty'.
+recipe = zc.recipe.egg
+eggs = kofacustom.nigeria [beaker]
+       z3c.evalexception>=2.0
+       Paste
+       PasteScript
+       PasteDeploy
+       repoze.profile
+       ZODB3
+interpreter = python-console
+
+[kofactl]
+# See http://pypi.python.org/pypi/zc.recipe.egg for details...
+# Here we create the kofactl script again, this time with a
+# fixed path to zdaemon.conf as argument.
+recipe = zc.recipe.egg
+eggs = kofacustom.nigeria [beaker]
+       waeup.kofa
+arguments = "${buildout:parts-directory}/etc/zdaemon.conf"
+scripts = kofactl=kofactl
+
+[mkdirs]
+recipe = z3c.recipe.mkdir
+paths =
+    ${zope_conf:filestorage}
+    ${zope_conf:logfiles}
+    ${zope_conf:blobstorage}
+    ${buildout:directory}/var/mailqueue/cur
+    ${buildout:directory}/var/mailqueue/tmp
+    ${buildout:directory}/var/mailqueue/new
+    ${buildout:directory}/var/datacenter/media
+    ${buildout:directory}/parts/test/datacenter
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = kofacustom.nigeria [beaker, test]
+defaults = ['--tests-pattern', '^f?tests$', '-v']
+
+# this section named so that the i18n scripts are called bin/i18n...
+[i18n]
+recipe = z3c.recipe.i18n:i18n
+packages = kofacustom.nigeria
+eggs = kofacustom.nigeria
+domain = waeup.custom
+output = src/kofacustom/nigeria/locales
+zcml =
+
+# This section is named so that the zpasswd utility is
+# called `zpasswd`
+[zpasswd]
+recipe = z3c.recipe.dev:script
+eggs = kofacustom.nigeria
+module = zope.app.server.zpasswd
+method = main
+
+[zope_conf]
+recipe = collective.recipe.template
+input = etc/zope.conf.in
+output = ${buildout:parts-directory}/etc/zope.conf
+filestorage = ${buildout:directory}/var/filestorage
+blobstorage = ${buildout:directory}/var/blobstorage
+logfiles = ${buildout:directory}/var/log
+extra =
+# extra = <grokwarnings>True</grokwarnings>
+# 'extra' is copied verbatim. Use it for product config sections and so.
+
+# The [data] and [log] parts are still in here to instruct buildout to not
+# unintentionally throw away the parts/data and parts/log subdirectories
+# that contain the Data.fs and the log files. These files should be
+# copied to the new locations. See the upgrade notes for more information.
+[data]
+recipe = zc.recipe.filestorage
+
+[log]
+recipe = zc.recipe.filestorage
+
+[mailqueue]
+recipe = zc.recipe.filestorage
+
+[site_zcml]
+recipe = collective.recipe.template
+input = etc/site.zcml.in
+output = ${buildout:parts-directory}/etc/site.zcml
+
+[zdaemon_conf]
+recipe = collective.recipe.template
+input = etc/zdaemon.conf.in
+output = ${buildout:parts-directory}/etc/zdaemon.conf
+
+[deploy_ini]
+recipe = collective.recipe.template
+input = etc/deploy.ini.in
+output = ${buildout:parts-directory}/etc/deploy.ini
+
+[debug_ini]
+recipe = collective.recipe.template
+input = etc/debug.ini.in
+output = ${buildout:parts-directory}/etc/debug.ini
+
+[profile_ini]
+recipe = collective.recipe.template
+input = etc/profile.ini.in
+output = ${buildout:parts-directory}/etc/profile.ini
+
+[eggbasket]
+recipe = z3c.recipe.eggbasket
+eggs = grok
+url = http://grok.zope.org/releaseinfo/grok-eggs-1.1.tgz
+
+#[waeupdocs]
+#recipe = collective.recipe.sphinxbuilder
+#eggs = kofacustom.nigeria[docs]
+#source = ${buildout:directory}/docs/source
+#build = ${buildout:directory}/docs/build
+
+# Collect test coverage data.
+[coverage-detect]
+recipe = zc.recipe.testrunner
+eggs = kofacustom.nigeria[beaker]
+defaults = ['--tests-pattern', '^f?tests$', '-v', '--coverage', 'coverage']
+
+# Create a coverage report.
+# Make sure to run bin/coverage-detect to collect the data for the report
+# first!
+[coverage-report]
+recipe = zc.recipe.egg
+eggs = z3c.coverage
+scripts = coveragereport
+arguments = ('${buildout:parts-directory}/coverage-detect/working-directory/coverage', '${buildout:directory}/coverage-report')
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/setup.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/setup.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/setup.py	(revision 8872)
@@ -0,0 +1,94 @@
+import os
+from setuptools import setup, find_packages
+
+version = '0.1dev'
+
+install_requires =[
+    'setuptools',
+    'grok',
+    'waeup.kofa',
+    ],
+
+# Having beaker installed additionally is a feature very recommended
+# for production use. The default buildout includes beaker for tests,
+# start scripts, and other parts that can benefit from it. The windows
+# buildout does not include it due to compiling problems with the
+# beaker package.
+beaker_require = [
+    'dolmen.beaker',
+    ]
+
+tests_require = [
+    'z3c.testsetup',
+    'zope.app.testing',
+    'zope.testbrowser',
+    'zope.testing',
+    'unittest2',
+    ]
+
+docs_require = [
+    'Sphinx',
+    'collective.recipe.sphinxbuilder',
+    'docutils',
+    'roman',
+    'repoze.sphinx.autointerface',
+    ]
+
+def read(*rnames):
+    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+long_description = (
+    read('README.txt')
+    + '\n\n'
+    + read('CHANGES.txt')
+    + '\n\n'
+    + 'Download\n'
+    + '********\n'
+    )
+
+setup(name = 'kofacustom.nigeria',
+      version = version,
+      description = "Nigerian customizations of the waeup.kofa package",
+      long_description = long_description,
+
+      keywords = "portal waeup kofa student university registration nigeria",
+      # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
+      classifiers = [
+        'Development Status :: 3 - Alpha',
+        'Environment :: Web Environment',
+        'Intended Audience :: Education',
+        'License :: OSI Approved :: GNU General Public License (GPL)',
+        'Programming Language :: Python',
+        'Operating System :: POSIX',
+        'Operating System :: POSIX :: Linux',
+        'Framework :: Zope3',
+        'Topic :: Education',
+        'Topic :: Internet :: WWW/HTTP',
+        ],
+      author = "The WAeUP team.",
+      author_email = "",
+      url = "http://www.waeup.org/",
+      license = "GPL",
+      package_dir = {'': 'src'},
+      packages= find_packages('src'),
+      namespace_packages = ['kofacustom',],
+      include_package_data = True,
+      zip_safe = False,
+      install_requires = install_requires,
+      tests_require = tests_require,
+      extras_require = dict(
+        test = tests_require,
+        docs = docs_require,
+        beaker = beaker_require,
+        ),
+      entry_points="""
+      # Add entry points here
+      [console_scripts]
+      kofa-debug = grokcore.startup:interactive_debug_prompt
+      kofactl = grokcore.startup:zdaemon_controller
+      [paste.app_factory]
+      main = grokcore.startup:application_factory
+      debug = grokcore.startup:debug_application_factory
+
+      """,
+      )
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/__init__.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/__init__.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/__init__.py	(revision 8872)
@@ -0,0 +1,7 @@
+# namespace package boilerplate
+try:
+    import pkg_resources
+    pkg_resources.declare_namespace(__name__)
+except ImportError, e:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/applicants/__init__.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/applicants/__init__.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/applicants/__init__.py	(revision 8872)
@@ -0,0 +1,1 @@
+# Make this a package.
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/applicants/utils.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/applicants/utils.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/applicants/utils.py	(revision 8872)
@@ -0,0 +1,56 @@
+## $Id$
+##
+## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+"""General helper functions and utilities for the application section.
+"""
+
+import grok
+from waeup.kofa.applicants.utils import ApplicantsUtils
+from kofacustom.nigeria.interfaces import MessageFactory as _
+
+
+class NigeriaApplicantsUtils(ApplicantsUtils):
+    """A collection of parameters and methods subject to customization.
+    """
+
+    APP_TYPES_DICT = {
+        'pude': ['Post-UDE Screening', 'PUDE'],
+        'prence': ['Pre-NCE Programme', 'PRE'],
+        'sandwich': ['Part-Time Degree in Education', 'SAND'],
+        'pt': ['Part-Time Degree Programmes', 'PTP'],
+        'putme': ['Post-UTME Screening Exercise', 'PUTME'],
+        'app': ['General Studies', 'APP'],
+        'cest': ['Common Entry Screening Test', 'CEST'],
+        'ct': ['Certificate Programmes', 'CTP'],
+        'dp': ['Diploma Programmes', 'DPP'],
+        'pce': ['PCE Screening', 'PCE'],
+        'pgft': ['Postgraduate Full-Time Programmes', 'PG'],
+        'pgpt': ['Postgraduate Part-Time Programmes', 'PG']
+        }
+
+    SEPARATORS_DICT = {
+        'form.applicant_id': _(u'Base Data'),
+        'form.course1': _(u'Programmes/Courses Desired'),
+        'form.hq_type': _(u'Higher Education Record'),
+        'form.presently': _(u'Course or Programme Presently Attending'),
+        'form.nysc_year': _(u'NYSC Information'),
+        'form.employer': _(u'Employment History'),
+        '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'),
+        }
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/configure.zcml
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/configure.zcml	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/configure.zcml	(revision 8872)
@@ -0,0 +1,10 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:grok="http://namespaces.zope.org/grok"
+           xmlns:i18n="http://namespaces.zope.org/i18n">
+
+  <!-- Loading grok also configures a lot of other needed packages correctly.
+  -->
+  <include package="kofacustom.nigeria" file="locales.zcml" />
+  <include package="grok" />
+  <includeOverrides package="kofacustom.nigeria" file="overrides.zcml" />
+</configure>
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/ftesting.zcml
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/ftesting.zcml	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/ftesting.zcml	(revision 8872)
@@ -0,0 +1,91 @@
+<configure
+   xmlns="http://namespaces.zope.org/zope"
+   xmlns:kofa="http://namespaces.waeup.org/kofa"
+   i18n_domain="kofacustom.nigeria"
+   package="kofacustom.nigeria"
+   >
+
+  <include package="grok" />
+  <includeOverrides package="kofacustom.nigeria" />
+  <include package="kofacustom.nigeria" file="mail.zcml" />
+
+  <!-- Where should the datacenter reside by default?
+
+       The path is relative to the `package` defined in top
+       `configure` directive.
+  -->
+  <kofa:datacenter
+      path="../../../parts/test/datacenter" />
+
+
+  <!-- Typical functional testing security setup -->
+  <securityPolicy
+      component="zope.securitypolicy.zopepolicy.ZopeSecurityPolicy"
+      />
+
+
+  <unauthenticatedPrincipal
+      id="zope.anybody"
+      title="Unauthenticated User"
+      />
+  <unauthenticatedGroup
+      id="zope.Anybody"
+      title="Unauthenticated Users"
+      />
+  <authenticatedGroup
+      id="zope.Authenticated"
+      title="Authenticated Users"
+      />
+  <everybodyGroup
+      id="zope.Everybody"
+      title="All Users"
+      />
+
+
+  <!-- grant
+      permission="zope.View"
+      principal="zope.Anybody"
+      / -->
+
+  <grant
+      permission="zope.app.dublincore.view"
+      principal="zope.Anybody" />
+  <grant
+      permission="zope.View"
+      principal="zope.Authenticated"
+      />
+  <grant
+      permission="zope.app.dublincore.view"
+      principal="zope.Authenticated"
+      />
+  <grant
+      permission="waeup.Public"
+      principal="zope.Everybody"
+      />
+  <grant
+      permission="waeup.Anonymous"
+      principal="zope.Anybody"
+      />
+
+  <principal
+      id="zope.mgr"
+      title="Manager"
+      login="mgr"
+      password="mgrpw"
+      />
+
+  <role
+      id="zope.Manager"
+      title="Site Manager"
+      />
+
+  <grantAll
+      role="zope.Manager"
+      />
+
+  <grant
+      role="zope.Manager"
+      principal="zope.mgr"
+      />
+
+</configure>
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/interfaces.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/interfaces.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/interfaces.py	(revision 8872)
@@ -0,0 +1,89 @@
+## $Id$
+##
+## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+
+import zope.i18nmessageid
+from zope import schema
+from zc.sourcefactory.basic import BasicSourceFactory
+from waeup.kofa.interfaces import (SimpleKofaVocabulary,
+    ISessionConfiguration, academic_sessions_vocab)
+from kofacustom.nigeria.utils.lgas import LGAS
+
+_ = MessageFactory = zope.i18nmessageid.MessageFactory('waeup.custom')
+
+high_qual = SimpleKofaVocabulary(
+    ('National Certificate of Education','nce'),
+    ('Pre Degree Programme','pre'),
+    ('Diploma Programme','dip'),
+    ('Ordinary National Diploma','ond'),
+    ('Bachelors Degree','bd'),
+    ('Masters Degree','md'),
+    ('Professional Qualification','pq'),
+    ('Other Certification','oc'),
+    ('Higher National Diploma','hnd'),
+    ('Post Graduate Diploma','pgd'),
+    ('NCE AL OTH','nce_al_oth'),
+    ('National Defence Academy','nda'),
+    ('Awaiting Results','a_rslt'),
+    ('RMC','rmc'),
+    )
+
+high_grade = SimpleKofaVocabulary(
+    ('Upper Credit','upper_credit'),
+    ('Distinction','distinction'),
+    ('Credit','credit'),
+    ('Merit','merit'),
+    ('Lower Credit','lower_credit'),
+    ('First Class','first_class'),
+    ('Second Class Upper','second_class_upper'),
+    ('Second Class Lower','second_class_lower'),
+    ('Third Class','third_class'),
+    ('Pass','pass'),
+    ('Awaiting Results','a_rslt'),
+    ('A Levels','al'),
+    )
+
+exam_types = SimpleKofaVocabulary(
+    ('SSCE','ssce'),
+    ('WAEC','waec'),
+    ('GCE O\' LEVEL','gce_o_level'),
+    ('TC II','tc_ii'),
+    ('RSA','rsa'),
+    ('NABTEB','nabteb'),
+    ('NECO','neco'),
+    ('ACE','ace'),
+    ('GCE A\' LEVEL','gce_a_level'),
+    ('IGCSE','igcse'),
+    )
+
+#lgas_vocab = SimpleKofaVocabulary(
+#    *sorted([(x[1],x[0]) for x in LGAS]))
+
+class LGASource(BasicSourceFactory):
+    """A source for school subjects used in exam documentation.
+    """
+    lga_dict = dict(LGAS)
+
+    def getValues(self):
+        return sorted(self.lga_dict.keys())
+
+    def getToken(self, value):
+        return str(value)
+
+    def getTitle(self, value):
+        return self.lga_dict.get(value,
+            _('Invalid key: ${a}', mapping = {'a':value}))
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/locales.zcml
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/locales.zcml	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/locales.zcml	(revision 8872)
@@ -0,0 +1,8 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:i18n="http://namespaces.zope.org/i18n">
+
+  <include package="zope.i18n" file="meta.zcml" />
+  <i18n:registerTranslations directory="locales" />
+  <include package="waeup.kofa" file="locales.zcml" />
+
+</configure>
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/locales/de/LC_MESSAGES/waeup.custom.po
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/locales/de/LC_MESSAGES/waeup.custom.po	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/locales/de/LC_MESSAGES/waeup.custom.po	(revision 8872)
@@ -0,0 +1,63 @@
+# #############################################################################
+#
+# Copyright (c) 2003-2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+# #############################################################################
+msgid ""
+msgstr ""
+"Project-Id-Version: Development/Unknown\n"
+"POT-Creation-Date: Wed Jun 27 07:30:55 2012\n"
+"PO-Revision-Date: 2012-06-27 07:36+0100\n"
+"Last-Translator: Henrik Bettermann <henrik@waeup.org>\n"
+"Language-Team: Zope 3 Developers <zope3-dev@zope.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: zope/app/locales/extract.py\n"
+
+#. Default: ""
+#: kofacustom/nigeria/interfaces.py:89
+msgid "Invalid key: ${a}"
+msgstr "Ungültiger Schlüssel: ${a}"
+
+#: kofacustom/nigeria/utils/utils.py:26
+msgid "Nigeria"
+msgstr "Nigeria"
+
+#: kofacustom/nigeria/utils/utils.py:27
+msgid "Germany"
+msgstr "Deutschland"
+
+#: kofacustom/nigeria/utils/utils.py:28
+msgid "United States"
+msgstr "Vereinigte Staaten"
+
+#: kofacustom/nigeria/utils/utils.py:29
+msgid "Niger"
+msgstr "Niger"
+
+#: kofacustom/nigeria/utils/utils.py:30
+msgid "Benin"
+msgstr "Benin"
+
+#: kofacustom/nigeria/utils/utils.py:31
+msgid "Cameroon"
+msgstr "Kamerun"
+
+#: kofacustom/nigeria/utils/utils.py:32
+msgid "United Kingdom"
+msgstr "Vereinigtes Königreich"
+
+#: kofacustom/nigeria/utils/utils.py:33
+msgid "France"
+msgstr "Frankreich"
+
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/locales/waeup.custom.pot
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/locales/waeup.custom.pot	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/locales/waeup.custom.pot	(revision 8872)
@@ -0,0 +1,62 @@
+##############################################################################
+#
+# Copyright (c) 2003-2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+msgid ""
+msgstr ""
+"Project-Id-Version: Development/Unknown\n"
+"POT-Creation-Date: Wed Jun 27 07:30:55 2012\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: Zope 3 Developers <zope3-dev@zope.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: zope/app/locales/extract.py\n"
+
+#: kofacustom/nigeria/interfaces.py:89
+#. Default: ""
+msgid "Invalid key: ${a}"
+msgstr ""
+
+#: kofacustom/nigeria/utils/utils.py:26
+msgid "Nigeria"
+msgstr ""
+
+#: kofacustom/nigeria/utils/utils.py:27
+msgid "Germany"
+msgstr ""
+
+#: kofacustom/nigeria/utils/utils.py:28
+msgid "United States"
+msgstr ""
+
+#: kofacustom/nigeria/utils/utils.py:29
+msgid "Niger"
+msgstr ""
+
+#: kofacustom/nigeria/utils/utils.py:30
+msgid "Benin"
+msgstr ""
+
+#: kofacustom/nigeria/utils/utils.py:31
+msgid "Cameroon"
+msgstr ""
+
+#: kofacustom/nigeria/utils/utils.py:32
+msgid "United Kingdom"
+msgstr ""
+
+#: kofacustom/nigeria/utils/utils.py:33
+msgid "France"
+msgstr ""
+
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/mail.zcml
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/mail.zcml	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/mail.zcml	(revision 8872)
@@ -0,0 +1,82 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:mail="http://namespaces.zope.org/mail">
+  <!--
+
+   SMTP Settings
+   *************
+
+   In here we define the mailers and mail deliveries we want to be
+   used by the portal.
+
+   They are set here (and not dynamically in the portal) to increase
+   security. Even portal users with all permissions cannot change mail
+   server credentials and related. You need filesystem access to
+   change/override the settings in here.
+
+   In the portal you can pick one of the deliveries for use with all
+   SMTP (aka mail) related functionality.
+
+   Each delivery (direct or queued) is bound to a certain mailer,
+   defined by a 'mail:smtpMailer' directive.
+
+   The smtpMailer directives define real mail hosts (local or remote)
+   where mail from the portal should be processed.
+
+   The 'mail:directDelivery' and 'mail:queuedDelivery' directives send
+   local mail to the mailer set in their 'mailer' attribute. While
+   directDelivery sends mail immediately when a request is finished
+   (see zope.sendmail for more info), queuedDelivery handles mail in a
+   background thread and sends mail independently from requests.
+
+   By default in KOFA we have a fake mailer activated, that does not
+   send real mail to the outside world.
+  -->
+
+  <!-- A mail server on localhost -->
+  <!-- Mail server definitions require the following attributes:
+
+        - name: (string) name to be used by deliveries
+
+       Mail server definitions allow the following additional attribs:
+
+        - hostname   (string) hostname or IP(?) of mail server to use
+                              ('localhost' by default)
+        - port       (int number) port to connect to SMTP mailer
+                              (25 by default)
+        - username   (string) Username to log in to mail server
+        - password   (string) Password to log in to mail server
+
+  -->
+  <mail:smtpMailer
+      name="smtp.localhost"
+      hostname="localhost"
+      port="25"
+      />
+
+  <!-- The mail deliveries -->
+  <!-- Mail deliveries require the following attributes:
+
+        - name:       (string) this string will appear in portal select
+                               boxes
+        - permission: (string) zope default perms only
+        - mailer:     (string) name of some mailer registered above or
+                               'smtp'
+        - queuePath:  (string) must exist and contain cur/, new/, and
+                               tmp/ dirs. Relative paths are relative
+                               to the directory this files lives in.
+
+   -->
+  <mail:queuedDelivery
+      name="Queued SMTP on localhost"
+      permission="zope.Public"
+      mailer="smtp.localhost"
+      queuePath="../../../var/mailqueue"
+      />
+
+  <mail:directDelivery
+      name="Direct SMTP on localhost"
+      permission="zope.Public"
+      mailer="smtp.localhost"
+      />
+
+</configure>
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/overrides.zcml
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/overrides.zcml	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/overrides.zcml	(revision 8872)
@@ -0,0 +1,15 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:grok="http://namespaces.zope.org/grok">
+  <includeDependencies package="." />
+  <grok:grok package="." />
+
+  <!-- Register edit widget for PhoneNumbers -->
+  <adapter
+      for="waeup.kofa.schema.interfaces.IPhoneNumber
+           zope.publisher.interfaces.browser.IBrowserRequest"
+      provides="zope.formlib.interfaces.ISimpleInputWidget"
+      factory="kofacustom.nigeria.widgets.phonewidget.NigeriaPhoneWidget"
+      permission="zope.Public"
+      />
+
+</configure>
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/payments/__init__.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/payments/__init__.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/payments/__init__.py	(revision 8872)
@@ -0,0 +1,1 @@
+# Make this a package.
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/payments/interfaces.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/payments/interfaces.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/payments/interfaces.py	(revision 8872)
@@ -0,0 +1,70 @@
+## $Id$
+##
+## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+from zope.interface import Attribute
+from zope import schema
+from waeup.kofa.payments.interfaces import IPayment
+from kofacustom.nigeria.interfaces import MessageFactory as _
+
+class INigeriaOnlinePayment(IPayment):
+    """A payment via payment gateways.
+
+    """
+
+    ac = schema.TextLine(
+        title = _(u'Activation Code'),
+        default = None,
+        required = False,
+        readonly = False,
+        )
+
+    r_amount_approved = schema.Float(
+        title = _(u'Response Amount Approved'),
+        default = 0.0,
+        required = False,
+        readonly = False,
+        )
+
+    r_code = schema.TextLine(
+        title = _(u'Response Code'),
+        default = None,
+        required = False,
+        readonly = False,
+        )
+
+    r_desc = schema.TextLine(
+        title = _(u'Response Description'),
+        default = None,
+        required = False,
+        readonly = False,
+        )
+
+    # Only defined in custom package
+
+    r_pay_reference = schema.TextLine(
+        title = _(u'Response Payment Reference'),
+        default = None,
+        required = False,
+        readonly = False,
+        )
+
+    r_card_num = schema.TextLine(
+        title = _(u'Response Card Number'),
+        default = None,
+        required = False,
+        readonly = False,
+        )
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/__init__.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/__init__.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/__init__.py	(revision 8872)
@@ -0,0 +1,1 @@
+# Make this a package.
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/batching.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/batching.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/batching.py	(revision 8872)
@@ -0,0 +1,37 @@
+## $Id$
+##
+## Copyright (C) 2012 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+"""Batch processing components for student objects.
+
+Batch processors eat CSV files to add, update or remove large numbers
+of certain kinds of objects at once.
+
+Here we define the processors for students specific objects like
+students, studycourses, payment tickets and accommodation tickets.
+"""
+from kofacustom.nigeria.students.interfaces import (
+    INigeriaStudent, INigeriaStudentUpdateByRegNo,
+    INigeriaStudentUpdateByMatricNo
+    )
+from waeup.kofa.students.batching import StudentProcessor
+
+class NigeriaStudentProcessor(StudentProcessor):
+    """A batch processor for IStudent objects.
+    """
+    iface = INigeriaStudent
+    iface_byregnumber = INigeriaStudentUpdateByRegNo
+    iface_bymatricnumber = INigeriaStudentUpdateByMatricNo
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/browser.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/browser.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/browser.py	(revision 8872)
@@ -0,0 +1,212 @@
+## $Id$
+##
+## Copyright (C) 2012 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+import grok
+from zope.formlib.textwidgets import BytesDisplayWidget
+from zope.component import getUtility
+from zope.i18n import translate
+from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
+from waeup.kofa.interfaces import IExtFileStore
+from waeup.kofa.browser.layout import action
+from waeup.kofa.students.browser import (
+    StudentPersonalDisplayFormPage,
+    StudentClearanceManageFormPage, StudentClearanceEditFormPage,
+    StudentClearanceDisplayFormPage, OnlinePaymentFakeApprovePage,
+    ExportPDFClearanceSlipPage, StudentBaseManageFormPage,
+    StudentBaseEditFormPage, StudentPersonalEditFormPage,
+    OnlinePaymentDisplayFormPage, OnlinePaymentAddFormPage,
+    OnlinePaymentBreadcrumb, ExportPDFPaymentSlipPage,
+    StudentFilesUploadPage, emit_lock_message)
+from waeup.kofa.students.viewlets import (
+    PaymentReceiptActionButton, StudentPassportActionButton)
+from kofacustom.nigeria.students.interfaces import (
+    INigeriaStudentBase, INigeriaStudent, INigeriaStudentPersonal,
+    INigeriaUGStudentClearance,INigeriaPGStudentClearance,
+    INigeriaStudentOnlinePayment,
+    )
+from waeup.kofa.students.workflow import ADMITTED
+from kofacustom.nigeria.interfaces import MessageFactory as _
+
+class NigeriaOnlinePaymentBreadcrumb(OnlinePaymentBreadcrumb):
+    """A breadcrumb for payments.
+    """
+    grok.context(INigeriaStudentOnlinePayment)
+
+class PaymentReceiptActionButton(PaymentReceiptActionButton):
+    grok.order(4)
+    grok.context(INigeriaStudentOnlinePayment)
+
+class NigeriaStudentBaseManageFormPage(StudentBaseManageFormPage):
+    """ View to manage student base data
+    """
+    form_fields = grok.AutoFields(INigeriaStudentBase).omit('student_id')
+
+class NigeriaStudentBaseEditFormPage(StudentBaseEditFormPage):
+    """ View to edit student base data
+    """
+    form_fields = grok.AutoFields(INigeriaStudentBase).select(
+        'email', 'phone')
+
+
+class NigeriaStudentPersonalDisplayFormPage(StudentPersonalDisplayFormPage):
+    """ Page to display student personal data
+    """
+    grok.context(INigeriaStudent)
+    form_fields = grok.AutoFields(INigeriaStudentPersonal)
+    form_fields['perm_address'].custom_widget = BytesDisplayWidget
+
+
+class NigeriaStudentPersonalEditFormPage(StudentPersonalEditFormPage):
+    """ Page to edit personal data
+    """
+    form_fields = grok.AutoFields(INigeriaStudentPersonal)
+
+
+class NigeriaStudentClearanceDisplayFormPage(StudentClearanceDisplayFormPage):
+    """ Page to display student clearance data
+    """
+    grok.context(INigeriaStudent)
+
+    @property
+    def form_fields(self):
+        cm = getattr(self.context,'current_mode', None)
+        if cm is not None and cm.startswith('pg'):
+            form_fields = grok.AutoFields(
+                INigeriaPGStudentClearance).omit('clearance_locked')
+        else:
+            form_fields = grok.AutoFields(
+                INigeriaUGStudentClearance).omit('clearance_locked')
+        return form_fields
+
+class NigeriaExportPDFClearanceSlipPage(ExportPDFClearanceSlipPage):
+    """Deliver a PDF slip of the context.
+    """
+    grok.context(INigeriaStudent)
+
+    @property
+    def form_fields(self):
+        cm = getattr(self.context,'current_mode', None)
+        if cm is not None and cm.startswith('pg'):
+            form_fields = grok.AutoFields(
+                INigeriaPGStudentClearance).omit('clearance_locked')
+        else:
+            form_fields = grok.AutoFields(
+                INigeriaUGStudentClearance).omit('clearance_locked')
+        return form_fields
+
+class NigeriaStudentClearanceManageFormPage(StudentClearanceManageFormPage):
+    """ Page to edit student clearance data
+    """
+    grok.context(INigeriaStudent)
+
+    @property
+    def form_fields(self):
+        cm = getattr(self.context,'current_mode', None)
+        if cm is not None and cm.startswith('pg'):
+            form_fields = grok.AutoFields(INigeriaPGStudentClearance)
+        else:
+            form_fields = grok.AutoFields(INigeriaUGStudentClearance)
+        return form_fields
+
+class NigeriaStudentClearanceEditFormPage(StudentClearanceEditFormPage):
+    """ View to edit student clearance data by student
+    """
+    grok.context(INigeriaStudent)
+
+    @property
+    def form_fields(self):
+        cm = getattr(self.context,'current_mode', None)
+        if cm is not None and cm.startswith('pg'):
+            form_fields = grok.AutoFields(INigeriaPGStudentClearance).omit('clearance_locked')
+        else:
+            form_fields = grok.AutoFields(INigeriaUGStudentClearance).omit('clearance_locked')
+        return form_fields
+
+    def dataNotComplete(self):
+        store = getUtility(IExtFileStore)
+        if not store.getFileByContext(self.context, attr=u'birth_certicicate.jpg'):
+            return _('No birth certificate uploaded.')
+        if not store.getFileByContext(self.context, attr=u'ref_let.jpg'):
+            return _('No 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.')
+        return False
+
+class NigeriaOnlinePaymentDisplayFormPage(OnlinePaymentDisplayFormPage):
+    """ Page to view an online payment ticket
+    """
+    grok.context(INigeriaStudentOnlinePayment)
+    form_fields = grok.AutoFields(INigeriaStudentOnlinePayment)
+    form_fields[
+        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
+    form_fields[
+        'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
+
+class NigeriaOnlinePaymentAddFormPage(OnlinePaymentAddFormPage):
+    """ Page to add an online payment ticket
+    """
+    form_fields = grok.AutoFields(INigeriaStudentOnlinePayment).select(
+        'p_category')
+
+class NigeriaOnlinePaymentFakeApprovePage(OnlinePaymentFakeApprovePage):
+    """ Disable payment approval view for students.
+
+    This view is used for browser tests only and
+    has to be neutralized here!
+    """
+
+    grok.name('fake_approve')
+    grok.require('waeup.managePortal')
+
+    def update(self):
+        return
+
+class NigeriaExportPDFPaymentSlipPage(ExportPDFPaymentSlipPage):
+    """Deliver a PDF slip of the context.
+    """
+    grok.context(INigeriaStudentOnlinePayment)
+    form_fields = grok.AutoFields(INigeriaStudentOnlinePayment)
+    form_fields['creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
+    form_fields['payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
+
+class StudentPassportActionButton(StudentPassportActionButton):
+
+    @property
+    def target_url(self):
+        slip = getUtility(IExtFileStore).getFileByContext(
+            self.context, 'application_slip')
+        if self.context.state != ADMITTED or slip is not None:
+            return ''
+        return self.view.url(self.view.context, self.target)
+
+class NigeriaStudentFilesUploadPage(StudentFilesUploadPage):
+    """ View to upload passport picture.
+
+    Students are not allowed to change the picture if they
+    passed the regular Kofa application.
+    """
+
+    def update(self):
+        slip = getUtility(IExtFileStore).getFileByContext(
+            self.context, 'application_slip')
+        if self.context.state != ADMITTED or slip is not None:
+            emit_lock_message(self)
+            return
+        super(StudentFilesUploadPage, self).update()
+        return
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/interfaces.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/interfaces.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/interfaces.py	(revision 8872)
@@ -0,0 +1,400 @@
+## $Id$
+##
+## Copyright (C) 2012 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+from zope import schema
+from waeup.kofa.schema import TextLineChoice
+from waeup.kofa.interfaces import SimpleKofaVocabulary, academic_sessions_vocab
+from waeup.kofa.schema import FormattedDate
+from waeup.kofa.schoolgrades import ResultEntryField
+from waeup.kofa.students.vocabularies import nats_vocab
+from waeup.kofa.students.interfaces import (
+    IStudentBase, IUGStudentClearance, IPGStudentClearance,
+    IStudentPersonal, IStudentNavigation, IStudentStudyLevel,
+    IStudentStudyCourse, ICourseTicket
+    )
+from waeup.kofa.students.vocabularies import (
+    nats_vocab, contextual_reg_num_source)
+from kofacustom.nigeria.interfaces import (
+    high_qual, high_grade, exam_types, LGASource)
+from kofacustom.nigeria.interfaces import MessageFactory as _
+from kofacustom.nigeria.payments.interfaces import INigeriaOnlinePayment
+
+
+class INigeriaStudentBase(IStudentBase):
+    """Representation of student base data.
+
+    """
+
+    reg_number = TextLineChoice(
+        title = _(u'Registration Number'),
+        required = False,
+        readonly = False,
+        source = contextual_reg_num_source,
+        )
+
+class INigeriaStudentPersonal(IStudentPersonal):
+    """Student personal data.
+
+    """
+
+    marit_stat = schema.Choice(
+        title = u'Maritual Status',
+        default = 'unmarried',
+        required = False,
+        vocabulary = SimpleKofaVocabulary(
+            (_('Unmarried'), 'unmarried'),
+            (_('Married'), 'married'),)
+        )
+
+class INigeriaUGStudentClearance(IUGStudentClearance):
+    """Representation of ug student clearance data.
+
+    """
+    date_of_birth = FormattedDate(
+        title = _(u'Date of Birth'),
+        required = False,
+        show_year = True,
+        )
+
+    nationality = schema.Choice(
+        source = nats_vocab,
+        title = _(u'Nationality'),
+        required = False,
+        )
+
+    lga = schema.Choice(
+        source = LGASource(),
+        title = _(u'State/LGA (Nigerians only)'),
+        required = False,
+        )
+
+    def_adm = schema.Bool(
+        title = _(u'Deferent of Admission'),
+        required = False,
+        readonly = 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_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,
+        default = [],
+        )
+
+    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_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,
+        default = [],
+        )
+
+    alr_fname = schema.TextLine(
+        title = _(u'Full Name'),
+        required = False,
+        readonly = False,
+        )
+    alr_no = schema.TextLine(
+        title = _(u'Exam Number'),
+        required = False,
+        readonly = False,
+        )
+
+    alr_date = FormattedDate(
+        title = _(u'Exam Date'),
+        required = False,
+        readonly = False,
+        show_year = True,
+        )
+
+    alr_results = schema.List(
+        title = _(u'Exam Results'),
+        value_type = ResultEntryField(),
+        required = False,
+        readonly = False,
+        default = [],
+        )
+
+    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,
+        )
+
+
+class INigeriaPGStudentClearance(INigeriaUGStudentClearance):
+    """Representation of pg student clearance data.
+
+    """
+
+    hq2_type = schema.Choice(
+        title = _(u'Qualification Obtained'),
+        required = False,
+        readonly = False,
+        vocabulary = high_qual,
+        )
+
+    hq2_matric_no = schema.TextLine(
+        title = _(u'Former Matric Number'),
+        required = False,
+        readonly = False,
+        )
+
+    hq2_degree = schema.Choice(
+        title = _(u'Class of Degree'),
+        required = False,
+        readonly = False,
+        vocabulary = high_grade,
+        )
+
+    hq2_school = schema.TextLine(
+        title = _(u'Institution Attended'),
+        required = False,
+        readonly = False,
+        )
+
+    hq2_session = schema.TextLine(
+        title = _(u'Years Attended'),
+        required = False,
+        readonly = False,
+        )
+
+    hq2_disc = schema.TextLine(
+        title = _(u'Discipline'),
+        required = False,
+        readonly = False,
+        )
+
+    nysc_year = schema.Int(
+        title = _(u'Nysc Year'),
+        required = False,
+        readonly = False,
+        )
+
+    nysc_lga = schema.Choice(
+        source = LGASource(),
+        title = _(u'Nysc Location'),
+        required = False,
+        )
+
+    employer = schema.TextLine(
+        title = _(u'Employer'),
+        required = False,
+        readonly = False,
+        )
+
+    emp_position = schema.TextLine(
+        title = _(u'Employer Position'),
+        required = False,
+        readonly = False,
+        )
+
+    emp_start = FormattedDate(
+        title = _(u'Start Date'),
+        required = False,
+        readonly = False,
+        show_year = True,
+        )
+
+    emp_end = FormattedDate(
+        title = _(u'End Date'),
+        required = False,
+        readonly = False,
+        show_year = True,
+        )
+
+    emp_reason = schema.TextLine(
+        title = _(u'Reason for Leaving'),
+        required = False,
+        readonly = False,
+        )
+
+    employer2 = schema.TextLine(
+        title = _(u'2nd Employer'),
+        required = False,
+        readonly = False,
+        )
+
+    emp2_position = schema.TextLine(
+        title = _(u'2nd Employer Position'),
+        required = False,
+        readonly = False,
+        )
+
+    emp2_start = FormattedDate(
+        title = _(u'Start Date'),
+        required = False,
+        readonly = False,
+        show_year = True,
+        )
+    emp2_end = FormattedDate(
+        title = _(u'End Date'),
+        required = False,
+        readonly = False,
+        show_year = True,
+        )
+
+    emp2_reason = schema.TextLine(
+        title = _(u'Reason for Leaving'),
+        required = False,
+        readonly = False,
+        )
+
+    former_matric = schema.TextLine(
+        title = _(u'If yes, matric number'),
+        required = False,
+        readonly = False,
+        )
+
+
+class INigeriaStudent(INigeriaStudentBase,INigeriaUGStudentClearance,
+    INigeriaPGStudentClearance,INigeriaStudentPersonal):
+    """Representation of a student.
+
+    """
+
+class INigeriaStudentStudyCourse(IStudentStudyCourse):
+    """A container for student study levels.
+
+    """
+
+class INigeriaStudentStudyLevel(IStudentStudyLevel):
+    """A container for course tickets.
+
+    """
+
+class INigeriaStudentOnlinePayment(INigeriaOnlinePayment):
+    """A student payment via payment gateways.
+
+    This Interface does not inherit from IStudentOnlinePayment.
+    Thus all fields from IStudentOnlinePayment have to be repeated here.
+    """
+
+    p_level = schema.Int(
+        title = _(u'Payment Level'),
+        required = False,
+        readonly = True,
+        )
+
+INigeriaStudentOnlinePayment['p_level'].order = INigeriaStudentOnlinePayment[
+    'p_session'].order
+
+class INigeriaCourseTicket(ICourseTicket):
+    """A course ticket.
+
+    """
+
+class INigeriaStudentUpdateByRegNo(INigeriaStudent):
+    """Representation of a student. Skip regular reg_number validation.
+
+    """
+    reg_number = schema.TextLine(
+        title = _(u'Registration Number'),
+        required = False,
+        )
+
+class INigeriaStudentUpdateByMatricNo(INigeriaStudent):
+    """Representation of a student. Skip regular matric_number validation.
+
+    """
+    matric_number = schema.TextLine(
+        title = _(u'Matriculation Number'),
+        required = False,
+        )
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/payments.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/payments.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/payments.py	(revision 8872)
@@ -0,0 +1,59 @@
+## $Id$
+##
+## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+"""
+Student payment components.
+"""
+import grok
+from zope.component.interfaces import IFactory
+from zope.interface import implementedBy
+from waeup.kofa.students.interfaces import IStudentNavigation
+from waeup.kofa.students.payments import (
+    StudentOnlinePayment, StudentOnlinePaymentFactory)
+from waeup.kofa.utils.helpers import attrs_to_fields
+from kofacustom.nigeria.students.interfaces import INigeriaStudentOnlinePayment
+
+class NigeriaStudentOnlinePayment(StudentOnlinePayment):
+    """This is a custom online payment for students.
+
+    Since this class inherits from StudentOnlinePayment, it automatically
+    implements the interfaces of the parent class which means
+    all viewlets and views meant for StudentOnlinePayment
+    can also be accessed in the customized system.
+    """
+    grok.implements(INigeriaStudentOnlinePayment, IStudentNavigation)
+    grok.provides(INigeriaStudentOnlinePayment)
+
+    def __init__(self):
+        super(NigeriaStudentOnlinePayment, self).__init__()
+        return
+
+    @property
+    def student(self):
+        return self.__parent__.__parent__
+
+NigeriaStudentOnlinePayment = attrs_to_fields(NigeriaStudentOnlinePayment)
+
+class NigeriaStudentOnlinePaymentFactory(StudentOnlinePaymentFactory):
+    """A factory for student online payments.
+    """
+
+    def __call__(self, *args, **kw):
+        return NigeriaStudentOnlinePayment()
+
+    def getInterfaces(self):
+        return implementedBy(NigeriaStudentOnlinePayment)
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/student.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/student.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/student.py	(revision 8872)
@@ -0,0 +1,50 @@
+## $Id$
+##
+## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+"""
+Container for the various objects owned by students.
+"""
+import grok
+from zope.interface import implementedBy
+from waeup.kofa.utils.helpers import attrs_to_fields
+from waeup.kofa.students.student import Student, StudentFactory
+from kofacustom.nigeria.students.interfaces import INigeriaStudent, IStudentNavigation
+
+
+class NigeriaStudent(Student):
+    """This is a student container for the various objects
+    owned by students.
+    """
+    grok.implements(INigeriaStudent, IStudentNavigation)
+    grok.provides(INigeriaStudent)
+
+
+# Set all attributes of Student required in IStudent as field
+# properties. Doing this, we do not have to set initial attributes
+# ourselves and as a bonus we get free validation when an attribute is
+# set.
+NigeriaStudent = attrs_to_fields(NigeriaStudent)
+
+class NigeriaStudentFactory(StudentFactory):
+    """A factory for students.
+    """
+
+    def __call__(self, *args, **kw):
+        return NigeriaStudent()
+
+    def getInterfaces(self):
+        return implementedBy(NigeriaStudent)
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/studycourse.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/studycourse.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/studycourse.py	(revision 8872)
@@ -0,0 +1,72 @@
+## $Id$
+##
+## Copyright (C) 2012 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+"""
+Container which holds the data of the student study courses
+and contains the (student) study level objects.
+"""
+import grok
+from zope.interface import implementedBy
+from waeup.kofa.students.studycourse import (
+    StudentStudyCourse, StudentStudyCourseFactory)
+from waeup.kofa.utils.helpers import attrs_to_fields
+from waeup.kofa.students.workflow import CLEARED, RETURNING, PAID
+from kofacustom.nigeria.students.interfaces import (
+    INigeriaStudentStudyCourse, IStudentNavigation)
+
+class NigeriaStudentStudyCourse(StudentStudyCourse):
+    """This is a container for study levels.
+    """
+
+    grok.implements(INigeriaStudentStudyCourse, IStudentNavigation)
+    grok.provides(INigeriaStudentStudyCourse)
+
+    @property
+    def next_session_allowed(self):
+        state = self.student.state
+        certificate = getattr(self, 'certificate', None)
+        if certificate == None:
+            return False
+        if state == CLEARED:
+            return True
+        cond0 = state == RETURNING
+        cond1 = self.previous_verdict in (
+            'A','B','C','F','J','L','M','N','O','X','Z')
+        cond2 = self.current_level in (0, 100)
+        cond3 = certificate.study_mode.startswith('de') and \
+            self.current_level == 200
+        cond4 = certificate.study_mode.startswith('ph') and \
+            self.current_level == 300
+        if cond0 and (cond1 or cond2 or cond3 or cond4):
+            return True
+        cond5 = self.is_postgrad
+        cond6 = state == PAID
+        if  cond5 and cond6:
+            return True
+        return False
+
+NigeriaStudentStudyCourse = attrs_to_fields(NigeriaStudentStudyCourse)
+
+class NigeriaStudentStudyCourseFactory(StudentStudyCourseFactory):
+    """A factory for student study courses.
+    """
+
+    def __call__(self, *args, **kw):
+        return NigeriaStudentStudyCourse()
+
+    def getInterfaces(self):
+        return implementedBy(NigeriaStudentStudyCourse)
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/studylevel.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/studylevel.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/studylevel.py	(revision 8872)
@@ -0,0 +1,74 @@
+## $Id$
+##
+## Copyright (C) 2012 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+"""
+Container which holds the data of a student study level
+and contains the course tickets.
+"""
+import grok
+from zope.component.interfaces import IFactory
+from zope.interface import implementedBy
+from waeup.kofa.utils.helpers import attrs_to_fields
+from waeup.kofa.students.studylevel import (
+    StudentStudyLevel, CourseTicket,
+    CourseTicketFactory, StudentStudyLevelFactory)
+from kofacustom.nigeria.students.interfaces import (
+    INigeriaStudentStudyLevel, IStudentNavigation, INigeriaCourseTicket)
+
+
+class NigeriaStudentStudyLevel(StudentStudyLevel):
+    """This is a container for course tickets.
+    """
+    grok.implements(INigeriaStudentStudyLevel, IStudentNavigation)
+    grok.provides(INigeriaStudentStudyLevel)
+
+NigeriaStudentStudyLevel = attrs_to_fields(NigeriaStudentStudyLevel)
+
+class NigeriaStudentStudyLevelFactory(StudentStudyLevelFactory):
+    """A factory for student study levels.
+    """
+
+    def __call__(self, *args, **kw):
+        return NigeriaStudentStudyLevel()
+
+    def getInterfaces(self):
+        return implementedBy(NigeriaStudentStudyLevel)
+
+class NigeriaCourseTicket(CourseTicket):
+    """This is a course ticket which allows the
+    student to attend the course. Lecturers will enter scores and more at
+    the end of the term.
+
+    A course ticket contains a copy of the original course and
+    course referrer data. If the courses and/or their referrers are removed, the
+    corresponding tickets remain unchanged. So we do not need any event
+    triggered actions on course tickets.
+    """
+    grok.implements(INigeriaCourseTicket, IStudentNavigation)
+    grok.provides(INigeriaCourseTicket)
+
+NigeriaCourseTicket = attrs_to_fields(NigeriaCourseTicket)
+
+class NigeriaCourseTicketFactory(CourseTicketFactory):
+    """A factory for student study levels.
+    """
+
+    def __call__(self, *args, **kw):
+        return NigeriaCourseTicket()
+
+    def getInterfaces(self):
+        return implementedBy(NigeriaCourseTicket)
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/tests/__init__.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/tests/__init__.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/tests/__init__.py	(revision 8872)
@@ -0,0 +1,1 @@
+# Make this a package.
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/tests/sample_student_data.csv
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/tests/sample_student_data.csv	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/tests/sample_student_data.csv	(revision 8872)
@@ -0,0 +1,4 @@
+firstname,lastname,reg_number,date_of_birth,matric_number,email,phone,sex
+Aaren,Pieri,1,,100000,aa@aa.ng,1234,m
+Aaren,Finau,2,,100001,aa@aa.ng,1234,m
+Aaren,Berson,3,,100002,aa@aa.ng,1234,m
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/tests/test_browser.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/tests/test_browser.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/tests/test_browser.py	(revision 8872)
@@ -0,0 +1,208 @@
+## $Id$
+##
+## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+import os
+import shutil
+import tempfile
+from StringIO import StringIO
+from hurry.workflow.interfaces import IWorkflowState
+from zope.component.hooks import setSite, clearSite
+from zope.component import getUtility, createObject
+from zope.interface import verify
+from waeup.kofa.app import University
+from waeup.kofa.students.tests.test_browser import StudentsFullSetup
+from waeup.kofa.testing import FunctionalTestCase
+from waeup.kofa.interfaces import (
+    IExtFileStore, IFileStoreNameChooser)
+from waeup.kofa.students.batching import StudentProcessor
+from waeup.kofa.students.interfaces import IStudentsUtils
+from kofacustom.nigeria.students.batching import NigeriaStudentProcessor
+from kofacustom.nigeria.testing import FunctionalLayer
+from kofacustom.nigeria.students.interfaces import (
+    INigeriaStudentStudyCourse, INigeriaStudent,
+    INigeriaStudentStudyLevel, INigeriaCourseTicket)
+
+
+STUDENT_SAMPLE_DATA = open(
+    os.path.join(os.path.dirname(__file__), 'sample_student_data.csv'),
+    'rb').read()
+
+STUDENT_HEADER_FIELDS = STUDENT_SAMPLE_DATA.split(
+    '\n')[0].split(',')
+
+class StudentProcessorTest(FunctionalTestCase):
+    """Perform some batching tests.
+    """
+
+    layer = FunctionalLayer
+
+    def setUp(self):
+        super(StudentProcessorTest, 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)
+
+        self.processor_base = StudentProcessor()
+        self.processor = NigeriaStudentProcessor()
+        self.workdir = tempfile.mkdtemp()
+        self.csv_file = os.path.join(self.workdir, 'sample_student_data.csv')
+        open(self.csv_file, 'wb').write(STUDENT_SAMPLE_DATA)
+
+    def tearDown(self):
+        super(StudentProcessorTest, self).tearDown()
+        shutil.rmtree(self.workdir)
+        shutil.rmtree(self.dc_root)
+        clearSite()
+        return
+
+    def test_import(self):
+        # We have an empty column 'date_of_birth' in  the import file.
+        # The original processor will fail because 'date_of_birth' is required
+        # in the base package.
+        num, num_warns, fin_file, fail_file = self.processor_base.doImport(
+            self.csv_file, STUDENT_HEADER_FIELDS)
+        self.assertEqual(num_warns,3)
+        assert len(self.app['students'].keys()) == 0
+        # The customized processor does not complain since 'date_of_birth' is
+        # not required in the custom package.
+        num, num_warns, fin_file, fail_file = self.processor.doImport(
+            self.csv_file, STUDENT_HEADER_FIELDS)
+        #print open(fail_file).read()
+        self.assertEqual(num_warns,0)
+        assert len(self.app['students'].keys()) == 3
+        shutil.rmtree(os.path.dirname(fin_file))
+
+
+class StudentUITests(StudentsFullSetup):
+    """Tests for customized student class views and pages
+    """
+
+    layer = FunctionalLayer
+
+    def test_classes(self):
+        # Let's see if objects created in the customized
+        # portal really implement the customized interfaces
+        verify.verifyObject(INigeriaStudent, self.student)
+        verify.verifyObject(
+            INigeriaStudentStudyCourse, self.student['studycourse'])
+        studylevel = createObject(u'waeup.StudentStudyLevel')
+        verify.verifyObject(INigeriaStudentStudyLevel, studylevel)
+        ticket = createObject(u'waeup.CourseTicket')
+        verify.verifyObject(INigeriaCourseTicket, ticket)
+        IWorkflowState(self.student).setState('returning')
+        # Let's see if next_session_allowed works as expected
+        # A, ug_ft, 100
+        self.assertTrue(self.student['studycourse'].next_session_allowed)
+        # O, ug_ft, 100
+        self.student['studycourse'].current_verdict = 'O'
+        self.assertTrue(self.student['studycourse'].next_session_allowed)
+        # O, ug_ft, 200
+        self.student['studycourse'].current_level = 200
+        self.assertFalse(self.student['studycourse'].next_session_allowed)
+        # O, de_ft, 200
+        self.student['studycourse'].certificate.study_mode = 'de_ft'
+        self.assertTrue(self.student['studycourse'].next_session_allowed)
+        # O, ph_ft, 300
+        self.student['studycourse'].certificate.study_mode = 'ph_ft'
+        self.student['studycourse'].current_level = 300
+        self.assertTrue(self.student['studycourse'].next_session_allowed)
+        # O, ph_ft, 400
+        self.student['studycourse'].current_level = 400
+        self.assertFalse(self.student['studycourse'].next_session_allowed)
+
+        # Now we convert the certificate into a postgraduate certificate
+        IWorkflowState(self.student).setState('school fee paid')
+        self.certificate.study_mode = 'pg_ft'
+        # ... and voila next session registration is allowed
+        self.assertTrue(self.student['studycourse'].next_session_allowed)
+
+    def test_manage_access(self):
+        # Managers can access the pages of students
+        # and can perform actions
+        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+        # The student created in the base package is an ug student
+        self.browser.open(self.student_path)
+        self.browser.getLink("Clearance Data").click()
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertEqual(self.browser.url, self.clearance_path)
+        self.browser.getLink("Manage").click()
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertEqual(self.browser.url, self.manage_clearance_path)
+        self.browser.getControl(name="form.date_of_birth").value = '09/10/1961'
+        self.browser.getControl("Save").click()
+        self.assertMatches('...Form has been saved...',
+                           self.browser.contents)
+        self.assertMatches('...First Sitting Record...',
+                           self.browser.contents)
+        # Managers can open clearance slip of ug students
+        self.browser.open(self.student_path + '/clearance.pdf')
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
+        # There is no pg field in the clearance form
+        self.assertFalse('Second Higher Education Record'
+            in self.browser.contents)
+        # Now we change the study mode ...
+        self.certificate.study_mode = 'pg_ft'
+        self.browser.open(self.clearance_path)
+        # ... and additional pg clearance fields appear
+        self.assertMatches('...Second Higher Education Record...',
+                           self.browser.contents)
+        # But also fields from the ug form are displayed
+        self.assertMatches('...First Sitting Record...',
+                           self.browser.contents)
+        # Managers can open clearance slip of pg students
+        self.browser.open(self.student_path + '/clearance.pdf')
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
+
+    def test_student_access(self):
+        # Students can edit clearance data
+        IWorkflowState(self.student).setState('cleared')
+        self.student.clearance_locked = False
+        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()
+        # Even in state admitted students can't change the portait if
+        # application slip exists.
+        IWorkflowState(self.student).setState('admitted')
+        self.browser.open(self.student_path)
+        self.assertTrue('Change portrait' in self.browser.contents)
+        file_store = getUtility(IExtFileStore)
+        applicant_slip = 'My application slip'
+        file_id = IFileStoreNameChooser(self.student).chooseName(
+            attr="application_slip.pdf")
+        file_store.createFile(file_id, StringIO(applicant_slip))
+        self.browser.open(self.student_path)
+        self.assertFalse('Change portrait' in self.browser.contents)
+        self.browser.open(self.student_path + '/change_portrait')
+        self.assertTrue('The requested form is locked' in self.browser.contents)
+        # Student can view and edit clearance data
+        self.browser.getLink("Clearance Data").click()
+        self.browser.getLink("Edit").click()
+        self.assertTrue('Save' in self.browser.contents)
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/tests/test_student.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/tests/test_student.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/tests/test_student.py	(revision 8872)
@@ -0,0 +1,127 @@
+## $Id$
+##
+## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+"""Tests for students and related.
+"""
+from datetime import tzinfo
+from zope.component.interfaces import IFactory
+from zope.interface import verify
+from waeup.kofa.testing import FunctionalTestCase
+from kofacustom.nigeria.students.student import NigeriaStudent, NigeriaStudentFactory
+from kofacustom.nigeria.students.studycourse import (
+    NigeriaStudentStudyCourse, NigeriaStudentStudyCourseFactory)
+from kofacustom.nigeria.students.studylevel import (
+    NigeriaStudentStudyLevel, NigeriaCourseTicket,
+    NigeriaStudentStudyLevelFactory,
+    NigeriaCourseTicketFactory)
+from kofacustom.nigeria.students.interfaces import (
+    INigeriaStudent, INigeriaStudentStudyCourse,
+    INigeriaStudentStudyLevel, INigeriaCourseTicket)
+from kofacustom.nigeria.testing import FunctionalLayer
+
+
+class NigeriaStudentFactoryTest(FunctionalTestCase):
+
+    layer = FunctionalLayer
+
+    def setUp(self):
+        super(NigeriaStudentFactoryTest, self).setUp()
+        self.factory = NigeriaStudentFactory()
+
+    def tearDown(self):
+        super(NigeriaStudentFactoryTest, self).tearDown()
+
+    def test_interfaces(self):
+        verify.verifyClass(IFactory, NigeriaStudentFactory)
+        verify.verifyObject(IFactory, self.factory)
+
+    def test_factory(self):
+        obj = self.factory()
+        assert isinstance(obj, NigeriaStudent)
+
+    def test_getInterfaces(self):
+        implemented_by = self.factory.getInterfaces()
+        assert implemented_by.isOrExtends(INigeriaStudent)
+
+class NigeriaStudentStudyCourseFactoryTest(FunctionalTestCase):
+
+    layer = FunctionalLayer
+
+    def setUp(self):
+        super(NigeriaStudentStudyCourseFactoryTest, self).setUp()
+        self.factory = NigeriaStudentStudyCourseFactory()
+
+    def tearDown(self):
+        super(NigeriaStudentStudyCourseFactoryTest, self).tearDown()
+
+    def test_interfaces(self):
+        verify.verifyClass(IFactory, NigeriaStudentStudyCourseFactory)
+        verify.verifyObject(IFactory, self.factory)
+
+    def test_factory(self):
+        obj = self.factory()
+        assert isinstance(obj, NigeriaStudentStudyCourse)
+
+    def test_getInterfaces(self):
+        implemented_by = self.factory.getInterfaces()
+        assert implemented_by.isOrExtends(INigeriaStudentStudyCourse)
+
+class NigeriaStudentStudyLevelFactoryTest(FunctionalTestCase):
+
+    layer = FunctionalLayer
+
+    def setUp(self):
+        super(NigeriaStudentStudyLevelFactoryTest, self).setUp()
+        self.factory = NigeriaStudentStudyLevelFactory()
+
+    def tearDown(self):
+        super(NigeriaStudentStudyLevelFactoryTest, self).tearDown()
+
+    def test_interfaces(self):
+        verify.verifyClass(IFactory, NigeriaStudentStudyLevelFactory)
+        verify.verifyObject(IFactory, self.factory)
+
+    def test_factory(self):
+        obj = self.factory()
+        assert isinstance(obj, NigeriaStudentStudyLevel)
+
+    def test_getInterfaces(self):
+        implemented_by = self.factory.getInterfaces()
+        assert implemented_by.isOrExtends(INigeriaStudentStudyLevel)
+
+class NigeriaCourseTicketFactoryTest(FunctionalTestCase):
+
+    layer = FunctionalLayer
+
+    def setUp(self):
+        super(NigeriaCourseTicketFactoryTest, self).setUp()
+        self.factory = NigeriaCourseTicketFactory()
+
+    def tearDown(self):
+        super(NigeriaCourseTicketFactoryTest, self).tearDown()
+
+    def test_interfaces(self):
+        verify.verifyClass(IFactory, NigeriaCourseTicketFactory)
+        verify.verifyObject(IFactory, self.factory)
+
+    def test_factory(self):
+        obj = self.factory()
+        assert isinstance(obj, NigeriaCourseTicket)
+
+    def test_getInterfaces(self):
+        implemented_by = self.factory.getInterfaces()
+        assert implemented_by.isOrExtends(INigeriaCourseTicket)
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/utils.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/utils.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/utils.py	(revision 8872)
@@ -0,0 +1,66 @@
+## $Id$
+##
+## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+import grok
+from waeup.kofa.students.utils import StudentsUtils
+from kofacustom.nigeria.interfaces import MessageFactory as _
+
+class NigeriaStudentsUtils(StudentsUtils):
+    """A collection of customized methods.
+
+    """
+
+    VERDICTS_DICT = {
+        '0': 'not yet',
+        'A': 'Successful student',
+        'B': 'Student with carryover courses',
+        'C': 'Student on probation',
+        'D': 'Withdrawn from the faculty',
+        'E': 'Student who were previously on probation',
+        'F': 'Medical case',
+        'G': 'Absent from examination',
+        'H': 'Withheld results',
+        'I': 'Expelled/rusticated/suspended student',
+        'J': 'Temporary withdrawn from the university',
+        'K': 'Unregistered student',
+        'L': 'Referred student',
+        'M': 'Reinstatement',
+        'N': 'Student on transfer',
+        'O': 'NCE-III repeater',
+        'Y': 'No previous verdict',
+        'X': 'New 300 level student',
+        'Z': 'Successful student (provisional)',
+        'A1': 'First Class',
+        'A2': 'Second Class Upper',
+        'A3': 'Second Class Lower',
+        'A4': 'Third Class',
+        'A5': 'Pass',
+        'A6': 'Distinction',
+        'A7': 'Credit',
+        'A8': 'Merit',
+        }
+
+    SEPARATORS_DICT = {
+        'form.fst_sit_fname': _(u'First Sitting Record'),
+        'form.scd_sit_fname': _(u'Second Sitting Record'),
+        'form.alr_fname': _(u'Advanced Level Record'),
+        'form.hq_type': _(u'Higher Education Record'),
+        'form.hq2_type': _(u'Second Higher Education Record'),
+        'form.nysc_year': _(u'NYSC Information'),
+        'form.employer': _(u'Employment History'),
+        'form.former_matric': _(u'Former Student'),
+        }
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/viewlets.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/viewlets.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/students/viewlets.py	(revision 8872)
@@ -0,0 +1,514 @@
+## $Id$
+##
+## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+
+import grok
+from waeup.kofa.students.viewlets import (
+    FileDisplay, FileUpload, Image)
+from waeup.kofa.students.browser import ExportPDFClearanceSlipPage
+
+from kofacustom.nigeria.interfaces import MessageFactory as _
+
+# LGA Identification
+
+class LGAIdentificationDisplay(FileDisplay):
+    """LGA Identification display viewlet.
+    """
+    grok.order(1)
+    label = _(u'LGA Identification')
+    title = _(u'LGA Identification Scan')
+    download_name = u'lga_ident'
+
+class LGAIdentificationSlip(LGAIdentificationDisplay):
+    grok.view(ExportPDFClearanceSlipPage)
+
+class LGAIdentificationUpload(FileUpload):
+    """LGA Identification upload viewlet.
+    """
+    grok.order(2)
+    label = _(u'LGA Identification')
+    title = _(u'LGA Identification Scan')
+    mus = 1024 * 150
+    download_name = u'lga_ident'
+
+class LGAIdentificationImage(Image):
+    """Renders LGA Identification scan.
+    """
+    grok.name('lga_ident')
+    download_name = u'lga_ident'
+
+# First Sitting Result
+
+class FirstSittingResultDisplay(FileDisplay):
+    """First Sitting Result display viewlet.
+    """
+    grok.order(1)
+    label = _(u'First Sitting Result')
+    title = _(u'First Sitting Result')
+    download_name = u'fst_sit_scan'
+
+class FirstSittingResultSlip(FirstSittingResultDisplay):
+    grok.view(ExportPDFClearanceSlipPage)
+
+class FirstSittingResultUpload(FileUpload):
+    """First Sitting Result upload viewlet.
+    """
+    grok.order(2)
+    label = _(u'First Sitting Result')
+    title = _(u'First Sitting Result Scan')
+    mus = 1024 * 150
+    download_name = u'fst_sit_scan'
+
+class FirstSittingResultImage(Image):
+    """Renders First Sitting Result scan.
+    """
+    grok.name('fst_sit_scan')
+    download_name = u'fst_sit_scan'
+
+# Second Sitting Result
+
+class SecondSittingResultDisplay(FileDisplay):
+    """Second Sitting Result display viewlet.
+    """
+    grok.order(1)
+    label = _(u'Second Sitting Result')
+    title = _(u'Second Sitting Result')
+    download_name = u'scd_sit_scan'
+
+class SecondSittingResultSlip(SecondSittingResultDisplay):
+    grok.view(ExportPDFClearanceSlipPage)
+
+class SecondSittingResultUpload(FileUpload):
+    """Second Sitting Result upload viewlet.
+    """
+    grok.order(2)
+    label = _(u'Second Sitting Result')
+    title = _(u'Second Sitting Result Scan')
+    mus = 1024 * 150
+    download_name = u'scd_sit_scan'
+
+class SecondSittingResultImage(Image):
+    """Renders Second Sitting Result scan.
+    """
+    grok.name('scd_sit_scan')
+    download_name = u'scd_sit_scan'
+
+# Higher Qualification Result
+
+class HigherQualificationResultDisplay(FileDisplay):
+    """Higher Qualification Result display viewlet.
+    """
+    grok.order(1)
+    label = _(u'Higher Qualification Result')
+    title = _(u'Higher Qualification Result')
+    download_name = u'hq_scan'
+
+class HigherQualificationResultSlip(HigherQualificationResultDisplay):
+    grok.view(ExportPDFClearanceSlipPage)
+
+class HigherQualificationResultUpload(FileUpload):
+    """Higher Qualification Result upload viewlet.
+    """
+    grok.order(2)
+    label = _(u'Higher Qualification Result')
+    title = _(u'Higher Qualification Result Scan')
+    mus = 1024 * 150
+    download_name = u'hq_scan'
+
+class HigherQualificationResultImage(Image):
+    """Renders Higher Qualification Result scan.
+    """
+    grok.name('hq_scan')
+    download_name = u'hq_scan'
+
+# 2nd Higher Qualification Result (PG Students only)
+
+class SecondHigherQualificationResultDisplay(FileDisplay):
+    """Second Higher Qualification Result display viewlet.
+    """
+    grok.order(1)
+    label = _(u'Second Higher Qualification Result')
+    title = _(u'Second Higher Qualification Result')
+    download_name = u'hq_scan2'
+
+class SecondHigherQualificationResultSlip(SecondHigherQualificationResultDisplay):
+    grok.view(ExportPDFClearanceSlipPage)
+
+class SecondHigherQualificationResultUpload(FileUpload):
+    """Second Higher Qualification Result upload viewlet.
+    """
+    grok.order(2)
+    label = _(u'Second Higher Qualification Result')
+    title = _(u'Second Higher Qualification Result Scan')
+    mus = 1024 * 150
+    download_name = u'hq_scan2'
+
+    @property
+    def show_viewlet(self):
+        cm = getattr(self.context,'current_mode', None)
+        if cm is not None and cm.startswith('pg'):
+            return True
+        return False
+
+class SecondHigherQualificationResultImage(Image):
+    """Renders Second Higher Qualification Result scan.
+    """
+    grok.name('hq_scan2')
+    download_name = u'hq_scan2'
+
+# Advanced Level Result
+
+class AdvancedLevelResultDisplay(FileDisplay):
+    """Advanced Level Result display viewlet.
+    """
+    grok.order(1)
+    label = _(u'Advanced Level Result')
+    title = _(u'Advanced Level Result')
+    download_name = u'alr_scan'
+
+class AdvancedLevelResultSlip(AdvancedLevelResultDisplay):
+    grok.view(ExportPDFClearanceSlipPage)
+
+class AdvancedLevelResultUpload(FileUpload):
+    """Advanced Level Result upload viewlet.
+    """
+    grok.order(2)
+    label = _(u'Advanced Level Result')
+    title = _(u'Advanced Level Result Scan')
+    mus = 1024 * 150
+    download_name = u'alr_scan'
+
+class AdvancedLevelResultImage(Image):
+    """Renders Advanced Level Result scan.
+    """
+    grok.name('alr_scan')
+    download_name = u'alr_scan'
+
+# Certificate 
+
+class CertificateDisplay(FileDisplay):
+    """Certificate display viewlet.
+    """
+    grok.order(1)
+    label = _(u'Certificate')
+    title = _(u'Certificate')
+    download_name = u'certificate'
+
+class CertificateSlip(CertificateDisplay):
+    grok.view(ExportPDFClearanceSlipPage)
+
+class CertificateUpload(FileUpload):
+    """Certificate upload viewlet.
+    """
+    grok.order(2)
+    label = _(u'Certificate')
+    title = _(u'Certificate Scan')
+    mus = 1024 * 150
+    download_name = u'certificate'
+
+class CertificateImage(Image):
+    """Renders Certificate scan.
+    """
+    grok.name('certificate')
+    download_name = u'certificate'
+
+# Second Certificate (PG Students only)
+
+class SecondCertificateDisplay(FileDisplay):
+    """ Second Certificate display viewlet.
+    """
+    grok.order(1)
+    label = _(u'Second Certificate')
+    title = _(u'Second Certificate')
+    download_name = u'certificate2'
+
+class SecondCertificateSlip(SecondCertificateDisplay):
+    grok.view(ExportPDFClearanceSlipPage)
+
+class SecondCertificateUpload(FileUpload):
+    """Second Certificate upload viewlet.
+    """
+    grok.order(2)
+    label = _(u'Second Certificate')
+    title = _(u'Second Certificate Scan')
+    mus = 1024 * 150
+    download_name = u'certificate2'
+
+    @property
+    def show_viewlet(self):
+        cm = getattr(self.context,'current_mode', None)
+        if cm is not None and cm.startswith('pg'):
+            return True
+        return False
+
+class CertificateImage(Image):
+    """Renders Second Certificate scan.
+    """
+    grok.name('certificate2')
+    download_name = u'certificate2'
+
+# Third Certificate (PG Students only)
+
+class ThirdCertificateDisplay(FileDisplay):
+    """ Third Certificate display viewlet.
+    """
+    grok.order(1)
+    label = _(u'Third Certificate')
+    title = _(u'Third Certificate')
+    download_name = u'certificate3'
+
+class ThirdCertificateSlip(ThirdCertificateDisplay):
+    grok.view(ExportPDFClearanceSlipPage)
+
+class ThirdCertificateUpload(FileUpload):
+    """Third Certificate upload viewlet.
+    """
+    grok.order(2)
+    label = _(u'Third Certificate')
+    title = _(u'Third Certificate Scan')
+    mus = 1024 * 150
+    download_name = u'certificate3'
+
+    @property
+    def show_viewlet(self):
+        cm = getattr(self.context,'current_mode', None)
+        if cm is not None and cm.startswith('pg'):
+            return True
+        return False
+
+class CertificateImage(Image):
+    """Renders Third Certificate scan.
+    """
+    grok.name('certificate3')
+    download_name = u'certificate3'
+
+# Evidence of Name
+
+class EvidenceNameDisplay(FileDisplay):
+    """Evidence of Name display viewlet.
+    """
+    grok.order(1)
+    label = _(u'Evidence of Name')
+    title = _(u'Evidence of Name')
+    download_name = u'evid'
+
+class EvidenceNameSlip(EvidenceNameDisplay):
+    grok.view(ExportPDFClearanceSlipPage)
+
+class EvidenceNameUpload(FileUpload):
+    """Evidence of Name upload viewlet.
+    """
+    grok.order(2)
+    label = _(u'Evidence of Name')
+    title = _(u'Evidence of Name Scan')
+    mus = 1024 * 150
+    download_name = u'evid'
+
+class EvidenceNameImage(Image):
+    """Renders Evidence of Name scan.
+    """
+    grok.name('evid')
+    download_name = u'evid'
+
+# Result Statement
+
+class ResultStatementDisplay(FileDisplay):
+    """Result Statement display viewlet.
+    """
+    grok.order(1)
+    label = _(u'Result Statement')
+    title = _(u'Result Statement')
+    download_name = u'res_stat'
+
+class ResultStatementSlip(ResultStatementDisplay):
+    grok.view(ExportPDFClearanceSlipPage)
+
+class ResultStatementUpload(FileUpload):
+    """Result Statement upload viewlet.
+    """
+    grok.order(2)
+    label = _(u'Result Statement')
+    title = _(u'Result Statement Scan')
+    mus = 1024 * 150
+    download_name = u'res_stat'
+
+class ResultStatementImage(Image):
+    """Renders Result Statement scan.
+    """
+    grok.name('res_stat')
+    download_name = u'res_stat'
+
+# Referee Letter
+
+class RefereeLetterDisplay(FileDisplay):
+    """Referee Letter display viewlet.
+    """
+    grok.order(1)
+    label = _(u'Referee Letter')
+    title = _(u'Referee Letter')
+    download_name = u'ref_let'
+
+class RefereeLetterSlip(RefereeLetterDisplay):
+    grok.view(ExportPDFClearanceSlipPage)
+
+class RefereeLetterUpload(FileUpload):
+    """Referee Letter upload viewlet.
+    """
+    grok.order(2)
+    label = _(u'Referee Letter')
+    title = _(u'Referee Letter Scan')
+    mus = 1024 * 150
+    download_name = u'ref_let'
+
+class RefereeLetterImage(Image):
+    """Renders Referee Letter scan.
+    """
+    grok.name('ref_let')
+    download_name = u'ref_let'
+
+# Second Referee Letter (PG Students only)
+
+class SecondRefereeLetterDisplay(FileDisplay):
+    """Second Referee Letter display viewlet.
+    """
+    grok.order(1)
+    label = _(u'Second Referee Letter')
+    title = _(u'Second Referee Letter')
+    download_name = u'ref_let2'
+
+class SecondRefereeLetterSlip(SecondRefereeLetterDisplay):
+    grok.view(ExportPDFClearanceSlipPage)
+
+class SecondRefereeLetterUpload(FileUpload):
+    """Referee Letter upload viewlet.
+    """
+    grok.order(2)
+    label = _(u'Second Referee Letter')
+    title = _(u'Second Referee Letter Scan')
+    mus = 1024 * 150
+    download_name = u'ref_let2'
+
+    @property
+    def show_viewlet(self):
+        cm = getattr(self.context,'current_mode', None)
+        if cm is not None and cm.startswith('pg'):
+            return True
+        return False
+
+class SecondRefereeLetterImage(Image):
+    """Renders Referee Letter scan.
+    """
+    grok.name('ref_let2')
+    download_name = u'ref_let2'
+
+# Third Referee Letter (PG Students only)
+
+class ThirdRefereeLetterDisplay(FileDisplay):
+    """Third Referee Letter display viewlet.
+    """
+    grok.order(1)
+    label = _(u'Third Referee Letter')
+    title = _(u'Third Referee Letter')
+    download_name = u'ref_let3'
+
+class ThirdRefereeLetterSlip(ThirdRefereeLetterDisplay):
+    grok.view(ExportPDFClearanceSlipPage)
+
+class ThirdRefereeLetterUpload(FileUpload):
+    """Referee Letter upload viewlet.
+    """
+    grok.order(2)
+    label = _(u'Third Referee Letter')
+    title = _(u'Third Referee Letter Scan')
+    mus = 1024 * 150
+    download_name = u'ref_let3'
+
+    @property
+    def show_viewlet(self):
+        cm = getattr(self.context,'current_mode', None)
+        if cm is not None and cm.startswith('pg'):
+            return True
+        return False
+
+class ThirdRefereeLetterImage(Image):
+    """Renders Referee Letter scan.
+    """
+    grok.name('ref_let3')
+    download_name = u'ref_let3'
+
+# Statutory Declaration of Good Conduct
+
+class StatutoryDeclarationDisplay(FileDisplay):
+    """Statutory Declaration of Good Conduct display viewlet.
+    """
+    grok.order(1)
+    label = _(u'Statutory Declaration of Good Conduct')
+    title = _(u'Statutory Declaration of Good Conduct')
+    download_name = u'stat_dec'
+
+class StatutoryDeclarationSlip(StatutoryDeclarationDisplay):
+    grok.view(ExportPDFClearanceSlipPage)
+
+class StatutoryDeclarationUpload(FileUpload):
+    """Statutory Declaration of Good Conduct upload viewlet.
+    """
+    grok.order(2)
+    label = _(u'Statutory Declaration of Good Conduct')
+    title = _(u'Statutory Declaration of Good Conduct Scan')
+    mus = 1024 * 150
+    download_name = u'stat_dec'
+
+class StatutoryDeclarationImage(Image):
+    """Renders Statutory Declaration of Good Conduct scan.
+    """
+    grok.name('stat_dec')
+    download_name = u'stat_dec'
+
+# Letter of Admission (PG Students only)
+
+class LetterAdmissionDisplay(FileDisplay):
+    """Letter of Admission display viewlet.
+    """
+    grok.order(1)
+    label = _(u'Letter of Admission')
+    title = _(u'Letter of Admission')
+    download_name = u'admission_let'
+
+class LetterAdmissionSlip(LetterAdmissionDisplay):
+    grok.view(ExportPDFClearanceSlipPage)
+
+class LetterAdmissionUpload(FileUpload):
+    """Letter of Admission upload viewlet.
+    """
+    grok.order(2)
+    label = _(u'Letter of Admission')
+    title = _(u'Letter of Admission Scan')
+    mus = 1024 * 150
+    download_name = u'admission_let'
+
+    @property
+    def show_viewlet(self):
+        cm = getattr(self.context,'current_mode', None)
+        if cm is not None and cm.startswith('pg'):
+            return True
+        return False
+
+class LetterAdmissionImage(Image):
+    """Renders Letter of Admission scan.
+    """
+    grok.name('admission_let')
+    download_name = u'admission_let'
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/testing.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/testing.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/testing.py	(revision 8872)
@@ -0,0 +1,29 @@
+## $Id$
+##
+## Copyright (C) 2012 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+"""Testing support for :mod:`waeup.kofa`.
+"""
+import os.path
+import kofacustom.nigeria
+from zope.app.testing.functional import ZCMLLayer
+from waeup.kofa.testing import FunctionalTestCase
+
+# Some funcional layer that groks kofacustom.nigeria.
+ftesting_zcml = os.path.join(
+    os.path.dirname(kofacustom.nigeria.__file__), 'ftesting.zcml')
+FunctionalLayer = ZCMLLayer(ftesting_zcml, __name__, 'FunctionalLayer',
+                            allow_teardown=True)
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/tests/__init__.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/tests/__init__.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/tests/__init__.py	(revision 8872)
@@ -0,0 +1,1 @@
+# make this a package.
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/tests/test_foo.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/tests/test_foo.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/tests/test_foo.py	(revision 8872)
@@ -0,0 +1,27 @@
+# Make sure that test setup basically works.
+# THIS FILE CAN BE REMOVED.
+
+from kofacustom.nigeria.testing import FunctionalTestCase, FunctionalLayer
+
+class FooTest(FunctionalTestCase):
+
+    layer = FunctionalLayer
+
+    def test_foo(self):
+        # we can access registered components
+        from zope.component import getUtility
+        from waeup.kofa.applicants.interfaces import IApplicantsUtils
+        from kofacustom.nigeria.applicants.utils import NigeriaApplicantsUtils
+        result = getUtility(IApplicantsUtils)
+        self.assertTrue(isinstance(result, NigeriaApplicantsUtils))
+        return
+
+    def test_bar(self):
+        # we can access browser contents
+        from waeup.kofa.app import University
+        self.getRootFolder()['app'] = University()
+        from zope.testbrowser.testing import Browser
+        br = Browser()
+        br.open('http://localhost/app/')
+        self.assertTrue('WAeUP.Kofa' in br.contents)
+        return
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/utils/__init__.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/utils/__init__.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/utils/__init__.py	(revision 8872)
@@ -0,0 +1,1 @@
+# Make this a package.
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/utils/lgas.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/utils/lgas.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/utils/lgas.py	(revision 8872)
@@ -0,0 +1,876 @@
+LGAS = (
+    ('abia_aba_north','Abia / Aba North'),
+    ('abia_aba_south','Abia / Aba South'),
+    ('abia_arochukwu','Abia / Arochukwu'),
+    ('abia_bende','Abia / Bende'),
+    ('abia_ikawuno','Abia / Ikawuno'),
+    ('abia_ikwuano','Abia / Ikwuano'),
+    ('abia_isiala-ngwa-north','Abia / Isiala-Ngwa-North'),
+    ('abia_isiala-ngwa-south','Abia / Isiala-Ngwa-South'),
+    ('abia_isikwuato','Abia / Isikwuato'),
+    ('abia_isuikwuato','Abia / Isuikwuato'),
+    ('abia_nneochi','Abia / Nneochi'),
+    ('abia_obi_ngwa','Abia / Obi Ngwa'),
+    ('abia_obioma-ngwa','Abia / Obioma-Ngwa'),
+    ('abia_ohafia','Abia / Ohafia'),
+    ('abia_ohaozara','Abia / Ohaozara'),
+    ('abia_osisioma','Abia / Osisioma'),
+    ('abia_ugwunagbo','Abia / Ugwunagbo'),
+    ('abia_ukwa_west','Abia / Ukwa West'),
+    ('abia_ukwu_east','Abia / Ukwu East'),
+    ('abia_umuahia','Abia / Umuahia'),
+    ('abia_umuahia_south','Abia / Umuahia South'),
+    ('abia_umuahia-north','Abia / Umuahia-North'),
+    ('abuja_abaji','Abuja / Abaji'),
+    ('abuja_amac','Abuja / Amac'),
+    ('abuja_bwari','Abuja / Bwari'),
+    ('abuja_kuje','Abuja / Kuje'),
+    ('abuja_gwagwalada','Abuja / Gwagwalada'),
+    ('abuja_kwali','Abuja / Kwali'),
+    ('abuja_municipal','Abuja / Municipal'),
+    ('adamawa_demsa','Adamawa / Demsa'),
+    ('adamawa_fufore','Adamawa / Fufore'),
+    ('adamawa_ganye','Adamawa / Ganye'),
+    ('adamawa_girei','Adamawa / Girei'),
+    ('adamawa_gombi','Adamawa / Gombi'),
+    ('adamawa_guyuk','Adamawa / Guyuk'),
+    ('adamawa_hong','Adamawa / Hong'),
+    ('adamawa_jada','Adamawa / Jada'),
+    ('adamawa_jimeta','Adamawa / Jimeta'),
+    ('adamawa_lamurde','Adamawa / Lamurde'),
+    ('adamawa_madagali','Adamawa / Madagali'),
+    ('adamawa_maiha','Adamawa / Maiha'),
+    ('adamawa_mayo-belwa','Adamawa / Mayo-Belwa'),
+    ('adamawa_michika','Adamawa / Michika'),
+    ('adamawa_mubi-north','Adamawa / Mubi-North'),
+    ('adamawa_mubi-south','Adamawa / Mubi-South'),
+    ('adamawa_numan','Adamawa / Numan'),
+    ('adamawa_shelleng','Adamawa / Shelleng'),
+    ('adamawa_song','Adamawa / Song'),
+    ('adamawa_toungo','Adamawa / Toungo'),
+    ('adamawa_yola','Adamawa / Yola'),
+    ('akwa_ibom_abak','Akwa Ibom / Abak'),
+    ('akwa_ibom_eastern-obolo','Akwa Ibom / Eastern-Obolo'),
+    ('akwa_ibom_eket','Akwa Ibom / Eket'),
+    ('akwa_ibom_ekpe-atani','Akwa Ibom / Ekpe-Atani'),
+    ('akwa_ibom_esit_ekit','Akwa Ibom / Esit Ekit'),
+    ('akwa_ibom_essien-udim','Akwa Ibom / Essien-Udim'),
+    ('akwa_ibom_etim-ekpo','Akwa Ibom / Etim-Ekpo'),
+    ('akwa_ibom_etinam','Akwa Ibom / Etinam'),
+    ('akwa_ibom_ibeno','Akwa Ibom / Ibeno'),
+    ('akwa_ibom_ibesikpo-asutan','Akwa Ibom / Ibesikpo-Asutan'),
+    ('akwa_ibom_ibiono-ibom','Akwa Ibom / Ibiono-Ibom'),
+    ('akwa_ibom_ika','Akwa Ibom / Ika'),
+    ('akwa_ibom_ikono','Akwa Ibom / Ikono'),
+    ('akwa_ibom_ikot-abasi','Akwa Ibom / Ikot-Abasi'),
+    ('akwa_ibom_ikot-ekpene','Akwa Ibom / Ikot-Ekpene'),
+    ('akwa_ibom_ini','Akwa Ibom / Ini'),
+    ('akwa_ibom_itu','Akwa Ibom / Itu'),
+    ('akwa_ibom_mbo','Akwa Ibom / Mbo'),
+    ('akwa_ibom_mkpat-enin','Akwa Ibom / Mkpat-Enin'),
+    ('akwa_ibom_nsit-ibom','Akwa Ibom / Nsit-Ibom'),
+    ('akwa_ibom_nsit-ubium','Akwa Ibom / Nsit-Ubium'),
+    ('akwa_ibom_obot-akara','Akwa Ibom / Obot-Akara'),
+    ('akwa_ibom_okobo','Akwa Ibom / Okobo'),
+    ('akwa_ibom_onna','Akwa Ibom / Onna'),
+    ('akwa_ibom_oron','Akwa Ibom / Oron'),
+    ('akwa_ibom_oruk_anam','Akwa Ibom / Oruk-Anam'),
+    ('akwa_ibom_udung-uko','Akwa Ibom / Udung-Uko'),
+    ('akwa_ibom_ukanefun','Akwa Ibom / Ukanefun'),
+    ('akwa_ibom_uquo_ibeno','Akwa Ibom / Uquo Ibeno'),
+    ('akwa_ibom_urue-offong-oruko','Akwa Ibom / Urue-Offong-Oruko'),
+    ('akwa_ibom_uruan','Akwa Ibom / Uruan'),
+    ('akwa_ibom_uruk-anam','Akwa Ibom / Uruk-Anam'),
+    ('akwa_ibom_uyo','Akwa Ibom / Uyo'),
+    ('anambra_aguata','Anambra / Aguata'),
+    ('anambra_anambra-east','Anambra / Anambra-East'),
+    ('anambra_anambra-west','Anambra / Anambra-West'),
+    ('anambra_anaocha','Anambra / Anaocha'),
+    ('anambra_awka-north','Anambra / Awka-North'),
+    ('anambra_awka-south','Anambra / Awka-South'),
+    ('anambra_ayamelum','Anambra / Ayamelum'),
+    ('anambra_dunukofia','Anambra / Dunukofia'),
+    ('anambra_ekwusigo','Anambra / Ekwusigo'),
+    ('anambra_idemili','Anambra / Idemili'),
+    ('anambra_idemili-north','Anambra / Idemili-North'),
+    ('anambra_idemili-south','Anambra / Idemili-South'),
+    ('anambra_ihiala','Anambra / Ihiala'),
+    ('anambra_nibo','Anambra / Nibo'),
+    ('anambra_njikoka','Anambra / Njikoka'),
+    ('anambra_nnewi','Anambra / Nnewi'),
+    ('anambra_nnewi-north','Anambra / Nnewi-North'),
+    ('anambra_nnewi-south','Anambra / Nnewi-South'),
+    ('anambra_ogbaru','Anambra / Ogbaru'),
+    ('anambra_olumba','Anambra / Olumba'),
+    ('anambra_onitsha-north','Anambra / Onitsha-North'),
+    ('anambra_onitsha-south','Anambra / Onitsha-South'),
+    ('anambra_orumba-north','Anambra / Orumba-North'),
+    ('anambra_orumba-south','Anambra / Orumba-South'),
+    ('anambra_oti','Anambra / Oti'),
+    ('anambra_oyi','Anambra / Oyi'),
+    ('anambra_ubuluizor-ihiala','Anambra / Ubuluizor-Ihiala'),
+    ('anambra_uyi','Anambra / Uyi'),
+    ('bauchi_alkaleri','Bauchi / Alkaleri'),
+    ('bauchi_bauchi','Bauchi / Bauchi'),
+    ('bauchi_bogoro','Bauchi / Bogoro'),
+    ('bauchi_damban','Bauchi / Damban'),
+    ('bauchi_darazo','Bauchi / Darazo'),
+    ('bauchi_dass','Bauchi / Dass'),
+    ('bauchi_gamawa','Bauchi / Gamawa'),
+    ('bauchi_ganjuwa','Bauchi / Ganjuwa'),
+    ('bauchi_giade','Bauchi / Giade'),
+    ('bauchi_itas/gadau','Bauchi / Itas/Gadau'),
+    ('bauchi_jamaare','Bauchi / Jamaare'),
+    ('bauchi_katagum','Bauchi / Katagum'),
+    ('bauchi_kirfi','Bauchi / Kirfi'),
+    ('bauchi_misau','Bauchi / Misau'),
+    ('bauchi_ningi','Bauchi / Ningi'),
+    ('bauchi_shira','Bauchi / Shira'),
+    ('bauchi_tafawa-balewa','Bauchi / Tafawa-Balewa'),
+    ('bauchi_toro','Bauchi / Toro'),
+    ('bauchi_warji','Bauchi / Warji'),
+    ('bauchi_zaki','Bauchi / Zaki'),
+    ('bayelsa_brass','Bayelsa / Brass'),
+    ('bayelsa_ekeremor','Bayelsa / Ekeremor'),
+    ('bayelsa_kembe','Bayelsa / Kembe'),
+    ('bayelsa_kolokuma','Bayelsa / Kolokuma'),
+    ('bayelsa_kolokuma/opkuma','Bayelsa / Kolokuma/Opkuma'),
+    ('bayelsa_nembe','Bayelsa / Nembe'),
+    ('bayelsa_ogbia','Bayelsa / Ogbia'),
+    ('bayelsa_sagbama','Bayelsa / Sagbama'),
+    ('bayelsa_southern-ijaw','Bayelsa / Southern-Ijaw'),
+    ('bayelsa_toru-abubo','Bayelsa / Toru-Abubo'),
+    ('bayelsa_yenegoa','Bayelsa / Yenegoa'),
+    ('benue_ado','Benue / Ado'),
+    ('benue_agatu','Benue / Agatu'),
+    ('benue_apa','Benue / Apa'),
+    ('benue_buruku','Benue / Buruku'),
+    ('benue_gboko','Benue / Gboko'),
+    ('benue_guma','Benue / Guma'),
+    ('benue_gwer-east','Benue / Gwer-East'),
+    ('benue_gwer-west','Benue / Gwer-West'),
+    ('benue_katsina-ala','Benue / Katsina-Ala'),
+    ('benue_konshisha','Benue / Konshisha'),
+    ('benue_kwande','Benue / Kwande'),
+    ('benue_logo','Benue / Logo'),
+    ('benue_makurdi','Benue / Makurdi'),
+    ('benue_ogbadibo','Benue / Ogbadibo'),
+    ('benue_ohimini','Benue / Ohimini'),
+    ('benue_oju','Benue / Oju'),
+    ('benue_okpokwu','Benue / Okpokwu'),
+    ('benue_otukpo','Benue / Otukpo'),
+    ('benue_oturkpa','Benue / Oturkpa'),
+    ('benue_tarka','Benue / Tarka'),
+    ('benue_ukum','Benue / Ukum'),
+    ('benue_ushongo','Benue / Ushongo'),
+    ('benue_vandeikya','Benue / Vandeikya'),
+    ('borno_abadan','Borno / Abadan'),
+    ('borno_askira-uba','Borno / Askira-Uba'),
+    ('borno_bama','Borno / Bama'),
+    ('borno_bayo','Borno / Bayo'),
+    ('borno_biu','Borno / Biu'),
+    ('borno_chibok','Borno / Chibok'),
+    ('borno_damboa','Borno / Damboa'),
+    ('borno_dikwa','Borno / Dikwa'),
+    ('borno_gubio','Borno / Gubio'),
+    ('borno_guzamala','Borno / Guzamala'),
+    ('borno_gwoza','Borno / Gwoza'),
+    ('borno_hawul','Borno / Hawul'),
+    ('borno_jere','Borno / Jere'),
+    ('borno_kaga','Borno / Kaga'),
+    ('borno_kala/balge','Borno / Kala/Balge'),
+    ('borno_konduga','Borno / Konduga'),
+    ('borno_kukawa','Borno / Kukawa'),
+    ('borno_kwaya-kusar','Borno / Kwaya-Kusar'),
+    ('borno_mafa','Borno / Mafa'),
+    ('borno_magumeri','Borno / Magumeri'),
+    ('borno_maiduguri','Borno / Maiduguri'),
+    ('borno_marte','Borno / Marte'),
+    ('borno_mobbar','Borno / Mobbar'),
+    ('borno_mongunu','Borno / Mongunu'),
+    ('borno_ngala','Borno / Ngala'),
+    ('borno_nganzai','Borno / Nganzai'),
+    ('borno_shani','Borno / Shani'),
+    ('cross_river_abi','Cross River / Abi'),
+    ('cross_river_abuochichie','Cross River / Abuochichie'),
+    ('cross_river_akamkpa','Cross River / Akamkpa'),
+    ('cross_river_akpabuyo','Cross River / Akpabuyo'),
+    ('cross_river_bakassi','Cross River / Bakassi'),
+    ('cross_river_bekwara','Cross River / Bekwara'),
+    ('cross_river_biasi','Cross River / Biasi'),
+    ('cross_river_boki','Cross River / Boki'),
+    ('cross_river_calabar-municipal','Cross River / Calabar-Municipal'),
+    ('cross_river_calabar-south','Cross River / Calabar-South'),
+    ('cross_river_etunk','Cross River / Etunk'),
+    ('cross_river_ikom','Cross River / Ikom'),
+    ('cross_river_obanliku','Cross River / Obanliku'),
+    ('cross_river_obubra','Cross River / Obubra'),
+    ('cross_river_obudu','Cross River / Obudu'),
+    ('cross_river_odukpani','Cross River / Odukpani'),
+    ('cross_river_ogoja','Cross River / Ogoja'),
+    ('cross_river_ugep-north','Cross River / Ugep-North'),
+    ('cross_river_yakurr','Cross River / Yakurr'),
+    ('cross_river_yala','Cross River / Yala'),
+    ('delta_aniocha-north','Delta / Aniocha-North'),
+    ('delta_aniocha-south','Delta / Aniocha-South'),
+    ('delta_bomadi','Delta / Bomadi'),
+    ('delta_burutu','Delta / Burutu'),
+    ('delta_effurun','Delta / Effurun'),
+    ('delta_ethiope-east','Delta / Ethiope-East'),
+    ('delta_ethiope-west','Delta / Ethiope-West'),
+    ('delta_idu','Delta / Idu'),
+    ('delta_ika-ne','Delta / Ika-Ne'),
+    ('delta_ika-north-east','Delta / Ika-North-East'),
+    ('delta_ika-south','Delta / Ika-South'),
+    ('delta_idemili-south','Delta / Idemili-South'),
+    ('delta_isoko-north','Delta / Isoko-North'),
+    ('delta_isoko-south','Delta / Isoko-South'),
+    ('delta_ndokwa-east','Delta / Ndokwa-East'),
+    ('delta_ndokwa-north','Delta / Ndokwa-North'),
+    ('delta_ndokwa-south','Delta / Ndokwa-South'),
+    ('delta_ndokwa-west','Delta / Ndokwa-West'),
+    ('delta_okpe','Delta / Okpe'),
+    ('delta_okwuani','Delta / Okwuani'),
+    ('delta_oleh','Delta / Oleh'),
+    ('delta_oshielli-north','Delta / Oshielli-North'),
+    ('delta_oshimili','Delta / Oshimili'),
+    ('delta_oshimili-north','Delta / Oshimili-North'),
+    ('delta_oshimili-south','Delta / Oshimili-South'),
+    ('delta_patani','Delta / Patani'),
+    ('delta_sapele','Delta / Sapele'),
+    ('delta_udokwa','Delta / Udokwa'),
+    ('delta_udu','Delta / Udu'),
+    ('delta_ughelli-north','Delta / Ughelli-North'),
+    ('delta_ughelli-south','Delta / Ughelli-South'),
+    ('delta_ukwuani','Delta / Ukwuani'),
+    ('delta_urwie','Delta / Urwie'),
+    ('delta_uvie','Delta / Uvie'),
+    ('delta_uvwei','Delta / Uvwei'),
+    ('delta_uvwie','Delta / Uvwie'),
+    ('delta_warri-central','Delta / Warri-Central'),
+    ('delta_warri-north','Delta / Warri-North'),
+    ('delta_warri-south','Delta / Warri-South'),
+    ('delta_warri-south-west','Delta / Warri-South-West'),
+    ('ebonyi_abakaliki','Ebonyi / Abakaliki'),
+    ('ebonyi_afikpo-north','Ebonyi / Afikpo-North'),
+    ('ebonyi_afikpo-south','Ebonyi / Afikpo-South'),
+    ('ebonyi_bomadim','Ebonyi / Bomadim'),
+    ('ebonyi_ebonyi','Ebonyi / Ebonyi'),
+    ('ebonyi_ezza-north','Ebonyi / Ezza-North'),
+    ('ebonyi_ezza-south','Ebonyi / Ezza-South'),
+    ('ebonyi_ikwo','Ebonyi / Ikwo'),
+    ('ebonyi_ishielu','Ebonyi / Ishielu'),
+    ('ebonyi_ivo','Ebonyi / Ivo'),
+    ('ebonyi_izzi','Ebonyi / Izzi'),
+    ('ebonyi_obaukwu','Ebonyi / Obaukwu'),
+    ('ebonyi_ohakwu','Ebonyi / Ohakwu'),
+    ('ebonyi_ohaozara','Ebonyi / Ohaozara'),
+    ('ebonyi_onicha','Ebonyi / Onicha'),
+    ('ebonyi_ukaba','Ebonyi / Ukaba'),
+    ('edo_afokpella','Edo / Afokpella'),
+    ('edo_afuze','Edo / Afuze'),
+    ('edo_agbazilo','Edo / Agbazilo'),
+    ('edo_akoko-edo','Edo / Akoko-Edo'),
+    ('edo_egor','Edo / Egor'),
+    ('edo_esan-central','Edo / Esan-Central'),
+    ('edo_esan-north-east','Edo / Esan-North-East'),
+    ('edo_esan-north-west','Edo / Esan-North-West'),
+    ('edo_esan-south-east','Edo / Esan-South-East'),
+    ('edo_esan-west','Edo / Esan-West'),
+    ('edo_etsako-central','Edo / Etsako-Central'),
+    ('edo_etsako-east','Edo / Etsako-East'),
+    ('edo_etsako-west','Edo / Etsako-West'),
+    ('edo_igueben','Edo / Igueben'),
+    ('edo_ikpoba-okha','Edo / Ikpoba-Okha'),
+    ('edo_ohunmwode','Edo / Ohunmwode'),
+    ('edo_ologbo','Edo / Ologbo'),
+    ('edo_opoji_irrua','Edo / Opoji Irrua'),
+    ('edo_oredo','Edo / Oredo'),
+    ('edo_orhionmwon','Edo / Orhionmwon'),
+    ('edo_ovia-north-east','Edo / Ovia-North-East'),
+    ('edo_ovia-north-west','Edo / Ovia-North-West'),
+    ('edo_ovia-south-west','Edo / Ovia-South-West'),
+    ('edo_owan-east','Edo / Owan-East'),
+    ('edo_owan-west','Edo / Owan-West'),
+    ('edo_ubiaja','Edo / Ubiaja'), 
+    ('edo_uhunmwonde','Edo / Uhunmwonde'),
+    ('ekiti_ado-ekiti','Ekiti / Ado-Ekiti'),
+    ('ekiti_aiyekire','Ekiti / Aiyekire'),
+    ('ekiti_efon','Ekiti / Efon'),
+    ('ekiti_ekiti-east','Ekiti / Ekiti-East'),
+    ('ekiti_ekiti-south-west','Ekiti / Ekiti-South-West'),
+    ('ekiti_ekiti-west','Ekiti / Ekiti-West'),
+    ('ekiti_emure/ise/orun','Ekiti / Emure/Ise/Orun'),
+    ('ekiti_gbonyin','Ekiti / Gbonyin'),
+    ('ekiti_ido-osi','Ekiti / Ido-Osi'),
+    ('ekiti_ijero','Ekiti / Ijero'),
+    ('ekiti_ikare','Ekiti / Ikare'),
+    ('ekiti_ikere','Ekiti / Ikere'),
+    ('ekiti_ikole','Ekiti / Ikole'),
+    ('ekiti_ilejemeje','Ekiti / Ilejemeje'),
+    ('ekiti_irepodun/ifelodun','Ekiti / Irepodun/Ifelodun'),
+    ('ekiti_ise-orun','Ekiti / Ise-Orun'),
+    ('ekiti_moba','Ekiti / Moba'),
+    ('ekiti_oye','Ekiti / Oye'),
+    ('enugu_aninri','Enugu / Aninri'),
+    ('enugu_awgu','Enugu / Awgu'),
+    ('enugu_enugu-east','Enugu / Enugu-East'),
+    ('enugu_enugu-north','Enugu / Enugu-North'),
+    ('enugu_enugu-south','Enugu / Enugu-South'),
+    ('enugu_ezeagu','Enugu / Ezeagu'),
+    ('enugu_igbo-etiti','Enugu / Igbo-Etiti'),
+    ('enugu_igbo-eze-north','Enugu / Igbo-Eze-North'),
+    ('enugu_igbo-eze-south','Enugu / Igbo-Eze-South'),
+    ('enugu_isi-uzo','Enugu / Isi-Uzo'),
+    ('enugu_nkanu-east','Enugu / Nkanu-East'),
+    ('enugu_nkanu-central','Enugu / Nkanu-Central'),
+    ('enugu_nkanu-west','Enugu / Nkanu-West'),
+    ('enugu_nsukka','Enugu / Nsukka'),
+    ('enugu_nukanu_east','Enugu / Nukanu East'),
+    ('enugu_oji-river','Enugu / Oji-River'),
+    ('enugu_udenu','Enugu / Udenu'),
+    ('enugu_udi','Enugu / Udi'),
+    ('enugu_uzo-uwani','Enugu / Uzo-Uwani'),
+    ('gombe_akko','Gombe / Akko'),
+    ('gombe_balanga','Gombe / Balanga'),
+    ('gombe_billiri','Gombe / Billiri'),
+    ('gombe_dukku','Gombe / Dukku'),
+    ('gombe_funakaye','Gombe / Funakaye'),
+    ('gombe_gombe','Gombe / Gombe'),
+    ('gombe_kaltungo','Gombe / Kaltungo'),
+    ('gombe_kwami','Gombe / Kwami'),
+    ('gombe_nafada/bajoga','Gombe / Nafada/Bajoga'),
+    ('gombe_shomgom','Gombe / Shomgom'),
+    ('gombe_yamaltu/deba','Gombe / Yamaltu/Deba'),
+    ('imo_aboh-mbaise','Imo / Aboh-Mbaise'),
+    ('imo_ahiazu-mbaise','Imo / Ahiazu-Mbaise'),
+    ('imo_dral-esat','Imo / Dral-Esat'),
+    ('imo_ehime-mbano','Imo / Ehime-Mbano'),
+    ('imo_ezinihitte','Imo / Ezinihitte'),
+    ('imo_ideato','Imo / Ideato'),
+    ('imo_ideato-north','Imo / Ideato-North'),
+    ('imo_ideato-south','Imo / Ideato-South'),
+    ('imo_ihitte/uboma','Imo / Ihitte/Uboma'),
+    ('imo_ikeduru','Imo / Ikeduru'),
+    ('imo_isiala-mbano','Imo / Isiala-Mbano'),
+    ('imo_isu','Imo / Isu'),
+    ('imo_mbaitoli','Imo / Mbaitoli'),
+    ('imo_mbano','Imo / Mbano'),
+    ('imo_ngor-okpala','Imo / Ngor-Okpala'),
+    ('imo_njaba','Imo / Njaba'),
+    ('imo_nkwerre','Imo / Nkwerre'),
+    ('imo_nwangele','Imo / Nwangele'),
+    ('imo_obowo','Imo / Obowo'),
+    ('imo_oguta','Imo / Oguta'),
+    ('imo_ohaji-egbema','Imo / Ohaji-Egbema'),
+    ('imo_okigwe','Imo / Okigwe'),
+    ('imo_onuimo','Imo / Onuimo'),
+    ('imo_orlu','Imo / Orlu'),
+    ('imo_orsu','Imo / Orsu'),
+    ('imo_oru-east','Imo / Oru-East'),
+    ('imo_oru-west','Imo / Oru-West'),
+    ('imo_owerri-municipal','Imo / Owerri-Municipal'),
+    ('imo_owerri-north','Imo / Owerri-North'),
+    ('imo_owerri-west','Imo / Owerri-West'),
+    ('imo_ugiri-ike_ikeduru','Imo / Ugiri-Ike Ikeduru'),
+    ('imo_ugiri-ikedikeduru','Imo / Ugiri-Ikedikeduru'),
+    ('imo_unbano','Imo / Unbano'),
+    ('imo_zinihitte','Imo / Zinihitte'),
+    ('jigawa_auyo','Jigawa / Auyo'),
+    ('jigawa_babura','Jigawa / Babura'),
+    ('jigawa_biriniwa','Jigawa / Biriniwa'),
+    ('jigawa_birnin-kudu','Jigawa / Birnin-Kudu'),
+    ('jigawa_bosuwa','Jigawa / Bosuwa'),
+    ('jigawa_buji','Jigawa / Buji'),
+    ('jigawa_dutse','Jigawa / Dutse'),
+    ('jigawa_gagarawa','Jigawa / Gagarawa'),
+    ('jigawa_garki','Jigawa / Garki'),
+    ('jigawa_gumel','Jigawa / Gumel'),
+    ('jigawa_guri','Jigawa / Guri'),
+    ('jigawa_gwaram','Jigawa / Gwaram'),
+    ('jigawa_gwiwa','Jigawa / Gwiwa'),
+    ('jigawa_hadejia','Jigawa / Hadejia'),
+    ('jigawa_jahun','Jigawa / Jahun'),
+    ('jigawa_kafin-hausa','Jigawa / Kafin-Hausa'),
+    ('jigawa_kaugama','Jigawa / Kaugama'),
+    ('jigawa_kazaure','Jigawa / Kazaure'),
+    ('jigawa_kirkasamma','Jigawa / Kirkasamma'),
+    ('jigawa_maigatari','Jigawa / Maigatari'),
+    ('jigawa_malam-maduri','Jigawa / Malam-Maduri'),
+    ('jigawa_miga','Jigawa / Miga'),
+    ('jigawa_ringim','Jigawa / Ringim'),
+    ('jigawa_roni','Jigawa / Roni'),
+    ('jigawa_sule-tankarkar','Jigawa / Sule-Tankarkar'),
+    ('jigawa_taura','Jigawa / Taura'),
+    ('jigawa_yankwashi','Jigawa / Yankwashi'),
+    ('kaduna_birnin-gwari','Kaduna / Birnin-Gwari'),
+    ('kaduna_chikun','Kaduna / Chikun'),
+    ('kaduna_giwa','Kaduna / Giwa'),
+    ('kaduna_gwagwada','Kaduna / Gwagwada'),
+    ('kaduna_igabi','Kaduna / Igabi'),
+    ('kaduna_ikara','Kaduna / Ikara'),
+    ('kaduna_jaba','Kaduna / Jaba'),
+    ('kaduna_jemaa','Kaduna / Jemaa'),
+    ('kaduna_kachia','Kaduna / Kachia'),
+    ('kaduna_kaduna-north','Kaduna / Kaduna-North'),
+    ('kaduna_kagarko','Kaduna / Kagarko'),
+    ('kaduna_kajuru','Kaduna / Kajuru'),
+    ('kaduna_kaura','Kaduna / Kaura'),
+    ('kaduna_kauru','Kaduna / Kauru'),
+    ('kaduna_koka/kawo','Kaduna / Koka/Kawo'),
+    ('kaduna_kubah','Kaduna / Kubah'),
+    ('kaduna_kudan','Kaduna / Kudan'),
+    ('kaduna_lere','Kaduna / Lere'),
+    ('kaduna_makarfi','Kaduna / Makarfi'),
+    ('kaduna_sabon-gari','Kaduna / Sabon-Gari'),
+    ('kaduna_sanga','Kaduna / Sanga'),
+    ('kaduna_soba','Kaduna / Soba'),
+    ('kaduna_tudun-wada/makera','Kaduna / Tudun-Wada/Makera'),
+    ('kaduna_zango-kataf','Kaduna / Zango-Kataf'),
+    ('kaduna_zaria','Kaduna / Zaria'),
+    ('kano_ajingi','Kano / Ajingi'),
+    ('kano_albasu','Kano / Albasu'),
+    ('kano_bagwai','Kano / Bagwai'),
+    ('kano_bebeji','Kano / Bebeji'),
+    ('kano_bichi','Kano / Bichi'),
+    ('kano_bunkure','Kano / Bunkure'),
+    ('kano_dala','Kano / Dala'),
+    ('kano_dambatta','Kano / Dambatta'),
+    ('kano_dawakin-kudu','Kano / Dawakin-Kudu'),
+    ('kano_dawakin-tofa','Kano / Dawakin-Tofa'),
+    ('kano_doguwa','Kano / Doguwa'),
+    ('kano_fagge','Kano / Fagge'),
+    ('kano_gabasawa','Kano / Gabasawa'),
+    ('kano_garko','Kano / Garko'),
+    ('kano_garun-mallam','Kano / Garun-Mallam'),
+    ('kano_gaya','Kano / Gaya'),
+    ('kano_gezawa','Kano / Gezawa'),
+    ('kano_gwale','Kano / Gwale'),
+    ('kano_gwarzo','Kano / Gwarzo'),
+    ('kano_kano-municipal','Kano / Kano-Municipal'),
+    ('kano_karaye','Kano / Karaye'),
+    ('kano_kibiya','Kano / Kibiya'),
+    ('kano_kiru','Kano / Kiru'),
+    ('kano_kumbotso','Kano / Kumbotso'),
+    ('kano_kunchi','Kano / Kunchi'),
+    ('kano_kura','Kano / Kura'),
+    ('kano_madobi','Kano / Madobi'),
+    ('kano_makoda','Kano / Makoda'),
+    ('kano_minjibir','Kano / Minjibir'),
+    ('kano_nasarawa','Kano / Nasarawa'),
+    ('kano_rano','Kano / Rano'),
+    ('kano_rimin-gado','Kano / Rimin-Gado'),
+    ('kano_rogo','Kano / Rogo'),
+    ('kano_shanono','Kano / Shanono'),
+    ('kano_sumaila','Kano / Sumaila'),
+    ('kano_takai','Kano / Takai'),
+    ('kano_tarauni','Kano / Tarauni'),
+    ('kano_tofa','Kano / Tofa'),
+    ('kano_tsanyawa','Kano / Tsanyawa'),
+    ('kano_tudun-wada','Kano / Tudun-Wada'),
+    ('kano_ungogo','Kano / Ungogo'),
+    ('kano_warawa','Kano / Warawa'),
+    ('kano_wudil','Kano / Wudil'),
+    ('katsina_bakori','Katsina / Bakori'),
+    ('katsina_batagarawa','Katsina / Batagarawa'),
+    ('katsina_batsari','Katsina / Batsari'),
+    ('katsina_baure','Katsina / Baure'),
+    ('katsina_bindawa','Katsina / Bindawa'),
+    ('katsina_charanchi','Katsina / Charanchi'),
+    ('katsina_dan-musa','Katsina / Dan-Musa'),
+    ('katsina_dandume','Katsina / Dandume'),
+    ('katsina_danji','Katsina / Danji'),
+    ('katsina_daura','Katsina / Daura'),
+    ('katsina_dutsi','Katsina / Dutsi'),
+    ('katsina_dutsinma','Katsina / Dutsinma'),
+    ('katsina_faskari','Katsina / Faskari'),
+    ('katsina_funtua','Katsina / Funtua'),
+    ('katsina_ingawa','Katsina / Ingawa'),
+    ('katsina_jibia','Katsina / Jibia'),
+    ('katsina_kafur','Katsina / Kafur'),
+    ('katsina_kaita','Katsina / Kaita'),
+    ('katsina_kankara','Katsina / Kankara'),
+    ('katsina_kankia','Katsina / Kankia'),
+    ('katsina_katsina','Katsina / Katsina'),
+    ('katsina_kurfi','Katsina / Kurfi'),
+    ('katsina_kusada','Katsina / Kusada'),
+    ('katsina_mai-adua','Katsina / Mai-Adua'),
+    ('katsina_malumfashi','Katsina / Malumfashi'),
+    ('katsina_mani','Katsina / Mani'),
+    ('katsina_mashi','Katsina / Mashi'),
+    ('katsina_matazu','Katsina / Matazu'),
+    ('katsina_musawa','Katsina / Musawa'),
+    ('katsina_rimi','Katsina / Rimi'),
+    ('katsina_sabuwa','Katsina / Sabuwa'),
+    ('katsina_safana','Katsina / Safana'),
+    ('katsina_sandamu','Katsina / Sandamu'),
+    ('katsina_zango','Katsina / Zango'),
+    ('kebbi_aleiro','Kebbi / Aleiro'),
+    ('kebbi_arewa-dandi','Kebbi / Arewa-Dandi'),
+    ('kebbi_argungu','Kebbi / Argungu'),
+    ('kebbi_augie','Kebbi / Augie'),
+    ('kebbi_bagudo','Kebbi / Bagudo'),
+    ('kebbi_birnin-kebbi','Kebbi / Birnin-Kebbi'),
+    ('kebbi_bumza','Kebbi / Bumza'),
+    ('kebbi_dandi','Kebbi / Dandi'),
+    ('kebbi_danko','Kebbi / Danko'),
+    ('kebbi_fakai','Kebbi / Fakai'),
+    ('kebbi_gwandu','Kebbi / Gwandu'),
+    ('kebbi_jega','Kebbi / Jega'),
+    ('kebbi_kalgo','Kebbi / Kalgo'),
+    ('kebbi_koko-besse','Kebbi / Koko-Besse'),
+    ('kebbi_maiyama','Kebbi / Maiyama'),
+    ('kebbi_ngaski','Kebbi / Ngaski'),
+    ('kebbi_sakaba','Kebbi / Sakaba'),
+    ('kebbi_shanga','Kebbi / Shanga'),
+    ('kebbi_suru','Kebbi / Suru'),
+    ('kebbi_wasagu','Kebbi / Wasagu'),
+    ('kebbi_yauri','Kebbi / Yauri'),
+    ('kebbi_zuru','Kebbi / Zuru'),
+    ('kogi_adavi','Kogi / Adavi'),
+    ('kogi_ajaokuta','Kogi / Ajaokuta'),
+    ('kogi_ankpa','Kogi / Ankpa'),
+    ('kogi_bassa','Kogi / Bassa'),
+    ('kogi_dekina','Kogi / Dekina'),
+    ('kogi_ibaji','Kogi / Ibaji'),
+    ('kogi_idah','Kogi / Idah'),
+    ('kogi_igalamela','Kogi / Igalamela'),
+    ('kogi_ijumu','Kogi / Ijumu'),
+    ('kogi_ikoyi-ijumu','Kogi / Ikoyi-Ijumu'),
+    ('kogi_kabba/bunu','Kogi / Kabba/Bunu'),
+    ('kogi_kogi','Kogi / Kogi'),
+    ('kogi_lokoja','Kogi / Lokoja'),
+    ('kogi_mopa-muro','Kogi / Mopa-Muro'),
+    ('kogi_obaji','Kogi / Obaji'),
+    ('kogi_ofu','Kogi / Ofu'),
+    ('kogi_ogori/magongo','Kogi / Ogori/Magongo'),
+    ('kogi_okehi','Kogi / Okehi'),
+    ('kogi_okene','Kogi / Okene'),
+    ('kogi_olamaboro','Kogi / Olamaboro'),
+    ('kogi_omala','Kogi / Omala'),
+    ('kogi_oru','Kogi / Oru'),
+    ('kogi_oyi','Kogi / Oyi'),
+    ('kogi_yagba-east','Kogi / Yagba-East'),
+    ('kogi_yagba-west','Kogi / Yagba-West'),
+    ('kwara_asa','Kwara / Asa'),
+    ('kwara_baruten','Kwara / Baruten'),
+    ('kwara_edu','Kwara / Edu'),
+    ('kwara_ekiti','Kwara / Ekiti'),
+    ('kwara_ilorin-east','Kwara / Ilorin-East'),
+    ('kwara_ilorin-south','Kwara / Ilorin-South'),
+    ('kwara_ilorin-west','Kwara / Ilorin-West'),
+    ('kwara_isin','Kwara / Isin'),
+    ('kwara_kaiama','Kwara / Kaiama'),
+    ('kwara_moro','Kwara / Moro'),
+    ('kwara_offa','Kwara / Offa'),
+    ('kwara_oke-ero','Kwara / Oke-Ero'),
+    ('kwara_oyun','Kwara / Oyun'),
+    ('kwara_pategi','Kwara / Pategi'),
+    ('kwara_ifelodun','Kwara / Ifelodun'),
+    ('kwara_irepodun','Kwara / Irepodun'),
+    ('lagos_agege','Lagos / Agege'),
+    ('lagos_ajeromi-ifelodun','Lagos / Ajeromi-Ifelodun'),
+    ('lagos_alimosho','Lagos / Alimosho'),
+    ('lagos_amuwo-odofin','Lagos / Amuwo-Odofin'),
+    ('lagos_apapa','Lagos / Apapa'),
+    ('lagos_badagry','Lagos / Badagry'),
+    ('lagos_epe','Lagos / Epe'),
+    ('lagos_eti-osa','Lagos / Eti-Osa'),
+    ('lagos_ibeju-lekki','Lagos / Ibeju-Lekki'),
+    ('lagos_ifako-ijaiye','Lagos / Ifako-Ijaiye'),
+    ('lagos_ikeja','Lagos / Ikeja'),
+    ('lagos_ikorodu','Lagos / Ikorodu'),
+    ('lagos_island','Lagos / Island'),
+    ('lagos_kosofe','Lagos / Kosofe'),
+    ('lagos_lagos-island','Lagos / Lagos-Island'),
+    ('lagos_lagos-mainland','Lagos / Lagos-Mainland'),
+    ('lagos_mushin','Lagos / Mushin'),
+    ('lagos_ojo','Lagos / Ojo'),
+    ('lagos_oshodi-isolo','Lagos / Oshodi-Isolo'),
+    ('lagos_shomolu','Lagos / Shomolu'),
+    ('lagos_somolu','Lagos / Somolu'),
+    ('lagos_suru-lere','Lagos / Suru-Lere'),
+    ('nassarawa_akwanga','Nassarawa / Akwanga'),
+    ('nassarawa_awe','Nassarawa / Awe'),
+    ('nassarawa_doma','Nassarawa / Doma'),
+    ('nassarawa_karu','Nassarawa / Karu'),
+    ('nassarawa_keana','Nassarawa / Keana'),
+    ('nassarawa_keffi','Nassarawa / Keffi'),
+    ('nassarawa_kokona','Nassarawa / Kokona'),
+    ('nassarawa_lafia','Nassarawa / Lafia'),
+    ('nassarawa_nassawara','Nassarawa / Nassawara'),
+    ('nassarawa_nassawara_eggon','Nassarawa / Nassawara Eggon'),
+    ('nassarawa_obi','Nassarawa / Obi'),
+    ('nassarawa_toto','Nassarawa / Toto'),
+    ('nassarawa_wambu','Nassarawa / Wambu'),
+    ('niger_agaie','Niger / Agaie'),
+    ('niger_agwara','Niger / Agwara'),
+    ('niger_bida','Niger / Bida'),
+    ('niger_borgu','Niger / Borgu'),
+    ('niger_bosso','Niger / Bosso'),
+    ('niger_chanchaga','Niger / Chanchaga'),
+    ('niger_edati','Niger / Edati'),
+    ('niger_gbako','Niger / Gbako'),
+    ('niger_gurara','Niger / Gurara'),
+    ('niger_katcha','Niger / Katcha'),
+    ('niger_kontagora','Niger / Kontagora'),
+    ('niger_lapai','Niger / Lapai'),
+    ('niger_lavun','Niger / Lavun'),
+    ('niger_magama','Niger / Magama'),
+    ('niger_mariga','Niger / Mariga'),
+    ('niger_mashegu','Niger / Mashegu'),
+    ('niger_mokwa','Niger / Mokwa'),
+    ('niger_muya','Niger / Muya'),
+    ('niger_paikoro','Niger / Paikoro'),
+    ('niger_rafi','Niger / Rafi'),
+    ('niger_rijau','Niger / Rijau'),
+    ('niger_shiroro','Niger / Shiroro'),
+    ('niger_suleja','Niger / Suleja'),
+    ('niger_tafa','Niger / Tafa'),
+    ('niger_wushishi','Niger / Wushishi'),
+    ('ogun_abeokuta-north','Ogun / Abeokuta-North'),
+    ('ogun_abeokuta-south','Ogun / Abeokuta-South'),
+    ('ogun_ado-odo/ota','Ogun / Ado-Odo/Ota'),
+    ('ogun_adoodo-ota','Ogun / Adoodo-Ota'),
+    ('ogun_ewekoro','Ogun / Ewekoro'),
+    ('ogun_idarapo','Ogun / Idarapo'),
+    ('ogun_iffo-otta','Ogun / Iffo-Otta'),
+    ('ogun_ifo','Ogun / Ifo'),
+    ('ogun_igbado-north','Ogun / Igbado-North'),
+    ('ogun_igbado-south','Ogun / Igbado-South'),
+    ('ogun_ijebu-east','Ogun / Ijebu-East'),
+    ('ogun_ijebu-north','Ogun / Ijebu-North'),
+    ('ogun_ijebu-north-east','Ogun / Ijebu-North-East'),
+    ('ogun_ijebu-ode','Ogun / Ijebu-Ode'),
+    ('ogun_ikenne','Ogun / Ikenne'),
+    ('ogun_ilishan_remo','Ogun / Ilishan Remo'),
+    ('ogun_ilugun-alaro','Ogun / Ilugun-Alaro'),
+    ('ogun_imeko-afon','Ogun / Imeko-Afon'),
+    ('ogun_ipokia','Ogun / Ipokia'),
+    ('ogun_lgayekpe_','Ogun / Lgayekpe'),
+    ('ogun_obafemi-owode','Ogun / Obafemi-Owode'),
+    ('ogun_odedah','Ogun / Odedah'),
+    ('ogun_odogbolu','Ogun / Odogbolu'),
+    ('ogun_ogun-waterside','Ogun / Ogun-Waterside'),
+    ('ogun_remo-north','Ogun / Remo-North'),
+    ('ogun_sagamu','Ogun / Sagamu'),
+    ('ogun_yewa','Ogun / Yewa'),
+    ('ondo_akoko','Ondo / Akoko'),
+    ('ondo_akoko-north','Ondo / Akoko-North'),
+    ('ondo_akoko-north-east','Ondo / Akoko-North-East'),
+    ('ondo_akoko-north-west','Ondo / Akoko-North-West'),
+    ('ondo_akoko-south','Ondo / Akoko-South'),
+    ('ondo_akoko-south-east','Ondo / Akoko-South-East'),
+    ('ondo_akoko-south-west','Ondo / Akoko-South-West'),
+    ('ondo_akure','Ondo / Akure'),
+    ('ondo_akure-north','Ondo / Akure-North'),
+    ('ondo_akure-south','Ondo / Akure-South'),
+    ('ondo_ese-odo','Ondo / Ese-Odo'),
+    ('ondo_idanre','Ondo / Idanre'),
+    ('ondo_ifedore','Ondo / Ifedore'),
+    ('ondo_ikale','Ondo / Ikale'),
+    ('ondo_ilaje','Ondo / Ilaje'),
+    ('ondo_ilaje-west','Ondo / Ilaje-West'),
+    ('ondo_ile-oluji-okeigbo','Ondo / Ile-Oluji-Okeigbo'),
+    ('ondo_irele','Ondo / Irele'),
+    ('ondo_odigbo','Ondo / Odigbo'),
+    ('ondo_okiti-pupa','Ondo / Okiti-Pupa'),
+    ('ondo_ondo','Ondo / Ondo'),
+    ('ondo_ondo-east','Ondo / Ondo-East'),
+    ('ondo_ondo-west','Ondo / Ondo-West'),
+    ('ondo_ose','Ondo / Ose'),
+    ('ondo_owo','Ondo / Owo'),
+    ('osun_atakumosa','Osun / Atakumosa'),
+    ('osun_atakumosa_east','Osun / Atakumosa East'),
+    ('osun_ayeda-ade','Osun / Ayeda-Ade'),
+    ('osun_ayedire','Osun / Ayedire'),
+    ('osun_boluwaduro','Osun / Boluwaduro'),
+    ('osun_boripe','Osun / Boripe'),
+    ('osun_ede','Osun / Ede'),
+    ('osun_ede-north','Osun / Ede North'),
+    ('osun_egbedore','Osun / Egbedore'),
+    ('osun_ejigbo','Osun / Ejigbo'),
+    ('osun_ife','Osun / Ife'),
+    ('osun_ife-north','Osun / Ife-North'),
+    ('osun_ife-south','Osun / Ife-South'),
+    ('osun_ife-central','Osun / Ife-Central'),
+    ('osun_ife-east','Osun / Ife-East'),
+    ('osun_ifelodun','Osun / Ifelodun'),
+    ('osun_ila','Osun / Ila'),
+    ('osun_ilesa-east','Osun / Ilesa-East'),
+    ('osun_ilesa-west','Osun / Ilesa-West'),
+    ('osun_ilesha','Osun / Ilesha'),
+    ('osun_ilesha_west','Osun / Ilesha West'),
+    ('osun_irepodun','Osun / Irepodun'),
+    ('osun_irewole','Osun / Irewole'),
+    ('osun_isokan','Osun / Isokan'),
+    ('osun_iwo','Osun / Iwo'),
+    ('osun_obokun','Osun / Obokun'),
+    ('osun_odo-otin','Osun / Odo-Otin'),
+    ('osun_ola_oluwa','Osun / Ola Oluwa'),
+    ('osun_olorunda','Osun / Olorunda'),
+    ('osun_ori-ade','Osun / Ori-Ade'),
+    ('osun_orolu','Osun / Orolu'),
+    ('osun_osogbo','Osun / Osogbo'),
+    ('oyo_afijio','Oyo / Afijio'),
+    ('oyo_akinyele','Oyo / Akinyele'),
+    ('oyo_atiba','Oyo / Atiba'),
+    ('oyo_atigbo','Oyo / Atigbo'),
+    ('oyo_egbeda','Oyo / Egbeda'),
+    ('oyo_ibadan-central','Oyo / Ibadan-Central'),
+    ('oyo_ibadan-north-east','Oyo / Ibadan-North-East'),
+    ('oyo_ibadan-north-west','Oyo / Ibadan-North-West'),
+    ('oyo_ibadan-south-east','Oyo / Ibadan-South-East'),
+    ('oyo_ibadan-south-west','Oyo / Ibadan-South-West'),
+    ('oyo_ibarapa-central','Oyo / Ibarapa-Central'),
+    ('oyo_ibarapa-east','Oyo / Ibarapa-East'),
+    ('oyo_ibarapa-north','Oyo / Ibarapa-North'),
+    ('oyo_ido','Oyo / Ido'),
+    ('oyo_ifedayo','Oyo / Ifedayo'),
+    ('oyo_ifeloju','Oyo / Ifeloju'),
+    ('oyo_irepo','Oyo / Irepo'),
+    ('oyo_iseyin','Oyo / Iseyin'),
+    ('oyo_itseiwaju','Oyo / Itseiwaju'),
+    ('oyo_iwajowa','Oyo / Iwajowa'),
+    ('oyo_kajola','Oyo / Kajola'),
+    ('oyo_lagelu','Oyo / Lagelu'),
+    ('oyo_odo-oluwa','Oyo / Odo-Oluwa'),
+    ('oyo_ogbomosho-north','Oyo / Ogbomosho-North'),
+    ('oyo_ogbomosho-south','Oyo / Ogbomosho-South'),
+    ('oyo_olorunsogo','Oyo / Olorunsogo'),
+    ('oyo_oluyole','Oyo / Oluyole'),
+    ('oyo_ona-ara','Oyo / Ona-Ara'),
+    ('oyo_orelope','Oyo / Orelope'),
+    ('oyo_ori-ire','Oyo / Ori-Ire'),
+    ('oyo_oyo-west','Oyo / Oyo-West'),
+    ('oyo_saki-east','Oyo / Saki-East'),
+    ('oyo_saki-west','Oyo / Saki-West'),
+    ('oyo_surulere','Oyo / Surulere'),
+    ('plateau_barkin-ladi','Plateau / Barkin-Ladi'),
+    ('plateau_bassa','Plateau / Bassa'),
+    ('plateau_bokkos','Plateau / Bokkos'),
+    ('plateau_jos-east','Plateau / Jos-East'),
+    ('plateau_jos-north','Plateau / Jos-North'),
+    ('plateau_jos-south','Plateau / Jos-South'),
+    ('plateau_kanam','Plateau / Kanam'),
+    ('plateau_kanke','Plateau / Kanke'),
+    ('plateau_langtang-north','Plateau / Langtang-North'),
+    ('plateau_langtang-south','Plateau / Langtang-South'),
+    ('plateau_mangu','Plateau / Mangu'),
+    ('plateau_mikang','Plateau / Mikang'),
+    ('plateau_pankshin','Plateau / Pankshin'),
+    ('plateau_quananpan','Plateau / Quananpan'),
+    ('plateau_riyom','Plateau / Riyom'),
+    ('plateau_shendam','Plateau / Shendam'),
+    ('plateau_wase','Plateau / Wase'),
+    ('rivers_aboa/odual','Rivers / Aboa/Odual'),
+    ('rivers_ahoada-east','Rivers / Ahoada-East'),
+    ('rivers_ahoada-west','Rivers / Ahoada-West'),
+    ('rivers_akukutoru','Rivers / Akukutoru'),
+    ('rivers_andoni','Rivers / Andoni'),
+    ('rivers_asari-toru','Rivers / Asari-Toru'),
+    ('rivers_bonny','Rivers / Bonny'),
+    ('rivers_buguma','Rivers / Buguma'),
+    ('rivers_degema','Rivers / Degema'),
+    ('rivers_eleme','Rivers / Eleme'),
+    ('rivers_elfane','Rivers / Elfane'),
+    ('rivers_emuoha','Rivers / Emuoha'),
+    ('rivers_etche','Rivers / Etche'),
+    ('rivers_gokana','Rivers / Gokana'),
+    ('rivers_ikwerre','Rivers / Ikwerre'),
+    ('rivers_khana','Rivers / Khana'),
+    ('rivers_obia/akpor','Rivers / Obia/Akpor'),
+    ('rivers_ogba-egbema-ndoni','Rivers / Ogba-Egbema-Ndoni'),
+    ('rivers_ogu/bolo','Rivers / Ogu/Bolo'),
+    ('rivers_okirika','Rivers / Okirika'),
+    ('rivers_omuma','Rivers / Omuma'),
+    ('rivers_opobo/nkoro','Rivers / Opobo/Nkoro'),
+    ('rivers_oyigbo','Rivers / Oyigbo'),
+    ('rivers_port-harcourt','Rivers / Port-Harcourt'),
+    ('rivers_tai','Rivers / Tai'),
+    ('sokoto_binji','Sokoto / Binji'),
+    ('sokoto_bodinga','Sokoto / Bodinga'),
+    ('sokoto_dange-shuni','Sokoto / Dange-Shuni'),
+    ('sokoto_gada','Sokoto / Gada'),
+    ('sokoto_goronyo','Sokoto / Goronyo'),
+    ('sokoto_gudu','Sokoto / Gudu'),
+    ('sokoto_gwadabawa','Sokoto / Gwadabawa'),
+    ('sokoto_illela','Sokoto / Illela'),
+    ('sokoto_kebbe','Sokoto / Kebbe'),
+    ('sokoto_kware','Sokoto / Kware'),
+    ('sokoto_raba','Sokoto / Raba'),
+    ('sokoto_sabo-birni','Sokoto / Sabo-Birni'),
+    ('sokoto_shagari','Sokoto / Shagari'),
+    ('sokoto_silame','Sokoto / Silame'),
+    ('sokoto_sokoto-north','Sokoto / Sokoto-North'),
+    ('sokoto_sokoto-south','Sokoto / Sokoto-South'),
+    ('sokoto_tambuwal','Sokoto / Tambuwal'),
+    ('sokoto_tangaza','Sokoto / Tangaza'),
+    ('sokoto_tureta','Sokoto / Tureta'),
+    ('sokoto_wamakko','Sokoto / Wamakko'),
+    ('sokoto_wurno','Sokoto / Wurno'),
+    ('sokoto_yabo','Sokoto / Yabo'),
+    ('taraba_ardo-kola','Taraba / Ardo-Kola'),
+    ('taraba_bali','Taraba / Bali'),
+    ('taraba_donga','Taraba / Donga'),
+    ('taraba_gashaka','Taraba / Gashaka'),
+    ('taraba_gassol','Taraba / Gassol'),
+    ('taraba_ibi','Taraba / Ibi'),
+    ('taraba_jalingo','Taraba / Jalingo'),
+    ('taraba_karim-lamido','Taraba / Karim-Lamido'),
+    ('taraba_kurmi','Taraba / Kurmi'),
+    ('taraba_lau','Taraba / Lau'),
+    ('taraba_oilingo','Taraba / Oilingo'),
+    ('taraba_sardauna','Taraba / Sardauna'),
+    ('taraba_takum','Taraba / Takum'),
+    ('taraba_ussa','Taraba / Ussa'),
+    ('taraba_wukari','Taraba / Wukari'),
+    ('taraba_yorro','Taraba / Yorro'),
+    ('taraba_zing','Taraba / Zing'),
+    ('yobe_bade','Yobe / Bade'),
+    ('yobe_borsali','Yobe / Borsali'),
+    ('yobe_damaturu','Yobe / Damaturu'),
+    ('yobe_fika','Yobe / Fika'),
+    ('yobe_fune','Yobe / Fune'),
+    ('yobe_geidam','Yobe / Geidam'),
+    ('yobe_gogaram','Yobe / Gogaram'),
+    ('yobe_gujba','Yobe / Gujba'),
+    ('yobe_gulani','Yobe / Gulani'),
+    ('yobe_jakusko','Yobe / Jakusko'),
+    ('yobe_karasuwa','Yobe / Karasuwa'),
+    ('yobe_machina','Yobe / Machina'),
+    ('yobe_nangere','Yobe / Nangere'),
+    ('yobe_nguru','Yobe / Nguru'),
+    ('yobe_potiskum','Yobe / Potiskum'),
+    ('yobe_tarmua','Yobe / Tarmua'),
+    ('yobe_yunusari','Yobe / Yunusari'),
+    ('zamfara_anka','Zamfara / Anka'),
+    ('zamfara_bakura','Zamfara / Bakura'),
+    ('zamfara_bukkuyum','Zamfara / Bukkuyum'),
+    ('zamfara_bungudu','Zamfara / Bungudu'),
+    ('zamfara_gumi','Zamfara / Gumi'),
+    ('zamfara_gusau','Zamfara / Gusau'),
+    ('zamfara_isa','Zamfara / Isa'),
+    ('zamfara_kaura-namoda','Zamfara / Kaura-Namoda'),
+    ('zamfara_kiyawa','Zamfara / Kiyawa'),
+    ('zamfara_maradun','Zamfara / Maradun'),
+    ('zamfara_maru','Zamfara / Maru'),
+    ('zamfara_shinkafi','Zamfara / Shinkafi'),
+    ('zamfara_talata-mafara','Zamfara / Talata-Mafara'),
+    ('zamfara_tsafe','Zamfara / Tsafe'),
+    ('zamfara_zurmi','Zamfara / Zurmi'),
+    ('osun_aiyedire','Osun / Aiyedire'),
+    ('cross_river_biase','Cross River / Biase'),
+    ('ogun_egbado-north','Ogun / Egbado-North'),
+    ('ogun_egbado-south','Ogun / Egbado-South'),
+    ('oyo_itesiwaju','Oyo / Itesiwaju'),
+    ('oyo_ogo-oluwa','Oyo / Ogo-Oluwa'),
+    ('ebonyi_ohaukwu','Ebonyi / Ohaukwu'),
+    ('ondo_okitipupa','Ondo / Okitipupa'),
+    ('osun_oriade','Osun / Oriade'),
+    ('benue_oturkpo','Benue / Oturkpo'),
+    ('oyo_oyo-east','Oyo / Oyo-East'),
+    ('abia_ukwa-east','Abia / Ukwa-East'),
+    ('akwa_ibom_urue-ffong-oruko','Akwa Ibom / Urue-Offong-Oruko'),
+    ('foreigner','Foreigner')
+    )
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/utils/utils.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/utils/utils.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/utils/utils.py	(revision 8872)
@@ -0,0 +1,208 @@
+## $Id$
+##
+## Copyright (C) 2012 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+"""Customize general helper utilities for Kofa.
+"""
+import os
+import pytz
+from waeup.kofa.utils.utils import KofaUtils, sorted_phone_prefixes
+from kofacustom.nigeria.interfaces import MessageFactory as _
+
+INT_PHONE_PREFIXES = [
+    (1, _('Nigeria'), '234'),
+    (99, _('Germany'), '49'),
+    (99, _('United States'), '1'),
+    (99, _('Niger'), '227'),
+    (99, _('Benin'), '229'),
+    (99, _('Cameroon'), '237'),
+    (99, _('United Kingdom'), '44'),
+    (99, _('France'), '33'),
+    ]
+
+class NigeriaKofaUtils(KofaUtils):
+    """A collection of methods subject to customization.
+    """
+    PORTAL_LANGUAGE = 'en'
+
+    PREFERRED_LANGUAGES_DICT = {
+        'en':(1, u'English'),
+        'fr':(2, u'Fran&ccedil;ais'),
+        'de':(3, u'Deutsch'),
+        'ha':(4, u'Hausa'),
+        'yo':(5, u'Yoruba'),
+        'ig':(6, u'Igbo'),
+        }
+
+    #: A function to return
+    @classmethod
+    def sorted_phone_prefixes(cls, data=INT_PHONE_PREFIXES, request=None):
+        return sorted_phone_prefixes(data, request)
+
+    EXAM_SUBJECTS_DICT = {
+        'accounts': 'Accounts',
+        'add_general_science': 'Add General Science',
+        'add_maths': 'Add Maths',
+        'adv_elect_install_maint': 'Adv. Electrical Installation and Maintenance',
+        'agricultural_science': 'Agricultural Science',
+        'applied_electricity': 'Applied Electricity',
+        'arabi': 'Arabic',
+        'arithmetics': 'Arithmetics',
+        'art': 'Art',
+        'auto_mechanics': 'Auto Mechanics',
+        'basic_electricity': 'Basic Electricity',
+        'bible_knowledge': 'Bible Knowledge',
+        'biology': 'Biology',
+        'biology_alt_syl': 'Biology (Alt.Syl)',
+        'book_keeping': 'Book Keeping',
+        'building_construction': 'Building Construction',
+        'business_management': 'Business Management',
+        'business_construction_management': 'Business/Construction Management (Adv)',
+        'chemistry': 'Chemistry',
+        'chemistry_alt_syl': 'Chemistry (Alt.Syl)',
+        'christian_religious_studies': 'Christian Religious Studies',
+        'class_teaching': 'Class Teaching',
+        'clerical_office_duties': 'Clerical Office Duties',
+        'clothing_and_textiles': 'Clothing and Textiles',
+        'commerce': 'Commerce',
+        'economics': 'Economics',
+        'education': 'Education',
+        'efik': 'Efik',
+        'electronics': 'Electronics',
+        'elementary_surveying': 'Elementary Surveying',
+        'english_language': 'English Language',
+        'engineering_science': 'Engineering Science',
+        'financial_accounting': 'Financial Accounting',
+        'food_and_nutrition': 'Food and Nutrition',
+        'french': 'French',
+        'further_mathematics': 'Further Mathematics',
+        'general_science': 'General Science',
+        'geography': 'Geography',
+        'german': 'German',
+        'government': 'Government',
+        'hausa': 'Hausa',
+        'hausa_literature': 'Hausa Literature',
+        'health_science': 'Health Science',
+        'history': 'History',
+        'home_management': 'Home Management',
+        'human_biology': 'Human Biology',
+        'industrial_electrical_installation': 'Industrial Elect Installation (Adv)',
+        'intergrated_science': 'Intergrated Science',
+        'islamic_studies': 'Islamic Studies',
+        'literature_in_english': 'Literature in English',
+        'literature_in_nigerian_languages': 'Literature in Nigerian Languages',
+        'igbo': 'Igbo',
+        'igbo_literature': 'Igbo Literature',
+        'yoruba': 'Yoruba',
+        'yoruba_literature': 'Yoruba Literature',
+        'management_in_living': 'Management in Living',
+        'mathematics': 'Mathematics',
+        'metalwork': 'Metalwork',
+        'music': 'Music',
+        'nigerian_language': 'Nigerian Language',
+        'office_practice': 'Office Practice',
+        'physical_education': 'Physical Education',
+        'physical_health_education': 'Physical and Health Education',
+        'physics': 'Physics',
+        'physics_alt_syl': 'Physics (Alt.Syl)',
+        'principles_and_practice_of_education': 'Principles and Practice of Education',
+        'principles_of_cost_accounting': 'Principles of Cost Accounting',
+        'rural_science': 'Rural Science',
+        'science': 'Science',
+        'secretarial_duties': 'Secretarial Duties',
+        'shorthand': 'Shorthand',
+        'sierra_leone_studies': 'Sierra Leone Studies',
+        'sierra_leone_languages': 'Sierra Leone Languages',
+        'social_studies': 'Social Studies',
+        'statistics': 'Statistics',
+        'teaching_practice': 'Teaching Practice',
+        'technical_drawing': 'Technical Drawing',
+        'typewriting': 'Typewriting',
+        'visual_art': 'Visual Art',
+        'woodwork': 'Woodwork',
+        'winding_elect_machines': 'Winding of Elect Machines and Elect Eng Sc'
+        }
+
+    EXAM_GRADES = (
+        ('A1', 'Excellent (A1)'),
+        ('A2', 'Very Good (A2)'),
+        ('A3', 'Good (A3)'),
+        ('B2', 'Very Good (B2)'),
+        ('B3', 'Good (B3)'),
+        ('C4', 'Credit (C4)'),
+        ('C5', 'Credit (C5)'),
+        ('C6', 'Credit (C6)'),
+        ('A', 'Pass (A)'),
+        ('B', 'Pass (B)'),
+        ('C', 'Pass (C)'),
+        ('U', 'Pass (U)'),
+        ('D7', 'Pass (D7)'),
+        ('P7', 'Pass (P7)'),
+        ('P8', 'Pass (P8)'),
+        ('E8', 'Pass (E8)'),
+        ('F9', 'Fail (F9)'),
+        ('Aa', 'A (a)'),
+        ('Bb', 'B (b)'),
+        ('Cc', 'C (c)'),
+        ('Dd', 'D (d)'),
+        ('Ee', 'E (e)'),
+        ('Ff', 'F (f)'),
+        ('Gg', 'G (g)')
+        )
+
+    INST_TYPES_DICT = {
+        'none': '',
+        'faculty': 'Faculty of',
+        'department': 'Department of',
+        'school': 'School of',
+        'office': 'Office for',
+        'centre': 'Centre for',
+        'institute': 'Institute of',
+        'school_for': 'School for',
+        'college': 'College of',
+        }
+
+    STUDY_MODES_DICT = {
+        'rmd_ft': 'Remedial with deficiencies',
+        'dp_pt': 'Diploma Part Time',
+        'ct_ft': 'Certificate Full Time',
+        'dp_ft': 'Diploma Full Time',
+        'de_pt': 'Direct Entry Part Time',
+        'pg_ft': 'Postgraduate Full Time',
+        'pg_pt': 'Postgraduate Part Time',
+        'jm_ft': 'Joint Matriculation Full Time',
+        'de_ft': 'Direct Entry Full Time',
+        'ph_ft': 'Post Higher Education Full Time',
+        'transfer_pt': 'Transfer Part Time',
+        'ug_pt': 'Undergraduate Part Time',
+        'transfer_ft': 'Transfer Full Time',
+        'ct_pt': 'Certificate Part Time',
+        'ug_ft': 'Undergraduate Full Time',
+        'rm_ft': 'Remedial'
+        }
+
+    APP_CATS_DICT = {
+        'basic': 'PUTME, PDE, PCE, PRENCE',
+        'no': 'no application',
+        'pg_ft': 'Postgraduate Full-Time',
+        'pg_pt': 'Postgraduate Part-Time',
+        'sandwich': 'Sandwich',
+        'cest': 'Part-Time, Diploma, Certificate'
+        }
+
+    @property
+    def tzinfo(self):
+        return pytz.timezone('Africa/Lagos')
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/widgets/__init__.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/widgets/__init__.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/widgets/__init__.py	(revision 8872)
@@ -0,0 +1,1 @@
+# Make this a package.
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/widgets/phonewidget.py
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/widgets/phonewidget.py	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/src/kofacustom/nigeria/widgets/phonewidget.py	(revision 8872)
@@ -0,0 +1,28 @@
+## $Id$
+##
+## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+"""
+A customized phone widget
+"""
+
+from waeup.kofa.widgets.phonewidget import PhoneWidget
+
+class NigeriaPhoneWidget(PhoneWidget):
+    """A phone widget without area prefix.
+    """
+    subwidget_names = ('country', 'ext')
+    bootstrap_span = 'span3'
Index: /main/kofacustom.nigeria/branches/uli-autoinclude-less/versions.cfg
===================================================================
--- /main/kofacustom.nigeria/branches/uli-autoinclude-less/versions.cfg	(revision 8872)
+++ /main/kofacustom.nigeria/branches/uli-autoinclude-less/versions.cfg	(revision 8872)
@@ -0,0 +1,35 @@
+# Versions of packages used by kofacustom.nigeria
+[buildout]
+# default set of versions we use.
+extends= http://grok.zope.org/releaseinfo/grok-1.1.cfg
+
+versions = versions
+
+[versions]
+collective.recipe.sphinxbuilder = 0.7.0
+hurry.workflow = 0.11
+# Pinned to circumvent breakage in 0.4.x
+hurry.zoperesource = 0.6
+# Pinned to prevent buildout svn-error.
+lovely.recipe = 1.0.0
+megrok.layout = 1.0.2
+reportlab = 2.5
+transaction = 1.1.0
+z3c.testsetup = 0.6.1
+zc.buildout = 1.5.0
+zc.recipe.egg = 1.3.0
+zc.recipe.testrunner = 1.4.0
+zope.app.testing = 3.8.1
+# for support of @provider directive
+zope.interface = 3.6.3
+# for support of contextual default values
+zope.schema = 3.8.0
+zope.testing = 3.10.2
+zope.xmlpickle = 3.4.0
+# Require latest version...
+Sphinx = 1.0.7
+ZODB3 = 3.10.3
+docutils = 0.7
+Jinja2 = 2.3
+# for support of unicode encoded passwords
+zope.password = 3.6.1
