Index: main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py	(revision 9795)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py	(revision 9797)
@@ -36,16 +36,24 @@
     KofaPage, KofaEditFormPage, KofaAddFormPage, KofaDisplayFormPage,
     KofaForm, NullValidator)
+from waeup.kofa.browser.breadcrumbs import Breadcrumb
 from waeup.kofa.browser.pages import ContactAdminForm
-from waeup.kofa.browser.breadcrumbs import Breadcrumb
-from waeup.kofa.browser.resources import datepicker, datatable, tabs, warning
+from waeup.kofa.browser.resources import (
+    datepicker, datatable, tabs, warning, toggleall)
 from waeup.kofa.browser.layout import jsaction, action, UtilityView
 from waeup.kofa.browser.interfaces import ICaptchaManager
+from waeup.kofa.hostels.hostel import NOT_OCCUPIED
 from waeup.kofa.interfaces import (
     IKofaObject, IUserAccount, IExtFileStore, IPasswordValidator, IContactForm,
-    IKofaUtils, IUniversity, IObjectHistory, academic_sessions)
+    IKofaUtils, IUniversity, IObjectHistory, academic_sessions, ICSVExporter,
+    academic_sessions_vocab, IJobManager)
 from waeup.kofa.interfaces import MessageFactory as _
 from waeup.kofa.widgets.datewidget import (
     FriendlyDateWidget, FriendlyDateDisplayWidget,
     FriendlyDatetimeDisplayWidget)
+from waeup.kofa.mandates.mandate import PasswordMandate
+from waeup.kofa.university.department import (
+    VirtualDepartmentExportJobContainer,)
+from waeup.kofa.university.vocabularies import course_levels
+from waeup.kofa.utils.helpers import get_current_principal, to_timezone
 from waeup.kofa.widgets.restwidget import ReSTDisplayWidget
 from waeup.kofa.students.interfaces import (
@@ -59,14 +67,11 @@
     IBedTicket, IStudentsUtils, IStudentRequestPW
     )
-from waeup.kofa.students.catalog import search
+from waeup.kofa.students.catalog import search, StudentsQuery
+from waeup.kofa.students.studylevel import StudentStudyLevel, CourseTicket
+from waeup.kofa.students.vocabularies import StudyLevelSource
 from waeup.kofa.students.workflow import (CREATED, ADMITTED, PAID,
     CLEARANCE, REQUESTED, RETURNING, CLEARED, REGISTERED, VALIDATED,
     FORBIDDEN_POSTGRAD_TRANS)
-from waeup.kofa.students.studylevel import StudentStudyLevel, CourseTicket
-from waeup.kofa.students.vocabularies import StudyLevelSource
-from waeup.kofa.browser.resources import toggleall
-from waeup.kofa.hostels.hostel import NOT_OCCUPIED
-from waeup.kofa.utils.helpers import get_current_principal, to_timezone
-from waeup.kofa.mandates.mandate import PasswordMandate
+
 
 grok.context(IKofaObject) # Make IKofaObject the default context
@@ -2496,2 +2501,108 @@
         self.student_id = student_id
         return
