Index: main/waeup.kofa/branches/henrik-transcript-workflow/src/waeup/kofa/students/browser.py
===================================================================
--- main/waeup.kofa/branches/henrik-transcript-workflow/src/waeup/kofa/students/browser.py	(revision 15149)
+++ main/waeup.kofa/branches/henrik-transcript-workflow/src/waeup/kofa/students/browser.py	(revision 15150)
@@ -1188,8 +1188,9 @@
         if prev_transcript_signees == None:
             prev_transcript_signees = ''
-        self.context.student.transcript_signees = '''Signed by %s (%s) on %s
-
-%s''' % (self.request.principal.title, self.request.principal.id, today,
-            prev_transcript_signees)
+        self.context.student.transcript_signees = (
+            u"Electronically signed by %s (%s) on %s\n%s"
+            % (self.request.principal.title, self.request.principal.id, today,
+            prev_transcript_signees))
+        self.redirect(self.url(self.context) + '/transcript')
         return
 
@@ -1221,5 +1222,6 @@
             self.correspondence = ''
         if self.context.transcript_signees is not None:
-            self.signees = self.context.transcript_signees.replace('\n', '<br>')
+            self.signees = self.context.transcript_signees.replace(
+                '\n', '<br><br>')
         else:
             self.signees = ''
@@ -1243,5 +1245,5 @@
         self.context.writeLogMessage(
             self, 'comment: %s' % comment.replace('\n', '<br>'))
-        # Show and produce transcript file
+        # Produce transcript file
         self.redirect(self.url(self.context) + '/studycourse/transcript.pdf')
         return
@@ -1273,7 +1275,8 @@
 
     def update(self):
-        if not self.context.student.transcript_enabled:
-            self.flash(_('You are not allowed to view the transcript.'),
-                       type="warning")
+        final_slip = getUtility(IExtFileStore).getFileByContext(
+            self.context.student, attr='final_transcript')
+        if not self.context.student.transcript_enabled or final_slip:
+            self.flash(_('Forbidden!'), type="warning")
             self.redirect(self.url(self.context))
             return
@@ -1306,7 +1309,9 @@
 
     def update(self):
-        if not self.context.student.transcript_enabled:
-            self.flash(_('You are not allowed to download the transcript.'),
-                       type="warning")
+        final_slip = getUtility(IExtFileStore).getFileByContext(
+            self.context.student, attr='final_transcript')
+        if not self.context.student.transcript_enabled \
+            or final_slip:
+            self.flash(_('Forbidden!'), type="warning")
             self.redirect(self.url(self.context))
             return
@@ -1327,8 +1332,15 @@
 
     def _sigsInFooter(self):
+        if self.context.student.transcript_signees:
+            return ()
         return (_('CERTIFIED TRUE COPY'),)
 
     def _signatures(self):
-        return None
+        return ()
+
+    def _digital_sigs(self):
+        if self.context.student.transcript_signees:
+            return self.context.student.transcript_signees #.split('\n')
+        return ()
 
     def _save_file(self):
@@ -1364,4 +1376,5 @@
             signatures=self._signatures(),
             sigs_in_footer=self._sigsInFooter(),
+            digital_sigs=self._digital_sigs(),
             save_file=self._save_file(),
             )
Index: main/waeup.kofa/branches/henrik-transcript-workflow/src/waeup/kofa/students/tests/test_browser.py
===================================================================
--- main/waeup.kofa/branches/henrik-transcript-workflow/src/waeup/kofa/students/tests/test_browser.py	(revision 15149)
+++ main/waeup.kofa/branches/henrik-transcript-workflow/src/waeup/kofa/students/tests/test_browser.py	(revision 15150)
@@ -2192,5 +2192,5 @@
         prmglobal.assignRoleToPrincipal('waeup.TranscriptSignee', 'mrtranscript')
         self.browser.open(self.studycourse_path + '/transcript')
-        self.browser.getLink("Sign transcript").click()
+        self.browser.getLink("Sign transcript electronically").click()
         # Transcript signing has been logged ...
         logfile = os.path.join(
@@ -2200,8 +2200,12 @@
             'mrtranscript - students.browser.StudentTranscriptSignView - '
             'K1000000 - Transcript signed' in logcontent)
-        # ... and appears in the student's history
+        # ... appears in the student's history ...
         self.browser.open(self.history_path)
         self.assertTrue('Transcript signed by Ruth Gordon'
             in self.browser.contents)
+        # ... and is also stored in the transcript_signee attribute.
+        self.assertTrue(
+            u'Electronically signed by Ruth Gordon (mrtranscript) on '
+            in self.student.transcript_signees)
         # Officer can release the transcript
         self.browser.open(self.student_path)
@@ -2245,4 +2249,19 @@
         self.assertEqual(self.browser.headers['Content-Type'],
                          'application/pdf')
