Index: main/waeup.kofa/trunk/CHANGES.txt
===================================================================
--- main/waeup.kofa/trunk/CHANGES.txt	(revision 17784)
+++ main/waeup.kofa/trunk/CHANGES.txt	(revision 17787)
@@ -5,4 +5,8 @@
 =======================
 
+* Add `SessionConfigurationProcessor`.
+
+* Add `ConfigurationContainerProcessor`.
+
 * Add `ConfigurationContainerExporter`.
 
@@ -17,5 +21,5 @@
 * Mangle referees and school grades when exporting applicants.
 
-* Add `ConfigurationExporter`.
+* Add `SessionConfigurationExporter`.
 
 * Do not allow to add a study level if course registration has ended.
Index: main/waeup.kofa/trunk/src/waeup/kofa/accesscodes/batching.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/accesscodes/batching.py	(revision 17784)
+++ main/waeup.kofa/trunk/src/waeup/kofa/accesscodes/batching.py	(revision 17787)
@@ -50,6 +50,4 @@
     factory_name = 'waeup.AccessCodeBatch'
 
-    mode = None
-
     def parentsExist(self, row, site):
         return 'accesscodes' in site.keys()
@@ -107,6 +105,4 @@
     location_fields = ['representation', 'batch_prefix', 'batch_num']
     factory_name = 'waeup.AccessCode'
-
-    mode = None
 
     @property
Index: main/waeup.kofa/trunk/src/waeup/kofa/applicants/batching.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/applicants/batching.py	(revision 17784)
+++ main/waeup.kofa/trunk/src/waeup/kofa/applicants/batching.py	(revision 17787)
@@ -106,6 +106,4 @@
     factory_name = 'waeup.Applicant'
 
-    mode = None
-
     @property
     def available_fields(self):