+
+class DepartmentExportJobContainerOverview(KofaPage):
+    """Page that filters and lists students.
+    """
+    grok.context(VirtualDepartmentExportJobContainer)
+    grok.require('waeup.showStudents')
+    grok.name('index.html')
+    grok.template('exportjobsindex')
+    label = _('Department Exports')
+    pnav = 1
+
+    def doll_up(self):
+        job_entries = self.context.get_running_export_jobs(
+            self.request.principal.id)
+        job_manager = getUtility(IJobManager)
+        entries = []
+        for job_id, exporter_name, user_id in job_entries:
+            job = job_manager.get(job_id)
+            descr = 'Export (%r, %r)' % (job.args[1:], job.kwargs)
+            status = job.status
+            start_time = '%s' % job.begin_after
+            download_url = self.url(self.context, 'download',
+                                    data=dict(job_id=job_id))
+            new_entry = dict(
+                job=job_id, descr=descr, status=status, start_time=start_time,
+                download_url=download_url)
+            entries.append(new_entry)
+        self.entries = entries
+        pass
+
+    def update(self, CREATE=None, DISCARD=None, job_id=None):
+        if CREATE:
+            self.redirect(self.url('jobconfig'))
+            return
+        if DISCARD and job_id:
+            print "DISCARD: ", job_id
+            entry = self.context.entry_from_job_id(job_id)
+            self.context.delete_export_entry(entry)
+            self.flash('Discarded export %s' % job_id)
+        self.doll_up()
+        return
+
+class DepartmentExportJobContainerJobConfig(KofaPage):
+    """Page that configures a students export job.
+    """
+    grok.context(VirtualDepartmentExportJobContainer)
+    grok.require('waeup.showStudents')
+    grok.name('jobconfig')
+    grok.template('exportjobsjobconfig')
+    label = _('Create New Export Job')
+    pnav = 1
+
+    def _set_session_values(self):
+        vocab_terms = academic_sessions_vocab.by_value.values()
+        self.sessions = sorted(
+            [(x.title, x.token) for x in vocab_terms], reverse=True)
+        self.sessions += [('All Sessions', 'all')]
+        return
+
+    def _set_level_values(self):
+        vocab_terms = course_levels.by_value.values()
+        self.levels = sorted(
+            [(x.title, x.token) for x in vocab_terms])
+        self.levels += [('All Levels', 'all')]
+        return
+
+    def update(self, START=None, session=None, level=None):
+        self._set_session_values()
+        self._set_level_values()
+        if START is None:
+            return
+        if session == 'all':
+            session=None
+        if level == 'all':
+            level = None
+        code = self.context.__parent__.code
+        self.context.start_export_job('students', self.request.principal.id,
+                                      current_session=session,
+                                      current_level=level,
+                                      depcode=code)
+        self.flash('Export started for students from %s '
+                   '(session=%s, level=%s)' % (
+                       code, session, level))
+        self.redirect(self.url(self.context))
+        return
+
+class DepartmentExportJobContainerDownload(grok.View):
+    """Page that configures a students export job.
+    """
+    grok.context(VirtualDepartmentExportJobContainer)
+    grok.require('waeup.showStudents')
+    grok.name('download')
+
+    def update(self, job_id=None):
+        self.job_id=job_id
+        return
+
+    def render(self):
+        job = getUtility(IJobManager).get(self.job_id)
+        self.response.setHeader(
+            'Content-Type', 'text/csv; charset=UTF-8')
+        self.response.setHeader(
+            'Content-Disposition:', 'attachment; filename="%s' % (
+                'students.csv',))
+        return open(job.result, 'rb')
+        return
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/browser_templates/exportjobsindex.pt
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/browser_templates/exportjobsindex.pt	(revision 9797)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/browser_templates/exportjobsindex.pt	(revision 9797)
@@ -0,0 +1,28 @@
+<br /><br />
+<div>
+  <form method="POST" tal:repeat="job view/entries">
+    <b><span tal:replace="job/job">666</span></b>
+    <span tal:replace="job/descr">Description</span>
+
+    <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+    start: <span tal:replace="job/start_time">23:55 h</span>
+
+    <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+    status: <span tal:replace="job/status">completed</span>
+
+    <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+    <input type="hidden" name="job_id" value=""
+           tal:attributes="value job/job" />
+    <a href="" class="btn" tal:attributes="href job/download_url">
+      Download</a>
+    <input type="submit" class="btn" name="DISCARD"
+           value="Discard" />
+
+  </form>
+</div>
+
+<form method="POST">
+  <input class="btn secondary" type="submit" name="CREATE"
+         value="Create new export"
+          />
+</form>
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/browser_templates/exportjobsjobconfig.pt
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/browser_templates/exportjobsjobconfig.pt	(revision 9797)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/browser_templates/exportjobsjobconfig.pt	(revision 9797)
@@ -0,0 +1,29 @@
+Export students with...
+
+<form method="POST">
+  <label for="session" class="span2">
+    Session
+  </label>
+  &nbsp;
+  <select name="session">
+    <option tal:repeat="item view/sessions"
+            tal:attributes="value python:item[1]">
+      <span tal:replace="python: item[0]">2012</span>
+    </option>
+  </select>
+  <br />
+  <label for="level" class="span2">
+    Course Level
+  </label>
+  &nbsp;
+  <select name="level">
+    <option tal:repeat="item view/levels"
+            tal:attributes="value python:item[1]">
+      <span tal:replace="python: item[0]">200</span>
+    </option>
+  </select>
+  <br />
+  <hr />
+  <input type="submit" name="START" value="Create"
+         class="btn primary" />
+</form>
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/export.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/export.py	(revision 9795)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/export.py	(revision 9797)
@@ -34,4 +34,9 @@
                   'coursetickets', 'studentpayments')
 