+        # Transcript views are no longer accesssible
+        self.browser.open(self.student_path)
+        self.assertFalse('studycourse/transcript' in self.browser.contents)
+        self.browser.open(self.studycourse_path)
+        self.assertFalse('studycourse/transcript' in self.browser.contents)
+        self.browser.open(self.studycourse_path + '/transcript')
+        self.assertTrue('Forbidden!' in self.browser.contents)
+        self.browser.open(self.studycourse_path + '/transcript.pdf')
+        self.assertTrue('Forbidden!' in self.browser.contents)
+        # If we reset the transcript process
+        # (can't be done by transcript officer), the file will be deleted
+        IWorkflowInfo(self.student).fireTransition('reset11')
+        self.browser.open(self.student_path)
+        self.assertFalse('Final Transcript' in self.browser.contents)
+
 
 class StudentUITests(StudentsFullSetup):
Index: main/waeup.kofa/branches/henrik-transcript-workflow/src/waeup/kofa/students/utils.py
===================================================================
--- main/waeup.kofa/branches/henrik-transcript-workflow/src/waeup/kofa/students/utils.py	(revision 15149)
+++ main/waeup.kofa/branches/henrik-transcript-workflow/src/waeup/kofa/students/utils.py	(revision 15150)
@@ -867,5 +867,8 @@
                   student=None,
                   studentview=None,
-                  note=None, signatures=None, sigs_in_footer=(),
+                  note=None,
+                  signatures=(),
+                  sigs_in_footer=(),
+                  digital_sigs=(),
                   show_scans=True, topMargin=1.5,
                   omit_fields=(),
@@ -967,4 +970,11 @@
                 signaturetables = get_signature_tables(signature)
                 data.append(signaturetables[0])
+
+        # Insert digital signatures
+        if digital_sigs:
+            data.append(Spacer(1, 20))
+            sigs = digital_sigs.split('\n')
+            for sig in sigs:
+                data.append(Paragraph(sig, NOTE_STYLE))
 
         view.response.setHeader(
Index: main/waeup.kofa/branches/henrik-transcript-workflow/src/waeup/kofa/students/viewlets.py
===================================================================
--- main/waeup.kofa/branches/henrik-transcript-workflow/src/waeup/kofa/students/viewlets.py	(revision 15149)
+++ main/waeup.kofa/branches/henrik-transcript-workflow/src/waeup/kofa/students/viewlets.py	(revision 15150)
@@ -40,5 +40,5 @@
 from waeup.kofa.students.workflow import (
     ADMITTED, PAID, REQUESTED, CLEARED, REGISTERED, VALIDATED, GRADUATED,
-    TRANSREQ, TRANSVAL)
+    TRANSREQ, TRANSVAL, TRANSREL)
 from waeup.kofa.university.interfaces import ICourse
 
@@ -738,5 +738,7 @@
     @property
     def target_url(self):
-        if self.context.student.transcript_enabled:
+        final_slip = getUtility(IExtFileStore).getFileByContext(
+            self.context.student, attr='final_transcript')
+        if self.context.student.transcript_enabled and not final_slip:
             return self.view.url(self.view.context, self.target)
         return False
@@ -810,5 +812,8 @@
     @property
     def target_url(self):
-        if self.context.student.transcript_enabled:
+        final_slip = getUtility(IExtFileStore).getFileByContext(
+            self.context.student, attr='final_transcript')
+        if self.context.student.transcript_enabled \
+            and not final_slip:
             return self.view.url(self.view.context, self.target)
         return False
@@ -820,5 +825,5 @@
     grok.view(StudyCourseTranscriptPage)
     grok.require('waeup.signTranscript')
-    text = _('Sign transcript')
+    text = _('Sign transcript electronically')
     target = 'sign_transcript'
     icon = 'actionicon_transcript.png'
@@ -833,6 +838,6 @@
     def onclick(self):
         return "return window.confirm(%s);" % _(
-            "'Signing a transcript cannot be revoked."
-            "\\n\\n"
+            "'Signing a transcript electronically cannot be revoked. "
+            "The electronic signature replaces your handwritten signature.\\n\\n"
             "You really want to sign the transcript?'")
 
Index: main/waeup.kofa/branches/henrik-transcript-workflow/src/waeup/kofa/students/workflow.py
===================================================================
--- main/waeup.kofa/branches/henrik-transcript-workflow/src/waeup/kofa/students/workflow.py	(revision 15149)
+++ main/waeup.kofa/branches/henrik-transcript-workflow/src/waeup/kofa/students/workflow.py	(revision 15150)
@@ -9,5 +9,6 @@
     IObjectHistory, IKofaWorkflowInfo, IKofaUtils,
     CREATED, ADMITTED, CLEARANCE, REQUESTED, CLEARED, PAID, RETURNING,
-    REGISTERED, VALIDATED, GRADUATED, TRANSREQ, TRANSVAL, TRANSREL)
+    REGISTERED, VALIDATED, GRADUATED, TRANSREQ, TRANSVAL, TRANSREL,
+    IExtFileStore)
 from waeup.kofa.interfaces import MessageFactory as _
 from waeup.kofa.workflow import KofaWorkflow, KofaWorkflowInfo
@@ -296,4 +297,10 @@
             level_object.validated_by = None
             level_object.validation_date = None
+    elif event.transition.transition_id == 'reset11':
+        transcript_file = getUtility(IExtFileStore).getFileByContext(
+            obj, attr='final_transcript')
+        if transcript_file:
+            getUtility(IExtFileStore).deleteFileByContext(
+                obj, attr='final_transcript')
     # In some tests we don't have a students container
     try:
