Index: /main/waeup.kofa/trunk/src/waeup/kofa/students/batching.py
===================================================================
--- /main/waeup.kofa/trunk/src/waeup/kofa/students/batching.py	(revision 8220)
+++ /main/waeup.kofa/trunk/src/waeup/kofa/students/batching.py	(revision 8221)
@@ -59,6 +59,4 @@
     factory_name = 'waeup.Student'
 
-    mode = None
-
     @property
     def available_fields(self):
@@ -154,30 +152,30 @@
         """Update obj to the values given in row.
         """
+        items_changed = ''
+
         # Remove student_id from row if empty
         if row.has_key('student_id') and row['student_id'] is None:
             row.pop('student_id')
-        items_changed = ''
-        for key, value in row.items():
-            # Set student password and all fields declared in interface.
-            if key == 'password' and value != '':
-                IUserAccount(obj).setPassword(value)
-            elif key == 'reg_state':
-                IWorkflowState(obj).setState(value)
-                msg = _("State '${a}' set", mapping = {'a':value})
-                history = IObjectHistory(obj)
-                history.addMessage(msg)
-            elif hasattr(obj, key):
-                # Set attribute to None if value is marked for deletion
-                #if value == DELETION_MARKER:
-                #    setattr(obj, key, None)
-                #elif value is not None:
-                #    setattr(obj, key, value)
-                #else:
-                #    # No change, no change log
-                #    continue
-                if value != '<IGNORE>':
-                    setattr(obj, key, value)
-                
-                    items_changed += '%s=%s, ' % (key,value)
+
+        # Update password
+        passwd = row.get('password', '')
+        if passwd:
+            IUserAccount(obj).setPassword(passwd)
+            row.pop('password')
+
+        # Update registration state
+        if 'reg_state' in row.keys():
+            value = row['reg_state']
+            IWorkflowState(obj).setState(value)
+            msg = _("State '${a}' set", mapping = {'a':value})
+            history = IObjectHistory(obj)
+            history.addMessage(msg)
+            row.pop('reg_state')
+
+        # apply other values...
+        items_changed = super(StudentProcessor, self).updateEntry(
+            obj, row, site)
+
+        # Log actions...
         parent = self.getParent(row, site)
         if hasattr(obj,'student_id'):
@@ -189,5 +187,5 @@
             # Create mode: the student does not yet exist
             parent.logger.info('Student data imported: %s' % items_changed)
-        return
+        return items_changed
 
     def getMapping(self, path, headerfields, mode):
@@ -198,6 +196,6 @@
         raw_header = reader.next()
         for num, field in enumerate(headerfields):
-            if field not in [
-                'student_id', 'reg_number', 'matric_number'] and mode == 'remove':
+            if field not in ['student_id', 'reg_number', 'matric_number'
+                             ] and mode == 'remove':
                 continue
             if field == u'--IGNORE--':
@@ -242,6 +240,4 @@
     location_fields = []
 
-    mode = None
-
     @property
     def available_fields(self):
@@ -302,20 +298,6 @@
         """Update obj to the values given in row.
         """
-        items_changed = ''
-        for key, value in row.items():
-            # Skip fields not declared in interface.
-            if hasattr(obj, key):
-                # Set attribute to None if value is marked for deletion
-                setattr(obj, key, value)
-                if key == 'certificate':
-                    value = value.code
-
-                #if value == DELETIONMARKER:
-                #    setattr(obj, key, None)
-                #elif value is not None:
-                #    setattr(obj, key, value)
-                #    if key == 'certificate':
-                #        value = value.code
-                items_changed += '%s=%s, ' % (key,value)
+        items_changed = super(StudentStudyCourseProcessor, self).updateEntry(
+            obj, row, site)
         parent = self.getParent(row, site)
         parent.__parent__.logger.info(
@@ -331,15 +313,10 @@
         converter = IObjectConverter(self.iface)
         errs, inv_errs, conv_dict =  converter.fromStringDict(
-            row, self.factory_name)
+            row, self.factory_name, mode=mode)
         # We have to check if current_level is in range of certificate.
-        # This is not done by the converter. This kind of conversion
-        # checking does only work if a combination of certificate and
-        # current_level is provided.
         if conv_dict.has_key('certificate'):
-          certificate = conv_dict['certificate']
-          start_level = certificate.start_level
-          end_level = certificate.end_level
-          if conv_dict['current_level'] < start_level or \
-              conv_dict['current_level'] > end_level+120:
+          cert = conv_dict['certificate']
+          if conv_dict['current_level'] < cert.start_level or \
+              conv_dict['current_level'] > cert.end_level+120:
               errs.append(('current_level','not in range'))
         return errs, inv_errs, conv_dict
@@ -360,6 +337,4 @@
     location_fields = []
 
-    mode = None
-
     @property
     def available_fields(self):
@@ -431,5 +406,5 @@
         converter = IObjectConverter(self.iface)
         errs, inv_errs, conv_dict =  converter.fromStringDict(
-            row, self.factory_name)
+            row, self.factory_name, mode=mode)
         # We have to check if level is a valid integer.
         # This is not done by the converter.
@@ -457,11 +432,9 @@
     location_fields = []
 
-    mode = None
-
     @property
     def available_fields(self):
         return sorted(list(set(
-            ['student_id','reg_number','matric_number','level','code'] + getFields(
-                self.iface).keys())))
+            ['student_id','reg_number','matric_number','level',
+             'code'] + getFields(self.iface).keys())))
 
     def checkHeaders(self, headerfields, mode='ignore'):
@@ -538,5 +511,5 @@
         converter = IObjectConverter(self.iface)
         errs, inv_errs, conv_dict =  converter.fromStringDict(
-            row, self.factory_name)
+            row, self.factory_name, mode=mode)
         # We have to check if course really exists.
         # This is not done by the converter.
@@ -562,6 +535,4 @@
 
     location_fields = []
-
-    mode = None
 
     @property
@@ -648,5 +619,5 @@
         converter = IObjectConverter(self.iface)
         errs, inv_errs, conv_dict =  converter.fromStringDict(
-            row, self.factory_name)
+            row, self.factory_name, mode=mode)
         # We have to check p_id.
         p_id = row['p_id'].strip('#')
@@ -699,17 +670,9 @@
         """Update obj to the values given in row.
         """
-        items_changed = ''
-        for key, value in row.items():
-            # Skip fields not declared in interface plus
-            # current_session and current_level
-            if hasattr(obj, key) and not key in [
-                'current_session','current_level']:
-                setattr(obj, key, value)
-                # Set attribute to None if value is marked for deletion
-                #if value == DELETIONMARKER:
-                #    setattr(obj, key, None)
-                #elif value is not None:
-                #    setattr(obj, key, value)
-                items_changed += '%s=%s, ' % (key,value)
+        # Don't set current_session, current_level
+        vals_to_set = dict((key, val) for key, val in row.items()
+                           if key not in ('current_session','current_level'))
+        items_changed = super(StudentVerdictProcessor, self).updateEntry(
+            obj, vals_to_set, site)
         parent = self.getParent(row, site)
         parent.__parent__.logger.info(
@@ -727,4 +690,4 @@
         converter = IObjectConverter(self.iface)
         errs, inv_errs, conv_dict =  converter.fromStringDict(
-            row, self.factory_name)
+            row, self.factory_name, mode=mode)
         return errs, inv_errs, conv_dict
