Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/app.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/app.py	(revision 12096)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/app.py	(revision 12097)
@@ -76,12 +76,12 @@
 
     @property
-    def unique_application_id(self):
-        """A unique application id for all application objects in customers.
+    def unique_contract_id(self):
+        """A unique contract id for all contract objects in customers.
 
-        The application id returned is guaranteed to be unique.
+        The contract id returned is guaranteed to be unique.
 
-        Once a application id was issued, it won't be issued again.
+        Once a contract id was issued, it won't be issued again.
 
-        Obtaining an application id is currently not thread-safe but can be
+        Obtaining an contract id is currently not thread-safe but can be
         made easily by enabling commented lines.
         """
Index: in/waeup.ikoba/trunk/src/waeup/ikoba/customers/applications.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/applications.py	(revision 12096)
+++ 	(revision )
@@ -1,171 +1,0 @@
-## $Id$
-##
-## Copyright (C) 2014 Uli Fouquet & Henrik Bettermann
-## This program is free software; you can redistribute it and/or modify
-## it under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 2 of the License, or
-## (at your option) any later version.
-##
-## This program is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-## GNU General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with this program; if not, write to the Free Software
-## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-##
-"""
-Customer application components.
-"""
-import os
-import grok
-from zope.component import queryUtility, getUtility
-from zope.component.interfaces import IFactory
-from zope.interface import implementedBy
-from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState
-from waeup.ikoba.interfaces import MessageFactory as _
-from waeup.ikoba.interfaces import IIkobaUtils, IObjectHistory
-from waeup.ikoba.customers.interfaces import (
-    IApplicationsContainer, ICustomerNavigation,
-    IApplication, IApplicationEdit, ICustomersUtils,
-    )
-from waeup.ikoba.customers.utils import generate_application_id
-from waeup.ikoba.utils.helpers import attrs_to_fields
-
-class ApplicationsContainer(grok.Container):
-    """This is a container for customer applications.
-    """
-    grok.implements(IApplicationsContainer, ICustomerNavigation)
-    grok.provides(IApplicationsContainer)
-
-    def addApplication(self, application):
-        if not IApplication.providedBy(application):
-            raise TypeError(
-                'ApplicationsContainers contain only IApplication instances')
-        self[application.application_id] = application
-        return
-
-    @property
-    def customer(self):
-        return self.__parent__
-
-    def writeLogMessage(self, view, message):
-        return self.__parent__.writeLogMessage(view, message)
-
-ApplicationsContainer = attrs_to_fields(ApplicationsContainer)
-
-class ApplicationBase(grok.Container):
-    """This is a customer application baseclass.
-    """
-    grok.implements(IApplication, IApplicationEdit, ICustomerNavigation)
-    grok.provides(IApplication)
-    grok.baseclass()
-
-    application_category = None
-
-    def __init__(self):
-        super(ApplicationBase, self).__init__()
-        # The site doesn't exist in unit tests
-        try:
-            self.application_id = generate_application_id()
-        except AttributeError:
-            self.application_id = u'a123'
-        self.last_product_id = None
-        return
-
-    @property
-    def history(self):
-        history = IObjectHistory(self)
-        return history
-
-    @property
-    def state(self):
-        return IWorkflowState(self).getState()
-
-    @property
-    def translated_state(self):
-        try:
-            TRANSLATED_STATES = getUtility(
-                ICustomersUtils).TRANSLATED_APPLICATION_STATES
-            return TRANSLATED_STATES[self.state]
-        except KeyError:
-            return
-
-    @property
-    def class_name(self):
-        return self.__class__.__name__
-
-    @property
-    def formatted_transition_date(self):
-        try:
-            return self.last_transition_date.strftime('%Y-%m-%d %H:%M:%S')
-        except AttributeError:
-            return
-
-    @property
-    def customer(self):
-        try:
-            return self.__parent__.__parent__
-        except AttributeError:
-            return None
-
-    def writeLogMessage(self, view, message):
-        return self.__parent__.__parent__.writeLogMessage(view, message)
-
-    @property
-    def is_editable(self):
-        try:
-            # Customer must be approved
-            cond1 = self.customer.state in getUtility(
-                ICustomersUtils).APPMANAGE_CUSTOMER_STATES
-            # Application must be in state created
-            cond2 = self.state in getUtility(
-                ICustomersUtils).APPMANAGE_APPLICATION_STATES
-            if not (cond1 and cond2):
-                return False
-        except AttributeError:
-            pass
-        return True
-
-    @property
-    def translated_class_name(self):
-        try:
-            APPTYPES_DICT = getUtility(ICustomersUtils).APPTYPES_DICT
-            return APPTYPES_DICT[self.class_name]
-        except KeyError:
-            return
-
-
-class SampleApplication(ApplicationBase):
-    """This is a sample application.
-    """
-
-    application_category = 'sample'
-
-SampleApplication = attrs_to_fields(SampleApplication)
-
-
-# Applications must be importable. So we might need a factory.
-class SampleApplicationFactory(grok.GlobalUtility):
-    """A factory for applications.
-    """
-    grok.implements(IFactory)
-    grok.name(u'waeup.SampleApplication')
-    title = u"Create a new application.",
-    description = u"This factory instantiates new sample application instances."
-
-    def __call__(self, *args, **kw):
-        return SampleApplication(*args, **kw)
-
-    def getInterfaces(self):
-        return implementedBy(SampleApplication)
-
-@grok.subscribe(IApplication, grok.IObjectAddedEvent)
-def handle_application_added(application, event):
-    """If an application is added the transition create is fired.
-    The latter produces a logging message.
-    """
-    if IWorkflowState(application).getState() is None:
-        IWorkflowInfo(application).fireTransition('create')
-    return
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/batching.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/batching.py	(revision 12096)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/batching.py	(revision 12097)
@@ -43,8 +43,8 @@
 from waeup.ikoba.customers.interfaces import (
     ICustomer, ICustomerUpdateByRegNo,
-    ICustomerDocument, IApplication)
+    ICustomerDocument, IContract)
 from waeup.ikoba.customers.workflow import  (
     IMPORTABLE_REGISTRATION_STATES, IMPORTABLE_REGISTRATION_TRANSITIONS,
-    IMPORTABLE_APPLICATION_STATES, IMPORTABLE_APPLICATION_TRANSITIONS)
+    IMPORTABLE_CONTRACT_STATES, IMPORTABLE_CONTRACT_TRANSITIONS)
 from waeup.ikoba.utils.batching import BatchProcessor
 
@@ -463,26 +463,26 @@
 
 
-class ApplicationProcessor(CustomerProcessorBase):
-    """A batch processor for IApplication objects.
+class ContractProcessor(CustomerProcessorBase):
+    """A batch processor for IContract objects.
     """
     grok.implements(IBatchProcessor)
     grok.provides(IBatchProcessor)
     grok.context(Interface)
-    util_name = 'applicationprocessor'
+    util_name = 'contractprocessor'
     grok.name(util_name)
 
-    name = _('Application Processor')
-    iface = IApplication
-    factory_name = 'waeup.SampleApplication'
+    name = _('Contract Processor')
+    iface = IContract
+    factory_name = 'waeup.SampleContract'
 
     location_fields = []
-    additional_fields = ['application_id', 'class_name']
+    additional_fields = ['contract_id', 'class_name']
     additional_headers = ['class_name']
 
     def checkHeaders(self, headerfields, mode='ignore'):
-        super(ApplicationProcessor, self).checkHeaders(headerfields)
-        if mode in ('update', 'remove') and not 'application_id' in headerfields:
-            raise FatalCSVError(
-                "Need application_id for import in update and remove modes!")
+        super(ContractProcessor, self).checkHeaders(headerfields)
+        if mode in ('update', 'remove') and not 'contract_id' in headerfields:
+            raise FatalCSVError(
+                "Need contract_id for import in update and remove modes!")
         return True
 
@@ -491,14 +491,14 @@
         if customer is None:
             return None
-        return customer['applications']
+        return customer['contracts']
 
     def getEntry(self, row, site):
-        applications = self.getParent(row, site)
-        if applications is None:
-            return None
-        application_id = row.get('application_id', None)
-        if application_id is None:
-            return None
-        entry = applications.get(application_id)
+        contracts = self.getParent(row, site)
+        if contracts is None:
+            return None
+        contract_id = row.get('contract_id', None)
+        if contract_id is None:
+            return None
+        entry = contracts.get(contract_id)
         return entry
 
@@ -506,5 +506,5 @@
         """Update obj to the values given in row.
         """
