Ignore:
Timestamp:
13 Dec 2012, 15:39:31 (12 years ago)
Author:
uli
Message:

Local exports for departments.

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

Legend:

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

    r9795 r9797  
    3636    KofaPage, KofaEditFormPage, KofaAddFormPage, KofaDisplayFormPage,
    3737    KofaForm, NullValidator)
     38from waeup.kofa.browser.breadcrumbs import Breadcrumb
    3839from waeup.kofa.browser.pages import ContactAdminForm
    39 from waeup.kofa.browser.breadcrumbs import Breadcrumb
    40 from waeup.kofa.browser.resources import datepicker, datatable, tabs, warning
     40from waeup.kofa.browser.resources import (
     41    datepicker, datatable, tabs, warning, toggleall)
    4142from waeup.kofa.browser.layout import jsaction, action, UtilityView
    4243from waeup.kofa.browser.interfaces import ICaptchaManager
     44from waeup.kofa.hostels.hostel import NOT_OCCUPIED
    4345from waeup.kofa.interfaces import (
    4446    IKofaObject, IUserAccount, IExtFileStore, IPasswordValidator, IContactForm,
    45     IKofaUtils, IUniversity, IObjectHistory, academic_sessions)
     47    IKofaUtils, IUniversity, IObjectHistory, academic_sessions, ICSVExporter,
     48    academic_sessions_vocab, IJobManager)
    4649from waeup.kofa.interfaces import MessageFactory as _
    4750from waeup.kofa.widgets.datewidget import (
    4851    FriendlyDateWidget, FriendlyDateDisplayWidget,
    4952    FriendlyDatetimeDisplayWidget)
     53from waeup.kofa.mandates.mandate import PasswordMandate
     54from waeup.kofa.university.department import (
     55    VirtualDepartmentExportJobContainer,)
     56from waeup.kofa.university.vocabularies import course_levels
     57from waeup.kofa.utils.helpers import get_current_principal, to_timezone
    5058from waeup.kofa.widgets.restwidget import ReSTDisplayWidget
    5159from waeup.kofa.students.interfaces import (
     
    5967    IBedTicket, IStudentsUtils, IStudentRequestPW
    6068    )
    61 from waeup.kofa.students.catalog import search
     69from waeup.kofa.students.catalog import search, StudentsQuery
     70from waeup.kofa.students.studylevel import StudentStudyLevel, CourseTicket
     71from waeup.kofa.students.vocabularies import StudyLevelSource
    6272from waeup.kofa.students.workflow import (CREATED, ADMITTED, PAID,
    6373    CLEARANCE, REQUESTED, RETURNING, CLEARED, REGISTERED, VALIDATED,
    6474    FORBIDDEN_POSTGRAD_TRANS)
    65 from waeup.kofa.students.studylevel import StudentStudyLevel, CourseTicket
    66 from waeup.kofa.students.vocabularies import StudyLevelSource
    67 from waeup.kofa.browser.resources import toggleall
    68 from waeup.kofa.hostels.hostel import NOT_OCCUPIED
    69 from waeup.kofa.utils.helpers import get_current_principal, to_timezone
    70 from waeup.kofa.mandates.mandate import PasswordMandate
     75
    7176
    7277grok.context(IKofaObject) # Make IKofaObject the default context
     
    24962501        self.student_id = student_id
    24972502        return
     2503
     2504class DepartmentExportJobContainerOverview(KofaPage):
     2505    """Page that filters and lists students.
     2506    """
     2507    grok.context(VirtualDepartmentExportJobContainer)
     2508    grok.require('waeup.showStudents')
     2509    grok.name('index.html')
     2510    grok.template('exportjobsindex')
     2511    label = _('Department Exports')
     2512    pnav = 1
     2513
     2514    def doll_up(self):
     2515        job_entries = self.context.get_running_export_jobs(
     2516            self.request.principal.id)
     2517        job_manager = getUtility(IJobManager)
     2518        entries = []
     2519        for job_id, exporter_name, user_id in job_entries:
     2520            job = job_manager.get(job_id)
     2521            descr = 'Export (%r, %r)' % (job.args[1:], job.kwargs)
     2522            status = job.status
     2523            start_time = '%s' % job.begin_after
     2524            download_url = self.url(self.context, 'download',
     2525                                    data=dict(job_id=job_id))
     2526            new_entry = dict(
     2527                job=job_id, descr=descr, status=status, start_time=start_time,
     2528                download_url=download_url)
     2529            entries.append(new_entry)
     2530        self.entries = entries
     2531        pass
     2532
     2533    def update(self, CREATE=None, DISCARD=None, job_id=None):
     2534        if CREATE:
     2535            self.redirect(self.url('jobconfig'))
     2536            return
     2537        if DISCARD and job_id:
     2538            print "DISCARD: ", job_id
     2539            entry = self.context.entry_from_job_id(job_id)
     2540            self.context.delete_export_entry(entry)
     2541            self.flash('Discarded export %s' % job_id)
     2542        self.doll_up()
     2543        return
     2544
     2545class DepartmentExportJobContainerJobConfig(KofaPage):
     2546    """Page that configures a students export job.
     2547    """
     2548    grok.context(VirtualDepartmentExportJobContainer)
     2549    grok.require('waeup.showStudents')
     2550    grok.name('jobconfig')
     2551    grok.template('exportjobsjobconfig')
     2552    label = _('Create New Export Job')
     2553    pnav = 1
     2554
     2555    def _set_session_values(self):
     2556        vocab_terms = academic_sessions_vocab.by_value.values()
     2557        self.sessions = sorted(
     2558            [(x.title, x.token) for x in vocab_terms], reverse=True)
     2559        self.sessions += [('All Sessions', 'all')]
     2560        return
     2561
     2562    def _set_level_values(self):
     2563        vocab_terms = course_levels.by_value.values()
     2564        self.levels = sorted(
     2565            [(x.title, x.token) for x in vocab_terms])
     2566        self.levels += [('All Levels', 'all')]
     2567        return
     2568
     2569    def update(self, START=None, session=None, level=None):
     2570        self._set_session_values()
     2571        self._set_level_values()
     2572        if START is None:
     2573            return
     2574        if session == 'all':
     2575            session=None
     2576        if level == 'all':
     2577            level = None
     2578        code = self.context.__parent__.code
     2579        self.context.start_export_job('students', self.request.principal.id,
     2580                                      current_session=session,
     2581                                      current_level=level,
     2582                                      depcode=code)
     2583        self.flash('Export started for students from %s '
     2584                   '(session=%s, level=%s)' % (
     2585                       code, session, level))
     2586        self.redirect(self.url(self.context))
     2587        return
     2588
     2589class DepartmentExportJobContainerDownload(grok.View):
     2590    """Page that configures a students export job.
     2591    """
     2592    grok.context(VirtualDepartmentExportJobContainer)
     2593    grok.require('waeup.showStudents')
     2594    grok.name('download')
     2595
     2596    def update(self, job_id=None):
     2597        self.job_id=job_id
     2598        return
     2599
     2600    def render(self):
     2601        job = getUtility(IJobManager).get(self.job_id)
     2602        self.response.setHeader(
     2603            'Content-Type', 'text/csv; charset=UTF-8')
     2604        self.response.setHeader(
     2605            'Content-Disposition:', 'attachment; filename="%s' % (
     2606                'students.csv',))
     2607        return open(job.result, 'rb')
     2608        return
  • main/waeup.kofa/trunk/src/waeup/kofa/students/export.py

    r9787 r9797  
    3434                  'coursetickets', 'studentpayments')
    3535
     36def ident(x):
     37    return x
     38    #for item in x:
     39    #    yield item
     40
    3641def get_students(site, stud_filter=StudentsQuery()):
    3742    """Get all students registered in catalog in `site`.
     
    9095    grok.provides(ICSVStudentExporter)
    9196
     97    def filter_func(self, x):
     98        return get_students(x)
     99
     100    def get_filtered(self, site, current_session=None,
     101                     current_level=None, faccode=None, depcode=None, ):
     102        query = StudentsQuery(
     103            current_session=current_session,
     104            current_level=current_level,
     105            faccode=faccode, depcode=depcode)
     106        return query.query()
     107
    92108    def export(self, values, filepath=None):
    93109        """Export `values`, an iterable, as CSV file.
     
    100116        return self.close_outfile(filepath, outfile)
    101117
    102     def export_filtered(self, site, session, level, faccode=None,
    103                         depcode=None, filepath=None):
    104         """Export all students denoted by the given parameters.
    105         """
    106         filter_inst = StudentsQuery(
    107             current_session=session, current_level=level,
    108             faccode=faccode, depcode=depcode)
    109         result_set = get_students(site, stud_filter=filter_inst)
    110         return self.export(result_set, filepath=filepath)
     118    def export_all(self, site, filepath=None):
     119        """Export students into filepath as CSV data.
     120
     121        If `filepath` is ``None``, a raw string with CSV data is returned.
     122        """
     123        return self.export(self.filter_func(site), filepath)
     124
     125    def export_student(self, student, filepath=None):
     126        return self.export(self.filter_func([student]), filepath=filepath)
    111127
    112128
     
    146162        return self.export([student], filepath=filepath)
    147163
    148 
    149164class StudentStudyCourseExporter(grok.GlobalUtility, StudentExporterBase):
    150165    """Exporter for StudentStudyCourses.
     
    157172    #: The title under which this exporter will be displayed
    158173    title = _(u'Student Study Courses')
     174
     175    def filter_func(self, x):
     176        return get_studycourses(x)
    159177
    160178    def mangle_value(self, value, name, context=None):
     
    183201        return self.export(get_studycourses([student]), filepath)
    184202
     203    def export_filtered(self, site, filepath=None, **kw):
     204        """Export items denoted by `args` and `kw`.
     205
     206        If `filepath` is ``None``, a raw string with CSV data should
     207        be returned.
     208        """
     209        data = self.get_filtered(site, **kw)
     210        return self.export(get_studycourses(data), filepath=filepath)
     211
    185212
    186213class StudentStudyLevelExporter(grok.GlobalUtility, StudentExporterBase):
     
    216243    def export_student(self, student, filepath=None):
    217244        return self.export(get_levels([student]), filepath)
     245
     246    def export_filtered(self, site, filepath=None, **kw):
     247        """Export items denoted by `args` and `kw`.
     248
     249        If `filepath` is ``None``, a raw string with CSV data should
     250        be returned.
     251        """
     252        data = self.get_filtered(site, **kw)
     253        return self.export(get_levels(data), filepath=filepath)
    218254
    219255class CourseTicketExporter(grok.GlobalUtility, StudentExporterBase):
     
    252288        return self.export(get_tickets([student]), filepath)
    253289
     290    def export_filtered(self, site, filepath=None, **kw):
     291        """Export items denoted by `args` and `kw`.
     292
     293        If `filepath` is ``None``, a raw string with CSV data should
     294        be returned.
     295        """
     296        data = self.get_filtered(site, **kw)
     297        return self.export(get_tickets(data), filepath=filepath)
     298
    254299
    255300class PaymentsExporter(grok.GlobalUtility, StudentExporterBase):
     
    287332    def export_student(self, student, filepath=None):
    288333        return self.export(get_payments([student]), filepath)
     334
     335    def export_filtered(self, site, filepath=None, **kw):
     336        """Export items denoted by `args` and `kw`.
     337
     338        If `filepath` is ``None``, a raw string with CSV data should
     339        be returned.
     340        """
     341        data = self.get_filtered(site, **kw)
     342        return self.export(get_payments(data), filepath=filepath)
    289343
    290344class BedTicketsExporter(grok.GlobalUtility, StudentExporterBase):
     
    326380    def export_student(self, student, filepath=None):
    327381        return self.export(get_bedtickets([student]), filepath)
     382
     383    def export_filtered(self, site, filepath=None, **kw):
     384        """Export items denoted by `args` and `kw`.
     385
     386        If `filepath` is ``None``, a raw string with CSV data should
     387        be returned.
     388        """
     389        data = self.get_filtered(site, **kw)
     390        return self.export(get_bedtickets(data), filepath=filepath)
    328391
    329392class StudentPaymentsOverviewExporter(StudentsExporter):
  • main/waeup.kofa/trunk/src/waeup/kofa/students/interfaces.py

    r9761 r9797  
    748748      data from a given student object.
    749749    """
     750    def get_filtered(site, current_session=None, current_level=None,
     751                     faculty_code=None, department_code=None):
     752        """Get a filtered set of students.
     753        """
    750754
    751755    def export_student(student, filepath=None):
     
    753757        """
    754758
    755     def export_filtered(site, session, level, faculty_code=None,
    756                         department_code=None, filepath=None):
     759    def export_filtered(site, filepath=None, **kw):
    757760        """Export filtered set of students.
    758761        """
  • main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_export.py

    r9788 r9797  
    183183        exporter = StudentsExporter()
    184184
    185         exporter.export_filtered(self.app, None, None, filepath=self.outfile)
     185        exporter.export_filtered(
     186            self.app, self.outfile,
     187            current_session=None, current_level=None)
    186188        result1 = open(self.outfile, 'rb').read()
    187         exporter.export_filtered(self.app, 2012, None, filepath=self.outfile)
     189        exporter.export_filtered(
     190            self.app, self.outfile,
     191            current_session=2012, current_level=None)
    188192        result2 = open(self.outfile, 'rb').read()
    189         exporter.export_filtered(self.app, None, 200, filepath=self.outfile)
     193        exporter.export_filtered(
     194            self.app, self.outfile,
     195            current_session=None, current_level=200)
    190196        result3 = open(self.outfile, 'rb').read()
    191         exporter.export_filtered(self.app, 2011, None, filepath=self.outfile)
     197        exporter.export_filtered(
     198            self.app, self.outfile,
     199            current_session=2011, current_level=None)
    192200        result4 = open(self.outfile, 'rb').read()
    193         exporter.export_filtered(self.app, None, 100, filepath=self.outfile)
     201        exporter.export_filtered(
     202            self.app, self.outfile,
     203            current_session=None, current_level=100)
    194204        result5 = open(self.outfile, 'rb').read()
    195205        self.assertTrue(self.std_csv_entry in result1)
     
    207217        exporter = StudentsExporter()
    208218
    209         exporter.export_filtered(self.app, 2012, 200, depcode='NA',
    210                                  filepath=self.outfile)
     219        exporter.export_filtered(
     220            self.app, self.outfile,
     221            current_session=2012, current_level=200, depcode='NA')
    211222        result1 = open(self.outfile, 'rb').read()
    212         exporter.export_filtered(self.app, 2012, 200, depcode='NODEPT',
    213                                  filepath=self.outfile)
     223        exporter.export_filtered(
     224            self.app, self.outfile,
     225            current_session=2012, current_level=200, depcode='NODEPT')
    214226        result2 = open(self.outfile, 'rb').read()
    215227        self.assertTrue(self.std_csv_entry in result1)
     
    225237
    226238        exporter.export_filtered(
    227             self.app, 2012, 200, faccode='NA', filepath=self.outfile)
     239            self.app, self.outfile,
     240            current_session=2012, current_level=200, faccode='NA')
    228241        result1 = open(self.outfile, 'rb').read()
    229         exporter.export_filtered(self.app, 2012, 200, faccode='NOFAC',
    230                                  filepath=self.outfile)
     242        exporter.export_filtered(
     243            self.app, self.outfile,
     244            current_session=2012, current_level=200, faccode='NOFAC')
    231245        result2 = open(self.outfile, 'rb').read()
    232246        self.assertTrue(self.std_csv_entry in result1)
     
    234248        return
    235249
    236 
    237250class StudentStudyCourseExporterTest(StudentImportExportSetup):
    238251
     
    247260        # make sure we fullfill interface contracts
    248261        obj = StudentStudyCourseExporter()
    249         verifyObject(ICSVExporter, obj)
    250         verifyClass(ICSVExporter, StudentStudyCourseExporter)
     262        verifyObject(ICSVStudentExporter, obj)
     263        verifyClass(ICSVStudentExporter, StudentStudyCourseExporter)
    251264        return
    252265
     
    320333        return
    321334
     335    def test_export_filtered(self):
     336        # we can export studycourses of a filtered set of students
     337        self.setup_student(self.student)
     338        self.app['students'].addStudent(self.student)
     339        notify(grok.ObjectModifiedEvent(self.student))
     340
     341        exporter = StudentStudyCourseExporter()
     342        exporter.export_filtered(
     343            self.student, self.outfile, current_session=2012)
     344        result = open(self.outfile, 'rb').read()
     345        self.assertEqual(
     346            result,
     347            'certificate,current_level,current_session,current_verdict,'
     348            'entry_mode,entry_session,previous_verdict,student_id\r\n'
     349
     350            'CERT1,200,2012,0,ug_ft,2010,0,A111111\r\n'
     351            )
     352        return
     353
     354
     355
    322356class StudentStudyLevelExporterTest(StudentImportExportSetup):
    323357
     
    332366        # make sure we fullfill interface contracts
    333367        obj = StudentStudyLevelExporter()
    334         verifyObject(ICSVExporter, obj)
    335         verifyClass(ICSVExporter, StudentStudyLevelExporter)
     368        verifyObject(ICSVStudentExporter, obj)
     369        verifyClass(ICSVStudentExporter, StudentStudyLevelExporter)
    336370        return
    337371
     
    406440        return
    407441
     442    def test_export_filtered(self):
     443        # we can export studylevels of a filtered set of students
     444        self.setup_student(self.student)
     445        self.app['students'].addStudent(self.student)
     446        notify(grok.ObjectModifiedEvent(self.student))
     447
     448        exporter = StudentStudyLevelExporter()
     449        exporter.export_filtered(
     450            self.student, self.outfile, current_level=200)
     451        result = open(self.outfile, 'rb').read()
     452        self.assertEqual(
     453            result,
     454            'gpa,level,level_session,level_verdict,total_credits,'
     455            'validated_by,validation_date,'
     456            'student_id,number_of_tickets,certcode\r\n'
     457            '0.0,100,2012,A,100,,,A111111,1,CERT1\r\n'
     458            )
     459        return
     460
    408461class CourseTicketExporterTest(StudentImportExportSetup):
    409462
     
    418471        # make sure we fullfill interface contracts
    419472        obj = CourseTicketExporter()
    420         verifyObject(ICSVExporter, obj)
    421         verifyClass(ICSVExporter, CourseTicketExporter)
     473        verifyObject(ICSVStudentExporter, obj)
     474        verifyClass(ICSVStudentExporter, CourseTicketExporter)
    422475        return
    423476
     
    489542        return
    490543
     544    def test_export_filtered(self):
     545        # we can export studylevels of a filtered set of students
     546        self.setup_student(self.student)
     547        self.app['students'].addStudent(self.student)
     548        notify(grok.ObjectModifiedEvent(self.student))
     549
     550        exporter = CourseTicketExporter()
     551        exporter.export_filtered(
     552            self.student, self.outfile, current_level=200)
     553        result = open(self.outfile, 'rb').read()
     554        self.assertEqual(
     555            result,
     556            'automatic,carry_over,code,credits,dcode,fcode,level,mandatory,'
     557            'passmark,score,semester,title,student_id,certcode\r\n'
     558            '1,1,CRS1,100,DEP1,FAC1,100,0,100,,2,Course 1,A111111,CERT1\r\n'
     559            )
     560        return
     561
    491562class PaymentsExporterTest(StudentImportExportSetup):
    492563
     
    501572        # make sure we fullfill interface contracts
    502573        obj = PaymentsExporter()
    503         verifyObject(ICSVExporter, obj)
    504         verifyClass(ICSVExporter, PaymentsExporter)
     574        verifyObject(ICSVStudentExporter, obj)
     575        verifyClass(ICSVStudentExporter, PaymentsExporter)
    505576        return
    506577
     
    586657        return
    587658
     659    def test_export_filtered(self):
     660        # we can export payments of a filtered set of students
     661        self.setup_student(self.student)
     662        self.app['students'].addStudent(self.student)
     663        notify(grok.ObjectModifiedEvent(self.student))
     664
     665        exporter = PaymentsExporter()
     666        exporter.export_filtered(
     667            self.student, self.outfile, current_level=200)
     668        result = open(self.outfile, 'rb').read()
     669        self.assertEqual(
     670            result,
     671            'ac,amount_auth,creation_date,p_category,p_current,p_id,'
     672            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
     673            'r_code,r_desc,student_id,student_state,current_session\r\n'
     674
     675            '666,0.0,2012-04-01 13:12:01,schoolfee,1,my-id,'
     676            'p-item,100,2012,unpaid,2012-04-01 14:12:01,12.12,'
     677            'r-code,,A111111,created,2012\r\n'
     678            )
     679        return
     680
    588681class BedTicketsExporterTest(StudentImportExportSetup):
    589682
     
    598691        # make sure we fullfill interface contracts
    599692        obj = BedTicketsExporter()
    600         verifyObject(ICSVExporter, obj)
    601         verifyClass(ICSVExporter, BedTicketsExporter)
     693        verifyObject(ICSVStudentExporter, obj)
     694        verifyClass(ICSVStudentExporter, BedTicketsExporter)
    602695        return
    603696
     
    673766        return
    674767
     768    def test_export_filtered(self):
     769        # we can export payments of a filtered set of students
     770        self.setup_student(self.student)
     771        self.app['students'].addStudent(self.student)
     772        notify(grok.ObjectModifiedEvent(self.student))
     773
     774        exporter = BedTicketsExporter()
     775        exporter.export_filtered(
     776            self.student, self.outfile, current_level=200)
     777        result = open(self.outfile, 'rb').read()
     778        self.assertMatches(
     779            result,
     780            'bed,bed_coordinates,bed_type,booking_code,booking_date,'
     781            'booking_session,student_id,actual_bed_type\r\n'
     782            'hall-1_A_101_A,,any bed type,,<YYYY-MM-DD hh:mm:ss>.<6-DIGITS>,'
     783            '2004,A111111,regular_male_fr\r\n')
     784        return
     785
     786
    675787class StudentPaymentsOverviewExporterTest(StudentImportExportSetup):
    676788
     
    685797        # make sure we fullfill interface contracts
    686798        obj = StudentPaymentsOverviewExporter()
    687         verifyObject(ICSVExporter, obj)
    688         verifyClass(ICSVExporter, StudentPaymentsOverviewExporter)
     799        verifyObject(ICSVStudentExporter, obj)
     800        verifyClass(ICSVStudentExporter, StudentPaymentsOverviewExporter)
    689801        return
    690802
     
    744856    def test_ifaces(self):
    745857        obj = StudentStudyLevelsOverviewExporter()
    746         verifyObject(ICSVExporter, obj)
    747         verifyClass(ICSVExporter, StudentStudyLevelsOverviewExporter)
     858        verifyObject(ICSVStudentExporter, obj)
     859        verifyClass(ICSVStudentExporter, StudentStudyLevelsOverviewExporter)
    748860        return
    749861
Note: See TracChangeset for help on using the changeset viewer.