Index: main/waeup.kofa/trunk/src/waeup/kofa/students/export.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/export.py	(revision 16825)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/export.py	(revision 16827)
@@ -41,16 +41,23 @@
     return stud_filter.query()
 
-def get_studycourses(students):
+def get_studycourses(students, previous=0):
     """Get studycourses of `students`.
     """
-    return [x.get('studycourse', None) for x in students
-            if x is not None]
-
-def get_levels(students, **kw):
+    studycourse = 'studycourse'
+    if previous == 1:
+        studycourse = 'studycourse_1'
+    elif previous == 2:
+        studycourse = 'studycourse_2'
+    for x in students:
+        if x.get(studycourse, None) is None:
+            continue
+        yield x.get(studycourse, None)
+
+def get_levels(students, previous=0, **kw):
     """Get all studylevels of `students`.
     """
     levels = []
     level_session = kw.get('level_session', None)
-    for course in get_studycourses(students):
+    for course in get_studycourses(students, previous):
         for level in course.values():
             if level_session not in ('all', None) and \
@@ -60,5 +67,5 @@
     return levels
 
-def get_tickets(students, **kw):
+def get_tickets(students, previous=0, **kw):
     """Get course tickets of `students`.
     If code is passed through, filter course tickets
@@ -78,5 +85,5 @@
     ct_semester = kw.get('ct_semester', None)
     if code is None:
-        for level_obj in get_levels(students, **kw):
+        for level_obj in get_levels(students, previous, **kw):
             for ticket in level_obj.values():
                 if ct_level not in ('all', None):
@@ -95,5 +102,5 @@
                 tickets.append(ticket)
     else:
-        for level_obj in get_levels(students, **kw):
+        for level_obj in get_levels(students, previous, **kw):
             for ticket in level_obj.values():
                 if ticket.code != code:
@@ -112,5 +119,5 @@
     return tickets
 
-def get_tickets_for_lecturer(students, **kw):
+def get_tickets_for_lecturer(students, previous=0, **kw):
     """Get course tickets of `students`.
     Filter course tickets which belong to this course code and
@@ -122,5 +129,5 @@
     level_session = kw.get('session', None)
     level = kw.get('level', None)
-    for level_obj in get_levels(students, **kw):
+    for level_obj in get_levels(students, previous, **kw):
         for ticket in level_obj.values():
             if ticket.code != code:
@@ -428,4 +435,25 @@
             value, name, context=context)
 
+class FirstStudentStudyCourseExporter(StudentStudyCourseExporter):
+    """The First Student Study Course Exporter exports the first
+    study course if student was transferred.
+    """
+    grok.name('studentstudycourses_1')
+
+    title = _(u'First Student Study Courses (Data Backup)')
+
+    def filter_func(self, x, **kw):
+        return get_studycourses(x, 1)
+
+class SecondStudentStudyCourseExporter(StudentStudyCourseExporter):
+    """The Second Student Study Course Exporter exports the second
+    study course if student was transferred twice.
+    """
+    grok.name('studentstudycourses_2')
+
+    title = _(u'Second Student Study Courses (Data Backup)')
+
+    def filter_func(self, x, **kw):
+        return get_studycourses(x, 2)
 
 class StudentStudyLevelExporter(grok.GlobalUtility, StudentExporterBase):
@@ -456,4 +484,26 @@
             value, name, context=context)
 
