Index: main/waeup.ikoba/trunk/CHANGES.txt
===================================================================
--- main/waeup.ikoba/trunk/CHANGES.txt	(revision 12985)
+++ main/waeup.ikoba/trunk/CHANGES.txt	(revision 12986)
@@ -4,4 +4,7 @@
 0.2dev (unreleased)
 ===================
+
+* Remove quite old bug in `doImport`: Replace empty strings *and* lists with
+  ignore-markers in update *and* create mode.
 
 * Update bootstrap.py and dependent package versions.
Index: main/waeup.ikoba/trunk/layout/static/css/base.css
===================================================================
--- main/waeup.ikoba/trunk/layout/static/css/base.css	(revision 12985)
+++ main/waeup.ikoba/trunk/layout/static/css/base.css	(revision 12986)
@@ -165,5 +165,5 @@
 }
 
-/* Kofa forms */
+/* Ikoba forms */
 
 .form-table {
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/browser/batchprocessing.txt
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/browser/batchprocessing.txt	(revision 12985)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/browser/batchprocessing.txt	(revision 12986)
@@ -205,10 +205,10 @@
     name,roles,title,public_name,phone,email,--ERRORS--
     henrik,"['waeup.PortalManager', 'waeup.ImportManager']",Henrik Bettermann,Admin,+49-234-567,henrik@abc.de,This object already exists. Skipping.
-    anne,['waeup.Nonsense'],Anne Palina,,+49-234-567,anne@abc.de,roles: invalid role
+    anne,['waeup.Nonsense'],Anne Palina,<IGNORE>,+49-234-567,anne@abc.de,roles: invalid role
 
     >>> finished_file = dc_path + '/finished/newusers_zope.mgr.create.finished.csv'
     >>> print open(finished_file).read()
     name,roles,title,public_name,phone,email
-    isouaba,[],Issoufou Abba Moussa,Chief Developer,+49-234-567,isouaba@abc.de
+    isouaba,<IGNORE>,Issoufou Abba Moussa,Chief Developer,+49-234-567,isouaba@abc.de
 
 The finished-file contains the dataset we could import, while the
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_batching.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_batching.py	(revision 12985)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_batching.py	(revision 12986)
@@ -289,7 +289,7 @@
             content,
             'reg_number,password,firstname,lastname,sex,phone,state,date_of_birth,customer_id,email,--ERRORS--\r\n'
-            '1,,Frank,Meyer,m,1234,,1990-01-06,F123456,cc@aa.ng,reg_number: Invalid input\r\n'
-            '3,,Uli,Schulz,m,1234,,1990-01-07,A123456,dd@aa.ng,This object already exists. Skipping.\r\n'
-            '4,,Berta,Pieri,m,1234,,1991-01-07,A234567,aa@aa.ng,email: Invalid input\r\n'
+            '1,<IGNORE>,Frank,Meyer,m,1234,<IGNORE>,1990-01-06,F123456,cc@aa.ng,reg_number: Invalid input\r\n'
+            '3,<IGNORE>,Uli,Schulz,m,1234,<IGNORE>,1990-01-07,A123456,dd@aa.ng,This object already exists. Skipping.\r\n'
+            '4,<IGNORE>,Berta,Pieri,m,1234,<IGNORE>,1991-01-07,A234567,aa@aa.ng,email: Invalid input\r\n'
             )
         shutil.rmtree(os.path.dirname(fin_file))
@@ -504,7 +504,7 @@
         self.assertEqual(fail_file,
             'reg_number,valid_from,contract_id,title,class_name,valid_to,product_object,tc_dict,document_object,product_options,--ERRORS--\r\n'
-            '2,,c5,,SampleContract,,SAM,,DOC1,[],This object already exists. Skipping.\r\n'
-            '3,,c6,,SampleContract,,SAM,,NONEXISTENT,[],document_object: Invalid value\r\n'
-            '3,,c7,,SampleContract,,NONEXISTENT,,DOC1,[],product_object: Invalid value\r\n'
+            '2,<IGNORE>,c5,<IGNORE>,SampleContract,<IGNORE>,SAM,<IGNORE>,DOC1,<IGNORE>,This object already exists. Skipping.\r\n'
+            '3,<IGNORE>,c6,<IGNORE>,SampleContract,<IGNORE>,SAM,<IGNORE>,NONEXISTENT,<IGNORE>,document_object: Invalid value\r\n'
+            '3,<IGNORE>,c7,<IGNORE>,SampleContract,<IGNORE>,NONEXISTENT,<IGNORE>,DOC1,<IGNORE>,product_object: Invalid value\r\n'
             )
         contract = self.processor.getEntry(dict(reg_number='1',
@@ -529,6 +529,6 @@
         self.assertTrue(
             'INFO - system - Customer Sample Contract Processor - sample_contract_data - '
-            'X666666 - %s - updated: valid_from=, title=, valid_to=, product_object=SAM, tc_dict=, document_object=DOC1, '
-            'product_options=[]' % conid
+            'X666666 - %s - updated: product_object=SAM, document_object=DOC1'
+            % conid
             in logcontent)
 
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/permissions.txt
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/permissions.txt	(revision 12985)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/permissions.txt	(revision 12986)
@@ -39,8 +39,8 @@
     >>> from waeup.ikoba.permissions import get_waeup_roles
     >>> len(list(get_waeup_roles()))
-    17
+    18
 
     >>> len(list(get_waeup_roles(also_local=True)))
-    21
+    22
 
 
@@ -67,4 +67,5 @@
     u'waeup.ProductsManager',
     u'waeup.ProductsOfficer',
+    u'waeup.ReportsManager',
     u'waeup.UsersManager',
     u'waeup.WorkflowManager',
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/reports.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/reports.py	(revision 12985)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/reports.py	(revision 12986)
@@ -139,8 +139,15 @@
     """
 
-class manageReportsPermission(grok.Permission):
-    """A permission to manage reports.
+class ManageReports(grok.Permission):
+    """The ManageReports permission allows to view, add and remove reports.
     """
     grok.name('waeup.manageReports')
+
+class ReportsManager(grok.Role):
+    """The ReportsManager has the permission to manage reports.
+    """
+    grok.name('waeup.ReportsManager')
+    grok.title(u'Reports Manager')
+    grok.permissions('waeup.manageReports')
 
 def get_generators():
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/utils/batching.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/utils/batching.py	(revision 12985)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/utils/batching.py	(revision 12986)
@@ -320,9 +320,9 @@
                 continue
             string_row = self.applyMapping(raw_row, mapping)
-            if ignore_empty and mode in ('update',):
-                # replace empty strings with ignore-markers
-                for key, val in string_row.items():
-                    if val == '':
-                        string_row[key] = IGNORE_MARKER
+            if ignore_empty:
+                  # Replace empty strings and empty lists with ignore-markers
+                  for key, val in string_row.items():
+                      if val == '' or val == '[]':
+                          string_row[key] = IGNORE_MARKER
             row = dict(string_row.items()) # create deep copy
             errs, inv_errs, conv_dict = self.checkConversion(string_row, mode)
