Index: main/waeup.ikoba/trunk/src/waeup/ikoba/customers/interfaces.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/customers/interfaces.py	(revision 12259)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/customers/interfaces.py	(revision 12260)
@@ -23,5 +23,5 @@
 from waeup.ikoba.interfaces import MessageFactory as _
 from waeup.ikoba.interfaces import (
-    IIkobaObject, validate_email, ICSVExporter)
+    IIkobaObject, validate_email, ICSVExporter, validate_uuid)
 from waeup.ikoba.schema import TextLineChoice, FormattedDate, PhoneNumber
 from waeup.ikoba.browser.interfaces import ICustomerNavigationBase
@@ -128,4 +128,5 @@
         constraint=validate_email,
         )
+
     phone = PhoneNumber(
         title = _(u'Phone'),
@@ -243,6 +244,12 @@
     is_editable_by_manager = Attribute('Document editable by manager')
 
-
-class ICustomerPDFDocument(IDocument):
+    document_id = schema.TextLine(
+        title = _(u'Document Id'),
+        required = False,
+        constraint=validate_uuid,
+        )
+
+
+class ICustomerPDFDocument(ICustomerDocument):
     """A customer document.
 
@@ -282,4 +289,5 @@
         title = _(u'Contract Id'),
         required = False,
+        constraint=validate_uuid,
         )
 
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 12259)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_batching.py	(revision 12260)
@@ -337,7 +337,7 @@
             dict(document_id='DOC', class_name='CustomerSampleDocument'))
         self.assertEqual(len(errs),0)
-        #errs, inv_errs, conv_dict = self.processor.checkConversion(
-        #    dict(document_id='id with spaces', class_name='CustomerSampleDocument'))
-        #self.assertEqual(len(errs),1)
+        errs, inv_errs, conv_dict = self.processor.checkConversion(
+            dict(document_id='id with spaces', class_name='CustomerSampleDocument'))
+        self.assertEqual(len(errs),1)
         errs, inv_errs, conv_dict = self.processor.checkConversion(
             dict(document_id='DOC', class_name='WrongDocument'))
@@ -468,7 +468,7 @@
                  document_object='DOC1', product_object='SAM'))
         self.assertEqual(len(errs),0)
-        #errs, inv_errs, conv_dict = self.processor.checkConversion(
-        #    dict(contract_id='id with spaces', class_name='SampleContract'))
-        #self.assertEqual(len(errs),1)
+        errs, inv_errs, conv_dict = self.processor.checkConversion(
+            dict(contract_id='id with spaces', class_name='SampleContract'))
+        self.assertEqual(len(errs),1)
         errs, inv_errs, conv_dict = self.processor.checkConversion(
             dict(contract_id='CON3', class_name='WrongContract'))
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/documents/batching.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/documents/batching.py	(revision 12259)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/documents/batching.py	(revision 12260)
@@ -119,6 +119,4 @@
                 errs.append(('class_name','wrong processor'))
         document_id = row.get('document_id', None)
-        if ' ' in document_id:
-            errs.append(('document_id','must not contain spaces'))
         return errs, inv_errs, conv_dict
 
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/documents/interfaces.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/documents/interfaces.py	(revision 12259)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/documents/interfaces.py	(revision 12260)
@@ -19,5 +19,5 @@
 from zope import schema
 from waeup.ikoba.interfaces import (
-    IIkobaObject,
+    IIkobaObject, validate_id,
     ContextualDictSourceFactoryBase)
 from waeup.ikoba.interfaces import MessageFactory as _
@@ -52,4 +52,5 @@
         title = _(u'Document Id'),
         required = False,
+        constraint=validate_id,
         )
 
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/interfaces.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/interfaces.py	(revision 12259)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/interfaces.py	(revision 12260)
@@ -142,4 +142,23 @@
     return True
 
+# Define a validation method for email addresses
+class NotIdValue(schema.ValidationError):
+    __doc__ = u"Invalid id"
+
+#: Regular expressions to check id formats.
+check_id = re.compile(r"^[a-zA-Z0-9_-]{2,6}$").match
+check_uuid = re.compile( r"^[a-zA-Z0-9]{32}$").match
+
+def validate_id(value):
+    if not check_id(value):
+        raise NotIdValue(value)
+    return True
+
+def validate_uuid(value):
+    # We are using also short ids in tests
+    if not check_uuid(value) and not check_id(value):
+        raise NotIdValue(value)
+    return True
+
 # Define a validation method for international phone numbers
 class InvalidPhoneNumber(schema.ValidationError):
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/tests/test_interfaces.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/tests/test_interfaces.py	(revision 12259)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/tests/test_interfaces.py	(revision 12260)
@@ -21,5 +21,6 @@
 import grok
 import unittest
-from waeup.ikoba.interfaces import DuplicationError, RoleSource, check_email
+from waeup.ikoba.interfaces import (
+    DuplicationError, RoleSource, check_email, check_id, check_uuid)
 from waeup.ikoba.testing import FunctionalLayer, FunctionalTestCase
 
@@ -61,4 +62,21 @@
         self.assertTrue(check_email('bob@foo,alice@bar') is None)
         return
+
+    def test_check_id(self):
+        self.assertTrue(check_id('abcABC') is not None)
+        # No spaces
+        self.assertTrue(check_id('abc ABC') is None)
+        # More than 6 characters are not allowed
+        self.assertTrue(check_id('abcdefg') is None)
+        # Only underscores and hyphens are allowed
+        self.assertTrue(check_id('a+b') is None)
+        self.assertTrue(check_id('a/b') is None)
+        self.assertTrue(check_id('a-b') is not None)
+        self.assertTrue(check_id('a_b') is not None)
+        # 32 charachters are allowed
+        self.assertTrue(
+            check_uuid('dfceb5c587364faf95e17b3cbaf98d5f') is not None)
+        return
+
 
 class DuplicationErrorTests(unittest.TestCase):