+def ident(x):
+    return x
+    #for item in x:
+    #    yield item
+
 def get_students(site, stud_filter=StudentsQuery()):
     """Get all students registered in catalog in `site`.
@@ -90,4 +95,15 @@
     grok.provides(ICSVStudentExporter)
 
+    def filter_func(self, x):
+        return get_students(x)
+
+    def get_filtered(self, site, current_session=None,
+                     current_level=None, faccode=None, depcode=None, ):
+        query = StudentsQuery(
+            current_session=current_session,
+            current_level=current_level,
+            faccode=faccode, depcode=depcode)
+        return query.query()
+
     def export(self, values, filepath=None):
         """Export `values`, an iterable, as CSV file.
@@ -100,13 +116,13 @@
         return self.close_outfile(filepath, outfile)
 
-    def export_filtered(self, site, session, level, faccode=None,
-                        depcode=None, filepath=None):
-        """Export all students denoted by the given parameters.
-        """
-        filter_inst = StudentsQuery(
-            current_session=session, current_level=level,
-            faccode=faccode, depcode=depcode)
-        result_set = get_students(site, stud_filter=filter_inst)
-        return self.export(result_set, filepath=filepath)
+    def export_all(self, site, filepath=None):
+        """Export students into filepath as CSV data.
+
+        If `filepath` is ``None``, a raw string with CSV data is returned.
+        """
+        return self.export(self.filter_func(site), filepath)
+
+    def export_student(self, student, filepath=None):
+        return self.export(self.filter_func([student]), filepath=filepath)
 
 
@@ -146,5 +162,4 @@
         return self.export([student], filepath=filepath)
 
-
 class StudentStudyCourseExporter(grok.GlobalUtility, StudentExporterBase):
     """Exporter for StudentStudyCourses.
@@ -157,4 +172,7 @@
     #: The title under which this exporter will be displayed
     title = _(u'Student Study Courses')
+
+    def filter_func(self, x):
+        return get_studycourses(x)
 
     def mangle_value(self, value, name, context=None):
@@ -183,4 +201,13 @@
         return self.export(get_studycourses([student]), filepath)
 
+    def export_filtered(self, site, filepath=None, **kw):
+        """Export items denoted by `args` and `kw`.
+
+        If `filepath` is ``None``, a raw string with CSV data should
+        be returned.
+        """
+        data = self.get_filtered(site, **kw)
+        return self.export(get_studycourses(data), filepath=filepath)
+
 
 class StudentStudyLevelExporter(grok.GlobalUtility, StudentExporterBase):
@@ -216,4 +243,13 @@
     def export_student(self, student, filepath=None):
         return self.export(get_levels([student]), filepath)
+
+    def export_filtered(self, site, filepath=None, **kw):
+        """Export items denoted by `args` and `kw`.
+
+        If `filepath` is ``None``, a raw string with CSV data should
+        be returned.
+        """
+        data = self.get_filtered(site, **kw)
+        return self.export(get_levels(data), filepath=filepath)
 
 class CourseTicketExporter(grok.GlobalUtility, StudentExporterBase):
@@ -252,4 +288,13 @@
         return self.export(get_tickets([student]), filepath)
 
+    def export_filtered(self, site, filepath=None, **kw):
+        """Export items denoted by `args` and `kw`.
+
+        If `filepath` is ``None``, a raw string with CSV data should
+        be returned.
+        """
+        data = self.get_filtered(site, **kw)
+        return self.export(get_tickets(data), filepath=filepath)
+
 
 class PaymentsExporter(grok.GlobalUtility, StudentExporterBase):
@@ -287,4 +332,13 @@
     def export_student(self, student, filepath=None):
         return self.export(get_payments([student]), filepath)
+
+    def export_filtered(self, site, filepath=None, **kw):
+        """Export items denoted by `args` and `kw`.
+
+        If `filepath` is ``None``, a raw string with CSV data should
+        be returned.
+        """
+        data = self.get_filtered(site, **kw)
+        return self.export(get_payments(data), filepath=filepath)
 
 class BedTicketsExporter(grok.GlobalUtility, StudentExporterBase):
@@ -326,4 +380,13 @@
     def export_student(self, student, filepath=None):
         return self.export(get_bedtickets([student]), filepath)
+
+    def export_filtered(self, site, filepath=None, **kw):
+        """Export items denoted by `args` and `kw`.
+
+        If `filepath` is ``None``, a raw string with CSV data should
+        be returned.
+        """
+        data = self.get_filtered(site, **kw)
+        return self.export(get_bedtickets(data), filepath=filepath)
 
 class StudentPaymentsOverviewExporter(StudentsExporter):
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/interfaces.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/interfaces.py	(revision 9795)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/interfaces.py	(revision 9797)
@@ -748,4 +748,8 @@
       data from a given student object.
     """