+class FirstStudentStudyLevelExporter(StudentStudyLevelExporter):
+    """The First Student Study Level Exporter exports study levels of the
+    first study course if the student was transferred.
+    """
+    grok.name('studentstudylevels_1')
+
+    title = _(u'First Course Student Study Levels (Data Backup)')
+
+    def filter_func(self, x, **kw):
+        return get_levels(x, 1, **kw)
+
+class SecondStudentStudyLevelExporter(StudentStudyLevelExporter):
+    """The Second Student Study Level Exporter exports study levels of the
+    second tudy course if the student was transferred twice.
+    """
+    grok.name('studentstudylevels_2')
+
+    title = _(u'Second Course Student Study Levels (Data Backup)')
+
+    def filter_func(self, x, **kw):
+        return get_levels(x, 2, **kw)
+
 class CourseTicketExporter(grok.GlobalUtility, StudentExporterBase):
     """The Course Ticket Exporter exports course tickets. Usually,
@@ -490,4 +540,26 @@
             CourseTicketExporter, self).mangle_value(
             value, name, context=context)
+
+class FirstCourseTicketExporter(CourseTicketExporter):
+    """The First Course Ticket Exporter exports course tickets of
+    first study courses if the student was transferred.
+    """
+    grok.name('coursetickets_1')
+
+    title = _(u'First Course Course Tickets (Data Backup)')
+
+    def filter_func(self, x, **kw):
+        return get_tickets(x, 1, **kw)
+
+class SecondCourseTicketExporter(CourseTicketExporter):
+    """The Second Course Ticket Exporter exports course tickets of
+    second study courses if the student was transferred twice.
+    """
+    grok.name('coursetickets_2')
+
+    title = _(u'Second Course Course Tickets (Data Backup)')
+
+    def filter_func(self, x, **kw):
+        return get_tickets(x, 2, **kw)
 
 class StudentPaymentExporter(grok.GlobalUtility, StudentExporterBase):
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 16825)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_export.py	(revision 16827)
@@ -21,5 +21,5 @@
 import datetime
 from cStringIO import StringIO
-from zope.component import queryUtility, getUtility
+from zope.component import queryUtility, getUtility, createObject
 from zope.event import notify
 from zope.interface.verify import verifyObject, verifyClass
@@ -30,6 +30,15 @@
 from waeup.kofa.university.certificate import CertificateCourse
 from waeup.kofa.students.export import (
-    StudentExporter, StudentStudyCourseExporter, StudentStudyLevelExporter,
-    CourseTicketExporter, StudentPaymentExporter, BedTicketExporter,
+    StudentExporter,
+    StudentStudyCourseExporter,
+    FirstStudentStudyCourseExporter,
+    SecondStudentStudyCourseExporter,
+    StudentStudyLevelExporter,
+    FirstStudentStudyLevelExporter,
+    SecondStudentStudyLevelExporter,
+    CourseTicketExporter,
+    FirstCourseTicketExporter,
+    SecondCourseTicketExporter,
+    StudentPaymentExporter, BedTicketExporter,
     SchoolFeePaymentsOverviewExporter, StudyLevelsOverviewExporter,
     ComboCardDataExporter, DataForBursaryExporter,
@@ -516,4 +525,177 @@
         return
 
+class PreviousStudyCourseExporterTests(StudentImportExportSetup):
+
+    layer = FunctionalLayer
+
+    def setUp(self):
+        super(PreviousStudyCourseExporterTests, self).setUp()
+        self.setup_for_export()
+        self.certificate2 = createObject('waeup.Certificate')
+        self.certificate2.code = 'CERT2'
+        self.certificate2.application_category = 'basic'
+        self.certificate2.start_level = 200
+        self.certificate2.end_level = 500
+        self.app['faculties']['fac1']['dep1'].certificates.addCertificate(
+            self.certificate2)
+        return
+
+    def test_export_studycourses(self):
+        self.setup_student(self.student)
+        exporter = FirstStudentStudyCourseExporter()
+        exporter.export_all(self.app, self.outfile)
+        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'
+            )
+        error = self.student.transfer(self.certificate2, current_session=2013)
+        self.assertTrue(error == None)
+        exporter.export_all(self.app, self.outfile)
+        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')
+        error = self.student.transfer(self.certificate,
+                                      current_session=2014,
+                                      current_level=300)
+        self.assertTrue(error == None)
+        exporter = SecondStudentStudyCourseExporter()
+        exporter.export_all(self.app, self.outfile)
+        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'
+            'CERT2,,2013,,transfer,2010,,A111111\r\n')
+        exporter = StudentStudyCourseExporter()
+        exporter.export_all(self.app, self.outfile)
+        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,300,2014,,transfer,2010,,A111111\r\n')
+        return
+
+    def test_export_studylevels(self):
+        self.setup_student(self.student)
+        exporter = FirstStudentStudyLevelExporter()
+        exporter.export_all(self.app, self.outfile)
+        result = open(self.outfile, 'rb').read()
+        self.assertEqual(
+            result,
+            'gpa,level,level_session,level_verdict,total_credits,'
+            'transcript_remark,validated_by,validation_date,student_id,'
+            'number_of_tickets,certcode\r\n'
+            )
+        error = self.student.transfer(self.certificate2, current_session=2013)
+        self.assertTrue(error == None)
+        exporter.export_all(self.app, self.outfile)
+        result = open(self.outfile, 'rb').read()
+        self.assertEqual(
+            result,
+            'gpa,level,level_session,level_verdict,total_credits,'
+            'transcript_remark,validated_by,validation_date,student_id,'
+            'number_of_tickets,certcode\r\n'
+            '0.00,100,2012,A,100,,,,A111111,1,CERT1\r\n' )
+        study_level = StudentStudyLevel()
+        study_level.level_session = 2015
+        study_level.level_verdict = "C"
+        study_level.level = 400
+        self.student['studycourse'].addStudentStudyLevel(
+            self.certificate2, study_level)
+        error = self.student.transfer(self.certificate,
+                                      current_session=2014,
+                                      current_level=300)
+        self.assertTrue(error == None)
+        exporter = SecondStudentStudyLevelExporter()
+        exporter.export_all(self.app, self.outfile)
+        result = open(self.outfile, 'rb').read()
+        self.assertEqual(
+            result,
+            'gpa,level,level_session,level_verdict,total_credits,'
+            'transcript_remark,validated_by,validation_date,student_id,'
+            'number_of_tickets,certcode\r\n'
+            '0.00,400,2015,C,0,,,,A111111,0,CERT2\r\n')
+        exporter = StudentStudyLevelExporter()
+        exporter.export_all(self.app, self.outfile)
+        result = open(self.outfile, 'rb').read()
+        self.assertEqual(
+            result,
+            'gpa,level,level_session,level_verdict,total_credits,'
+            'transcript_remark,validated_by,validation_date,student_id,'
+            'number_of_tickets,certcode\r\n')
+        return
+
+    def test_export_coursetickets(self):
+        self.setup_student(self.student)
+        exporter = FirstCourseTicketExporter()
+        exporter.export_all(self.app, self.outfile)
+        result = open(self.outfile, 'rb').read()
+        self.assertEqual(
+            result,
+            'automatic,carry_over,code,course_category,credits,dcode,'
+            'fcode,level,level_session,mandatory,outstanding,passmark,'
+            'score,semester,ticket_session,title,student_id,certcode,'
+            'display_fullname\r\n'
+            )
+        error = self.student.transfer(self.certificate2, current_session=2013)
+        self.assertTrue(error == None)
+        exporter.export_all(self.app, self.outfile)
+        result = open(self.outfile, 'rb').read()
+        self.assertEqual(
+            result,
+            'automatic,carry_over,code,course_category,credits,dcode,'
+            'fcode,level,level_session,mandatory,outstanding,passmark,'
+            'score,semester,ticket_session,title,student_id,certcode,'
+            'display_fullname\r\n'
+            '1,1,CRS1,,100,DEP1,FAC1,100,2012,0,0,100,,2,,Course 1,'
+            'A111111,CERT1,Anna M. Tester\r\n')
+        study_level = StudentStudyLevel()
+        study_level.level_session = 2015
+        study_level.level_verdict = "C"
+        study_level.level = 400
+        self.student['studycourse'].addStudentStudyLevel(
+            self.certificate2, study_level)
+        ticket = CourseTicket()
+        ticket.automatic = True
+        ticket.carry_over = True
+        ticket.code = u'CRS9'
+        ticket.title = u'Course 9'
+        ticket.fcode = u'FAC9'
+        ticket.dcode = u'DEP9'
+        ticket.credits = 150
+        ticket.passmark = 100
+        ticket.semester = 2
+        study_level[ticket.code] = ticket
+        error = self.student.transfer(self.certificate,
+                                      current_session=2014,
+                                      current_level=300)
+        self.assertTrue(error == None)
+        exporter = SecondCourseTicketExporter()
+        exporter.export_all(self.app, self.outfile)
+        result = open(self.outfile, 'rb').read()
+        self.assertEqual(
+            result,
+            'automatic,carry_over,code,course_category,credits,dcode,'
+            'fcode,level,level_session,mandatory,outstanding,passmark,'
+            'score,semester,ticket_session,title,student_id,certcode,'
+            'display_fullname\r\n1,1,CRS9,,150,DEP9,FAC9,400,2015,0,0,'
+            '100,,2,,Course 9,A111111,CERT2,Anna M. Tester\r\n')
+        exporter = CourseTicketExporter()
+        exporter.export_all(self.app, self.outfile)
+        result = open(self.outfile, 'rb').read()
+        self.assertEqual(
+            result,
+            'automatic,carry_over,code,course_category,credits,dcode,'
+            'fcode,level,level_session,mandatory,outstanding,passmark,'
+            'score,semester,ticket_session,title,student_id,certcode,'
+            'display_fullname\r\n'
+            )
+        return
 
 class StudentStudyLevelExporterTest(StudentImportExportSetup):
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_student.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_student.py	(revision 16825)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_student.py	(revision 16827)
@@ -160,4 +160,11 @@
         super(StudentRemovalTests, self).setUp()
         self.setup_for_export()
+        self.certificate2 = createObject('waeup.Certificate')
+        self.certificate2.code = 'CERT2'
+        self.certificate2.application_category = 'basic'
+        self.certificate2.start_level = 200
+        self.certificate2.end_level = 500
+        self.app['faculties']['fac1']['dep1'].certificates.addCertificate(
+            self.certificate2)
         return
 
@@ -190,4 +197,6 @@
             IStudentsUtils).STUDENT_BACKUP_EXPORTER_NAMES
         for name in STUDENT_BACKUP_EXPORTER_NAMES:
+            if name[-2:-1] == '_':
+                continue
             csv_path = os.path.join(del_dir, '%s.csv' % name)
             self.assertTrue(os.path.isfile(csv_path))
@@ -218,4 +227,6 @@
             IStudentsUtils).STUDENT_BACKUP_EXPORTER_NAMES
         for name in STUDENT_BACKUP_EXPORTER_NAMES:
+            if name[-2:-1] == '_':
+                continue
             csv_path = os.path.join(del_dir, '%s.csv' % name)
             self.assertTrue(os.path.isfile(csv_path))
@@ -223,4 +234,40 @@
             # We expect 3 lines output including a linebreak at end of file.
             self.assertEqual(len(contents), 3)
+        return
+
+    def test_backup_single_graduated_transferred_data(self):
+        del_dir = self.app['datacenter'].graduated_path
+        # when a single graduated student is removed, the data is backed up
+        # somewhere else including previous study courses
+        self.setup_student(self.student)
+        error = self.student.transfer(self.certificate2, current_session=2013)
+        self.assertTrue(error == None)
+        IWorkflowState(self.student).setState('graduated')
+        handle_student_removed(self.student, None)
+        # The previous study course data were put into CSV files
+        name = 'studentstudycourses_1'
+        csv_path = os.path.join(del_dir, '%s.csv' % name)
+        self.assertTrue(os.path.isfile(csv_path))
+        contents = open(csv_path, 'rb').read().split('\r\n')
+        # We expect 3 lines output including a linebreak at end of file.
+        self.assertEqual(len(contents), 3)
+        name = 'studentstudycourses_2'
+        csv_path = os.path.join(del_dir, '%s.csv' % name)
+        self.assertTrue(os.path.isfile(csv_path))
+        contents = open(csv_path, 'rb').read().split('\r\n')
+        # We expect only 2 lines output including a linebreak at end of file.
+        self.assertEqual(len(contents), 2)
+        name = 'studentstudylevels_1'
+        csv_path = os.path.join(del_dir, '%s.csv' % name)
+        self.assertTrue(os.path.isfile(csv_path))
+        contents = open(csv_path, 'rb').read().split('\r\n')
+        # We expect 3 lines output including a linebreak at end of file.
+        self.assertEqual(len(contents), 3)
+        name = 'coursetickets_1'
+        csv_path = os.path.join(del_dir, '%s.csv' % name)
+        self.assertTrue(os.path.isfile(csv_path))
+        contents = open(csv_path, 'rb').read().split('\r\n')
+        # We expect 3 lines output including a linebreak at end of file.
+        self.assertEqual(len(contents), 3)
         return
 
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/utils.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/utils.py	(revision 16825)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/utils.py	(revision 16827)
@@ -1258,6 +1258,12 @@
             'students',
             'studentstudycourses',
+            #'studentstudycourses_1',
+            #'studentstudycourses_2',
             'studentstudylevels',
+            #'studentstudylevels_1',
+            #'studentstudylevels_2',
             'coursetickets',
+            #'coursetickets_1',
+            #'coursetickets_2',
             'studentpayments',
             'bedtickets',
@@ -1277,7 +1283,17 @@
     #: A tuple containing all exporter names needed for backing
     #: up student data
-    STUDENT_BACKUP_EXPORTER_NAMES = ('students', 'studentstudycourses',
-            'studentstudylevels', 'coursetickets',
-            'studentpayments', 'bedtickets')
+    STUDENT_BACKUP_EXPORTER_NAMES = (
+            'students',
+            'studentstudycourses',
+            'studentstudycourses_1',
+            'studentstudycourses_2',
+            'studentstudylevels',
+            'studentstudylevels_1',
+            'studentstudylevels_2',
+            'coursetickets',
+            'coursetickets_1',
+            'coursetickets_2',
+            'studentpayments',
+            'bedtickets')
 
     # Maximum size of upload files in kB