-        items_changed = super(ApplicationProcessor, self).updateEntry(
+        items_changed = super(ContractProcessor, self).updateEntry(
             obj, row, site, filename)
         customer = self.getParent(row, site).__parent__
@@ -516,16 +516,16 @@
     def addEntry(self, obj, row, site):
         parent = self.getParent(row, site)
-        application_id = row['application_id'].strip('#')
-        parent[application_id] = obj
+        contract_id = row['contract_id'].strip('#')
+        parent[contract_id] = obj
         return
 
     def delEntry(self, row, site):
-        application = self.getEntry(row, site)
+        contract = self.getEntry(row, site)
         parent = self.getParent(row, site)
-        if application is not None:
+        if contract is not None:
             customer = self._getCustomer(row, site)
-            customer.__parent__.logger.info('%s - Application removed: %s'
-                % (customer.customer_id, application.application_id))
-            del parent[application.application_id]
+            customer.__parent__.logger.info('%s - Contract removed: %s'
+                % (customer.customer_id, contract.contract_id))
+            del parent[contract.contract_id]
         return
 
@@ -534,5 +534,5 @@
         """
         errs, inv_errs, conv_dict = super(
-            ApplicationProcessor, self).checkConversion(row, mode=mode)
+            ContractProcessor, self).checkConversion(row, mode=mode)
         # We need to check if the class_name corresponds with the
         # processor chosen. This is to avoid accidentally wrong imports.
@@ -541,19 +541,19 @@
             if class_name != self.factory_name.strip('waeup.'):
                 errs.append(('class_name','wrong processor'))
-        # We have to check application_id.
-        application_id = row.get('application_id', None)
+        # We have to check contract_id.
+        contract_id = row.get('contract_id', None)
         if mode == 'create':
-            if not application_id:
-                application_id = generate_application_id()
-                conv_dict['application_id'] = application_id
+            if not contract_id:
+                contract_id = generate_contract_id()
+                conv_dict['contract_id'] = contract_id
                 return errs, inv_errs, conv_dict
-            cat = queryUtility(ICatalog, name='applications_catalog')
+            cat = queryUtility(ICatalog, name='contracts_catalog')
             results = list(
-                cat.searchResults(application_id=(application_id, application_id)))
+                cat.searchResults(contract_id=(contract_id, contract_id)))
             if results:
-                # application_id must not exist.
-                errs.append(('application_id','id exists'))
+                # contract_id must not exist.
+                errs.append(('contract_id','id exists'))
         else:
-            if not application_id.startswith('a'):
-                errs.append(('application_id','invalid format'))
+            if not contract_id.startswith('a'):
+                errs.append(('contract_id','invalid format'))
         return errs, inv_errs, conv_dict
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser.py	(revision 12096)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser.py	(revision 12097)
@@ -51,5 +51,5 @@
     ICustomer, ICustomersContainer, ICustomerRequestPW, ICustomersUtils,
     ICustomerDocument, ICustomerDocumentsContainer, ICustomerCreate,
-    ICustomerPDFDocument, IApplicationsContainer, IApplication, IApplicationEdit
+    ICustomerPDFDocument, IContractsContainer, IContract, IContractEdit
     )
 from waeup.ikoba.customers.catalog import search
@@ -1029,60 +1029,60 @@
             omit_fields=self.omit_fields)
 
-# Pages for customer applications
-
-class ApplicationsBreadcrumb(Breadcrumb):
-    """A breadcrumb for the applications container.
-    """
-    grok.context(IApplicationsContainer)
-    title = _('Applications')
-
-
-class ApplicationBreadcrumb(Breadcrumb):
+# Pages for customer contracts
+
+class ContractsBreadcrumb(Breadcrumb):
+    """A breadcrumb for the contracts container.
+    """
+    grok.context(IContractsContainer)
+    title = _('Contracts')
+
+
+class ContractBreadcrumb(Breadcrumb):
     """A breadcrumb for the customer container.
     """
-    grok.context(IApplication)
+    grok.context(IContract)
 
     @property
     def title(self):
-        return self.context.application_id
-
-
-class ApplicationsManageFormPage(IkobaEditFormPage):
-    """ Page to manage the customer applications
+        return self.context.contract_id
+
+
+class ContractsManageFormPage(IkobaEditFormPage):
+    """ Page to manage the customer contracts
 
     This manage form page is for both customers and officers.
     """
-    grok.context(IApplicationsContainer)
+    grok.context(IContractsContainer)
     grok.name('index')
     grok.require('waeup.viewCustomer')
-    form_fields = grok.AutoFields(IApplicationsContainer)
-    grok.template('applicationsmanagepage')
-    pnav = 4
-
-    @property
-    def manage_applications_allowed(self):
-        return checkPermission('waeup.editApplications', self.context)
-
-    def unremovable(self, application):
+    form_fields = grok.AutoFields(IContractsContainer)
+    grok.template('contractsmanagepage')
+    pnav = 4
+
+    @property
+    def manage_contracts_allowed(self):
+        return checkPermission('waeup.editContracts', self.context)
+
+    def unremovable(self, contract):
         usertype = getattr(self.request.principal, 'user_type', None)
         if not usertype:
             return False
-        if not self.manage_applications_allowed:
+        if not self.manage_contracts_allowed:
             return True
         return (self.request.principal.user_type == 'customer' and \
-            application.state in (APPROVED, REJECTED, EXPIRED))
-
-    @property
-    def label(self):
-        return _('${a}: Applications',
+            contract.state in (APPROVED, REJECTED, EXPIRED))
+
+    @property
+    def label(self):
+        return _('${a}: Contracts',
             mapping = {'a':self.context.__parent__.display_fullname})
 
-    @jsaction(_('Remove selected applications'))
-    def delApplication(self, **data):
+    @jsaction(_('Remove selected contracts'))
+    def delContract(self, **data):
         form = self.request.form
         if 'val_id' in form:
             child_id = form['val_id']
         else:
-            self.flash(_('No application selected.'), type="warning")
+            self.flash(_('No contract selected.'), type="warning")
             self.redirect(self.url(self.context))
             return
@@ -1091,7 +1091,7 @@
         deleted = []
         for id in child_id:
-            # Customers are not allowed to remove used applications
-            application = self.context.get(id, None)
-            if application is not None and not self.unremovable(application):
+            # Customers are not allowed to remove used contracts
+            contract = self.context.get(id, None)
+            if contract is not None and not self.unremovable(contract):
                 del self.context[id]
                 deleted.append(id)
@@ -1105,13 +1105,13 @@
 
 
-class ApplicationAddFormPage(IkobaAddFormPage):
-    """ Page to add an application
-    """
-    grok.context(IApplicationsContainer)
+class ContractAddFormPage(IkobaAddFormPage):
+    """ Page to add an contract
+    """
+    grok.context(IContractsContainer)
     grok.name('addapp')
-    grok.template('applicationaddform')
-    grok.require('waeup.editApplications')
-    form_fields = grok.AutoFields(IApplication)
-    label = _('Add application')
+    grok.template('contractaddform')
+    grok.require('waeup.editContracts')
+    form_fields = grok.AutoFields(IContract)
+    label = _('Add contract')
     pnav = 4
 
@@ -1121,18 +1121,18 @@
         return sorted(apptypes.items())
 
-    @action(_('Create application'), style='primary')
-    def createApplication(self, **data):
+    @action(_('Create contract'), style='primary')
+    def createContract(self, **data):
         form = self.request.form
         customer = self.context.__parent__
         apptype = form.get('apptype', None)
-        # Here we can create various instances of Application derived
+        # Here we can create various instances of Contract derived
         # classes depending on the apptype parameter given in form.
-        application = createObject('waeup.%s' % apptype)
-        self.context.addApplication(application)
+        contract = createObject('waeup.%s' % apptype)
+        self.context.addContract(contract)
         apptype = getUtility(ICustomersUtils).SELECTABLE_APPTYPES_DICT[apptype]
         self.flash(_('${a} created.',
             mapping = {'a': apptype}))
         self.context.writeLogMessage(
-            self,'added: %s %s' % (apptype, application.application_id))
+            self,'added: %s %s' % (apptype, contract.contract_id))
         self.redirect(self.url(self.context))
         return
@@ -1143,12 +1143,12 @@
 
 
-class ApplicationDisplayFormPage(IkobaDisplayFormPage):
-    """ Page to view a application
-    """
-    grok.context(IApplication)
+class ContractDisplayFormPage(IkobaDisplayFormPage):
+    """ Page to view a contract
+    """
+    grok.context(IContract)
     grok.name('index')
     grok.require('waeup.viewCustomer')
-    grok.template('applicationpage')
-    form_fields = grok.AutoFields(IApplication).omit('last_transition_date')
+    grok.template('contractpage')
+    form_fields = grok.AutoFields(IContract).omit('last_transition_date')
     pnav = 4
 
@@ -1158,12 +1158,12 @@
 
 
-class ApplicationManageFormPage(IkobaEditFormPage):
-    """ Page to edit a application
-    """
-    grok.context(IApplication)
+class ContractManageFormPage(IkobaEditFormPage):
+    """ Page to edit a contract
+    """
+    grok.context(IContract)
     grok.name('manage')
     grok.require('waeup.manageCustomer')
-    grok.template('applicationeditpage')
-    form_fields = grok.AutoFields(IApplication).omit('last_transition_date')
+    grok.template('contracteditpage')
+    form_fields = grok.AutoFields(IContract).omit('last_transition_date')
     pnav = 4
     deletion_warning = _('Are you sure?')
