Index: /main/waeup.kofa/trunk/src/waeup/kofa/students/export.py
===================================================================
--- /main/waeup.kofa/trunk/src/waeup/kofa/students/export.py	(revision 8410)
+++ /main/waeup.kofa/trunk/src/waeup/kofa/students/export.py	(revision 8411)
@@ -21,9 +21,8 @@
 from zope.catalog.interfaces import ICatalog
 from zope.component import queryUtility
-from waeup.kofa.interfaces import ICSVExporter
 from waeup.kofa.interfaces import MessageFactory as _
 from waeup.kofa.students.interfaces import (
     IStudent, IStudentStudyCourse, IStudentStudyLevel, ICourseTicket,
-    IStudentOnlinePayment)
+    IStudentOnlinePayment, ICSVStudentExporter)
 from waeup.kofa.utils.batching import ExporterBase
 from waeup.kofa.utils.helpers import iface_names
@@ -37,5 +36,6 @@
     """Exporter for Students.
     """
-    grok.implements(ICSVExporter)
+    grok.implements(ICSVStudentExporter)
+    grok.provides(ICSVStudentExporter)
     grok.name('students')
 
@@ -69,8 +69,12 @@
         return self.export(students, filepath)
 
+    def export_student(self, student, filepath=None):
+        return self.export([student], filepath=filepath)
+
 class StudentStudyCourseExporter(grok.GlobalUtility, ExporterBase):
     """Exporter for StudentStudyCourses.
     """
-    grok.implements(ICSVExporter)
+    grok.implements(ICSVStudentExporter)
+    grok.provides(ICSVStudentExporter)
     grok.name('studentstudycourses')
 
@@ -120,8 +124,15 @@
         return self.export(study_courses, filepath)
 
+    def export_student(self, student, filepath=None):
+        if 'studycourse' in student.keys():
+            return self.export([student['studycourse']], filepath=filepath)
+        return self.export([], filepath=filepath)
+
+
 class StudentStudyLevelExporter(grok.GlobalUtility, ExporterBase):
     """Exporter for StudentStudyLevels.
     """
-    grok.implements(ICSVExporter)
+    grok.implements(ICSVStudentExporter)
+    grok.provides(ICSVStudentExporter)
     grok.name('studentstudylevels')
 
@@ -181,8 +192,15 @@
         return self.export(levels, filepath)
 
+    def export_student(self, student, filepath=None):
+        if 'studycourse' in student.keys():
+            return self.export(student['studycourse'].values(),
+                               filepath=filepath)
+        return self.export([], filepath=filepath)
+
 class CourseTicketExporter(grok.GlobalUtility, ExporterBase):
     """Exporter for CourseTickets.
     """
-    grok.implements(ICSVExporter)
+    grok.implements(ICSVStudentExporter)
+    grok.provides(ICSVStudentExporter)
     grok.name('coursetickets')
 
@@ -242,8 +260,19 @@
         return self.export(tickets, filepath)
 
+    def export_student(self, student, filepath=None):
+        if 'studycourse' not in student.keys():
+            return self.export([], filepath=filepath)
+        levels = student['studycourse'].values()
+        tickets = []
+        for level in levels:
+            for ticket in level.values():
+                tickets.append(ticket)
+        return self.export(tickets, filepath=filepath)
+
 class PaymentsExporter(grok.GlobalUtility, ExporterBase):
     """Exporter for OnlinePayment instances.
     """
-    grok.implements(ICSVExporter)
+    grok.implements(ICSVStudentExporter)
+    grok.provides(ICSVStudentExporter)
     grok.name('studentpayments')
 
@@ -295,2 +324,7 @@
                 payments.append(payment)
         return self.export(payments, filepath)
+
+    def export_student(self, student, filepath=None):
+        if not 'payments' in student.keys():
+            return self.export([], filepath=filepath)
+        return self.export(student['payments'].values(), filepath=filepath)
Index: /main/waeup.kofa/trunk/src/waeup/kofa/students/student.py
===================================================================
--- /main/waeup.kofa/trunk/src/waeup/kofa/students/student.py	(revision 8410)
+++ /main/waeup.kofa/trunk/src/waeup/kofa/students/student.py	(revision 8411)
@@ -32,9 +32,9 @@
 from waeup.kofa.interfaces import (
     IObjectHistory, IUserAccount, IFileStoreNameChooser, IFileStoreHandler,
-    IKofaUtils, CLEARANCE, registration_states_vocab, IExtFileStore,
-    ICSVExporter)
+    IKofaUtils, CLEARANCE, registration_states_vocab, IExtFileStore,)
 from waeup.kofa.students.accommodation import StudentAccommodation
 from waeup.kofa.students.export import EXPORTER_NAMES
-from waeup.kofa.students.interfaces import IStudent, IStudentNavigation
+from waeup.kofa.students.interfaces import (
+    IStudent, IStudentNavigation, ICSVStudentExporter)
 from waeup.kofa.students.payments import StudentPaymentsContainer
 from waeup.kofa.students.utils import generate_student_id
