Index: main/waeup.kofa/trunk/src/waeup/kofa/browser/viewlets.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/browser/viewlets.py	(revision 13886)
+++ main/waeup.kofa/trunk/src/waeup/kofa/browser/viewlets.py	(revision 13894)
@@ -27,4 +27,5 @@
     DepartmentPage, CoursePage, CertificatePage, CertificateCoursePage,
     UsersContainerPage, UserManageFormPage, DatacenterImportStep1)
+from waeup.kofa.students.browser import EditScoresPage
 from waeup.kofa.browser.interfaces import (
     IFacultiesContainer, IFaculty, IDepartment, ICourse, ICertificate,
@@ -537,4 +538,16 @@
     target = 'edit_scores'
     grok.order(4)
+
+class DownloadCSVFileActionButton(ManageActionButton):
+    """ 'Download csv file' button for courses.
+    """
+    grok.context(ICourse)
+    grok.view(EditScoresPage)
+    grok.name('downloadcsv')
+    grok.require('waeup.editScores')
+    icon = 'actionicon_down.png'
+    text = _('Download editable tickets')
+    target = 'download_scores'
+    grok.order(1)
 
 class ManageCertificateActionButton(ManageActionButton):
Index: main/waeup.kofa/trunk/src/waeup/kofa/permissions.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/permissions.py	(revision 13886)
+++ main/waeup.kofa/trunk/src/waeup/kofa/permissions.py	(revision 13894)
@@ -362,5 +362,5 @@
 class Lecturer(grok.Role):
     """The local Lecturer role can be assigned at course level.
-    The role allows to export student
+    The role allows to export some student
     data within the course the local role is assigned. Lecturers can't access
     student data directly but they can edit the scores in course tickets.
@@ -368,6 +368,5 @@
     grok.name('waeup.local.Lecturer')
     grok.title(u'Lecturer')
-    grok.permissions('waeup.showStudents',
-                     'waeup.editScores',
+    grok.permissions('waeup.editScores',
                      'waeup.viewAcademics',
                      'waeup.exportData')
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py	(revision 13886)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py	(revision 13894)
@@ -3081,5 +3081,5 @@
 
 class EditScoresPage(KofaPage):
-    """Page that filters and lists students.
+    """Page that allows to edit batches of scores.
     """
     grok.context(ICourse)
@@ -3156,4 +3156,42 @@
                   type="danger")
         return
+
+class DownloadScoresView(UtilityView, grok.View):
+    """View that exports scores.
+    """
+    grok.context(ICourse)
+    grok.require('waeup.editScores')
+    grok.name('download_scores')
+    redirect_target = '@@export'
+
+    def update(self):
+        ob_class = self.__implemented__.__name__.replace('waeup.kofa.','')
+        self.current_academic_session = grok.getSite()[
+            'configuration'].current_academic_session
+        if self.context.__parent__.__parent__.score_editing_disabled:
+            self.flash(_('Score editing disabled.'), type="warning")
+            self.redirect(self.url(self.context))
+            return
+        if not self.current_academic_session:
+            self.flash(_('Current academic session not set.'), type="warning")
+            self.redirect(self.url(self.context))
+            return
+        site = grok.getSite()
+        exporter = getUtility(ICSVExporter, name='lecturer')
+        self.csv = exporter.export_filtered(site, filepath=None,
+                                 catalog='coursetickets',
+                                 session=self.current_academic_session,
+                                 level=None,
+                                 code=self.context.code)
+        return
+
+    def render(self):
+        filename = 'results_%s_%s.csv' % (
+            self.context.code, self.current_academic_session)
+        self.response.setHeader(
+            'Content-Type', 'text/csv; charset=UTF-8')
+        self.response.setHeader(
+            'Content-Disposition:', 'attachment; filename="%s' % filename)
+        return self.csv
 
 class ExportJobContainerOverview(KofaPage):
@@ -3430,7 +3468,8 @@
 
     def _set_exporter_values(self):
-        # We provide only the 'lecturer' exporter but can add more.
+        # We provide only the 'coursetickets' and 'lecturer' exporter
+        # but can add more.
         exporters = []
-        for name in ('lecturer',):
+        for name in ('coursetickets', 'lecturer'):
             util = getUtility(ICSVExporter, name=name)
             exporters.append((util.title, name),)
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/export.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/export.py	(revision 13886)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/export.py	(revision 13894)
@@ -84,4 +84,32 @@
                     continue
                 tickets.append(ticket)
