Changeset 9843


Ignore:
Timestamp:
8 Jan 2013, 11:38:14 (12 years ago)
Author:
Henrik Bettermann
Message:

Implement local student data exports in courses.

Location:
main/waeup.kofa/trunk/src/waeup/kofa
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.kofa/trunk/src/waeup/kofa/browser/tests/test_browser.py

    r9837 r9843  
    316316        self.assertTrue(
    317317            'zope.mgr - students.browser.DatacenterExportJobContainerJobConfig '
    318             '- exported: students (None, None, None, None), job_id='
    319             in logcontent)
     318            '- exported: students (None, None, None, None, None), job_id=%s'
     319            % job_id in logcontent)
    320320        self.assertTrue(
    321321            'zope.mgr - browser.pages.ExportCSVView '
  • main/waeup.kofa/trunk/src/waeup/kofa/browser/viewlets.py

    r9842 r9843  
    471471    grok.view(CoursePage)
    472472    text = _('Edit course')
     473    grok.order(1)
    473474   
    474475class ShowCourseStudentsActionButton(ManageActionButton):
     
    481482    text = _('Show students')
    482483    target = 'students'
     484    grok.order(2)
     485
     486class ExportCourseStudentsActionButton(ManageActionButton):
     487    """ 'Export student data' button for courses.
     488    """
     489    grok.context(ICourse)
     490    grok.view(CoursePage)
     491    grok.require('waeup.showStudents')
     492    icon = 'actionicon_down.png'
     493    text = _('Export student data')
     494    target = 'exports'
     495    grok.order(3)
    483496
    484497class ManageCertificateActionButton(ManageActionButton):
  • main/waeup.kofa/trunk/src/waeup/kofa/catalog.py

    r9773 r9843  
    122122        query = dict()
    123123        for idx_name, value in self._kw.items():
     124            if idx_name == 'cat':
     125                continue
    124126            if not isinstance(value, tuple):
    125127                value = (value, value)
  • main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py

    r9842 r9843  
    5858from waeup.kofa.university.certificate import (
    5959    VirtualCertificateExportJobContainer,)
     60from waeup.kofa.university.course import (
     61    VirtualCourseExportJobContainer,)
    6062from waeup.kofa.university.vocabularies import course_levels
    6163from waeup.kofa.utils.batching import VirtualExportJobContainer
     
    27912793    """
    27922794    grok.context(VirtualCertificateExportJobContainer)
     2795    grok.template('exportconfig_certificate')
    27932796
    27942797    @property
    27952798    def certcode(self):
    27962799        return self.context.__parent__.code
     2800
     2801class CourseExportJobContainerJobConfig(ExportJobContainerJobConfig):
     2802    """Page that configures a students export job for courses.
     2803
     2804    In contrast to department or certificate student data exports the
     2805    coursetickets_catalog is searched here. Therefore the update
     2806    method from the base class is customized.
     2807    """
     2808    grok.context(VirtualCourseExportJobContainer)
     2809    grok.template('exportconfig_course')
     2810
     2811    def _set_exporter_values(self):
     2812        # We provide only the students exporter.
     2813        exporters = []
     2814        for name in ('students',):
     2815            util = getUtility(ICSVExporter, name=name)
     2816            exporters.append((util.title, name),)
     2817        self.exporters = exporters
     2818
     2819    def update(self, START=None, session=None, level=None, mode=None,
     2820               exporter=None):
     2821        self._set_session_values()
     2822        self._set_level_values()
     2823        self._set_mode_values()
     2824        self._set_exporter_values()
     2825        if START is None:
     2826            return
     2827        if session == 'all':
     2828            session=None
     2829        if level == 'all':
     2830            level = None
     2831        job_id = self.context.start_export_job(exporter,
     2832                                      self.request.principal.id,
     2833                                      # Use a different catalog and
     2834                                      # pass different keywords than
     2835                                      # for the (default) students_catalog
     2836                                      cat='coursetickets',
     2837                                      session=session,
     2838                                      level=level,
     2839                                      code=self.context.__parent__.code)
     2840        ob_class = self.__implemented__.__name__.replace('waeup.kofa.','')
     2841        self.context.logger.info(
     2842            '%s - exported: %s (%s, %s, %s), job_id=%s'
     2843            % (ob_class, exporter, session, level,
     2844            self.context.__parent__.code, job_id))
     2845        self.flash(_('Export started for course tickets with') +
     2846                   ' level_session=%s, level=%s' % (
     2847                   session, level))
     2848        self.redirect(self.url(self.redirect_target))
     2849        return
  • main/waeup.kofa/trunk/src/waeup/kofa/students/catalog.py

    r9795 r9843  
    140140    cat_name = 'students_catalog'
    141141    defaults = dict(student_id=None) # make sure we get all studs by default
     142
     143class CourseTicketsQuery(FilteredCatalogQueryBase):
     144    """Query students in a site. See waeup.kofa.catalog for more info.
     145    """
     146    cat_name = 'coursetickets_catalog'
     147    defaults = dict(code=None) # make sure we get all tickets by default
  • main/waeup.kofa/trunk/src/waeup/kofa/students/export.py

    r9834 r9843  
    2121from datetime import datetime
    2222from waeup.kofa.interfaces import MessageFactory as _
    23 from waeup.kofa.students.catalog import StudentsQuery
     23from waeup.kofa.students.catalog import StudentsQuery, CourseTicketsQuery
    2424from waeup.kofa.students.interfaces import (
    2525    IStudent, IStudentStudyCourse, IStudentStudyLevel, ICourseTicket,
     
    9696
    9797    def get_filtered(self, site, **kw):
    98         """Get students filtered by keywords.
    99 
    100         The keys must be valid students catalog index names. Returns a
    101         simple empty list or a catalog result set with `Student`
     98        """Get students from a catalog filtered by keywords.
     99
     100        students_catalog is the default catalog. The keys must be valid
     101        atalog index names.
     102        Returns a simple empty list, a list with `Student`
     103        objects or a catalog result set with `Student`
    102104        objects.
    103105
     
    105107
    106108        """
    107         # Pass only given keywords to StudentsQuery. This way we avoid
     109        # Pass only given keywords to create FilteredCatalogQuery objects.
     110        # This way we avoid
    108111        # trouble with `None` value ambivalences and queries are also
    109112        # faster (normally less indexes to ask). Drawback is, that
    110113        # developers must look into catalog to see what keywords are
    111114        # valid.
     115        if kw.get('cat', None) == 'coursetickets':
     116            coursetickets = CourseTicketsQuery(**kw).query()
     117            students = []
     118            for ticket in coursetickets:
     119                students.append(ticket.student)
     120            return list(set(students))
    112121        query = StudentsQuery(**kw)
    113122        return query.query()
  • main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py

    r9842 r9843  
    27982798        self.browser.getControl(name="session").value = ['2004']
    27992799        self.browser.getControl(name="level").value = ['100']
    2800         self.browser.getControl(name="mode").value = ['ug_ft']
    28012800        self.browser.getControl("Create CSV file").click()
    28022801
     
    28232822        self.assertTrue(
    28242823            'zope.mgr - students.browser.CertificateExportJobContainerJobConfig '
    2825             '- exported: students (2004, 100, ug_ft, None, CERT1), job_id=%s'
     2824            '- exported: students (2004, 100, None, None, CERT1), job_id=%s'
    28262825            % job_id in logcontent
    28272826            )
     
    28352834            '- discarded: job_id=%s' % job_id in logcontent
    28362835            )
     2836
     2837    def test_course_export(self):
     2838        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
     2839        course1_path = 'http://localhost/app/faculties/fac1/dep1/courses/COURSE1'
     2840        self.browser.open(course1_path)
     2841        self.browser.getLink("Export student data").click()
     2842        self.browser.getControl("Configure new export").click()
     2843        self.browser.getControl(name="exporter").value = ['students']
     2844        self.browser.getControl(name="session").value = ['2004']
     2845        self.browser.getControl(name="level").value = ['100']
     2846        self.browser.getControl("Create CSV file").click()
     2847
     2848        # When the job is finished and we reload the page...
     2849        job_id = self.wait_for_export_job_completed()
     2850        self.browser.open(course1_path + '/exports')
     2851        # ... the csv file can be downloaded ...
     2852        self.browser.getLink("Download").click()
     2853        self.assertEqual(self.browser.headers['content-type'],
     2854            'text/csv; charset=UTF-8')
     2855        self.assertTrue(
     2856            'filename="WAeUP.Kofa_students_%s.csv' % job_id in
     2857            self.browser.headers['content-disposition'])
     2858        self.assertEqual(len(self.app['datacenter'].running_exports), 1)
     2859        job_id = self.app['datacenter'].running_exports[0][0]
     2860        # ... and discarded
     2861        self.browser.open(course1_path + '/exports')
     2862        self.browser.getControl("Discard").click()
     2863        self.assertEqual(len(self.app['datacenter'].running_exports), 0)
     2864        # Creation, downloading and discarding is logged
     2865        logfile = os.path.join(
     2866            self.app['datacenter'].storage, 'logs', 'datacenter.log')
     2867        logcontent = open(logfile).read()
     2868        self.assertTrue(
     2869            'zope.mgr - students.browser.CourseExportJobContainerJobConfig '
     2870            '- exported: students (2004, 100, COURSE1), job_id=%s'
     2871            % job_id in logcontent
     2872            )
     2873        self.assertTrue(
     2874            'zope.mgr - students.browser.ExportJobContainerDownload '
     2875            '- downloaded: WAeUP.Kofa_students_%s.csv, job_id=%s'
     2876            % (job_id, job_id) in logcontent
     2877            )
     2878        self.assertTrue(
     2879            'zope.mgr - students.browser.ExportJobContainerOverview '
     2880            '- discarded: job_id=%s' % job_id in logcontent
     2881            )
  • main/waeup.kofa/trunk/src/waeup/kofa/university/course.py

    r9828 r9843  
    1919"""
    2020import grok
     21import zope.location.location
    2122from zope.catalog.interfaces import ICatalog
    2223from zope.interface import implementedBy
     
    2728from waeup.kofa.interfaces import IKofaPluggable
    2829from waeup.kofa.university.interfaces import ICourse, ICourseAdd
     30from waeup.kofa.utils.batching import VirtualExportJobContainer
     31
     32class VirtualCourseExportJobContainer(VirtualExportJobContainer):
     33    """A virtual export job container for courses.
     34    """
    2935
    3036class Course(grok.Model):
     
    5056        self.semester = semester
    5157        self.former_course = former_course
     58
     59    def traverse(self, name):
     60        """Deliver appropriate containers.
     61        """
     62        if name == 'exports':
     63            # create a virtual exports container and return it
     64            container = VirtualCourseExportJobContainer()
     65            zope.location.location.located(container, self, 'exports')
     66            return container
     67        return None
    5268
    5369    def longtitle(self):
Note: See TracChangeset for help on using the changeset viewer.