Index: main/waeup.ikoba/trunk/src/waeup/ikoba/customers/export.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/customers/export.py	(revision 12142)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/customers/export.py	(revision 12143)
@@ -27,5 +27,6 @@
 from waeup.ikoba.customers.catalog import CustomersQuery
 from waeup.ikoba.customers.interfaces import (
-    ICustomer, ICSVCustomerExporter, ICustomerDocument)
+    ICustomer, ICSVCustomerExporter, ICustomerDocument,
+    ISampleContract)
 from waeup.ikoba.utils.batching import ExporterBase
 from waeup.ikoba.utils.helpers import iface_names, to_timezone
@@ -50,4 +51,12 @@
     return documents
 
+def get_contracts(customers):
+    """Get all contracts of `customers`.
+    """
+    contracts = []
+    for customer in customers:
+        for contract in customer.get('contracts', {}).values():
+            contracts.append(contract)
+    return contracts
 
 class CustomerExporterBase(ExporterBase):
@@ -137,4 +146,5 @@
             value, name, context=context)
 
+
 class CustomerDocumentExporter(grok.GlobalUtility, CustomerExporterBase):
     """Exporter for CustomerDocument instances.
@@ -159,6 +169,5 @@
 
     def mangle_value(self, value, name, context=None):
-        """Treat location values special.
-        """
+
         if name == 'history':
             value = value.messages
@@ -166,2 +175,38 @@
             CustomerDocumentExporter, self).mangle_value(
             value, name, context=context)
+
+
+class ContractExporter(grok.GlobalUtility, CustomerExporterBase):
+    """Exporter for Contract instances.
+    """
+    grok.name('contracts')
+
+    #: Fieldnames considered by this exporter
+    fields = tuple(
+        sorted(iface_names(
+            ISampleContract,
+            exclude_attribs=False,
+            omit=['translated_state',
+                  'formatted_transition_date',
+                  'translated_class_name'])))
+
+    #: The title under which this exporter will be displayed
+    title = _(u'Contracts')
+
+    def filter_func(self, x, **kw):
+        return get_contracts(x, **kw)
+
+    def mangle_value(self, value, name, context=None):
+
+        if name == 'history':
+            value = value.messages
+        if name.endswith('_object'):
+            mangled_value = getattr(value, 'document_id', None)
+            if mangled_value:
+                return mangled_value
+            mangled_value = getattr(value, 'product_id', None)
+            if mangled_value:
+                return mangled_value
+        return super(
+            ContractExporter, self).mangle_value(
+            value, name, context=context)
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/customers/interfaces.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/customers/interfaces.py	(revision 12142)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/customers/interfaces.py	(revision 12143)
@@ -276,4 +276,6 @@
     last_product_id = Attribute(
         'Id of product recently stored with the contract')
+    is_editable = Attribute('Document editable by customer')
+    translated_class_name = Attribute('Translatable class name')
 
     title = schema.TextLine(
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 12142)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_batching.py	(revision 12143)
@@ -138,4 +138,6 @@
         contract = createObject('waeup.SampleContract')
         contract.title = u'My Contract'
+        contract.product_object = self.product
+        contract.document_object = self.document
         customer['contracts'].addContract(contract)
         self.contract = contract
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_export.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_export.py	(revision 12142)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_export.py	(revision 12143)
@@ -31,8 +31,10 @@
 from waeup.ikoba.customers.catalog import CustomersQuery
 from waeup.ikoba.customers.export import (
-    CustomerExporter, CustomerDocumentExporter, get_customers)
+    CustomerExporter, CustomerDocumentExporter, ContractExporter,
+    get_customers)
 from waeup.ikoba.customers.interfaces import ICSVCustomerExporter
 from waeup.ikoba.customers.customer import Customer
 from waeup.ikoba.customers.documents import CustomerSampleDocument
+from waeup.ikoba.customers.contracts import SampleContract
 from waeup.ikoba.customers.tests.test_batching import CustomerImportExportSetup
 from waeup.ikoba.testing import FunctionalLayer
@@ -88,11 +90,11 @@
         exporter.export([self.customer], self.outfile)
         result = open(self.outfile, 'rb').read()
-        self.assertTrue(
-            'customer_id,email,firstname,lastname,middlename,phone,'
-            'reg_number,sex,suspended,suspended_comment,password,state,'
-            'history\r\n'
-            'A111111,anna@sample.com,Anna,Tester,M.,+234-123-12345#,'
-            '123,,0,,,created'
-            in result
+        self.assertMatches(
+            'customer_id,email,firstname,lastname,middlename,phone,reg_number,'
+            'sex,suspended,suspended_comment,password,state,history\r\n'
+            'A111111,anna@sample.com,Anna,Tester,M.,+234-123-12345#,123,,0,,,'
+            'created,[u\'2014-12-04 11:25:35 UTC - Customer record created '
+            'by system\']\r\n',
+            result
             )
         return
@@ -202,5 +204,5 @@
         return
 
-    def test_export_customer(self):
+    def test_export_customer_document(self):
         # we can really export all documents of a certain customer
         # set values we can expect in export file
@@ -219,2 +221,99 @@
             )
         return
+
+
+class ContractExporterTest(CustomerImportExportSetup):
+
+    layer = FunctionalLayer
+
+    def setUp(self):
+        super(ContractExporterTest, self).setUp()
+        self.setup_for_export()
+        return
+
+    def test_ifaces(self):
+        # make sure we fullfill interface contracts
+        obj = ContractExporter()
+        verifyObject(ICSVCustomerExporter, obj)
+        verifyClass(ICSVCustomerExporter, ContractExporter)
+        return
+
+    def test_get_as_utility(self):
+        # we can get a contracts exporter as utility
+        result = queryUtility(ICSVExporter, name="contracts")
+        self.assertTrue(result is not None)
+        return
+
+    def test_export_empty(self):
+        # we can export a nearly empty contract
+        contract = SampleContract()
+        exporter = ContractExporter()
+        exporter.export([contract], self.outfile)
+        result = open(self.outfile, 'rb').read()
+        self.assertEqual(
+            result,
+            'class_name,contract_category,contract_id,document_object,'
+            'history,is_editable,last_product_id,last_transition_date,'
+            'product_object,state,title\r\n'
+
+            'SampleContract,sample,c101,,[],1,,,,,\r\n'
+            )
+        return
+
+    def test_export(self):
+        # we can really export customer contracts.
+        # set values we can expect in export file
+        self.setup_customer(self.customer)
+        exporter = ContractExporter()
+        exporter.export([self.contract], self.outfile)
+        result = open(self.outfile, 'rb').read()
+        self.assertMatches(
+            'class_name,contract_category,contract_id,document_object,'
+            'history,is_editable,last_product_id,last_transition_date,'
+            'product_object,state,title\r\n'
+
+            'SampleContract,sample,c101,d101,[u\'2014-12-04 12:10:46 UTC - '
+            'Contract record created by system\'],0,,'
+            '2014-12-04 12:10:46.333445#,SAM,created,My Contract\r\n',
+            result
+            )
+        return
+
+    def test_export_all(self):
+        # we can really export all contracts
+        # set values we can expect in export file
+        self.setup_customer(self.customer)
+        exporter = ContractExporter()
+        exporter.export_all(self.app, self.outfile)
+        result = open(self.outfile, 'rb').read()
+        self.assertMatches(
+            'class_name,contract_category,contract_id,document_object,'
+            'history,is_editable,last_product_id,last_transition_date,'
+            'product_object,state,title\r\n'
+
+            'SampleContract,sample,c101,d101,[u\'2014-12-04 12:10:46 UTC - '
+            'Contract record created by system\'],0,,'
+            '2014-12-04 12:10:46.333445#,SAM,created,My Contract\r\n',
+            result
+            )
+        return
+
+    def test_export_contract(self):
+        # we can really export all contracts of a certain customer
+        # set values we can expect in export file
+        self.setup_customer(self.customer)
+        exporter = ContractExporter()
+        exporter.export_customer(self.customer, self.outfile)
+        result = open(self.outfile, 'rb').read()
+        self.assertMatches(
+            'class_name,contract_category,contract_id,document_object,'
+            'history,is_editable,last_product_id,last_transition_date,'
+            'product_object,state,title\r\n'
+
+            'SampleContract,sample,c101,d101,[u\'2014-12-04 12:10:46 UTC - '
+            'Contract record created by system\'],0,,'
+            '2014-12-04 12:10:46.333445#,SAM,created,My Contract\r\n',
+            result
+            )
+        return
+