@@ -1179,10 +1179,10 @@
 
 
-class ApplicationEditFormPage(ApplicationManageFormPage):
-    """ Page to edit a application
+class ContractEditFormPage(ContractManageFormPage):
+    """ Page to edit a contract
     """
     grok.name('edit')
     grok.require('waeup.handleCustomer')
-    form_fields = grok.AutoFields(IApplicationEdit).omit('last_transition_date')
+    form_fields = grok.AutoFields(IContractEdit).omit('last_transition_date')
 
     def update(self):
@@ -1190,5 +1190,5 @@
             emit_lock_message(self)
             return
-        return super(ApplicationEditFormPage, self).update()
+        return super(ContractEditFormPage, self).update()
 
     @action(_('Save'), style='primary')
@@ -1206,12 +1206,12 @@
 
 
-class ApplicationTriggerTransitionFormPage(IkobaEditFormPage):
-    """ View to trigger customer application transitions
-    """
-    grok.context(IApplication)
+class ContractTriggerTransitionFormPage(IkobaEditFormPage):
+    """ View to trigger customer contract transitions
+    """
+    grok.context(IContract)
     grok.name('trigtrans')
     grok.require('waeup.triggerTransition')
     grok.template('trigtrans')
-    label = _('Trigger application transition')
+    label = _('Trigger contract transition')
     pnav = 4
 
@@ -1240,9 +1240,9 @@
         return
 
-class PDFApplicationsOverviewPage(UtilityView, grok.View):
+class PDFContractsOverviewPage(UtilityView, grok.View):
     """Deliver an overview slip.
     """
-    grok.context(IApplicationsContainer)
-    grok.name('applications_overview_slip.pdf')
+    grok.context(IContractsContainer)
+    grok.name('contracts_overview_slip.pdf')
     grok.require('waeup.viewCustomer')
     prefix = 'form'
@@ -1256,5 +1256,5 @@
     def label(self):
         portal_language = getUtility(IIkobaUtils).PORTAL_LANGUAGE
-        return translate(_('Applications of'),
+        return translate(_('Contracts of'),
             'waeup.ikoba', target_language=portal_language) \
             + ' %s' % self.context.customer.display_fullname
@@ -1264,5 +1264,5 @@
         portal_language = getUtility(IIkobaUtils).PORTAL_LANGUAGE
         tabletitle = []
-        tabletitle.append(translate(_('Customer Applications'), 'waeup.ikoba',
+        tabletitle.append(translate(_('Customer Contracts'), 'waeup.ikoba',
             target_language=portal_language))
         return tabletitle
@@ -1281,5 +1281,5 @@
             tabledata.append(sorted(
                 [value for value in self.context.values()]))
-            tableheader.append([(Id, 'application_id', 2),
+            tableheader.append([(Id, 'contract_id', 2),
                              (Title, 'title', 6),
                              (Type, 'translated_class_name', 6),
@@ -1298,9 +1298,9 @@
 
 
-class PDFApplicationSlipPage(UtilityView, grok.View):
+class PDFContractSlipPage(UtilityView, grok.View):
     """Deliver pdf file including metadata.
     """
-    grok.context(IApplication)
-    grok.name('application_slip.pdf')
+    grok.context(IContract)
+    grok.name('contract_slip.pdf')
     grok.require('waeup.viewCustomer')
     prefix = 'form'
@@ -1309,5 +1309,5 @@
                    'suspended_comment',)
 
-    #form_fields = grok.AutoFields(ICustomerPDFApplication).omit(
+    #form_fields = grok.AutoFields(ICustomerPDFContract).omit(
     #    'last_transition_date')
     form_fields =()
@@ -1327,5 +1327,5 @@
         customers_utils = getUtility(ICustomersUtils)
         return customers_utils.renderPDF(
-            self, 'application_slip.pdf',
+            self, 'contract_slip.pdf',
             self.context.customer, customerview,
             omit_fields=self.omit_fields)
Index: in/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/applicationaddform.pt
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/applicationaddform.pt	(revision 12096)
+++ 	(revision )
@@ -1,26 +1,0 @@
-<form action="." tal:attributes="action request/URL" method="post"
-      enctype="multipart/form-data" i18n:domain="waeup.ikoba">
-  <table class="form-table">
-    <tbody>
-      <tr>
-        <td class="fieldname">
-          <span i18n:translate="">Application Type</span>:
-        </td>
-        <td>
-          <select id="apptype" name="apptype" size="1"
-                  class="form-control half">
-            <option tal:repeat="item view/selectable_apptypes"
-                    tal:attributes="value python:item[0]">
-              <span tal:replace="python:item[1]">APPTYPE</span>
-            </option>
-          </select>
-        </td>
-      </tr>
-    </tbody>
-  </table>
-  <div tal:condition="view/availableActions">
-    <input tal:repeat="action view/actions"
-           tal:replace="structure action/render"
-           />
-  </div>
-</form>
Index: in/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/applicationeditpage.pt
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/applicationeditpage.pt	(revision 12096)
+++ 	(revision )
@@ -1,41 +1,0 @@
-<form action="." tal:attributes="action request/URL" method="post"
-      i18n:domain="waeup.ikoba" enctype="multipart/form-data">
-
-  <ul class="tabs nav nav-tabs" data-tabs="tabs">
-    <li class="active">
-      <a href="#tab1" data-toggle="tab">
-        <span i18n:translate="">Metadata</span>
-      </a>
-    </li>
-    <li>
-      <a href="#tab2" data-toggle="tab">
-        <span i18n:translate="">Documents</span>
-      </a>
-    </li>
-  </ul>
-  <div class="tab-content">
-    <div id="tab1" class="active tab-pane">
-      <br />
-      <table class="form-table">
-        <tbody>
-          <tal:widgets content="structure provider:widgets" />
-        </tbody>
-      </table>
-
-      <div tal:condition="view/availableActions">
-        <input tal:repeat="action view/actions"
-               tal:replace="structure action/render"
-               />
-      </div>
-    </div>
-
-    <div id="tab2" class="tab-pane">
-      <br />
-      <table class="form-table">
-        <tbody>
-
-        </tbody>
-      </table>
-    </div>
-  </div>
-</form>
Index: in/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/applicationpage.pt
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/applicationpage.pt	(revision 12096)
+++ 	(revision )
@@ -1,24 +1,0 @@
-<div class="wfstatus-sub"  i18n:domain="waeup.ikoba">
-  Application State: <span tal:replace="context/translated_state">
-    APPLICATIONSTATE</span>
-</div>
-
-<div class="workflow">
-  <div tal:repeat="msg context/history/messages">
-    <span tal:replace="msg">MESSAGE</span><br />
-  </div>
-</div>
-
-<table class="form-table" i18n:domain="waeup.ikoba">
-  <tbody>
-    <tr>
-      <td i18n:translate="" class="fieldname">
-        Application Type:
-      </td>
-      <td>
-        <span tal:content="context/translated_class_name">CLASSNAME</span>
-      </td>
-    </tr>
-    <tal:widgets content="structure provider:widgets" />
-  </tbody>
-</table>
Index: in/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/applicationsmanagepage.pt
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/applicationsmanagepage.pt	(revision 12096)
+++ 	(revision )
@@ -1,51 +1,0 @@
-<form action="." tal:attributes="action request/URL" method="POST"
-      i18n:domain="waeup.ikoba" enctype="multipart/form-data">
-
-  <table class="ikoba-data-table dataTableManage">
-    <thead>
-    <tr>
-      <th>&nbsp;</th>
-      <th i18n:translate="">Id</th>
-      <th i18n:translate="">Title</th>
-      <th i18n:translate="">Type</th>
-      <th i18n:translate="">State</th>
-      <th i18n:translate="">Last Transition</th>
-    </tr>
-    </thead>
-    <tbody>
-      <tr tal:repeat="cl context/values">
-         <td>
-          <input type="checkbox"
-    		 name="val_id"
-    		 tal:attributes="value cl/__name__"
-         tal:condition="python: not view.unremovable(cl)" />
-        </td>
-        <td>
-          <a tal:attributes="href python: view.url(cl)">
-          <span tal:content="cl/application_id">APPID</span></a>
-        </td>
-        <td>
-          <span tal:content="cl/title">TITLE</span>
-        </td>
-        <td>
-          <span tal:content="cl/translated_class_name">CLASSNAME</span>
-        </td>
-        <td>
-          <span tal:content="cl/translated_state">STATE</span>
-        </td>
-        <td>
-          <span tal:content="cl/formatted_transition_date">
-              LASTTRANSITIONDATE
-          </span>
-        </td>
-      </tr>
-    </tbody>
-  </table>
-
-  <div tal:condition="python: view.availableActions and view.manage_applications_allowed">
-    <span tal:repeat="action view/actions"
-          tal:omit-tag="">
-      <input tal:replace="structure action/render"/>
-    </span>
-  </div>
-</form>
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/contractaddform.pt
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/contractaddform.pt	(revision 12097)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/contractaddform.pt	(revision 12097)
@@ -0,0 +1,26 @@
+<form action="." tal:attributes="action request/URL" method="post"
+      enctype="multipart/form-data" i18n:domain="waeup.ikoba">
+  <table class="form-table">
+    <tbody>
+      <tr>
+        <td class="fieldname">
+          <span i18n:translate="">Contract Type</span>:
+        </td>
+        <td>
+          <select id="apptype" name="apptype" size="1"
+                  class="form-control half">
+            <option tal:repeat="item view/selectable_apptypes"
+                    tal:attributes="value python:item[0]">
+              <span tal:replace="python:item[1]">APPTYPE</span>
+            </option>
+          </select>
+        </td>
+      </tr>
+    </tbody>
+  </table>
+  <div tal:condition="view/availableActions">
+    <input tal:repeat="action view/actions"
+           tal:replace="structure action/render"
+           />
+  </div>
+</form>
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/contracteditpage.pt
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/contracteditpage.pt	(revision 12097)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/contracteditpage.pt	(revision 12097)
@@ -0,0 +1,41 @@
+<form action="." tal:attributes="action request/URL" method="post"
+      i18n:domain="waeup.ikoba" enctype="multipart/form-data">
+
+  <ul class="tabs nav nav-tabs" data-tabs="tabs">
+    <li class="active">
+      <a href="#tab1" data-toggle="tab">
+        <span i18n:translate="">Metadata</span>
+      </a>
+    </li>
+    <li>
+      <a href="#tab2" data-toggle="tab">
+        <span i18n:translate="">Documents</span>
+      </a>
+    </li>
+  </ul>
+  <div class="tab-content">
+    <div id="tab1" class="active tab-pane">
+      <br />
+      <table class="form-table">
+        <tbody>
+          <tal:widgets content="structure provider:widgets" />
+        </tbody>
+      </table>
+
+      <div tal:condition="view/availableActions">
+        <input tal:repeat="action view/actions"
+               tal:replace="structure action/render"
+               />
+      </div>
+    </div>
+
+    <div id="tab2" class="tab-pane">
+      <br />
+      <table class="form-table">
+        <tbody>
+
+        </tbody>
+      </table>
+    </div>
+  </div>
+</form>
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/contractpage.pt
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/contractpage.pt	(revision 12097)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/contractpage.pt	(revision 12097)
@@ -0,0 +1,24 @@
+<div class="wfstatus-sub"  i18n:domain="waeup.ikoba">
+  Contract State: <span tal:replace="context/translated_state">
+    CONTRACTSTATE</span>
+</div>
+
+<div class="workflow">
+  <div tal:repeat="msg context/history/messages">
+    <span tal:replace="msg">MESSAGE</span><br />
+  </div>
+</div>
+
+<table class="form-table" i18n:domain="waeup.ikoba">
+  <tbody>
+    <tr>
+      <td i18n:translate="" class="fieldname">
+        Contract Type:
+      </td>
+      <td>
+        <span tal:content="context/translated_class_name">CLASSNAME</span>
+      </td>
+    </tr>
+    <tal:widgets content="structure provider:widgets" />
+  </tbody>
+</table>
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/contractsmanagepage.pt
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/contractsmanagepage.pt	(revision 12097)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/contractsmanagepage.pt	(revision 12097)
@@ -0,0 +1,51 @@
+<form action="." tal:attributes="action request/URL" method="POST"
+      i18n:domain="waeup.ikoba" enctype="multipart/form-data">
+
+  <table class="ikoba-data-table dataTableManage">
+    <thead>
+    <tr>
+      <th>&nbsp;</th>
+      <th i18n:translate="">Id</th>
+      <th i18n:translate="">Title</th>
+      <th i18n:translate="">Type</th>
+      <th i18n:translate="">State</th>
+      <th i18n:translate="">Last Transition</th>
+    </tr>
+    </thead>
+    <tbody>
+      <tr tal:repeat="cl context/values">
+         <td>
+          <input type="checkbox"
+    		 name="val_id"
+    		 tal:attributes="value cl/__name__"
+         tal:condition="python: not view.unremovable(cl)" />
+        </td>
+        <td>
+          <a tal:attributes="href python: view.url(cl)">
+          <span tal:content="cl/contract_id">CONID</span></a>
+        </td>
+        <td>
+          <span tal:content="cl/title">TITLE</span>
+        </td>
+        <td>
+          <span tal:content="cl/translated_class_name">CLASSNAME</span>
+        </td>
+        <td>
+          <span tal:content="cl/translated_state">STATE</span>
+        </td>
+        <td>
+          <span tal:content="cl/formatted_transition_date">
+              LASTTRANSITIONDATE
+          </span>
+        </td>
+      </tr>
+    </tbody>
+  </table>
+
+  <div tal:condition="python: view.availableActions and view.manage_contracts_allowed">
+    <span tal:repeat="action view/actions"
+          tal:omit-tag="">
+      <input tal:replace="structure action/render"/>
+    </span>
+  </div>
+</form>
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/catalog.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/catalog.py	(revision 12096)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/catalog.py	(revision 12097)
@@ -27,5 +27,5 @@
 from waeup.ikoba.interfaces import (
     ICompany, IQueryResultItem)
-from waeup.ikoba.customers.interfaces import ICustomer, IApplication
+from waeup.ikoba.customers.interfaces import ICustomer, IContract
 
 
@@ -119,14 +119,14 @@
 
 
-# Catalog for customer applications
+# Catalog for customer contracts
 
-class ApplicationIndexes(grok.Indexes):
-    """A catalog for all applications.
+class ContractIndexes(grok.Indexes):
+    """A catalog for all contracts.
     """
     grok.site(ICompany)