+    return tickets
+
+def get_tickets_for_lecturer(students, **kw):
+    """Get course tickets of `students`.
+    Filter course tickets which belong to this course code and
+    which are editable by lecturers.
+    """
+    tickets = []
+    code = kw.get('code', None)
+    level_session = kw.get('session', None)
+    level = kw.get('level', None)
+    for level_obj in get_levels(students):
+        for ticket in level_obj.values():
+            if ticket.code != code:
+                continue
+            if not ticket.editable_by_lecturer:
+                continue
+            if level is not None:
+                level = int(level)
+                if level_obj.level in (10, 999, None)  \
+                    and int(level) != level_obj.level:
+                    continue
+                if level_obj.level not in range(level, level+100, 10):
+                    continue
+            if level_session is not None and \
+                int(level_session) != level_obj.level_session:
+                continue
+            tickets.append(ticket)
     return tickets
 
@@ -349,13 +377,16 @@
             value, name, context=context)
 
-class DataForLecturerExporter(CourseTicketExporter):
+class DataForLecturerExporter(grok.GlobalUtility, StudentExporterBase):
     """
     """
     grok.name('lecturer')
 
-    fields = ('matric_number', 'reg_number', 'student_id', 'display_fullname',
+    fields = ('matric_number', 'student_id', 'display_fullname',
               'level', 'code', 'level_session', 'score')
 
     title = _(u'Data for Lecturer')
+
+    def filter_func(self, x, **kw):
+        return get_tickets_for_lecturer(x, **kw)
 
     def mangle_value(self, value, name, context=None):
@@ -370,5 +401,5 @@
                 value = getattr(student, name, None)
         return super(
-            CourseTicketExporter, self).mangle_value(
+            DataForLecturerExporter, self).mangle_value(
             value, name, context=context)
 
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/reports/level_report.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/reports/level_report.py	(revision 13886)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/reports/level_report.py	(revision 13894)
@@ -190,5 +190,5 @@
         pdf_data.append(Spacer(1, 40))
         signatures = [
-            translate(_('Ag. Head of Department')),
+            translate(_('Head of Department')),
             translate(_('Dean of Faculty'))]
         signaturetables = get_signature_tables(signatures, landscape=True)
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py	(revision 13886)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py	(revision 13894)
@@ -3806,4 +3806,5 @@
         studylevel.level = 100
         studylevel.level_session = 2004
+        IWorkflowState(self.student).setState('courses validated')
         self.student['studycourse'].addStudentStudyLevel(
             self.certificate,studylevel)
@@ -3834,6 +3835,6 @@
         # ... and contains the course ticket COURSE1
         self.assertEqual(self.browser.contents,
-            'matric_number,reg_number,student_id,display_fullname,level,code,'
-            'level_session,score\r\n234,123,K1000000,Anna Tester,'
+            'matric_number,student_id,display_fullname,level,code,'
+            'level_session,score\r\n234,K1000000,Anna Tester,'
             '100,COURSE1,2004,\r\n')
         self.assertEqual(len(self.app['datacenter'].running_exports), 1)
@@ -3861,4 +3862,39 @@
             '- discarded: job_id=%s' % job_id in logcontent
             )
+
+    def test_course_download_lecturer(self):
+        # We add study level 100 to the student's studycourse
+        studylevel = StudentStudyLevel()
+        studylevel.level = 100
+        studylevel.level_session = 2004
+        IWorkflowState(self.student).setState('courses validated')
+        self.student['studycourse'].addStudentStudyLevel(
+            self.certificate,studylevel)
+        course1_path = 'http://localhost/app/faculties/fac1/dep1/courses/COURSE1'
+        # Create lecturer
+        self.app['users'].addUser('mrlecturer', 'mrlecturersecret')
+        self.app['users']['mrlecturer'].email = 'mrlecturer@foo.ng'
+        self.app['users']['mrlecturer'].title = 'Carlo Intelligent'
+        prmglobal = IPrincipalRoleManager(self.course)
+        prmglobal.assignRoleToPrincipal('waeup.local.Lecturer', 'mrlecturer')
+        # Login as lecturer
+        self.browser.open(self.login_path)
+        self.browser.getControl(name="form.login").value = 'mrlecturer'
+        self.browser.getControl(name="form.password").value = 'mrlecturersecret'
+        self.browser.getControl("Login").click()
+        self.assertMatches('...You logged in...', self.browser.contents)
+        self.browser.open(course1_path)
+        self.assertFalse('Export' in self.browser.contents)
+        self.browser.getLink("Update scores").click()
+        self.assertTrue('Current academic session not set' in self.browser.contents)
+        self.app['configuration'].current_academic_session = 2004
+        self.browser.getLink("Update scores").click()
+        self.browser.getLink("Download editable tickets").click()
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertEqual(self.browser.headers['Content-Type'],
+                         'text/csv; charset=UTF-8')
+        self.assertEqual(self.browser.contents, 'matric_number,student_id,'
+            'display_fullname,level,code,level_session,score\r\n234,'
+            'K1000000,Anna Tester,100,COURSE1,2004,\r\n')
 
     def test_export_departmet_officers(self):
