Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser.py	(revision 12017)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser.py	(revision 12018)
@@ -43,4 +43,5 @@
 from waeup.ikoba.browser.interfaces import ICaptchaManager
 from waeup.ikoba.mandates.mandate import PasswordMandate
+from waeup.ikoba.documents.workflow import VERIFIED, REJECTED, OUTDATED
 from waeup.ikoba.utils.helpers import get_current_principal, to_timezone, now
 from waeup.ikoba.customers.interfaces import (
@@ -577,6 +578,6 @@
 
     def update(self):
-        PWCHANGE_STATES = getUtility(ICustomersUtils).PWCHANGE_STATES
-        if self.context.customer.state not in PWCHANGE_STATES:
+        CUSTMANAGE_STATES = getUtility(ICustomersUtils).CUSTMANAGE_STATES
+        if self.context.customer.state not in CUSTMANAGE_STATES:
             emit_lock_message(self)
             return
@@ -756,10 +757,13 @@
     pnav = 4
 
+    #@property
+    #def label(self):
+    #    return _('${a}: Document ${b}', mapping = {
+    #        'a':self.context.customer.display_fullname,
+    #        'b':self.context.document_id})
+
     @property
     def label(self):
-        return _('${a}: Document ${b}', mapping = {
-            'a':self.context.customer.display_fullname,
-            'b':self.context.document_id})
-        return self.context.document_id
+        return _('${a}', mapping = {'a':self.context.title})
 
 
@@ -770,13 +774,17 @@
     grok.name('manage')
     grok.require('waeup.manageCustomer')
+    grok.template('documenteditpage')
     form_fields = grok.AutoFields(ICustomerDocument)
     pnav = 4
 
+    #@property
+    #def label(self):
+    #    return _('${a}: Document ${b}', mapping = {
+    #        'a':self.context.customer.display_fullname,
+    #        'b':self.context.document_id})
+
     @property
     def label(self):
-        return _('${a}: Document ${b}', mapping = {
-            'a':self.context.customer.display_fullname,
-            'b':self.context.document_id})
-        return self.context.document_id
+        return _('${a}', mapping = {'a':self.context.title})
 
     @action(_('Save'), style='primary')
@@ -784,2 +792,17 @@
         msave(self, **data)
         return
+
+class DocumentEditFormPage(DocumentManageFormPage):
+    """ Page to edit a document
+    """
+    grok.context(ICustomerDocument)
+    grok.name('edit')
+    grok.require('waeup.handleCustomer')
+    form_fields = grok.AutoFields(ICustomerDocument)
+    pnav = 4
+
+    def update(self):
+        if not self.context.is_editable:
+            emit_lock_message(self)
+            return
+        return super(DocumentEditFormPage, self).update()
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/documenteditpage.pt
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/documenteditpage.pt	(revision 12018)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/browser_templates/documenteditpage.pt	(revision 12018)
@@ -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="">Scans</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>
+          <tal:files content="structure provider:files" />
+        </tbody>
+      </table>
+    </div>
+  </div>
+</form>
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/documents.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/documents.py	(revision 12017)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/documents.py	(revision 12018)
@@ -20,10 +20,13 @@
 """
 import grok
+from zope.component import queryUtility, getUtility
 from zope.component.interfaces import IFactory
 from zope.interface import implementedBy
 from waeup.ikoba.interfaces import MessageFactory as _
 from waeup.ikoba.customers.interfaces import (
-    ICustomerDocumentsContainer, ICustomerNavigation, ICustomerDocument)
+    ICustomerDocumentsContainer, ICustomerNavigation, ICustomerDocument,
+    ICustomersUtils)
 from waeup.ikoba.documents import DocumentsContainer, Document
+from waeup.ikoba.documents.interfaces import IDocumentsUtils
 from waeup.ikoba.utils.helpers import attrs_to_fields
 
@@ -67,4 +70,19 @@
         return self.__parent__.__parent__.writeLogMessage(view, message)
 
+    @property
+    def is_editable(self):
+        try:
+            # Customer must be approved
+            cond1 = self.customer.state in getUtility(
+                ICustomersUtils).DOCMANAGE_STATES
+            # Document must be in state created
+            cond2 = self.state in getUtility(
+                IDocumentsUtils).DOCMANAGE_STATES
+            if not (cond1 and cond2):
+                return False
+        except AttributeError:
+            pass
+        return True
+
 CustomerDocument = attrs_to_fields(CustomerDocument)
 
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/export.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/export.py	(revision 12017)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/export.py	(revision 12018)
@@ -145,5 +145,7 @@
     fields = tuple(
         sorted(iface_names(
-            ICustomerDocument, exclude_attribs=False))) + (
+            ICustomerDocument,
+            exclude_attribs=False,
+            omit=['is_editable']))) + (
             'customer_id',)
 
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/interfaces.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/interfaces.py	(revision 12017)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/interfaces.py	(revision 12018)
@@ -1,3 +1,3 @@
-## $Id: interfaces.py 11589 2014-04-22 07:13:16Z henrik $
+## $Id$
 ##
 ## Copyright (C) 2014 Uli Fouquet & Henrik Bettermann
@@ -241,2 +241,3 @@
     """
 
+    is_editable = Attribute('Document editable by customer')
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 12017)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_browser.py	(revision 12018)
@@ -107,5 +107,5 @@
         # Set password
         IUserAccount(
-            self.app['customers'][self.customer_id]).setPassword('spwd')
+            self.app['customers'][self.customer_id]).setPassword('cpwd')
 
         self.login_path = 'http://localhost/app/login'