-    grok.name('applications_catalog')
-    grok.context(IApplication)
+    grok.name('contracts_catalog')
+    grok.context(IContract)
 
-    application_id = grok.index.Field(attribute='application_id')
+    contract_id = grok.index.Field(attribute='contract_id')
     last_product_id = grok.index.Field(attribute='last_product_id')
-    application_category = grok.index.Field(attribute='application_category')
+    contract_category = grok.index.Field(attribute='contract_category')
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/contracts.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/contracts.py	(revision 12097)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/contracts.py	(revision 12097)
@@ -0,0 +1,171 @@
+## $Id$
+##
+## Copyright (C) 2014 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+"""
+Customer contract components.
+"""
+import os
+import grok
+from zope.component import queryUtility, getUtility
+from zope.component.interfaces import IFactory
+from zope.interface import implementedBy
+from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState
+from waeup.ikoba.interfaces import MessageFactory as _
+from waeup.ikoba.interfaces import IIkobaUtils, IObjectHistory
+from waeup.ikoba.customers.interfaces import (
+    IContractsContainer, ICustomerNavigation,
+    IContract, IContractEdit, ICustomersUtils,
+    )
+from waeup.ikoba.customers.utils import generate_contract_id
+from waeup.ikoba.utils.helpers import attrs_to_fields
+
+class ContractsContainer(grok.Container):
+    """This is a container for customer contracts.
+    """
+    grok.implements(IContractsContainer, ICustomerNavigation)
+    grok.provides(IContractsContainer)
+
+    def addContract(self, contract):
+        if not IContract.providedBy(contract):
+            raise TypeError(
+                'ContractsContainers contain only IContract instances')
+        self[contract.contract_id] = contract
+        return
+
+    @property
+    def customer(self):
+        return self.__parent__
+
+    def writeLogMessage(self, view, message):
+        return self.__parent__.writeLogMessage(view, message)
+
+ContractsContainer = attrs_to_fields(ContractsContainer)
+
+class ContractBase(grok.Container):
+    """This is a customer contract baseclass.
+    """
+    grok.implements(IContract, IContractEdit, ICustomerNavigation)
+    grok.provides(IContract)
+    grok.baseclass()
+
+    contract_category = None
+
+    def __init__(self):
+        super(ContractBase, self).__init__()
+        # The site doesn't exist in unit tests
+        try:
+            self.contract_id = generate_contract_id()
+        except AttributeError:
+            self.contract_id = u'a123'
+        self.last_product_id = None
+        return
+
+    @property
+    def history(self):
+        history = IObjectHistory(self)
+        return history
+
+    @property
+    def state(self):
+        return IWorkflowState(self).getState()
+
+    @property
+    def translated_state(self):
+        try:
+            TRANSLATED_STATES = getUtility(
+                ICustomersUtils).TRANSLATED_CONTRACT_STATES
+            return TRANSLATED_STATES[self.state]
+        except KeyError:
+            return
+
+    @property
+    def class_name(self):
+        return self.__class__.__name__
+
+    @property
+    def formatted_transition_date(self):
+        try:
+            return self.last_transition_date.strftime('%Y-%m-%d %H:%M:%S')
+        except AttributeError:
+            return
+
+    @property
+    def customer(self):
+        try:
+            return self.__parent__.__parent__
+        except AttributeError:
+            return None
+
+    def writeLogMessage(self, view, message):
+        return self.__parent__.__parent__.writeLogMessage(view, message)
+
+    @property
+    def is_editable(self):
+        try:
+            # Customer must be approved
+            cond1 = self.customer.state in getUtility(
+                ICustomersUtils).APPMANAGE_CUSTOMER_STATES
+            # Contract must be in state created
+            cond2 = self.state in getUtility(
+                ICustomersUtils).APPMANAGE_CONTRACT_STATES
+            if not (cond1 and cond2):
+                return False
+        except AttributeError:
+            pass
+        return True
+
+    @property
+    def translated_class_name(self):
+        try:
+            APPTYPES_DICT = getUtility(ICustomersUtils).APPTYPES_DICT
+            return APPTYPES_DICT[self.class_name]
+        except KeyError:
+            return
+
+
+class SampleContract(ContractBase):
+    """This is a sample contract.
+    """
+
+    contract_category = 'sample'
+
+SampleContract = attrs_to_fields(SampleContract)
+
+
+# Contracts must be importable. So we might need a factory.
+class SampleContractFactory(grok.GlobalUtility):
+    """A factory for contracts.
+    """
+    grok.implements(IFactory)
+    grok.name(u'waeup.SampleContract')
+    title = u"Create a new contract.",
+    description = u"This factory instantiates new sample contract instances."
+
+    def __call__(self, *args, **kw):
+        return SampleContract(*args, **kw)
+
+    def getInterfaces(self):
+        return implementedBy(SampleContract)
+
+@grok.subscribe(IContract, grok.IObjectAddedEvent)
+def handle_contract_added(contract, event):
+    """If an contract is added the transition create is fired.
+    The latter produces a logging message.
+    """
+    if IWorkflowState(contract).getState() is None:
+        IWorkflowInfo(contract).fireTransition('create')
+    return
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/customer.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/customer.py	(revision 12096)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/customer.py	(revision 12097)
@@ -43,5 +43,5 @@
 from waeup.ikoba.customers.utils import generate_customer_id, path_from_custid
 from waeup.ikoba.customers.documents import CustomerDocumentsContainer
-from waeup.ikoba.customers.applications import ApplicationsContainer
+from waeup.ikoba.customers.contracts import ContractsContainer
 from waeup.ikoba.utils.helpers import attrs_to_fields, now, copy_filesystem_tree
 
@@ -184,6 +184,6 @@
     documents = CustomerDocumentsContainer()
     customer['documents'] = documents
-    applications = ApplicationsContainer()
-    customer['applications'] = applications
+    contracts = ContractsContainer()
+    customer['contracts'] = contracts
     return
 
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/interfaces.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/interfaces.py	(revision 12096)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/interfaces.py	(revision 12097)
@@ -23,5 +23,5 @@
 from waeup.ikoba.interfaces import MessageFactory as _
 from waeup.ikoba.interfaces import (
-    IIkobaObject, application_sessions_vocab, validate_email, ICSVExporter)
+    IIkobaObject, validate_email, ICSVExporter)
 from waeup.ikoba.schema import TextLineChoice, FormattedDate, PhoneNumber
 from waeup.ikoba.browser.interfaces import ICustomerNavigationBase
@@ -248,34 +248,34 @@
     """
 
