Index: main/waeup.kofa/trunk/src/waeup/kofa/students/export.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/export.py	(revision 9426)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/export.py	(revision 9427)
@@ -24,5 +24,5 @@
 from waeup.kofa.students.interfaces import (
     IStudent, IStudentStudyCourse, IStudentStudyLevel, ICourseTicket,
-    IStudentOnlinePayment, ICSVStudentExporter)
+    IStudentOnlinePayment, ICSVStudentExporter, IBedTicket)
 from waeup.kofa.utils.batching import ExporterBase
 from waeup.kofa.utils.helpers import iface_names
@@ -76,4 +76,12 @@
     return payments
 
+def get_bedtickets(students):
+    """Get all bedtickets of `students`.
+    """
+    tickets = []
+    for student in students:
+        for ticket in student.get('accommodation', {}).values():
+            tickets.append(ticket)
+    return tickets
 
 class StudentExporterBase(ExporterBase):
@@ -273,2 +281,41 @@
     def export_student(self, student, filepath=None):
         return self.export(get_payments([student]), filepath)
+
+class BedTicketsExporter(grok.GlobalUtility, StudentExporterBase):
+    """Exporter for BedTicket instances.
+    """
+    grok.name('bedtickets')
+
+    #: Fieldnames considered by this exporter
+    fields = tuple(
+        sorted(iface_names(
+            IBedTicket, exclude_attribs=False))) + (
+                'student_id', 'actual_bed_type')
+
+    #: The title under which this exporter will be displayed
+    title = _(u'Bed Tickets')
+
+    def mangle_value(self, value, name, context=None):
+        """Treat location values and others special.
+        """
+        if context is not None:
+            student = context.student
+            if name in ['student_id'] and student is not None:
+                value = getattr(student, name, None)
+        if name == 'bed' and value is not None:
+            value = getattr(value, 'bed_id', None)
+        if name == 'actual_bed_type':
+            value = getattr(getattr(context, 'bed', None), 'bed_type')
+        return super(
+            BedTicketsExporter, self).mangle_value(
+            value, name, context=context)
+
+    def export_all(self, site, filepath=None):
+        """Export payments into filepath as CSV data.
+
+        If `filepath` is ``None``, a raw string with CSV data is returned.
+        """
+        return self.export(get_bedtickets(get_students(site)), filepath)
+
+    def export_student(self, student, filepath=None):
+        return self.export(get_bedtickets([student]), filepath)
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 9426)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_export.py	(revision 9427)
@@ -5,6 +5,7 @@
 from waeup.kofa.students.export import (
     StudentsExporter, StudentStudyCourseExporter, StudentStudyLevelExporter,
-    CourseTicketExporter, PaymentsExporter)
+    CourseTicketExporter, PaymentsExporter, BedTicketsExporter)
 from waeup.kofa.students.payments import StudentOnlinePayment
+from waeup.kofa.students.accommodation import BedTicket
 from waeup.kofa.students.studycourse import StudentStudyCourse
 from waeup.kofa.students.studylevel import StudentStudyLevel, CourseTicket
@@ -440,2 +441,89 @@
             )
         return
+
+class BedTicketsExporterTest(StudentImportExportSetup):
+
+    layer = FunctionalLayer
+
+    def setUp(self):
+        super(BedTicketsExporterTest, self).setUp()
+        self.setup_for_export()
+        return
+
+    def test_ifaces(self):
+        # make sure we fullfill interface contracts
+        obj = BedTicketsExporter()
+        verifyObject(ICSVExporter, obj)
+        verifyClass(ICSVExporter, BedTicketsExporter)
+        return
+
+    def test_get_as_utility(self):
+        # we can get a bedtickets exporter as utility
+        result = queryUtility(ICSVExporter, name="bedtickets")
+        self.assertTrue(result is not None)
+        return
+
+    def test_export_empty(self):
+        # we can export a nearly empty bedticket
+        bedticket = BedTicket()
+        bed = self.app['hostels']['hall-1']['hall-1_A_101_A']
+        bedticket.bed = bed
+        exporter = BedTicketsExporter()
+        exporter.export([bedticket], self.outfile)
+        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,,,,<YYYY-MM-DD hh:mm:ss>.<6-DIGITS>,,,regular_male_fr\r\n'
+            )
+        return
+
+    def test_export(self):
+        # we can really export student bedtickets.
+        # set values we can expect in export file
+        self.setup_student(self.student)
+        bedticket = self.student['accommodation']['2004']
+        exporter = BedTicketsExporter()
+        exporter.export([bedticket], self.outfile)
+        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
+
+    def test_export_all(self):
+        # we can really export all bedtickets
+        # set values we can expect in export file
+        self.setup_student(self.student)
+        exporter = BedTicketsExporter()
+        exporter.export_all(self.app, self.outfile)
+        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
+
+    def test_export_student(self):
+        # we can really export all bedtickets of a certain student
+        # set values we can expect in export file
+        self.setup_student(self.student)
+        exporter = BedTicketsExporter()
+        exporter.export_student(self.student, self.outfile)
+        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
