Index: main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/customers/contracts.py
===================================================================
--- main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/customers/contracts.py	(revision 12726)
+++ main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/customers/contracts.py	(revision 12727)
@@ -33,5 +33,5 @@
     IContractSelectProduct, ICustomersUtils, ISampleContract,
     ISampleContractProcess, ISampleContractEdit, ISampleContractOfficialUse)
-from waeup.ikoba.payments.interfaces import IPayer, IPayableFinder
+from waeup.ikoba.payments.interfaces import IPayer, IPayableFinder, IPayable
 from waeup.ikoba.payments.payment import PaymentItem
 from waeup.ikoba.utils.helpers import attrs_to_fields
@@ -276,2 +276,43 @@
         # there should not be more than one result really.
         return result[0]
+
+
+class PayableContract(grok.Adapter):
+    """Adapter to adapt IContracts to IPayable.
+    """
+
+    grok.context(IContract)
+    grok.implements(IPayable)
+
+    def __init__(self, context):
+        self.context = context
+        currencies = set([x.currency for x in context.product_options])
+        if len(currencies) > 1:
+            raise ValueError(
+                "Only contracts with same currency for all options allowed.")
+        return
+
+    @property
+    def payable_id(self):
+        return self.context.contract_id
+
+    @property
+    def title(self):
+        return self.context.title
+
+    @property
+    def currency(self):
+        if not len(self.context.product_options):
+            return None
+        return self.context.product_options[0].currency
+
+    @property
+    def payment_items(self):
+        result = []
+        for num, option in enumerate(self.context.product_options):
+            item = PaymentItem()
+            item.item_id = u'%s' % num
+            item.title = option.title
+            item.amount = option.fee
+            result.append(item)
+        return tuple(result)
Index: main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/customers/tests/test_contract.py
===================================================================
--- main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/customers/tests/test_contract.py	(revision 12726)
+++ main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/customers/tests/test_contract.py	(revision 12727)
@@ -29,10 +29,10 @@
 from waeup.ikoba.customers.contracts import (
     ContractsContainer, SampleContract, payment_items_from_contract,
-    ContractPayer, ContractFinder
+    ContractPayer, ContractFinder, PayableContract,
     )
 from waeup.ikoba.app import Company
 from waeup.ikoba.customers.customer import Customer
 from waeup.ikoba.payments.interfaces import (
-    IPaymentItem, IPayer, IPayableFinder,
+    IPaymentItem, IPayer, IPayableFinder, IPayable,
     )
 from waeup.ikoba.products.productoptions import ProductOption
@@ -187,2 +187,69 @@
         result = finder.get_payable_by_id('CON1234')
         self.assertTrue(result is None)
+
+
+class TestContractAsPayable(FunctionalTestCase):
+
+    layer = FunctionalLayer
+
+    def test_adaptable(self):
+        # we can turn contracts into payables.
+        contract = SampleContract()
+        payable = IPayable(contract)
+        self.assertTrue(payable is not None)
+        self.assertTrue(isinstance(payable, PayableContract))
+
+    def test_payable_iface(self):
+        # PayableContracts really provide IPayable
+        contract = SampleContract()
+        option1 = ProductOption(u"Fee 1", decimal.Decimal("31.10"), "USD")
+        option2 = ProductOption(u"Fee 2", decimal.Decimal("12.12"), "USD")
+        contract.product_options = [option1, option2]
+        payable = PayableContract(contract)
+        verifyObject(IPayable, payable)
+        verifyClass(IPayable, PayableContract)
+
+    def test_payable_simple_attributes(self):
+        # the simple attribs are set correctly, according to context contract
+        contract = SampleContract()
+        contract.title = u'the title'
+        option1 = ProductOption(u"Fee 1", decimal.Decimal("31.10"), "EUR")
+        option2 = ProductOption(u"Fee 2", decimal.Decimal("12.12"), "EUR")
+        contract.product_options = [option1, option2]
+        payable = PayableContract(contract)
+        self.assertTrue(contract.contract_id, payable.payable_id)
+        self.assertEqual(payable.title, contract.title)
+        self.assertEqual(payable.currency, 'EUR')
+
+    def test_payable_items(self):
+        # we can get payment items from payable
+        contract = SampleContract()
+        option1 = ProductOption(u"Fee 1", decimal.Decimal("31.10"), "EUR")
+        option2 = ProductOption(u"Fee 2", decimal.Decimal("12.12"), "EUR")
+        contract.product_options = [option1, option2]
+        payable = PayableContract(contract)
+        items = payable.payment_items
+        self.assertTrue(isinstance(items, tuple))
+        self.assertEqual(len(items), 2)
+        verifyObject(IPaymentItem, items[0])
+        verifyObject(IPaymentItem, items[1])
+        self.assertEqual(items[0].item_id, '0')
+        self.assertEqual(items[0].title, u'Fee 1')
+        self.assertEqual(items[0].amount, decimal.Decimal("31.10"))
+
+    def test_payable_no_items(self):
+        # payables work also with no options set on contract
+        contract = SampleContract()
+        payable = PayableContract(contract)
+        items = payable.payment_items
+        self.assertTrue(isinstance(items, tuple))
+        self.assertEqual(len(items), 0)
+        self.assertEqual(payable.currency, None)
+
+    def test_different_currencies_forbiddedn(self):
+        # we do not accept different currencies in payment items
+        contract = SampleContract()
+        option1 = ProductOption(u"Fee 1", decimal.Decimal("31.10"), "EUR")
+        option2 = ProductOption(u"Fee 2", decimal.Decimal("12.12"), "USD")
+        contract.product_options = [option1, option2]
+        self.assertRaises(ValueError, PayableContract, contract)