-# Customer application interfaces
-
-class IApplicationsContainer(IIkobaObject):
+# Customer contract interfaces
+
+class IContractsContainer(IIkobaObject):
     """A container for customer aplication objects.
 
     """
 
-    def addApplication(application):
-        """Add an application object.
-        """
-
-
-class IApplication(IIkobaObject):
-    """A customer application.
-
-    """
-    application_id = Attribute('Application Identifier')
+    def addContract(contract):
+        """Add an contract object.
+        """
+
+
+class IContract(IIkobaObject):
+    """A customer contract.
+
+    """
+    contract_id = Attribute('Contract Identifier')
     history = Attribute('Object history, a list of messages')
-    state = Attribute('Returns the application state')
+    state = Attribute('Returns the contract state')
     translated_state = Attribute(
         'Returns a translated, more verbose appliction state')
-    class_name = Attribute('Name of the application class')
+    class_name = Attribute('Name of the contract class')
     formatted_transition_date = Attribute(
         'Last transition formatted date string')
-    application_category = Attribute('Category for the grouping of products')
+    contract_category = Attribute('Category for the grouping of products')
     last_product_id = Attribute(
-        'Id of product recently stored with the application')
+        'Id of product recently stored with the contract')
 
     title = schema.TextLine(
-        title = _(u'Application Title'),
+        title = _(u'Contract Title'),
         required = True,
         )
@@ -293,6 +293,6 @@
         )
 