Index: main/waeup.kofa/trunk/src/waeup/kofa/browser/pages.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/browser/pages.py	(revision 17784)
+++ main/waeup.kofa/trunk/src/waeup/kofa/browser/pages.py	(revision 17787)
@@ -1233,5 +1233,4 @@
     # We don't need to edit next matric integers in the base package.
     form_fields = grok.AutoFields(IConfigurationContainer).omit(
-        'frontpage_dict',
         'next_matric_integer',
         'next_matric_integer_2',
Index: main/waeup.kofa/trunk/src/waeup/kofa/configuration.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/configuration.py	(revision 17784)
+++ main/waeup.kofa/trunk/src/waeup/kofa/configuration.py	(revision 17787)
@@ -39,4 +39,6 @@
     grok.implements(IConfigurationContainer)
 
+    frontpage_dict = dict()
+
     def addSessionConfiguration(self, sessionconfiguration):
         """Add a session configuration object.
@@ -52,4 +54,18 @@
 ConfigurationContainer = attrs_to_fields(ConfigurationContainer)
 
+
+class ConfigurationContainerFactory(grok.GlobalUtility):
+    """A factory for configuration container. This factory is only needed
+    for import.
+    """
+    grok.implements(IFactory)
+    grok.name(u'waeup.ConfigurationContainer')
+
+    def __call__(self, *args, **kw):
+        return ConfigurationContainer(*args, **kw)
+
+    def getInterfaces(self):
+        return implementedBy(ConfigurationContainer)
+
 class SessionConfiguration(grok.Model):
     """
@@ -88,5 +104,6 @@
 
     title = _(u'Base Configuration')
-    fields = tuple(sorted(iface_names(IConfigurationContainer))) + ('curr_stud_id',)
+    fields = tuple(sorted(iface_names(
+        IConfigurationContainer, omit=['captcha',]))) + ('curr_stud_id',)
 
     def mangle_value(self, value, name, context=None):
@@ -106,10 +123,10 @@
         return self.close_outfile(filepath, outfile)
 
-class ConfigurationExporter(grok.GlobalUtility, ExporterBase):
-    """The Configuration Exporter exports all configuration data. It iterates over all
-    objects of the ``configuration`` container.
+class SessionConfigurationExporter(grok.GlobalUtility, ExporterBase):
+    """The Session Configuration Exporter exports all configuration data.
+    It iterates over all objects of the ``configuration`` container.
     """
     grok.implements(ICSVExporter)
-    grok.name('configurations')
+    grok.name('sessionconfigurations')
 
     title = _(u'Session Configurations')
@@ -128,5 +145,5 @@
 
     def export_all(self, site, filepath=None):
-        """Export configurations into filepath as CSV data.
+        """Export session configurations into filepath as CSV data.
 
         If `filepath` is ``None``, a raw string with CSV data is returned.
@@ -135,7 +152,8 @@
         return self.export(configurations.values(), filepath)
 
-class ConfigurationProcessor(BatchProcessor):
-    """The Configuration Processor processes session configuration objects in
-    the ``configuration`` container.
+class ConfigurationContainerProcessor(BatchProcessor):
+    """The Configuration Container Processor processes processes the
+    portal's base confoiguration data. This container exists in the portal.
+    Thus only the update method is allowed.
 
     """
@@ -143,5 +161,49 @@
     grok.provides(IBatchProcessor)
     grok.context(Interface)
-    util_name = 'configurationprocessor'
+    util_name = 'configurationcontainerupdater'
+    grok.name(util_name)
+
+    name = u'ConfigurationConainer Processor (update only)'
+    iface = IConfigurationContainer
+    factory_name = 'waeup.ConfigurationContainer'
+
+    @property
+    def available_fields(self):
+        return tuple(
+            sorted(iface_names(
+                IConfigurationContainer,
+                omit=['captcha',]))) + ('curr_stud_id',)
+
+    def parentsExist(self, row, site):
+        return True
+
+    def entryExists(self, row, site):
+        return True
+
+    def getParent(self, row, site):
+        return site
+
+    def getEntry(self, row, site):
+        return site['configuration']
+
+    def updateEntry(self, obj, row, site, filename):
+        """Update obj to the values given in row.
+        """
+        if 'curr_stud_id' in row:
+            studid = row.get('curr_stud_id')
+            site['students']._curr_stud_id = int(studid)
+        row.pop('curr_stud_id')
+        super(ConfigurationContainerProcessor, self).updateEntry(
+            obj, row, site, filename)
+        return
+
+class SessionConfigurationProcessor(BatchProcessor):
+    """The (Session) Configuration Processor processes session configuration
+    objects in the ``configuration`` container.
+    """
+    grok.implements(IBatchProcessor)
+    grok.provides(IBatchProcessor)
+    grok.context(Interface)
+    util_name = 'sessionconfigurationprocessor'
     grok.name(util_name)
 
@@ -149,6 +211,4 @@
     iface = ISessionConfiguration
     factory_name = 'waeup.SessionConfiguration'
-
-    mode = None
 
     def parentsExist(self, row, site):
@@ -181,2 +241,3 @@
         pass
 
+
Index: main/waeup.kofa/trunk/src/waeup/kofa/doctests/batchprocessing_browser.txt
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/doctests/batchprocessing_browser.txt	(revision 17784)
+++ main/waeup.kofa/trunk/src/waeup/kofa/doctests/batchprocessing_browser.txt	(revision 17787)
@@ -105,5 +105,5 @@
     'CertificateCourse Processor',
     'Certificate Processor',
-    'SessionConfiguration Processor',
+    'ConfigurationConainer Processor (update only)',
     'Course Processor',
     'CourseTicket Processor',
@@ -115,4 +115,5 @@
     'Public PDF Document Processor',
     'Public REST Document Processor',
+    'SessionConfiguration Processor',
     'Student Processor',
     'StudentStudyCourse Processor',
Index: main/waeup.kofa/trunk/src/waeup/kofa/documents/batching.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/documents/batching.py	(revision 17784)
+++ main/waeup.kofa/trunk/src/waeup/kofa/documents/batching.py	(revision 17787)
@@ -67,6 +67,4 @@
 
     factory_name = None
-
-    mode = None
 
     @property
Index: main/waeup.kofa/trunk/src/waeup/kofa/hostels/batching.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/hostels/batching.py	(revision 17784)
+++ main/waeup.kofa/trunk/src/waeup/kofa/hostels/batching.py	(revision 17787)
@@ -45,6 +45,4 @@
     location_fields = ['hostel_id',]
     factory_name = 'waeup.Hostel'
-
-    mode = None
 
     def parentsExist(self, row, site):
@@ -98,6 +96,4 @@
     location_fields = ['hostel_id', 'bed_id']
     factory_name = None
-
-    mode = None
 
     @property
Index: main/waeup.kofa/trunk/src/waeup/kofa/interfaces.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/interfaces.py	(revision 17784)
+++ main/waeup.kofa/trunk/src/waeup/kofa/interfaces.py	(revision 17787)
@@ -724,4 +724,6 @@
     """
 
+    frontpage_dict = Attribute('Language translation dictionary with values in HTML format')
+
     name = schema.TextLine(
         title = _(u'Name of University'),
@@ -741,10 +743,4 @@
         default = default_html_frontpage,
         constraint=validate_html,
-        )
-
-    frontpage_dict = schema.Dict(
-        title = u'Content as language dictionary with values in html format',
-        required = False,
-        default = {},
         )
 
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_webservices.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_webservices.py	(revision 17784)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_webservices.py	(revision 17787)
@@ -1111,2 +1111,128 @@
         self.assertEqual(xmlout, RESPONSE_XML)
         return
+
+    def test_get_student_info(self):
+        server = ServerProxy('http://mgr:mgrpw@localhost/app')
+        self.setup_student(self.student)
+        result = server.get_student_info('123')
+        self.assertEqual(result,
+            ['Anna Tester', 'CERT1', '1234', 'aa@aa.ng'])
+        REQUEST_XML = """\
+<?xml version="1.0"?>
+<methodCall>
+<methodName>get_student_info</methodName>
+<params>
+<param>
+<value><string>K1000000</string></value>
+</param>
+</params>
+</methodCall>"""
+        RESPONSE_XML = """\
+<?xml version='1.0'?>
+<methodResponse>
+<params>
+<param>
+<value><array><data>
+<value><string>Anna Tester</string></value>
+<value><string>CERT1</string></value>
+<value><string>1234</string></value>
+<value><string>aa@aa.ng</string></value>
+</data></array></value>
+</param>
+</params>
+</methodResponse>
+"""
+        xmlout = self.XMLRPC_post(REQUEST_XML)
+        self.assertEqual(xmlout, RESPONSE_XML)
+        return
+
+    def test_get_student_base_data(self):
+        server = ServerProxy('http://mgr:mgrpw@localhost/app')
+        result = server.get_student_base_data()
+        self.assertEqual(result,
+            [{'entry_mode': None,
+              'reg_number': '123',
+              'firstname': 'Anna',
+              'middlename': None,
+              'current_session': 2004,
+              'entry_session': 2004,
+              'certcode': 'CERT1',
+              'state': 'created',
+              'student_id': 'K1000000',
+              'faccode': 'fac1',
+              'lastname': 'Tester',
+              'matric_number': '234',
+              'depcode': 'dep1'}])
+        REQUEST_XML = """\
+<?xml version="1.0"?>
+<methodCall>
+<methodName>get_student_base_data</methodName>
+<params>
+</params>
+</methodCall>"""
+        RESPONSE_XML = """\
+<?xml version='1.0'?>
+<methodResponse>
+<params>
+<param>
+<value><array><data>
+<value><struct>
+<member>
+<name>entry_mode</name>
+<value><nil/></value></member>
+<member>
+<name>reg_number</name>
+<value><string>123</string></value>
+</member>
+<member>
+<name>firstname</name>
+<value><string>Anna</string></value>
+</member>
+<member>
+<name>middlename</name>
+<value><nil/></value></member>
+<member>
+<name>current_session</name>
+<value><int>2004</int></value>
+</member>
+<member>
+<name>entry_session</name>
+<value><int>2004</int></value>
+</member>
+<member>
+<name>certcode</name>
+<value><string>CERT1</string></value>
+</member>
+<member>
+<name>matric_number</name>
+<value><string>234</string></value>
+</member>
+<member>
+<name>state</name>
+<value><string>created</string></value>
+</member>
+<member>
+<name>faccode</name>
+<value><string>fac1</string></value>
+</member>
+<member>
+<name>lastname</name>
+<value><string>Tester</string></value>
+</member>
+<member>
+<name>student_id</name>
+<value><string>K1000000</string></value>
+</member>
+<member>
+<name>depcode</name>
+<value><string>dep1</string></value>
+</member>
+</struct></value>
+</data></array></value>
+</param>
+</params>
+</methodResponse>
+"""
+        xmlout = self.XMLRPC_post(REQUEST_XML)
+        self.assertEqual(xmlout, RESPONSE_XML)
+        return
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/webservices.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/webservices.py	(revision 17784)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/webservices.py	(revision 17787)
@@ -533,2 +533,48 @@
               )
         return hitlist
+
+    # Data requested by the WAeUP team
+
+    @grok.require('waeup.xmlrpc')
+    def get_student_base_data(self,
+            current_session=None, current_level=None, certcode=None,
+            current_mode=None, depcode=None, p_session=None):
+        """Returns bursary data of a subset of students.
+        """
+        if not current_session:
+            current_session = None
+        if not current_level:
+            current_level = None
+        if not depcode:
+            depcode = None
+        if not certcode:
+            certcode = None
+        if not current_mode:
+            current_mode = None
+        hitlist = []
+        cat = queryUtility(ICatalog, name='students_catalog')
+        results = cat.searchResults(
+                current_session=(current_session, current_session),
+                current_level=(current_level, current_level),
+                certcode=(certcode, certcode),
+                current_mode=(current_mode, current_mode),
+                depcode=(depcode, depcode),
+                )
+        for student in results:
+            hitlist.append(dict(
+                student_id=student.student_id,
+                matric_number=student.matric_number,
+                reg_number=student.reg_number,
+                firstname=student.firstname,
+                middlename=student.middlename,
+                lastname=student.lastname,
+                state=student.state,
+                current_session=student.current_session,
+                entry_session=student.entry_session,
+                entry_mode=student.entry_mode,
+                faccode=student.faccode,
+                depcode=student.depcode,
+                certcode=student.certcode,
+                )
+            )
+        return hitlist
Index: main/waeup.kofa/trunk/src/waeup/kofa/tests/sample_baseconfig_data.csv
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/tests/sample_baseconfig_data.csv	(revision 17787)
+++ main/waeup.kofa/trunk/src/waeup/kofa/tests/sample_baseconfig_data.csv	(revision 17787)
@@ -0,0 +1,2 @@
+acronym,carry_over,current_academic_session,email_admin,email_subject,export_disabled_message,frontpage,maintmode_enabled_by,name,name_admin,next_matric_integer,next_matric_integer_2,next_matric_integer_3,next_matric_integer_4,smtp_mailer,curr_stud_id
+WAeUP.Kofa,0,2011,henrik@waeup.org,Kofa Contact,,Hello World,,Sample University,Administrator,333,0,0,0,No email service,1000412
Index: main/waeup.kofa/trunk/src/waeup/kofa/tests/sample_sessionconfig_data.csv
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/tests/sample_sessionconfig_data.csv	(revision 17787)
+++ main/waeup.kofa/trunk/src/waeup/kofa/tests/sample_sessionconfig_data.csv	(revision 17787)
@@ -0,0 +1,3 @@
+academic_session,booking_fee,clearance_enabled,clearance_fee,coursereg_deadline,late_registration_fee,maint_fee,payment_disabled,transcript_fee,transfer_fee
+2017,300.0,0,222.0,,333.0,0.0,['sf_all'],222.0,0.0
+2019,0.0,0,0.0,,0.0,0.0,[],0.0,0.0
Index: main/waeup.kofa/trunk/src/waeup/kofa/tests/test_configuration.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/tests/test_configuration.py	(revision 17784)
+++ main/waeup.kofa/trunk/src/waeup/kofa/tests/test_configuration.py	(revision 17787)
@@ -30,6 +30,7 @@
 from waeup.kofa.configuration import (
     ConfigurationContainer, SessionConfiguration, SessionConfigurationFactory,
-    ConfigurationContainerExporter, ConfigurationExporter)
-from waeup.kofa.interfaces import(ICSVExporter,
+    ConfigurationContainerExporter, SessionConfigurationExporter,
+    ConfigurationContainerProcessor, SessionConfigurationProcessor)
+from waeup.kofa.interfaces import(ICSVExporter, IBatchProcessor,
     IConfigurationContainer, ISessionConfiguration, ISessionConfigurationAdd)
 
@@ -124,10 +125,10 @@
         result = open(self.outfile, 'rb').read()
         self.assertTrue(
-            'acronym,captcha,carry_over,current_academic_session,email_admin,'
-            'email_subject,export_disabled_message,frontpage,frontpage_dict,'
+            'acronym,carry_over,current_academic_session,email_admin,'
+            'email_subject,export_disabled_message,frontpage,'
             'maintmode_enabled_by,name,name_admin,next_matric_integer,'
             'next_matric_integer_2,next_matric_integer_3,'
             'next_matric_integer_4,smtp_mailer,curr_stud_id\r\n'
-            'WAeUP.Kofa,No captcha,0,,contact@waeup.org,Kofa Contact,,'
+            'WAeUP.Kofa,0,,contact@waeup.org,Kofa Contact,,'
             '"<h1>Welcome to WAeUP.Kofa\n<br>' in result
             )
@@ -138,12 +139,12 @@
     def test_ifaces(self):
         # make sure we fullfill interface contracts
-        obj = ConfigurationExporter()
+        obj = SessionConfigurationExporter()
         verify.verifyObject(ICSVExporter, obj)
-        verify.verifyClass(ICSVExporter, ConfigurationExporter)
+        verify.verifyClass(ICSVExporter, SessionConfigurationExporter)
         return
 
     def test_get_as_utility(self):
         # we can get a faculty exporter as utility
-        result = queryUtility(ICSVExporter, name="configurations")
+        result = queryUtility(ICSVExporter, name="sessionconfigurations")
         self.assertTrue(result is not None)
         return
@@ -154,5 +155,5 @@
         self.sessionconfig.clearance_fee = 3000.6
         self.app['configuration'].addSessionConfiguration(self.sessionconfig)
-        exporter = ConfigurationExporter()
+        exporter = SessionConfigurationExporter()
         exporter.export_all(self.app, self.outfile)
         result = open(self.outfile, 'rb').read()
@@ -164,2 +165,66 @@
             )
         return
+
+BASECONFIG_SAMPLE_DATA = open(
+    os.path.join(os.path.dirname(__file__), 'sample_baseconfig_data.csv'),
+    'rb').read()
+
+BASECONFIG_HEADER_FIELDS = BASECONFIG_SAMPLE_DATA.split(
+    '\n')[0].split(',')
+
+class BaseConfigurationProcessorTests(ConfigurationImportExportSetup):
+
+    layer = FunctionalLayer
+
+    def setUp(self):
+        super(BaseConfigurationProcessorTests, self).setUp()
+        self.processor = ConfigurationContainerProcessor()
+
+    def test_interface(self):
+        # Make sure we fulfill the interface contracts.
+        assert verify.verifyObject(IBatchProcessor, self.processor) is True
+        assert verify.verifyClass(
+            IBatchProcessor, ConfigurationContainerProcessor) is True
+
+    def test_import(self):
+        self.csv_file = os.path.join(
+            self.workdir, 'sample_baseconfig_data.csv')
+        open(self.csv_file, 'wb').write(BASECONFIG_SAMPLE_DATA)
+        num, num_warns, fin_file, fail_file = self.processor.doImport(
+            self.csv_file, BASECONFIG_HEADER_FIELDS,'update')
+        self.assertEqual(num_warns,0)
+        configcontainer = self.processor.getEntry(dict(), self.app)
+        self.assertEqual(configcontainer.frontpage, 'Hello World')
+
+SESSIONCONFIG_SAMPLE_DATA = open(
+    os.path.join(os.path.dirname(__file__), 'sample_sessionconfig_data.csv'),
+    'rb').read()
+
+SESSIONCONFIG_HEADER_FIELDS = SESSIONCONFIG_SAMPLE_DATA.split(
+    '\n')[0].split(',')
+
+class SessionConfigurationProcessorTests(ConfigurationImportExportSetup):
+
+    layer = FunctionalLayer
+
+    def setUp(self):
+        super(SessionConfigurationProcessorTests, self).setUp()
+        self.processor = SessionConfigurationProcessor()
+
+    def test_interface(self):
+        # Make sure we fulfill the interface contracts.
+        assert verify.verifyObject(IBatchProcessor, self.processor) is True
+        assert verify.verifyClass(
+            IBatchProcessor, SessionConfigurationProcessor) is True
+
+    def test_import(self):
+        self.csv_file = os.path.join(
+            self.workdir, 'sample_sessionconfig_data.csv')
+        open(self.csv_file, 'wb').write(SESSIONCONFIG_SAMPLE_DATA)
+        num, num_warns, fin_file, fail_file = self.processor.doImport(
+            self.csv_file, SESSIONCONFIG_HEADER_FIELDS,'create')
+        self.assertEqual(num_warns,0)
+        sessionconfig = self.processor.getEntry({'academic_session':'2017'}, self.app)
+        self.assertEqual(sessionconfig.payment_disabled[0], 'sf_all')
+
+
Index: main/waeup.kofa/trunk/src/waeup/kofa/university/batching.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/university/batching.py	(revision 17784)
+++ main/waeup.kofa/trunk/src/waeup/kofa/university/batching.py	(revision 17787)
@@ -65,6 +65,4 @@
     location_fields = ['code',]
     factory_name = 'waeup.Faculty'
-
-    mode = None
 
     def parentsExist(self, row, site):
@@ -192,6 +190,4 @@
     factory_name = 'waeup.Department'
 
-    mode = None
-
     def parentsExist(self, row, site):
         if not 'faculties' in site.keys():
@@ -244,6 +240,4 @@
     location_fields = ['code']
     factory_name = 'waeup.Certificate'
-
-    mode = None
 
     @property
@@ -328,6 +322,4 @@
     location_fields = ['code']
     factory_name = 'waeup.Course'
-
-    mode = None
 
     def getParent(self, row, site):
@@ -384,6 +376,4 @@
     factory_name = 'waeup.CertificateCourse'
 
-    mode = None
-
     def parentsExist(self, row, site):
         if not 'faculties' in site.keys():
Index: main/waeup.kofa/trunk/src/waeup/kofa/utils/converters.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/utils/converters.py	(revision 17784)
+++ main/waeup.kofa/trunk/src/waeup/kofa/utils/converters.py	(revision 17787)
@@ -242,5 +242,6 @@
         # Omit known dictionaries since there is no widget available
         # for dictionary schema fields
-        self.default_form_fields = form.Fields(iface).omit('description_dict')
+        self.default_form_fields = form.Fields(iface).omit(
+            'description_dict', 'frontpage_dict')
         return
 