@@ -220,6 +220,6 @@
     """
     for name in EXPORTER_NAMES:
-        exporter = getUtility(ICSVExporter, name=name)
-        csv_data = exporter.export([student])
+        exporter = getUtility(ICSVStudentExporter, name=name)
+        csv_data = exporter.export_student(student)
         csv_data = csv_data.split('\r\n')
 
Index: /main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_batching.py
===================================================================
--- /main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_batching.py	(revision 8410)
+++ /main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_batching.py	(revision 8411)
@@ -34,4 +34,5 @@
     StudentStudyLevelProcessor, CourseTicketProcessor,
     StudentOnlinePaymentProcessor, StudentVerdictProcessor)
+from waeup.kofa.students.payments import StudentOnlinePayment
 from waeup.kofa.students.student import Student
 from waeup.kofa.students.studylevel import StudentStudyLevel, CourseTicket
@@ -208,6 +209,23 @@
         ticket.semester = 2
         study_level.addCourseTicket(ticket)
-
+        self.add_payment(student)
         return student
+
+    def add_payment(self, student):
+        # get a payment with all fields set
+        payment = StudentOnlinePayment()
+        payment.creation_date = datetime.datetime(2012, 4, 1, 13, 12, 1)
+        payment.p_id = 'my-id'
+        payment.ac = u'666'
+        payment.p_item = u'p-item'
+        payment.p_level = 100
+        payment.p_session = 2012
+        payment.payment_date = datetime.datetime(2012, 4, 1, 14, 12, 1)
+        payment.r_amount_approved = 12.12
+        payment.r_code = u'r-code'
+        # XXX: there is no addPayment method to give predictable names
+        student['payments']['my-payment'] = payment
+        return payment
+
 
 
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 8410)
+++ /main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_export.py	(revision 8411)
@@ -72,4 +72,23 @@
         return
 
+    def test_export_student(self):
+        # we can export a single student
+        self.setup_student(self.student)
+        exporter = StudentsExporter()
+        exporter.export_student(self.student, self.outfile)
+        result = open(self.outfile, 'rb').read()
+        self.assertEqual(
+            result,
+            'adm_code,clearance_locked,clr_code,date_of_birth,email,employer,'
+            'firstname,lastname,matric_number,middlename,nationality,'
+            'perm_address,phone,reg_number,sex,student_id\r\n'
+
+            'my adm code,0,my clr code,1981-02-04#,anna@sample.com,,Anna,'
+            'Tester,M123456,M.,NG,"Studentroad 21\nLagos 123456\n",'
+            '+234-123-12345,123456,f,A111111\r\n'
+            )
+        return
+
+
 class StudentStudyCourseExporterTest(StudentImportExportSetup):
 
@@ -142,4 +161,19 @@
         return
 
+    def test_export_student(self):
+        # we can export studycourse of a certain student
+        self.setup_student(self.student)
+        exporter = StudentStudyCourseExporter()
+        exporter.export_student(self.student, self.outfile)
+        result = open(self.outfile, 'rb').read()
+        self.assertEqual(
+            result,
+            'certificate,current_level,current_session,current_verdict,'
+            'entry_mode,entry_session,previous_verdict\r\n'
+
+            'CERT1,200,2012,0,ug_ft,2010,0\r\n'
+            )
+        return
+
 class StudentStudyLevelExporterTest(StudentImportExportSetup):
 
@@ -207,4 +241,17 @@
         return
 
+    def test_export_student(self):
+        # we can really export study levels of a certain student
+        self.setup_student(self.student)
+        exporter = StudentStudyLevelExporter()
+        exporter.export_student(self.student, self.outfile)
+        result = open(self.outfile, 'rb').read()
+        self.assertEqual(
+            result,
+            'level,level_session,level_verdict,matric_number,reg_number\r\n'
+            '100,2012,A,M123456,123456\r\n'
+            )
+        return
+
 class CourseTicketExporterTest(StudentImportExportSetup):
 
@@ -276,4 +323,18 @@
         return
 
+    def test_export_student(self):
+        # we can really export all course tickets of a certain student
+        self.setup_student(self.student)
+        exporter = CourseTicketExporter()
+        exporter.export_student(self.student, self.outfile)
+        result = open(self.outfile, 'rb').read()
+        self.assertEqual(
+            result,
+            'automatic,carry_over,code,credits,dcode,fcode,level,mandatory,'
+            'matric_number,passmark,reg_number,score,semester,title\r\n'
+            '1,1,CRS1,100,DEP1,FAC1,100,0,M123456,100,123456,0,2,Course 1\r\n'
+            )
+        return
+
 class PaymentsExporterTest(StudentImportExportSetup):
 
@@ -284,20 +345,4 @@
         self.setup_for_export()
         return
-
-    def get_payment(self):
-        # get a payment with all fields set
-        payment = StudentOnlinePayment()
-        payment.creation_date = datetime.datetime(2012, 4, 1, 13, 12, 1)
-        payment.p_id = 'my-id'
-        payment.ac = u'666'
-        payment.p_item = u'p-item'
-        payment.p_level = 100
-        payment.p_session = 2012
-        payment.payment_date = datetime.datetime(2012, 4, 1, 14, 12, 1)
-        payment.r_amount_approved = 12.12
-        payment.r_code = u'r-code'
-        # XXX: there is no addPayment method to give predictable names
-        self.student['payments']['my-payment'] = payment
-        return payment
 
     def test_ifaces(self):
@@ -335,5 +380,5 @@
         # set values we can expect in export file
         self.setup_student(self.student)
-        payment = self.get_payment()
+        payment = self.student['payments']['my-payment']
         exporter = PaymentsExporter()
         exporter.export([payment], self.outfile)
@@ -355,5 +400,4 @@
         # set values we can expect in export file
         self.setup_student(self.student)
-        self.get_payment() # adds new payment to student
         exporter = PaymentsExporter()
         exporter.export_all(self.app, self.outfile)
@@ -370,2 +414,21 @@
             )
         return
+
+    def test_export_student(self):
+        # we can really export all payments of a certain student
+        # set values we can expect in export file
+        self.setup_student(self.student)
+        exporter = PaymentsExporter()
+        exporter.export_student(self.student, self.outfile)
+        result = open(self.outfile, 'rb').read()
+        self.assertEqual(
+            result,
+            'ac,amount_auth,creation_date,matric_number,p_category,p_id,'
+            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
+            'r_code,reg_number\r\n'
+
+            '666,0.0,2012-04-01 13:12:01,M123456,schoolfee,my-id,'
+            'p-item,100,2012,unpaid,2012-04-01 14:12:01,12.12,'
+            'r-code,123456\r\n'
+            )
+        return