-class IApplicationEdit(IApplication):
-    """Interface for editing application data by customers.
+class IContractEdit(IContract):
+    """Interface for editing contract data by customers.
 
     """
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/permissions.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/permissions.py	(revision 12096)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/permissions.py	(revision 12097)
@@ -48,6 +48,6 @@
 
 
-class EditApplications(grok.Permission):
-    grok.name('waeup.editApplications')
+class EditContracts(grok.Permission):
+    grok.name('waeup.editContracts')
 
 
@@ -74,5 +74,5 @@
     grok.permissions('waeup.handleCustomer', 'waeup.uploadCustomerFile',
                      'waeup.viewCustomer', 'waeup.editCustomerDocuments',
-                     'waeup.editApplications')
+                     'waeup.editContracts')
 
 
@@ -99,5 +99,5 @@
                      'waeup.editCustomerDocuments', 'waeup.uploadCustomerFile',
                      'waeup.viewCustomersTab', 'waeup.triggerTransition',
-                     'waeup.editApplications')
+                     'waeup.editContracts')
 
 
Index: in/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_application.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_application.py	(revision 12096)
+++ 	(revision )
@@ -1,91 +1,0 @@
-## $Id$
-##
-## Copyright (C) 2014 Uli Fouquet & Henrik Bettermann
-## This program is free software; you can redistribute it and/or modify
-## it under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 2 of the License, or
-## (at your option) any later version.
-##
-## This program is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-## GNU General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with this program; if not, write to the Free Software
-## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-##
-"""
-Tests for applications.
-"""
-from zope.interface.verify import verifyClass, verifyObject
-from zope.component import createObject
-from hurry.workflow.interfaces import (
-    IWorkflowInfo, IWorkflowState, InvalidTransitionError)
-from waeup.ikoba.customers.interfaces import (
-    IApplicationsContainer, IApplication)
-from waeup.ikoba.interfaces import IObjectHistory
-from waeup.ikoba.customers.applications import (
-    ApplicationsContainer, SampleApplication)
-from waeup.ikoba.testing import (FunctionalLayer, FunctionalTestCase)
-
-class ApplicationsContainerTestCase(FunctionalTestCase):
-
-    layer = FunctionalLayer
-
-    def test_interfaces(self):
-        # Make sure the correct interfaces are implemented.
-        self.assertTrue(
-            verifyClass(
-                IApplicationsContainer, ApplicationsContainer)
-            )
-        self.assertTrue(
-            verifyObject(
-                IApplicationsContainer, ApplicationsContainer())
-            )
-        self.assertTrue(
-            verifyClass(
-                IApplication, SampleApplication)
-            )
-        self.assertTrue(
-            verifyObject(
-                IApplication, SampleApplication())
-            )
-        return
-
-    def test_addApplication(self):
-        container = ApplicationsContainer()
-        application = createObject(u'waeup.SampleApplication')
-        id = application.application_id
-        container.addApplication(application)
-        self.assertEqual(container[id], application)
-        self.assertRaises(TypeError, container.addApplication, object())
-        self.assertEqual(application.class_name, 'SampleApplication')
-        self.assertEqual(id, 'a123')
-        return
-
-    def test_application_workflow(self):
-        application = createObject(u'waeup.SampleApplication')
-        IWorkflowInfo(application).fireTransition('create')
-        self.assertEqual(IWorkflowState(application).getState(), 'created')
-        IWorkflowInfo(application).fireTransition('submit')
-        self.assertEqual(IWorkflowState(application).getState(), 'submitted')
-        IWorkflowInfo(application).fireTransition('approve')
-        self.assertEqual(IWorkflowState(application).getState(), 'approved')
-        IWorkflowInfo(application).fireTransition('expire')
-        self.assertEqual(IWorkflowState(application).getState(), 'expired')
-        IWorkflowInfo(application).fireTransition('reset4')
-        self.assertEqual(IWorkflowState(application).getState(), 'created')
-        self.assertRaises(InvalidTransitionError,
-            IWorkflowInfo(application).fireTransition, 'approve')
-        IWorkflowInfo(application).fireTransition('submit')
-        IWorkflowInfo(application).fireTransition('reset3')
-        self.assertEqual(IWorkflowState(application).getState(), 'created')
-        return
-
-    def test_application_history(self):
-        doc = createObject(u'waeup.SampleApplication')
-        IWorkflowInfo(doc).fireTransition('create')
-        messages = ' '.join(doc.history.messages)
-        self.assertTrue('Application record created by system' in messages)
-        return
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_browser.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_browser.py	(revision 12096)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_browser.py	(revision 12097)
@@ -96,5 +96,5 @@
         self.product.product_id = u'SAM'
         self.product.title = u'Our Samle Product'
-        self.product.application_category = u'sample'
+        self.product.contract_category = u'sample'
         self.app['products'].addProduct(self.product)
 
@@ -114,7 +114,7 @@
         document.title = u'My first document'
         self.customer['documents'].addDocument(document)
-        application = createObject('waeup.SampleApplication')
-        application.title = u'My first application'
-        self.customer['applications'].addApplication(application)
+        contract = createObject('waeup.SampleContract')
+        contract.title = u'My first contract'
+        self.customer['contracts'].addContract(contract)
 
         # Set password
@@ -131,5 +131,5 @@
         self.history_path = self.customer_path + '/history'
         self.documents_path = self.customer_path + '/documents'
-        self.applications_path = self.customer_path + '/applications'
+        self.contracts_path = self.customer_path + '/contracts'
 
         self.app['configuration'].carry_over = True
@@ -1052,9 +1052,9 @@
 
 
-class ApplicationUITests(CustomersFullSetup):
-    # Tests for CustomerSampleApplication relates views and pages
-
-    def test_manage_application(self):
-        # Managers can access the pages of customer applicationsconter
+class ContractUITests(CustomersFullSetup):
+    # Tests for CustomerSampleContract relates views and pages
+
+    def test_manage_contract(self):
+        # Managers can access the pages of customer contractsconter
         # and can perform actions
         self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
@@ -1063,12 +1063,12 @@
         self.assertEqual(self.browser.url, self.customer_path)
         self.browser.open(self.customer_path)
-        self.browser.getLink("Applications").click()
-        self.browser.getLink("Add application").click()
-        self.browser.getControl(name="apptype").value = ['SampleApplication']
-        self.browser.getControl("Create application").click()
-        self.assertTrue('Sample Application created.' in self.browser.contents)
-        application = self.customer['applications']['a102']
-
-        # Application can be edited
+        self.browser.getLink("Contracts").click()
+        self.browser.getLink("Add contract").click()
+        self.browser.getControl(name="apptype").value = ['SampleContract']
+        self.browser.getControl("Create contract").click()
+        self.assertTrue('Sample Contract created.' in self.browser.contents)
+        contract = self.customer['contracts']['a102']
+
+        # Contract can be edited
         self.browser.getLink("a102").click()
         self.browser.getLink("Manage").click()
@@ -1078,5 +1078,5 @@
         self.assertTrue('Form has been saved.' in self.browser.contents)
         self.browser.getLink("View").click()
-        self.assertEqual(self.browser.url, self.applications_path + '/a102/index')
+        self.assertEqual(self.browser.url, self.contracts_path + '/a102/index')
 
         # Transitions can be performed
@@ -1086,10 +1086,10 @@
         self.browser.getControl(name="transition").value = ['approve']
         self.browser.getControl("Save").click()
-        self.assertEqual(application.state, 'approved')
-
-        # Applications can be removed
-        self.browser.getLink("Applications").click()
+        self.assertEqual(contract.state, 'approved')
+
+        # Contracts can be removed
+        self.browser.getLink("Contracts").click()
         ctrl = self.browser.getControl(name='val_id')
-        ctrl.getControl(value=application.application_id).selected = True
+        ctrl.getControl(value=contract.contract_id).selected = True
         self.browser.getControl("Remove selected", index=0).click()
         self.assertTrue('Successfully removed' in self.browser.contents)
@@ -1100,24 +1100,24 @@
         logcontent = open(logfile).read()
         self.assertTrue(
-            'INFO - zope.mgr - customers.browser.ApplicationManageFormPage '
+            'INFO - zope.mgr - customers.browser.ContractManageFormPage '
             '- K1000000 - a102 - saved: title'
             in logcontent)
         self.assertTrue(
-            'INFO - zope.mgr - customers.browser.ApplicationAddFormPage '
-            '- K1000000 - added: Sample Application %s'
-            % application.application_id in logcontent)
-        self.assertTrue(
-            'INFO - zope.mgr - customers.browser.ApplicationsManageFormPage '
+            'INFO - zope.mgr - customers.browser.ContractAddFormPage '
+            '- K1000000 - added: Sample Contract %s'
+            % contract.contract_id in logcontent)
+        self.assertTrue(
+            'INFO - zope.mgr - customers.browser.ContractsManageFormPage '
             '- K1000000 - removed: %s'
-            % application.application_id in logcontent)
-
-    def test_edit_sample_application(self):
+            % contract.contract_id in logcontent)
+
+    def test_edit_sample_contract(self):
         # We add a second product.
         product = createObject('waeup.Product')
         product.product_id = u'LIC'
         product.title = u'Our License Product'
-        product.application_category = u'license'
+        product.contract_category = u'license'
         self.app['products'].addProduct(product)
-        # Customers can manage applications under certain conditions
+        # Customers can manage contracts under certain conditions
         self.browser.open(self.login_path)
         self.browser.getControl(name="form.login").value = self.customer_id
@@ -1126,65 +1126,65 @@
         self.assertMatches(
             '...You logged in...', self.browser.contents)
-        self.browser.getLink("Applications").click()
-        self.browser.getLink("Add application").click()
-        self.browser.getControl(name="apptype").value = ['SampleApplication']
-        self.browser.getControl("Create application").click()
-        self.assertTrue('Sample Application created.' in self.browser.contents)
-        application = self.customer['applications']['a102']
-        # Application can be edited ...
+        self.browser.getLink("Contracts").click()
+        self.browser.getLink("Add contract").click()
+        self.browser.getControl(name="apptype").value = ['SampleContract']
+        self.browser.getControl("Create contract").click()
+        self.assertTrue('Sample Contract created.' in self.browser.contents)
+        contract = self.customer['contracts']['a102']
+        # Contract can be edited ...
         self.browser.getLink("a102").click()
-        self.browser.open(self.applications_path + '/a102/edit')
+        self.browser.open(self.contracts_path + '/a102/edit')
         #self.browser.getLink("Edit").click()
         self.assertTrue('The requested form is locked' in self.browser.contents)
         # Customer is in wrong state
         IWorkflowState(self.customer).setState(APPROVED)
-        self.browser.open(self.applications_path + '/a102/edit')
+        self.browser.open(self.contracts_path + '/a102/edit')
         self.browser.getControl(name="form.title").value = 'My second app'
-        # SAM is in the correct application_category ...
+        # SAM is in the correct contract_category ...
         self.assertTrue('<option value="SAM">' in self.browser.contents)
         # ... but NOTSAM not.
         self.assertFalse('<option value="LIC">' in self.browser.contents)
         # So far last_product_id is None.
-        self.assertTrue(self.customer['applications']['a102'].last_product_id is None)
+        self.assertTrue(self.customer['contracts']['a102'].last_product_id is None)
         self.browser.getControl(name="form.product").value = ['SAM']
         self.browser.getControl("Save").click()
         # After saving the form, last_product_id is set.
-        self.assertEqual(self.customer['applications']['a102'].last_product_id, 'SAM')
+        self.assertEqual(self.customer['contracts']['a102'].last_product_id, 'SAM')
         self.assertTrue('Form has been saved.' in self.browser.contents)
         # Saving the form again does not unset last_product_id
-        self.assertEqual(application.title, 'My second app')
-        self.browser.getControl("Save").click()
-        self.assertEqual(self.customer['applications']['a102'].last_product_id, 'SAM')
+        self.assertEqual(contract.title, 'My second app')
+        self.browser.getControl("Save").click()
+        self.assertEqual(self.customer['contracts']['a102'].last_product_id, 'SAM')
         self.assertTrue('Form has been saved.' in self.browser.contents)
         self.browser.getLink("View").click()
-        self.assertEqual(self.browser.url, self.applications_path + '/a102/index')
+        self.assertEqual(self.browser.url, self.contracts_path + '/a102/index')
         # Customer can submit the form. The form is also saved.
         self.browser.getLink("Edit").click()
         self.browser.getControl(name="form.title").value = 'My third app'
         self.browser.getControl("Apply now").click()
-        self.assertEqual(application.title, 'My third app')
-        self.assertEqual(application.state, 'submitted')
-        self.assertTrue('Application State: submitted for approval' in self.browser.contents)
-        # Customer can't edit the application once it has been submitted
-        self.browser.open(self.applications_path + '/a102/edit')
+        self.assertEqual(contract.title, 'My third app')
+        self.assertEqual(contract.state, 'submitted')
+        self.assertTrue('Contract State: submitted for approval' in self.browser.contents)
+        # Customer can't edit the contract once it has been submitted
+        self.browser.open(self.contracts_path + '/a102/edit')
         self.assertTrue('The requested form is locked' in self.browser.contents)
 
     def test_view_slips(self):
         self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
-        # Officers can open the application overview
-        self.browser.open(self.customer_path + '/applications')
-        self.browser.getLink("Download applications overview").click()
+        # Officers can open the contract overview
+        self.browser.open(self.customer_path + '/contracts')
+        self.browser.getLink("Download contracts overview").click()
         self.assertEqual(self.browser.headers['Status'], '200 Ok')
         self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
-        path = os.path.join(samples_dir(), 'applications_overview_slip.pdf')
+        path = os.path.join(samples_dir(), 'contracts_overview_slip.pdf')
         open(path, 'wb').write(self.browser.contents)
         print "Sample PDF overview_slip.pdf written to %s" % path
-        # Officers can open application slips
-        self.browser.open(self.customer_path + '/applications/a101')
-        self.browser.getLink("Download application slip").click()
+        # Officers can open contract slips
+        self.browser.open(self.customer_path + '/contracts/a101')
+        self.browser.getLink("Download contract slip").click()
         self.assertEqual(self.browser.headers['Status'], '200 Ok')
         self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
-        path = os.path.join(samples_dir(), 'application_slip.pdf')
+        path = os.path.join(samples_dir(), 'contract_slip.pdf')
         open(path, 'wb').write(self.browser.contents)
-        print "Sample application_slip.pdf written to %s" % path
-
+        print "Sample contract_slip.pdf written to %s" % path
+
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_catalog.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_catalog.py	(revision 12096)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_catalog.py	(revision 12097)
@@ -27,5 +27,5 @@
 from waeup.ikoba.testing import FunctionalLayer, FunctionalTestCase
 from waeup.ikoba.customers.customer import Customer
-from waeup.ikoba.customers.applications import SampleApplication
+from waeup.ikoba.customers.contracts import SampleContract
 
 
@@ -61,16 +61,16 @@
         product.product_id = u'SAM'
         product.title = u'Our Samle Product'
-        product.application_category = u'sample'
+        product.contract_category = u'sample'
         self.app['products'].addProduct(product)
         self.product_id = product.product_id
         self.product = self.app['products'][self.product_id]
 
-        application = createObject('waeup.SampleApplication')
-        application.title = u'My Samle Application'
-        application.product = product
-        application.last_product_id = product.product_id
-        self.customer['applications'].addApplication(application)
-        self.application_id = application.application_id
-        self.application = self.customer['applications'][self.application_id]
+        contract = createObject('waeup.SampleContract')
+        contract.title = u'My Samle Contract'
+        contract.product = product
+        contract.last_product_id = product.product_id
+        self.customer['contracts'].addContract(contract)
+        self.contract_id = contract.contract_id
+        self.contract = self.customer['contracts'][self.contract_id]
 
         document = createObject('waeup.CustomerSampleDocument')
@@ -125,5 +125,5 @@
 
     def test_search_by_id(self):
-        # We can find a certain application id
+        # We can find a certain contract id
         cat = queryUtility(ICatalog, name='documents_catalog')
         results = cat.searchResults(document_id=(self.document_id,
@@ -134,5 +134,5 @@
 
 
-class ApplicationsCatalogTests(CatalogTestSetup):
+class ContractsCatalogTests(CatalogTestSetup):
 
     layer = FunctionalLayer
@@ -140,45 +140,45 @@
     def test_get_catalog(self):
         # We can get an customers catalog if we wish
-        cat = queryUtility(ICatalog, name='applications_catalog')
+        cat = queryUtility(ICatalog, name='contracts_catalog')
         assert cat is not None
 
     def test_search_by_id(self):
-        # We can find a certain application id
-        cat = queryUtility(ICatalog, name='applications_catalog')
-        results = cat.searchResults(application_id=(self.application_id,
-                                                self.application_id))
+        # We can find a certain contract id
+        cat = queryUtility(ICatalog, name='contracts_catalog')
+        results = cat.searchResults(contract_id=(self.contract_id,
+                                                self.contract_id))
         results = [x for x in results] # Turn results generator into list
         assert len(results) == 1
-        assert results[0] is self.customer['applications'][self.application_id]
+        assert results[0] is self.customer['contracts'][self.contract_id]
 
     def test_search_by_category(self):
         # We can find a certain name
-        cat = queryUtility(ICatalog, name='applications_catalog')
-        results = cat.searchResults(application_category=('sample', 'sample'))
+        cat = queryUtility(ICatalog, name='contracts_catalog')
+        results = cat.searchResults(contract_category=('sample', 'sample'))
         results = [x for x in results] # Turn results generator into list
         assert len(results) == 1
-        assert results[0] is self.customer['applications'][self.application_id]
+        assert results[0] is self.customer['contracts'][self.contract_id]
 
     def test_search_by_last_product_id(self):
         # We can find a certain name
-        cat = queryUtility(ICatalog, name='applications_catalog')
+        cat = queryUtility(ICatalog, name='contracts_catalog')
         results = cat.searchResults(last_product_id=('SAM', 'SAM'))
         results = [x for x in results] # Turn results generator into list
         assert len(results) == 1
-        assert results[0] is self.customer['applications'][self.application_id]
+        assert results[0] is self.customer['contracts'][self.contract_id]
         assert results[0].product is self.product
 
     def test_product_removal(self):
         # This test does not only test catalog components, it also ensures
-        # that the product attribute of an application is cleared
+        # that the product attribute of an contract is cleared
         # but the last_product_id is not.
         del self.app['products'][self.product_id]
-        self.assertTrue(self.application.product is None)
-        self.assertEqual(self.application.last_product_id, 'SAM')
-        cat = queryUtility(ICatalog, name='applications_catalog')
+        self.assertTrue(self.contract.product is None)
+        self.assertEqual(self.contract.last_product_id, 'SAM')
+        cat = queryUtility(ICatalog, name='contracts_catalog')
         results = cat.searchResults(last_product_id=('SAM', 'SAM'))
         results = [x for x in results]
         assert len(results) == 1
-        assert results[0] is self.customer['applications'][self.application_id]
+        assert results[0] is self.customer['contracts'][self.contract_id]
         assert results[0].product is None
         # Product removal is being logged in customers.log
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_contract.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_contract.py	(revision 12097)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_contract.py	(revision 12097)
@@ -0,0 +1,91 @@
+## $Id$
+##
+## Copyright (C) 2014 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+"""
+Tests for contracts.
+"""
+from zope.interface.verify import verifyClass, verifyObject
+from zope.component import createObject
+from hurry.workflow.interfaces import (
+    IWorkflowInfo, IWorkflowState, InvalidTransitionError)
+from waeup.ikoba.customers.interfaces import (
+    IContractsContainer, IContract)
+from waeup.ikoba.interfaces import IObjectHistory
+from waeup.ikoba.customers.contracts import (
+    ContractsContainer, SampleContract)
+from waeup.ikoba.testing import (FunctionalLayer, FunctionalTestCase)
+
+class ContractsContainerTestCase(FunctionalTestCase):
+
+    layer = FunctionalLayer
+
+    def test_interfaces(self):
+        # Make sure the correct interfaces are implemented.
+        self.assertTrue(
+            verifyClass(
+                IContractsContainer, ContractsContainer)
+            )
+        self.assertTrue(
+            verifyObject(
+                IContractsContainer, ContractsContainer())
+            )
+        self.assertTrue(
+            verifyClass(
+                IContract, SampleContract)
+            )
+        self.assertTrue(
+            verifyObject(
+                IContract, SampleContract())
+            )
+        return
+
+    def test_addContract(self):
+        container = ContractsContainer()
+        contract = createObject(u'waeup.SampleContract')
+        id = contract.contract_id
+        container.addContract(contract)
+        self.assertEqual(container[id], contract)
+        self.assertRaises(TypeError, container.addContract, object())
+        self.assertEqual(contract.class_name, 'SampleContract')
+        self.assertEqual(id, 'a123')
+        return
+
+    def test_contract_workflow(self):
+        contract = createObject(u'waeup.SampleContract')
+        IWorkflowInfo(contract).fireTransition('create')
+        self.assertEqual(IWorkflowState(contract).getState(), 'created')
+        IWorkflowInfo(contract).fireTransition('submit')
+        self.assertEqual(IWorkflowState(contract).getState(), 'submitted')
+        IWorkflowInfo(contract).fireTransition('approve')
+        self.assertEqual(IWorkflowState(contract).getState(), 'approved')
+        IWorkflowInfo(contract).fireTransition('expire')
+        self.assertEqual(IWorkflowState(contract).getState(), 'expired')
+        IWorkflowInfo(contract).fireTransition('reset4')
+        self.assertEqual(IWorkflowState(contract).getState(), 'created')
+        self.assertRaises(InvalidTransitionError,
+            IWorkflowInfo(contract).fireTransition, 'approve')
+        IWorkflowInfo(contract).fireTransition('submit')
+        IWorkflowInfo(contract).fireTransition('reset3')
+        self.assertEqual(IWorkflowState(contract).getState(), 'created')
+        return
+
+    def test_contract_history(self):
+        doc = createObject(u'waeup.SampleContract')
+        IWorkflowInfo(doc).fireTransition('create')
+        messages = ' '.join(doc.history.messages)
+        self.assertTrue('Contract record created by system' in messages)
+        return
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/utils.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/utils.py	(revision 12096)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/utils.py	(revision 12097)
@@ -268,6 +268,6 @@
         )
 
-def generate_application_id():
-    new_id = grok.getSite().unique_application_id
+def generate_contract_id():
+    new_id = grok.getSite().unique_contract_id
     return new_id
 
@@ -289,5 +289,5 @@
     APPMANAGE_CUSTOMER_STATES = DOCMANAGE_CUSTOMER_STATES
 
-    APPMANAGE_APPLICATION_STATES = (CREATED,)
+    APPMANAGE_CONTRACT_STATES = (CREATED,)
 
     SKIP_UPLOAD_VIEWLETS = ()
@@ -301,5 +301,5 @@
 
 
-    TRANSLATED_APPLICATION_STATES = {
+    TRANSLATED_CONTRACT_STATES = {
         CREATED: _('created'),
         SUBMITTED: _('submitted for approval'),
@@ -315,5 +315,5 @@
 
     APPTYPES_DICT = {
-        'SampleApplication': 'Sample Application',
+        'SampleContract': 'Sample Contract',
         }
 
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/viewlets.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/viewlets.py	(revision 12096)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/viewlets.py	(revision 12097)
@@ -28,11 +28,11 @@
     ICustomer, ICustomersContainer,
     ICustomerDocumentsContainer, ICustomerDocument,
-    IApplicationsContainer, IApplication)
+    IContractsContainer, IContract)
 from waeup.ikoba.customers.browser import (
     CustomersContainerPage, CustomersContainerManagePage,
     CustomerBaseDisplayFormPage,
     DocumentsManageFormPage, DocumentDisplayFormPage, DocumentManageFormPage,
-    ApplicationsManageFormPage, ApplicationDisplayFormPage,
-    ApplicationManageFormPage)
+    ContractsManageFormPage, ContractDisplayFormPage,
+    ContractManageFormPage)
 
 grok.context(IIkobaObject)  # Make IIkobaObject the default context
@@ -110,5 +110,5 @@
         targets += [
             {'url':customer_url, 'title':'Base Data'},
-            {'url':customer_url + '/applications', 'title':_('My Applications')},
+            {'url':customer_url + '/contracts', 'title':_('My Contracts')},
             {'url':customer_url + '/documents', 'title':_('My Documents')},
             {'url':customer_url + '/history', 'title':_('History')},
@@ -153,8 +153,8 @@
 
 
-class CustomerManageApplicationsLink(CustomerManageLink):
-    grok.order(3)
-    link = 'applications'
-    text = _(u'Applications')
+class CustomerManageContractsLink(CustomerManageLink):
+    grok.order(3)
+    link = 'contracts'
+    text = _(u'Contracts')
 
 
@@ -372,29 +372,29 @@
     target = 'document_slip.pdf'
 
-# Viewlets for customer applications
-
-class AddApplicationActionButton(AddActionButton):
-    grok.order(1)
-    grok.context(IApplicationsContainer)
-    grok.view(ApplicationsManageFormPage)
-    grok.require('waeup.editApplications')
-    text = _('Add application')
+# Viewlets for customer contracts
+
+class AddContractActionButton(AddActionButton):
+    grok.order(1)
+    grok.context(IContractsContainer)
+    grok.view(ContractsManageFormPage)
+    grok.require('waeup.editContracts')
+    text = _('Add contract')
     target = 'addapp'
 
 
-class PDFApplicationOverviewActionButton(ManageActionButton):
-    grok.order(2)
-    grok.context(IApplicationsContainer)
-    grok.view(ApplicationsManageFormPage)
+class PDFContractOverviewActionButton(ManageActionButton):
+    grok.order(2)
+    grok.context(IContractsContainer)
+    grok.view(ContractsManageFormPage)
     grok.require('waeup.viewCustomer')
     icon = 'actionicon_pdf.png'
-    text = _('Download applications overview')
-    target = 'applications_overview_slip.pdf'
-
-
-class ApplicationManageActionButton(ManageActionButton):
-    grok.order(1)
-    grok.context(IApplication)
-    grok.view(ApplicationDisplayFormPage)
+    text = _('Download contracts overview')
+    target = 'contracts_overview_slip.pdf'
+
+
+class ContractManageActionButton(ManageActionButton):
+    grok.order(1)
+    grok.context(IContract)
+    grok.view(ContractDisplayFormPage)
     grok.require('waeup.manageCustomer')
     text = _('Manage')
@@ -402,8 +402,8 @@
 
 
-class ApplicationEditActionButton(ManageActionButton):
-    grok.order(1)
-    grok.context(IApplication)
-    grok.view(ApplicationDisplayFormPage)
+class ContractEditActionButton(ManageActionButton):
+    grok.order(1)
+    grok.context(IContract)
+    grok.view(ContractDisplayFormPage)
     grok.require('waeup.handleCustomer')
     text = _('Edit')
@@ -417,8 +417,8 @@
 
 
-class ApplicationTrigTransActionButton(ManageActionButton):
-    grok.order(2)
-    grok.context(IApplication)
-    grok.view(ApplicationDisplayFormPage)
+class ContractTrigTransActionButton(ManageActionButton):
+    grok.order(2)
+    grok.context(IContract)
+    grok.view(ContractDisplayFormPage)
     grok.require('waeup.triggerTransition')
     icon = 'actionicon_trigtrans.png'
@@ -427,8 +427,8 @@
 
 
-class ApplicationViewActionButton(ManageActionButton):
-    grok.order(1)
-    grok.context(IApplication)
-    grok.view(ApplicationManageFormPage)
+class ContractViewActionButton(ManageActionButton):
+    grok.order(1)
+    grok.context(IContract)
+    grok.view(ContractManageFormPage)
     grok.require('waeup.handleCustomer')
     text = _('View')
@@ -437,11 +437,11 @@
 
 
-class PDFApplicationSlipActionButton(ManageActionButton):
-    grok.order(3)
-    grok.context(IApplication)
-    grok.view(ApplicationDisplayFormPage)
+class PDFContractSlipActionButton(ManageActionButton):
+    grok.order(3)
+    grok.context(IContract)
+    grok.view(ContractDisplayFormPage)
     grok.require('waeup.viewCustomer')
     icon = 'actionicon_pdf.png'
-    text = _('Download application slip')
-    target = 'application_slip.pdf'
-
+    text = _('Download contract slip')
+    target = 'contract_slip.pdf'
+
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/vocabularies.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/vocabularies.py	(revision 12096)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/vocabularies.py	(revision 12097)
@@ -121,20 +121,20 @@
 
 class AppCatProductSource(SmartBasicContextualSourceFactory):
-    """An application category product delivers all products
-    which belong to a certain application_category.
+    """An contract category product delivers all products
+    which belong to a certain contract_category.
     """
     def contains(self, context, value):
