Index: /main/waeup.kofa/trunk/src/waeup/kofa/browser/viewlets.py
===================================================================
--- /main/waeup.kofa/trunk/src/waeup/kofa/browser/viewlets.py	(revision 10246)
+++ /main/waeup.kofa/trunk/src/waeup/kofa/browser/viewlets.py	(revision 10247)
@@ -419,4 +419,15 @@
     text = _('Manage academic section')
 
+class ExportFacultiesStudentsActionButton(ManageActionButton):
+    """ 'Export student data' button for faculties.
+    """
+    grok.context(IFacultiesContainer)
+    grok.view(FacultiesContainerPage)
+    grok.require('waeup.showStudents')
+    icon = 'actionicon_down.png'
+    text = _('Export student data')
+    target = 'exports'
+    grok.order(3)
+
 class SearchFacultiesContainerActionButton(ManageActionButton):
     """ 'Manage settings' button for faculties.
Index: /main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py
===================================================================
--- /main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py	(revision 10246)
+++ /main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py	(revision 10247)
@@ -56,4 +56,6 @@
 from waeup.kofa.university.department import (
     VirtualDepartmentExportJobContainer,)
+from waeup.kofa.university.facultiescontainer import (
+    VirtualFacultiesExportJobContainer, FacultiesContainer)
 from waeup.kofa.university.certificate import (
     VirtualCertificateExportJobContainer,)
@@ -2878,4 +2880,5 @@
             exporters.append((util.title, name),)
         self.exporters = exporters
+        return
 
     @property
@@ -2938,4 +2941,16 @@
     grok.context(IDataCenter)
     redirect_target = '@@export'
+
+class FacultiesExportJobContainerJobConfig(ExportJobContainerJobConfig):
+    """Page that configures a students export job in facultiescontainer.
+
+    """
+    grok.context(VirtualFacultiesExportJobContainer)
+
+    def _set_exporter_values(self):
+        # Only Bursary Officers will use this export. They must
+        # not be allowed to export regular student data at faculties level
+        self.exporters = [('Bursary Data', 'bursary')]
+        return
 
 class DepartmentExportJobContainerJobConfig(ExportJobContainerJobConfig):
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 10246)
+++ /main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py	(revision 10247)
@@ -2879,4 +2879,54 @@
         return job_id
 
+    def test_faculties_export(self):
+        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+        facs_path = 'http://localhost/app/faculties'
+        self.browser.open(facs_path)
+        self.browser.getLink("Export student data").click()
+        self.browser.getControl("Configure new export").click()
+        # Only the bursary exporter us available ot this level
+        self.assertFalse('<option value="students">' in self.browser.contents)
+        self.assertTrue('<option value="bursary">' in self.browser.contents)
+        self.browser.getControl(name="exporter").value = ['bursary']
+        self.browser.getControl(name="session").value = ['2004']
+        self.browser.getControl(name="level").value = ['100']
+        self.browser.getControl(name="mode").value = ['ug_ft']
+        self.browser.getControl("Create CSV file").click()
+
+        # When the job is finished and we reload the page...
+        job_id = self.wait_for_export_job_completed()
+        self.browser.open(facs_path + '/exports')
+        # ... the csv file can be downloaded ...
+        self.browser.getLink("Download").click()
+        self.assertEqual(self.browser.headers['content-type'],
+            'text/csv; charset=UTF-8')
+        self.assertTrue(
+            'filename="WAeUP.Kofa_bursary_%s.csv' % job_id in
+            self.browser.headers['content-disposition'])
+        self.assertEqual(len(self.app['datacenter'].running_exports), 1)
+        job_id = self.app['datacenter'].running_exports[0][0]
+        # ... and discarded
+        self.browser.open(facs_path + '/exports')
+        self.browser.getControl("Discard").click()
+        self.assertEqual(len(self.app['datacenter'].running_exports), 0)
+        # Creation, downloading and discarding is logged
+        logfile = os.path.join(
+            self.app['datacenter'].storage, 'logs', 'datacenter.log')
+        logcontent = open(logfile).read()
+        self.assertTrue(
+            'zope.mgr - students.browser.FacultiesExportJobContainerJobConfig '
+            '- exported: bursary (2004, 100, ug_ft, None, None), job_id=%s'
+            % job_id in logcontent
+            )
+        self.assertTrue(
+            'zope.mgr - students.browser.ExportJobContainerDownload '
+            '- downloaded: WAeUP.Kofa_bursary_%s.csv, job_id=%s'
+            % (job_id, job_id) in logcontent
+            )
+        self.assertTrue(
+            'zope.mgr - students.browser.ExportJobContainerOverview '
+            '- discarded: job_id=%s' % job_id in logcontent
+            )
+
     def test_department_export(self):
         self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
Index: /main/waeup.kofa/trunk/src/waeup/kofa/university/facultiescontainer.py
===================================================================
--- /main/waeup.kofa/trunk/src/waeup/kofa/university/facultiescontainer.py	(revision 10246)
+++ /main/waeup.kofa/trunk/src/waeup/kofa/university/facultiescontainer.py	(revision 10247)
@@ -17,8 +17,14 @@
 ##
 import grok
+import zope.location.location
 from zope.component.interfaces import IFactory
 from zope.interface import implementedBy
 from waeup.kofa.interfaces import IKofaPluggable
 from waeup.kofa.university.interfaces import IFacultiesContainer, IFaculty
+from waeup.kofa.utils.batching import VirtualExportJobContainer
+
+class VirtualFacultiesExportJobContainer(VirtualExportJobContainer):
+    """A virtual export job container for certificates.
+    """
 
 class FacultiesContainer(grok.Container):
@@ -26,4 +32,12 @@
     """
     grok.implements(IFacultiesContainer)
+
+    def traverse(self, name):
+        if name == 'exports':
+            # create a virtual exports container and return it
+            container = VirtualFacultiesExportJobContainer()
+            zope.location.location.located(container, self, 'exports')
+            return container
+        return None
 
     def addFaculty(self, faculty):