+    def get_filtered(site, current_session=None, current_level=None,
+                     faculty_code=None, department_code=None):
+        """Get a filtered set of students.
+        """
 
     def export_student(student, filepath=None):
@@ -753,6 +757,5 @@
         """
 
-    def export_filtered(site, session, level, faculty_code=None,
-                        department_code=None, filepath=None):
+    def export_filtered(site, filepath=None, **kw):
         """Export filtered set of students.
         """
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_export.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_export.py	(revision 9795)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_export.py	(revision 9797)
@@ -183,13 +183,23 @@
         exporter = StudentsExporter()
 
-        exporter.export_filtered(self.app, None, None, filepath=self.outfile)
+        exporter.export_filtered(
+            self.app, self.outfile,
+            current_session=None, current_level=None)
         result1 = open(self.outfile, 'rb').read()
-        exporter.export_filtered(self.app, 2012, None, filepath=self.outfile)
+        exporter.export_filtered(
+            self.app, self.outfile,
+            current_session=2012, current_level=None)
         result2 = open(self.outfile, 'rb').read()
-        exporter.export_filtered(self.app, None, 200, filepath=self.outfile)
+        exporter.export_filtered(
+            self.app, self.outfile,
+            current_session=None, current_level=200)
         result3 = open(self.outfile, 'rb').read()
-        exporter.export_filtered(self.app, 2011, None, filepath=self.outfile)
+        exporter.export_filtered(
+            self.app, self.outfile,
+            current_session=2011, current_level=None)
         result4 = open(self.outfile, 'rb').read()
-        exporter.export_filtered(self.app, None, 100, filepath=self.outfile)
+        exporter.export_filtered(
+            self.app, self.outfile,
+            current_session=None, current_level=100)
         result5 = open(self.outfile, 'rb').read()
         self.assertTrue(self.std_csv_entry in result1)
@@ -207,9 +217,11 @@
         exporter = StudentsExporter()
 
-        exporter.export_filtered(self.app, 2012, 200, depcode='NA',
-                                 filepath=self.outfile)
+        exporter.export_filtered(
+            self.app, self.outfile,
+            current_session=2012, current_level=200, depcode='NA')
         result1 = open(self.outfile, 'rb').read()
-        exporter.export_filtered(self.app, 2012, 200, depcode='NODEPT',
-                                 filepath=self.outfile)
+        exporter.export_filtered(
+            self.app, self.outfile,
+            current_session=2012, current_level=200, depcode='NODEPT')
         result2 = open(self.outfile, 'rb').read()
         self.assertTrue(self.std_csv_entry in result1)
@@ -225,8 +237,10 @@
 
         exporter.export_filtered(
-            self.app, 2012, 200, faccode='NA', filepath=self.outfile)
+            self.app, self.outfile,
+            current_session=2012, current_level=200, faccode='NA')
         result1 = open(self.outfile, 'rb').read()
-        exporter.export_filtered(self.app, 2012, 200, faccode='NOFAC',
-                                 filepath=self.outfile)
+        exporter.export_filtered(
+            self.app, self.outfile,
+            current_session=2012, current_level=200, faccode='NOFAC')
         result2 = open(self.outfile, 'rb').read()
         self.assertTrue(self.std_csv_entry in result1)
@@ -234,5 +248,4 @@
         return
 
-
 class StudentStudyCourseExporterTest(StudentImportExportSetup):
 
@@ -247,6 +260,6 @@
         # make sure we fullfill interface contracts
         obj = StudentStudyCourseExporter()
-        verifyObject(ICSVExporter, obj)
-        verifyClass(ICSVExporter, StudentStudyCourseExporter)
+        verifyObject(ICSVStudentExporter, obj)
+        verifyClass(ICSVStudentExporter, StudentStudyCourseExporter)
         return
 
@@ -320,4 +333,25 @@
         return
 
+    def test_export_filtered(self):
+        # we can export studycourses of a filtered set of students
+        self.setup_student(self.student)
+        self.app['students'].addStudent(self.student)
+        notify(grok.ObjectModifiedEvent(self.student))
+
+        exporter = StudentStudyCourseExporter()
+        exporter.export_filtered(
+            self.student, self.outfile, current_session=2012)
+        result = open(self.outfile, 'rb').read()
+        self.assertEqual(
+            result,
+            'certificate,current_level,current_session,current_verdict,'
+            'entry_mode,entry_session,previous_verdict,student_id\r\n'
+
+            'CERT1,200,2012,0,ug_ft,2010,0,A111111\r\n'
+            )
+        return
+
+
+
 class StudentStudyLevelExporterTest(StudentImportExportSetup):
 
@@ -332,6 +366,6 @@
         # make sure we fullfill interface contracts
         obj = StudentStudyLevelExporter()
-        verifyObject(ICSVExporter, obj)
-        verifyClass(ICSVExporter, StudentStudyLevelExporter)
+        verifyObject(ICSVStudentExporter, obj)
+        verifyClass(ICSVStudentExporter, StudentStudyLevelExporter)
         return
 
@@ -406,4 +440,23 @@
         return
 
+    def test_export_filtered(self):
+        # we can export studylevels of a filtered set of students
+        self.setup_student(self.student)
+        self.app['students'].addStudent(self.student)
+        notify(grok.ObjectModifiedEvent(self.student))
+
+        exporter = StudentStudyLevelExporter()
+        exporter.export_filtered(
+            self.student, self.outfile, current_level=200)
+        result = open(self.outfile, 'rb').read()
+        self.assertEqual(
+            result,
+            'gpa,level,level_session,level_verdict,total_credits,'
+            'validated_by,validation_date,'
+            'student_id,number_of_tickets,certcode\r\n'
+            '0.0,100,2012,A,100,,,A111111,1,CERT1\r\n'
+            )
+        return
+
 class CourseTicketExporterTest(StudentImportExportSetup):
 
@@ -418,6 +471,6 @@
         # make sure we fullfill interface contracts
         obj = CourseTicketExporter()
-        verifyObject(ICSVExporter, obj)
-        verifyClass(ICSVExporter, CourseTicketExporter)
+        verifyObject(ICSVStudentExporter, obj)
+        verifyClass(ICSVStudentExporter, CourseTicketExporter)
         return
 
@@ -489,4 +542,22 @@
         return
 
+    def test_export_filtered(self):
+        # we can export studylevels of a filtered set of students
+        self.setup_student(self.student)
+        self.app['students'].addStudent(self.student)
+        notify(grok.ObjectModifiedEvent(self.student))
+
+        exporter = CourseTicketExporter()
+        exporter.export_filtered(
+            self.student, self.outfile, current_level=200)
+        result = open(self.outfile, 'rb').read()
+        self.assertEqual(
+            result,
+            'automatic,carry_over,code,credits,dcode,fcode,level,mandatory,'
+            'passmark,score,semester,title,student_id,certcode\r\n'
+            '1,1,CRS1,100,DEP1,FAC1,100,0,100,,2,Course 1,A111111,CERT1\r\n'
+            )
+        return
+
 class PaymentsExporterTest(StudentImportExportSetup):
 
@@ -501,6 +572,6 @@
         # make sure we fullfill interface contracts
         obj = PaymentsExporter()
-        verifyObject(ICSVExporter, obj)
-        verifyClass(ICSVExporter, PaymentsExporter)
+        verifyObject(ICSVStudentExporter, obj)
+        verifyClass(ICSVStudentExporter, PaymentsExporter)
         return
 
@@ -586,4 +657,26 @@
         return
 
+    def test_export_filtered(self):
+        # we can export payments of a filtered set of students
+        self.setup_student(self.student)
+        self.app['students'].addStudent(self.student)
+        notify(grok.ObjectModifiedEvent(self.student))
+
+        exporter = PaymentsExporter()
+        exporter.export_filtered(
+            self.student, self.outfile, current_level=200)
+        result = open(self.outfile, 'rb').read()
+        self.assertEqual(
+            result,
+            'ac,amount_auth,creation_date,p_category,p_current,p_id,'
+            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
+            'r_code,r_desc,student_id,student_state,current_session\r\n'
+
+            '666,0.0,2012-04-01 13:12:01,schoolfee,1,my-id,'
+            'p-item,100,2012,unpaid,2012-04-01 14:12:01,12.12,'
+            'r-code,,A111111,created,2012\r\n'
+            )
+        return
+
 class BedTicketsExporterTest(StudentImportExportSetup):
 
@@ -598,6 +691,6 @@
         # make sure we fullfill interface contracts
         obj = BedTicketsExporter()
-        verifyObject(ICSVExporter, obj)
-        verifyClass(ICSVExporter, BedTicketsExporter)
+        verifyObject(ICSVStudentExporter, obj)
+        verifyClass(ICSVStudentExporter, BedTicketsExporter)
         return
 
@@ -673,4 +766,23 @@
         return
 
+    def test_export_filtered(self):
+        # we can export payments of a filtered set of students
+        self.setup_student(self.student)
+        self.app['students'].addStudent(self.student)
+        notify(grok.ObjectModifiedEvent(self.student))
+
+        exporter = BedTicketsExporter()
+        exporter.export_filtered(
+            self.student, self.outfile, current_level=200)
+        result = open(self.outfile, 'rb').read()
+        self.assertMatches(
+            result,
+            'bed,bed_coordinates,bed_type,booking_code,booking_date,'
+            'booking_session,student_id,actual_bed_type\r\n'
+            'hall-1_A_101_A,,any bed type,,<YYYY-MM-DD hh:mm:ss>.<6-DIGITS>,'
+            '2004,A111111,regular_male_fr\r\n')
+        return
+
+
 class StudentPaymentsOverviewExporterTest(StudentImportExportSetup):
 
@@ -685,6 +797,6 @@
         # make sure we fullfill interface contracts
         obj = StudentPaymentsOverviewExporter()
-        verifyObject(ICSVExporter, obj)
-        verifyClass(ICSVExporter, StudentPaymentsOverviewExporter)
+        verifyObject(ICSVStudentExporter, obj)
+        verifyClass(ICSVStudentExporter, StudentPaymentsOverviewExporter)
         return
 
@@ -744,6 +856,6 @@
     def test_ifaces(self):
         obj = StudentStudyLevelsOverviewExporter()
-        verifyObject(ICSVExporter, obj)
-        verifyClass(ICSVExporter, StudentStudyLevelsOverviewExporter)
+        verifyObject(ICSVStudentExporter, obj)
+        verifyClass(ICSVStudentExporter, StudentStudyLevelsOverviewExporter)
         return
 