-        appcat = getattr(context, 'application_category', None)
-        if value.application_category == appcat:
+        appcat = getattr(context, 'contract_category', None)
+        if value.contract_category == appcat:
             return True
         return False
 
     def getValues(self, context):
-        appcat = getattr(context, 'application_category', None)
+        appcat = getattr(context, 'contract_category', None)
         products = grok.getSite()['products'].values()
         if not appcat:
             return products
         resultlist = [
-            value for value in products if value.application_category == appcat]
+            value for value in products if value.contract_category == appcat]
         return resultlist
 
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/workflow.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/workflow.py	(revision 12096)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/workflow.py	(revision 12097)
@@ -31,5 +31,5 @@
 from waeup.ikoba.customers.interfaces import (
     ICustomer, ICustomersUtils,
-    IApplication)
+    IContract)
 from waeup.ikoba.utils.helpers import get_current_principal
 from waeup.ikoba.documents.workflow import VERIFICATION_TRANSITIONS
@@ -142,15 +142,15 @@
     return
 
-# Application workflow (the same as verification workflow)
-
-IMPORTABLE_APPLICATION_STATES = (CREATED, SUBMITTED, APPROVED, REJECTED, EXPIRED)
-
-APPLICATION_TRANSITIONS = (
+# Contract workflow (the same as verification workflow)
+
+IMPORTABLE_CONTRACT_STATES = (CREATED, SUBMITTED, APPROVED, REJECTED, EXPIRED)
+
+CONTRACT_TRANSITIONS = (
     Transition(
         transition_id = 'create',
-        title = _('Create application record'),
+        title = _('Create contract record'),
         source = None,
         condition = NullCondition,
-        msg = _('Application record created'),
+        msg = _('Contract record created'),
         destination = CREATED),
 
@@ -213,31 +213,31 @@
 
 
-IMPORTABLE_APPLICATION_TRANSITIONS = [
+IMPORTABLE_CONTRACT_TRANSITIONS = [
     i.transition_id for i in REGISTRATION_TRANSITIONS]
 
-application_workflow = IkobaWorkflow(APPLICATION_TRANSITIONS)
-
-class ApplicationWorkflowState(WorkflowState, grok.Adapter):
-    """An adapter to adapt Application objects to workflow states.
-    """
-    grok.context(IApplication)
+contract_workflow = IkobaWorkflow(CONTRACT_TRANSITIONS)
+
+class ContractWorkflowState(WorkflowState, grok.Adapter):
+    """An adapter to adapt Contract objects to workflow states.
+    """
+    grok.context(IContract)
     grok.provides(IWorkflowState)
 
-    state_key = 'wf.application.state'
-    state_id = 'wf.application.id'
-
-class ApplicationWorkflowInfo(IkobaWorkflowInfo, grok.Adapter):
-    """Adapter to adapt Application objects to workflow info objects.
-    """
-    grok.context(IApplication)
+    state_key = 'wf.contract.state'
+    state_id = 'wf.contract.id'
+
+class ContractWorkflowInfo(IkobaWorkflowInfo, grok.Adapter):
+    """Adapter to adapt Contract objects to workflow info objects.
+    """
+    grok.context(IContract)
     grok.provides(IIkobaWorkflowInfo)
 
     def __init__(self, context):
         self.context = context
-        self.wf = application_workflow
-
-@grok.subscribe(IApplication, IWorkflowTransitionEvent)
+        self.wf = contract_workflow
+
+@grok.subscribe(IContract, IWorkflowTransitionEvent)
 def handle_document_transition_event(obj, event):
-    """Append message to application history and log file and update
+    """Append message to contract history and log file and update
     last_transition_date when transition happened.
     """
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/permissions.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/permissions.py	(revision 12096)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/permissions.py	(revision 12097)
@@ -144,5 +144,5 @@
                      'waeup.triggerTransition',
                      'waeup.viewCustomersTab',
-                     'waeup.editApplications'
+                     'waeup.editContracts'
                      )
 
@@ -170,5 +170,5 @@
                      'waeup.triggerTransition',
                      'waeup.viewCustomersTab',
-                     'waeup.editApplications'
+                     'waeup.editContracts'
                      )
 
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/products/interfaces.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/products/interfaces.py	(revision 12096)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/products/interfaces.py	(revision 12097)
@@ -24,5 +24,5 @@
 
 class AppCatSource(ContextualDictSourceFactoryBase):
-    """A application category source delivers all application categories
+    """A contract category source delivers all contract categories
     provided in the portal.
     """
@@ -55,6 +55,6 @@
         )
 
-    application_category = schema.Choice(
-        title = _(u'Application Category'),
+    contract_category = schema.Choice(
+        title = _(u'Contract Category'),
         source = AppCatSource(),
         default = u'license',
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/products/product.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/products/product.py	(revision 12096)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/products/product.py	(revision 12097)
@@ -66,22 +66,22 @@
 def handle_product_removed(product, event):
     """If a product is deleted, we make sure that also referrers to
-    customer application objects are removed.
+    customer contract objects are removed.
     """
     prodid = product.product_id
 
-    # Find all customer applications that refer to given product...
+    # Find all customer contracts that refer to given product...
     try:
-        cat = getUtility(ICatalog, name='applications_catalog')
+        cat = getUtility(ICatalog, name='contracts_catalog')
     except ComponentLookupError:
         # catalog not available. This might happen during tests.
         return
     results = cat.searchResults(last_product_id=(prodid, prodid))
-    for application in results:
+    for contract in results:
         # Remove that referrer...
-        application.product = None
-        notify(grok.ObjectModifiedEvent(application))
-        application.customer.__parent__.logger.info(
+        contract.product = None
+        notify(grok.ObjectModifiedEvent(contract))
+        contract.customer.__parent__.logger.info(
             'ObjectRemovedEvent - %s - %s - removed: product' % (
-                application.customer.customer_id, application.application_id))
+                contract.customer.customer_id, contract.contract_id))
     return
 
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/products/tests/sample_product_data.csv
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/products/tests/sample_product_data.csv	(revision 12096)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/products/tests/sample_product_data.csv	(revision 12097)
@@ -1,3 +1,3 @@
-product_id,title,application_category
+product_id,title,contract_category
 ABC,ABC title,license
 CDE,CDE title,license
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/products/tests/test_batching.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/products/tests/test_batching.py	(revision 12096)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/products/tests/test_batching.py	(revision 12097)
@@ -165,5 +165,5 @@
             'INFO - system - Product Processor - sample_product_data - '
             'EFG - updated: product_id=EFG, title=EFG title, '
-            'application_category=license\n'
+            'contract_category=license\n'
             in logcontent)
         failcontent = open(fail_file).read()
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/products/tests/test_export.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/products/tests/test_export.py	(revision 12096)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/products/tests/test_export.py	(revision 12097)
@@ -62,5 +62,5 @@
         result = open(self.outfile, 'rb').read()
         self.assertTrue(
-            'application_category,product_id,title,users_with_local_roles\r\n'
+            'contract_category,product_id,title,users_with_local_roles\r\n'
             'license,LIC,Unnamed,"[{\'user_name\': u\'john\', \'local_role\': '
             'u\'johnsrole\'}]"\r\n'
@@ -75,5 +75,5 @@
         result = open(self.outfile, 'rb').read()
         self.assertTrue(
-            'application_category,product_id,title,users_with_local_roles\r\n'
+            'contract_category,product_id,title,users_with_local_roles\r\n'
             'license,LIC,Unnamed,"[{\'user_name\': u\'john\', \'local_role\': '
             'u\'johnsrole\'}]"\r\n'
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/webservices.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/webservices.py	(revision 12096)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/webservices.py	(revision 12097)
@@ -20,5 +20,5 @@
 from zope.component import getUtility
 from zope.catalog.interfaces import ICatalog
-from waeup.ikoba.interfaces import ICompany, application_sessions_vocab
+from waeup.ikoba.interfaces import ICompany
 
 class XMLRPCPermission(grok.Permission):
