Index: main/waeup.uniben/trunk/src/waeup/uniben/students/browser.py
===================================================================
--- main/waeup.uniben/trunk/src/waeup/uniben/students/browser.py	(revision 18051)
+++ main/waeup.uniben/trunk/src/waeup/uniben/students/browser.py	(revision 18064)
@@ -26,4 +26,5 @@
 from zope.formlib.textwidgets import BytesDisplayWidget
 from zope.component import getUtility, queryUtility
+from zope.catalog.interfaces import ICatalog
 from hurry.workflow.interfaces import IWorkflowInfo
 from waeup.kofa.interfaces import (
@@ -31,4 +32,6 @@
 from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
 from waeup.kofa.browser.layout import action, KofaEditFormPage, UtilityView, KofaPage
+from waeup.kofa.browser.pages import LocalRoleAssignmentUtilityView
+from waeup.kofa.university.interfaces import ICourse
 from waeup.kofa.students.browser import (
     StudentBaseEditFormPage,
@@ -875,4 +878,77 @@
     form_fields['email'].field.required = True
 
+class ExportMarkSheetSlip(UtilityView, grok.View,
+    LocalRoleAssignmentUtilityView):
+    """Deliver a PDF slip of course tickets in attendance sheet format.
+    """
+    grok.context(ICourse)
+    grok.name('marksheet.pdf')
+    grok.require('waeup.showStudents')
+
+    def update(self):
+        self.current_academic_session = grok.getSite()[
+            'configuration'].current_academic_session
+        if not self.current_academic_session:
+            self.flash(_('Current academic session not set.'), type="danger")
+            self.redirect(self.url(self.context))
+            return
+
+    @property
+    def note(self):
+        return
+
+    def data(self, session):
+        cat = queryUtility(ICatalog, name='coursetickets_catalog')
+        # Attention: Also tickets of previous studycourses are found
+        coursetickets = cat.searchResults(
+            session=(session, session),
+            code=(self.context.code, self.context.code)
+            )
+        header = [[_('S/N'),
+                   _('Matric No.'),
+                   _('Name'),
+                   _('Level'),
+                   _('Course of\nStudies'),
+                   _('CA'),
+                   _('Exam'),
+                   _('Total'),
+                   ],]
+        tickets = []
+        sn = 1
+        ctlist = sorted(list(coursetickets),
+                        key=lambda value: str(value.student.faccode) +
+                                          str(value.student.depcode) +
+                                          str(value.student.certcode) +
+                                          str(value.student.matric_number))
+        # In AAUE only editable appear on the attendance sheet. Hopefully
+        # this holds for other universities too.
+        editable_tickets = [ticket for ticket in ctlist
+            if ticket.editable_by_lecturer]
+        for ticket in editable_tickets:
+            name = textwrap.fill(ticket.student.display_fullname, 20)
+            row = [sn,
+                  ticket.student.matric_number,
+                  name,
+                  ticket.level,
+                  ticket.student.certcode,
+                  20 * ' ',
+                  20 * ' ',
+                  20 * ' ',
+                  ]
+            tickets.append(row)
+            sn += 1
+        return header + tickets, None
+
+    def render(self):
+        lecturers = [i['user_title'] for i in self.getUsersWithLocalRoles()
+                     if i['local_role'] == 'waeup.local.Lecturer']
+        lecturers =  ', '.join(lecturers)
+        students_utils = getUtility(IStudentsUtils)
+        return students_utils.renderPDFCourseticketsOverview(
+            self, 'marksheet', self.current_academic_session,
+            self.data(self.current_academic_session),
+            lecturers, '', 65, self.note)
+
+
 
 
Index: main/waeup.uniben/trunk/src/waeup/uniben/students/tests/test_browser.py
===================================================================
--- main/waeup.uniben/trunk/src/waeup/uniben/students/tests/test_browser.py	(revision 18051)
+++ main/waeup.uniben/trunk/src/waeup/uniben/students/tests/test_browser.py	(revision 18064)
@@ -1348,2 +1348,22 @@
         open(path, 'wb').write(self.browser.contents)
         print "Sample PDF affidavit_good_conduct.pdf written to %s" % path
+
+    def test_download_mark_sheet(self):
+        # A course ticket slip can be downloaded
+        self.course.title = (u'Lorem ipsum     dolor sit amet, consectetur     adipisici, '
+                             u'sed         eiusmod tempor    incidunt ut  labore et dolore')
+        self.student.firstname = u'Emmanuella Woyengifigha Mercy Onosemudiana'
+        self.student.lastname = u'OYAKEMIEGBEGHA'
+        self.student.matric_number = u'hdk7gd62i872z27zt27ge'
+        self.app['configuration'].current_academic_session = 2004
+        course_url = (
+            'http://localhost/app/faculties/fac1/dep1/courses/COURSE1')
+        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+        pdf_url = '%s/marksheet.pdf' % course_url
+        self.browser.open(pdf_url)
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertEqual(
+            self.browser.headers['Content-Type'], 'application/pdf')
+        path = os.path.join(samples_dir(), 'marksheet.pdf')
+        open(path, 'wb').write(self.browser.contents)
+        print "Sample PDF marksheet.pdf written to %s" % path