@@ -484,5 +484,5 @@
         self.browser.open(self.login_path)
         self.browser.getControl(name="form.login").value = self.customer_id
-        self.browser.getControl(name="form.password").value = 'spwd'
+        self.browser.getControl(name="form.password").value = 'cpwd'
         self.browser.getControl("Login").click()
         self.assertMatches(
@@ -511,5 +511,5 @@
         self.browser.open(self.login_path)
         self.browser.getControl(name="form.login").value = self.customer_id
-        self.browser.getControl(name="form.password").value = 'spwd'
+        self.browser.getControl(name="form.password").value = 'cpwd'
         self.browser.getControl("Login").click()
         self.assertEqual(self.browser.url, self.customer_path)
@@ -554,5 +554,5 @@
         self.browser.open(self.login_path)
         self.browser.getControl(name="form.login").value = self.customer_id
-        self.browser.getControl(name="form.password").value = 'spwd'
+        self.browser.getControl(name="form.password").value = 'cpwd'
         self.browser.getControl("Login").click()
         self.assertMatches(
@@ -575,5 +575,5 @@
         self.browser.open(self.login_path)
         self.browser.getControl(name="form.login").value = self.customer_id
-        self.browser.getControl(name="form.password").value = 'spwd'
+        self.browser.getControl(name="form.password").value = 'cpwd'
         self.browser.getControl("Login").click()
         self.assertEqual(self.browser.url, self.customer_path)
@@ -594,5 +594,5 @@
         self.browser.open(self.login_path)
         self.browser.getControl(name="form.login").value = self.customer_id
-        self.browser.getControl(name="form.password").value = 'spwd'
+        self.browser.getControl(name="form.password").value = 'cpwd'
         self.browser.getControl("Login").click()
         self.assertTrue(
@@ -600,10 +600,10 @@
         # We set the password again
         IUserAccount(
-            self.app['customers'][self.customer_id]).setPassword('spwd')
+            self.app['customers'][self.customer_id]).setPassword('cpwd')
         # Customers can't login if their account is suspended/deactivated
         self.customer.suspended = True
         self.browser.open(self.login_path)
         self.browser.getControl(name="form.login").value = self.customer_id
-        self.browser.getControl(name="form.password").value = 'spwd'
+        self.browser.getControl(name="form.password").value = 'cpwd'
         self.browser.getControl("Login").click()
         self.assertMatches(
@@ -613,5 +613,5 @@
         self.customer.suspended_comment = u'Aetsch baetsch!'
         self.browser.getControl(name="form.login").value = self.customer_id
-        self.browser.getControl(name="form.password").value = 'spwd'
+        self.browser.getControl(name="form.password").value = 'cpwd'
         self.browser.getControl("Login").click()
         self.assertMatches(
@@ -622,8 +622,8 @@
         # is not expired
         self.app['customers'][self.customer_id].setTempPassword(
-            'anybody', 'temp_spwd')
-        self.browser.open(self.login_path)
-        self.browser.getControl(name="form.login").value = self.customer_id
-        self.browser.getControl(name="form.password").value = 'spwd'
+            'anybody', 'temp_cpwd')
+        self.browser.open(self.login_path)
+        self.browser.getControl(name="form.login").value = self.customer_id
+        self.browser.getControl(name="form.password").value = 'cpwd'
         self.browser.getControl("Login").click()
         self.assertMatches(
@@ -633,5 +633,5 @@
         self.browser.open(self.login_path)
         self.browser.getControl(name="form.login").value = self.customer_id
-        self.browser.getControl(name="form.password").value = 'temp_spwd'
+        self.browser.getControl(name="form.password").value = 'temp_cpwd'
         self.browser.getControl("Login").click()
         self.assertMatches(
@@ -652,5 +652,5 @@
         self.browser.open(self.login_path)
         self.browser.getControl(name="form.login").value = self.customer_id
-        self.browser.getControl(name="form.password").value = 'spwd'
+        self.browser.getControl(name="form.password").value = 'cpwd'
         self.browser.getControl("Login").click()
         self.assertMatches(
@@ -825,2 +825,37 @@
             '- K1000000 - removed: %s'
             % document.document_id in logcontent)
+
+    def test_edit_document(self):
+        # Customers can manage documents under certain conditions
+        self.browser.open(self.login_path)
+        self.browser.getControl(name="form.login").value = self.customer_id
+        self.browser.getControl(name="form.password").value = 'cpwd'
+        self.browser.getControl("Login").click()
+        self.assertMatches(
+            '...You logged in...', self.browser.contents)
+        self.browser.getLink("Documents").click()
+        self.browser.getLink("Add document").click()
+        self.browser.getControl(name="doctype").value = ['generic']
+        self.browser.getControl("Create document").click()
+        self.assertTrue('Generic Document created.' in self.browser.contents)
+        document = self.customer['documents']['d102']
+
+        # Document can be edited ...
+        self.browser.getLink("d102").click()
+
+
+        self.browser.open(self.documents_path + '/d102/edit')
+        #self.browser.getLink("Edit").click()
+        self.assertTrue('The requested form is locked' in self.browser.contents)
+
+
+
+
+
+
+
+        self.browser.getControl(name="form.title").value = 'My second doc'
+        self.browser.getControl("Save").click()
+        self.assertTrue('Form has been saved.' in self.browser.contents)
+        self.browser.getLink("View").click()
+        self.assertEqual(self.browser.url, self.documents_path + '/d102/index')
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/utils.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/utils.py	(revision 12017)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/utils.py	(revision 12018)
@@ -1,3 +1,3 @@
-## $Id: utils.py 11875 2014-10-24 12:47:13Z henrik $
+## $Id$
 ##
 ## Copyright (C) 2014 Uli Fouquet & Henrik Bettermann
@@ -19,5 +19,5 @@
 """
 import grok
-from waeup.ikoba.interfaces import STARTED
+from waeup.ikoba.interfaces import STARTED, APPROVED
 from waeup.ikoba.customers.interfaces import ICustomersUtils
 
@@ -38,3 +38,5 @@
     CUSTOMER_ID_PREFIX = u'K'
 
-    PWCHANGE_STATES = (STARTED,)
+    CUSTMANAGE_STATES = (STARTED,)
+
+    DOCMANAGE_STATES = (APPROVED,)
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/viewlets.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/viewlets.py	(revision 12017)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/customers/viewlets.py	(revision 12018)
@@ -307,9 +307,25 @@
     target = 'manage'
 
+
+class DocumentEditActionButton(ManageActionButton):
+    grok.order(1)
+    grok.context(ICustomerDocument)
+    grok.view(DocumentDisplayFormPage)
+    grok.require('waeup.handleCustomer')
+    text = _('Edit')
+    target = 'edit'
+
+    @property
+    def target_url(self):
+        if not self.context.is_editable:
+            return ''
+        return self.view.url(self.view.context, self.target)
+
+
 class DocumentViewActionButton(ManageActionButton):
     grok.order(1)
     grok.context(ICustomerDocument)
     grok.view(DocumentManageFormPage)
-    grok.require('waeup.manageCustomer')
+    grok.require('waeup.handleCustomer')
     text = _('View')
     target = 'index'
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/documents/interfaces.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/documents/interfaces.py	(revision 12017)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/documents/interfaces.py	(revision 12018)
@@ -16,5 +16,5 @@
 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 ##
-from zope.interface import Attribute
+from zope.interface import Attribute, Interface
 from zope import schema
 from waeup.ikoba.interfaces import (
@@ -52,3 +52,7 @@
         )
 
+class IDocumentsUtils(Interface):
+    """A collection of methods which are subject to customization.
 
+    """
+
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/documents/utils.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/documents/utils.py	(revision 12017)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/documents/utils.py	(revision 12018)
@@ -19,4 +19,6 @@
 """
 import grok
+from waeup.ikoba.documents.workflow import CREATED
+from waeup.ikoba.documents.interfaces import IDocumentsUtils
 
 
@@ -24,2 +26,10 @@
     new_id = grok.getSite().unique_document_id
     return new_id
+
+
+class DocumentssUtils(grok.GlobalUtility):
+    """A collection of methods subject to customization.
+    """
+    grok.implements(IDocumentsUtils)
+
+    DOCMANAGE_STATES = (CREATED,)
