source: main/waeup.kofa/trunk/src/waeup/kofa/students/interfaces.py @ 14181

Last change on this file since 14181 was 14159, checked in by Henrik Bettermann, 8 years ago

Rename getDegreeClass.

  • Property svn:keywords set to Id
File size: 25.9 KB
Line 
1## $Id: interfaces.py 14159 2016-09-05 08:31:40Z henrik $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18#from datetime import datetime
19from zope.component import getUtility
20from zope.interface import Attribute, Interface
21from zope import schema
22from zc.sourcefactory.contextual import BasicContextualSourceFactory
23from waeup.kofa.browser.interfaces import IStudentNavigationBase
24from waeup.kofa.interfaces import (
25    IKofaObject, academic_sessions_vocab, validate_email, ICSVExporter,
26    ContextualDictSourceFactoryBase, IKofaUtils)
27from waeup.kofa.interfaces import MessageFactory as _
28from waeup.kofa.schema import TextLineChoice, FormattedDate, PhoneNumber
29from waeup.kofa.students.vocabularies import (
30    StudyLevelSource, contextual_reg_num_source, contextual_mat_num_source,
31    GenderSource, nats_vocab
32    )
33from waeup.kofa.payments.interfaces import (
34    IPaymentsContainer, IOnlinePayment)
35from waeup.kofa.university.vocabularies import (
36    CourseSource, StudyModeSource, CertificateSource, SemesterSource,
37    )
38
39class PreviousPaymentCategorySource(ContextualDictSourceFactoryBase):
40    """A source that delivers all selectable categories of previous session
41    payments.
42    """
43    #: name of dict to deliver from kofa utils.
44    DICT_NAME = 'PREVIOUS_PAYMENT_CATEGORIES'
45
46class BalancePaymentCategorySource(ContextualDictSourceFactoryBase):
47    """A source that delivers all selectable items of balance payments.
48    """
49    #: name of dict to deliver from kofa utils.
50    DICT_NAME = 'BALANCE_PAYMENT_CATEGORIES'
51
52# VerdictSource can't be placed into the vocabularies module because it
53# requires importing IStudentsUtils which then leads to circular imports.
54class VerdictSource(BasicContextualSourceFactory):
55    """A verdicts source delivers all verdicts provided
56    in the portal.
57    """
58    def getValues(self, context):
59        verdicts_dict = getUtility(IKofaUtils).VERDICTS_DICT
60        return sorted(verdicts_dict.keys())
61
62    def getToken(self, context, value):
63        return value
64
65    def getTitle(self, context, value):
66        verdicts_dict = getUtility(IKofaUtils).VERDICTS_DICT
67        if value != '0':
68            return verdicts_dict[value] + ' (%s)' % value
69        return verdicts_dict[value]
70
71
72class IStudentsUtils(Interface):
73    """A collection of methods which are subject to customization.
74    """
75    def setReturningData(student):
76        """ This method defines what happens after school fee payment
77        depending on the student's senate verdict.
78
79        In the base configuration current level is always increased
80        by 100 no matter which verdict has been assigned.
81        """
82
83    def setPaymentDetails(category, student, previous_session=None,
84            previous_level=None,):
85        """Create Payment object and set the payment data of a student for
86        the payment category specified.
87        """
88
89    def increaseMatricInteger(student):
90        """Increase counter for matric numbers.
91
92        This counter can be a centrally stored attribute or an attribute of
93        faculties, departments or certificates. In the base package the counter
94        is as an attribute of the site configuration object.
95        """
96
97    def constructMatricNumber(student):
98        """Fetch the matric number counter which fits the student and
99        construct the new matric number of the student.
100
101        In the base package the counter is returned which is as an attribute
102        of the site configuration object.
103        """
104
105    def setMatricNumber(student):
106        """Set matriculation number of student.
107
108        If the student's matric number is unset a new matric number is
109        constructed according to the matriculation number construction rules
110        defined in the constructMatricNumber method. The new matric number is
111        set, the students catalog updated. The corresponding matric number
112        counter is increased by one.
113
114        This method is tested but not used in the base package. It can
115        be used in custom packages by adding respective views
116        and by customizing increaseMatricInteger and constructMatricNumber
117        according to the university's matriculation number construction rules.
118
119        The method can be disabled by setting the counter to zero.
120        """
121
122    def getAccommodation_details(student):
123        """Determine the accommodation dates of a student.
124        """
125
126    def selectBed(available_beds):
127        """Select a bed from a list of available beds.
128        In the standard configuration we select the first bed found,
129        but can also randomize the selection if we like.
130        """
131
132    def getPDFCreator(context):
133        """Get some IPDFCreator instance suitable for use with `context`.
134        """
135
136    def renderPDF(view, subject='', filename='slip.pdf',):
137        """Render pdf slips for various pages.
138        """
139
140    def getDegreeClassNumber(level_obj):
141        """Get degree class number (used for SessionResultsPresentation
142        reports).
143        """
144
145class IStudentsContainer(IKofaObject):
146    """A students container contains university students.
147    """
148    def addStudent(student):
149        """Add an IStudent object and subcontainers.
150        """
151
152    unique_student_id = Attribute('A unique student id')
153
154class IStudentNavigation(IStudentNavigationBase):
155    """Interface needed for navigation and logging. This interface is
156    implemented by all content classes in the students section.
157    """
158    student = Attribute('Student object of context')
159
160    def writeLogMessage(view, message):
161        """Add an INFO message to students.log.
162        """
163
164class IStudentBase(IKofaObject):
165    """Representation of student base data.
166    """
167    history = Attribute('Object history, a list of messages')
168    state = Attribute('Registration state')
169    translated_state = Attribute('Real name of the registration state')
170    certcode = Attribute('Certificate code of any chosen study course')
171    depcode = Attribute('Department code of any chosen study course')
172    faccode = Attribute('Faculty code of any chosen study course')
173    entry_session = Attribute('Entry session')
174    current_session = Attribute('Current session')
175    current_level = Attribute('Current level')
176    current_mode = Attribute('Current mode')
177    current_verdict = Attribute('Current verdict')
178    fullname = Attribute('All name parts separated by hyphens')
179    display_fullname = Attribute('Fullname as displayed on pages')
180    is_postgrad = Attribute('True if postgraduate student')
181    is_special_postgrad = Attribute('True if special postgraduate student')
182    is_fresh = Attribute('True if fresh student')
183    before_payment = Attribute('True if no previous payment has to be made')
184    personal_data_expired = Attribute('True if personal data expired')
185    transcript_enabled = Attribute('True if transcript processing is enabled')
186    clearance_locked = Attribute('True if clearance form is locked')
187
188    password = Attribute('Encrypted password')
189    temp_password = Attribute('Dictionary with user name, timestamp and encrypted password')
190
191    suspended = schema.Bool(
192        title = _(u'Account suspended'),
193        default = False,
194        required = False,
195        )
196
197    suspended_comment = schema.Text(
198        title = _(u"Reasons for Deactivation"),
199        required = False,
200        description = _(
201            u'This message will be shown if and only if deactivated '
202            'students try to login.'),
203        )
204
205    flash_notice = schema.TextLine(
206        title = _(u'Flash Notice'),
207        required = False,
208        readonly = False,
209        description = _(
210            u'This single-line message will be shown in a flash box.'),
211        )
212
213    student_id = schema.TextLine(
214        title = _(u'Student Id'),
215        required = False,
216        )
217
218    firstname = schema.TextLine(
219        title = _(u'First Name'),
220        required = True,
221        )
222
223    middlename = schema.TextLine(
224        title = _(u'Middle Name'),
225        required = False,
226        )
227
228    lastname = schema.TextLine(
229        title = _(u'Last Name (Surname)'),
230        required = True,
231        )
232
233    sex = schema.Choice(
234        title = _(u'Sex'),
235        source = GenderSource(),
236        required = True,
237        )
238
239    reg_number = TextLineChoice(
240        title = _(u'Registration Number'),
241        required = True,
242        readonly = False,
243        source = contextual_reg_num_source,
244        )
245
246    matric_number = TextLineChoice(
247        title = _(u'Matriculation Number'),
248        required = False,
249        readonly = False,
250        source = contextual_mat_num_source,
251        )
252
253    adm_code = schema.TextLine(
254        title = _(u'PWD Activation Code'),
255        required = False,
256        readonly = False,
257        )
258
259    email = schema.ASCIILine(
260        title = _(u'Email'),
261        required = False,
262        constraint=validate_email,
263        )
264    phone = PhoneNumber(
265        title = _(u'Phone'),
266        required = False,
267        )
268
269    def setTempPassword(user, password):
270        """Set a temporary password (LDAP-compatible) SSHA encoded for
271        officers.
272        """
273
274    def getTempPassword():
275        """Check if a temporary password has been set and if it
276        is not expired. Return the temporary password if valid,
277        None otherwise. Unset the temporary password if expired.
278        """
279
280    def transfer(certificate, current_session,
281        current_level, current_verdict):
282        """ Creates a new studycourse and backups the old one.
283        """
284
285    def revert_transfer():
286        """ Revert previous transfer.
287        """
288
289class IUGStudentClearance(IKofaObject):
290    """Representation of undergraduate student clearance data.
291    """
292    officer_comment = schema.Text(
293        title = _(u"Officer's Comment"),
294        required = False,
295        )
296
297    clr_code = schema.TextLine(
298        title = _(u'CLR Activation Code'),
299        required = False,
300        readonly = False,
301        )
302
303    date_of_birth = FormattedDate(
304        title = _(u'Date of Birth'),
305        required = True,
306        show_year = True,
307        )
308
309    nationality = schema.Choice(
310        vocabulary = nats_vocab,
311        title = _(u'Nationality'),
312        required = False,
313        )
314
315class IPGStudentClearance(IUGStudentClearance):
316    """Representation of postgraduate student clearance data.
317    """
318    employer = schema.TextLine(
319        title = _(u'Employer'),
320        required = False,
321        readonly = False,
322        )
323
324class IStudentPersonal(IKofaObject):
325    """Representation of student personal data.
326    """
327    personal_updated = schema.Datetime(
328        title = _(u'Updated'),
329        required = False,
330        readonly = False,
331        )
332
333    perm_address = schema.Text(
334        title = _(u'Permanent Address'),
335        required = False,
336        )
337
338class IStudentTranscript(IKofaObject):
339    """Representation of student transcript data.
340    """
341
342    transcript_comment = schema.Text(
343        title = _(u'Comment'),
344        required = False,
345        )
346
347
348class IStudent(IStudentBase,IUGStudentClearance,IPGStudentClearance,
349    IStudentPersonal, IStudentTranscript):
350    """Representation of a student.
351    """
352
353class IStudentPersonalEdit(IStudentPersonal):
354    """Interface for editing personal data by students.
355    Here we can repeat the fields from IStudentPersonal and set the
356    `required` if necessary.
357    """
358
359    perm_address = schema.Text(
360        title = _(u'Permanent Address'),
361        required = True,
362        )
363
364class IStudentUpdateByRegNo(IStudent):
365    """Representation of a student. Skip regular reg_number validation.
366    """
367    reg_number = schema.TextLine(
368        title = _(u'Registration Number'),
369        required = False,
370        )
371
372class IStudentUpdateByMatricNo(IStudent):
373    """Representation of a student. Skip regular matric_number validation.
374    """
375    matric_number = schema.TextLine(
376        title = _(u'Matriculation Number'),
377        required = False,
378        )
379
380class IStudentRequestPW(IStudent):
381    """Representation of a student for first-time password request.
382    This interface is used when students use the requestpw page to
383    login for the the first time.
384    """
385    number = schema.TextLine(
386        title = _(u'Registr. or Matric. Number'),
387        required = True,
388        )
389
390    firstname = schema.TextLine(
391        title = _(u'First Name'),
392        required = True,
393        )
394
395    email = schema.ASCIILine(
396        title = _(u'Email Address'),
397        required = True,
398        constraint=validate_email,
399        )
400
401class IStudentStudyCourse(IKofaObject):
402    """Representation of student study course data.
403    """
404    next_session_allowed = Attribute('True if the student can proceed to next session')
405    is_postgrad = Attribute('True if student is postgraduate student')
406    is_current = Attribute('True if the study course is the current course of studies')
407    is_previous = Attribute('True if the study course is the previous course of studies')
408
409    certificate = schema.Choice(
410        title = _(u'Certificate'),
411        source = CertificateSource(),
412        required = False,
413        )
414
415    entry_mode = schema.Choice(
416        title = _(u'Entry Mode'),
417        source = StudyModeSource(),
418        required = True,
419        readonly = False,
420        )
421
422    entry_session = schema.Choice(
423        title = _(u'Entry Session'),
424        source = academic_sessions_vocab,
425        #default = datetime.now().year,
426        required = True,
427        readonly = False,
428        )
429
430    current_session = schema.Choice(
431        title = _(u'Current Session'),
432        source = academic_sessions_vocab,
433        required = True,
434        readonly = False,
435        )
436
437    current_level = schema.Choice(
438        title = _(u'Current Level'),
439        source = StudyLevelSource(),
440        required = False,
441        readonly = False,
442        )
443
444    current_verdict = schema.Choice(
445        title = _(u'Current Verdict'),
446        source = VerdictSource(),
447        default = '0',
448        required = False,
449        )
450
451    previous_verdict = schema.Choice(
452        title = _(u'Previous Verdict'),
453        source = VerdictSource(),
454        default = '0',
455        required = False,
456        )
457
458    def addStudentStudyLevel(cert, studylevel):
459        """Add a study level object.
460        """
461
462    def getTranscriptData():
463        """Get a sorted list of dicts with level and course ticket data.
464        This method is used for transcripts.
465        """
466
467class IStudentStudyCourseTransfer(IStudentStudyCourse):
468    """An interface used for student transfers.
469    """
470    certificate = schema.Choice(
471        title = _(u'Certificate'),
472        source = CertificateSource(),
473        required = True,
474        )
475
476    current_level = schema.Choice(
477        title = _(u'Current Level'),
478        source = StudyLevelSource(),
479        required = True,
480        readonly = False,
481        )
482
483    entry_session = schema.Choice(
484        title = _(u'Entry Session'),
485        source = academic_sessions_vocab,
486        #default = datetime.now().year,
487        required = False,
488        readonly = False,
489        )
490
491
492IStudentStudyCourseTransfer['certificate'].order = IStudentStudyCourse[
493    'certificate'].order
494IStudentStudyCourseTransfer['current_level'].order = IStudentStudyCourse[
495    'current_level'].order
496
497class IStudentStudyCourseTranscript(IKofaObject):
498    """An interface for student transcripts.
499    """
500    entry_mode = schema.Choice(
501        title = _(u'Entry Mode'),
502        source = StudyModeSource(),
503        required = True,
504        readonly = False,
505        )
506
507    entry_session = schema.Choice(
508        title = _(u'Entry Session'),
509        source = academic_sessions_vocab,
510        #default = datetime.now().year,
511        required = True,
512        readonly = False,
513        )
514
515class IStudentVerdictUpdate(IKofaObject):
516    """A interface for verdict imports.
517    """
518    current_verdict = schema.Choice(
519        title = _(u'Current Verdict'),
520        source = VerdictSource(),
521        required = True,
522        )
523
524    current_session = schema.Choice(
525        title = _(u'Current Session'),
526        source = academic_sessions_vocab,
527        required = True,
528        )
529
530    current_level = schema.Choice(
531        title = _(u'Current Level'),
532        source = StudyLevelSource(),
533        required = True,
534        )
535
536    bypass_validation = schema.Bool(
537        title = _(u'Bypass validation'),
538        required = False,
539        )
540
541    validated_by = schema.TextLine(
542        title = _(u'Validated by'),
543        required = False,
544        )
545
546class IStudentStudyLevel(IKofaObject):
547    """A representation of student study level data.
548    """
549    certcode = Attribute('The certificate code of the study course')
550    is_current_level = Attribute('True if level is current level of the student')
551    level_title = Attribute('Level title from source')
552    getSessionString = Attribute('Session title from source')
553    number_of_tickets = Attribute('Number of tickets contained in this level')
554    passed_params = Attribute('Information about passed and failed courses')
555    gpa_params_rectified = Attribute('Corrected sessional GPA parameters')
556    gpa_params = Attribute('GPA parameters for this level.')
557    cumulative_params = Attribute('Cumulative GPA and other cumulative parameters for this level')
558    course_registration_allowed = Attribute('True if registerin courses is allowed')
559
560    level = schema.Choice(
561        title = _(u'Level'),
562        source = StudyLevelSource(),
563        required = True,
564        readonly = False,
565        )
566
567    level_session = schema.Choice(
568        title = _(u'Session'),
569        source = academic_sessions_vocab,
570        required = True,
571        )
572
573    level_verdict = schema.Choice(
574        title = _(u'Verdict'),
575        source = VerdictSource(),
576        default = '0',
577        required = False,
578        )
579
580    validated_by = schema.TextLine(
581        title = _(u'Validated by'),
582        default = None,
583        required = False,
584        )
585
586    validation_date = schema.Datetime(
587        title = _(u'Validation Date'),
588        required = False,
589        readonly = False,
590        )
591
592    total_credits = schema.Int(
593        title = _(u'Total Credits'),
594        required = False,
595        readonly = True,
596        )
597
598    gpa = schema.Int(
599        title = _(u'Unrectified GPA'),
600        required = False,
601        readonly = True,
602        )
603
604    def addCourseTicket(ticket, course):
605        """Add a course ticket object.
606        """
607
608    def addCertCourseTickets(cert):
609        """Collect all certificate courses and create course
610        tickets automatically.
611        """
612
613class ICourseTicket(IKofaObject):
614    """A representation of course ticket data.
615    """
616    certcode = Attribute('Certificate code of the study course')
617    level_session = Attribute('Session of the study level the ticket has been added to')
618    level = Attribute('Level value of the study level the ticket has been added to')
619    total_score = Attribute('Score')
620    grade = Attribute('Grade calculated from total score')
621    weight = Attribute('Weight calculated from total score')
622    removable_by_student = Attribute('True if student is allowed to remove the ticket')
623    editable_by_lecturer = Attribute('True if lecturer is allowed to edit the ticket')
624
625    code = Attribute('Code of the original course')
626
627    title = schema.TextLine(
628        title = _(u'Title'),
629        required = False,
630        )
631
632    fcode = schema.TextLine(
633        title = _(u'Faculty Code'),
634        required = False,
635        )
636
637    dcode = schema.TextLine(
638        title = _(u'Department Code'),
639        required = False,
640        )
641
642    semester = schema.Choice(
643        title = _(u'Semester/Term'),
644        source = SemesterSource(),
645        required = False,
646        )
647
648    passmark = schema.Int(
649        title = _(u'Passmark'),
650        required = False,
651        )
652
653    credits = schema.Int(
654        title = _(u'Credits'),
655        required = False,
656        )
657
658    mandatory = schema.Bool(
659        title = _(u'Required'),
660        default = False,
661        required = False,
662        )
663
664    score = schema.Int(
665        title = _(u'Score'),
666        default = None,
667        required = False,
668        missing_value = None,
669        )
670
671    carry_over = schema.Bool(
672        title = _(u'Carry-over Course'),
673        default = False,
674        required = False,
675        )
676
677    automatic = schema.Bool(
678        title = _(u'Automatical Creation'),
679        default = False,
680        required = False,
681        )
682
683class ICourseTicketAdd(IKofaObject):
684    """An interface for adding course tickets.
685    """
686    course = schema.Choice(
687        title = _(u'Course'),
688        source = CourseSource(),
689        readonly = False,
690        )
691
692class ICourseTicketImport(ICourseTicket):
693    """An interface for importing course results and nothing more.
694    """
695    score = schema.Int(
696        title = _(u'Score'),
697        required = False,
698        readonly = False,
699        )
700
701    level_session = schema.Choice(
702        title = _(u'Level Session'),
703        source = academic_sessions_vocab,
704        required = False,
705        readonly = False,
706        )
707
708class IStudentAccommodation(IKofaObject):
709    """A container for student accommodation objects.
710    """
711
712    desired_hostel = schema.TextLine(
713        title = _(u'Desired Hostel'),
714        required = False,
715        )
716
717    def addBedTicket(bedticket):
718        """Add a bed ticket object.
719        """
720
721
722class IBedTicket(IKofaObject):
723    """A representation of accommodation booking data.
724    """
725    bed = Attribute('The bed object')
726    maint_payment_made = Attribute('True if maintenance payment is made')
727
728    display_coordinates = schema.TextLine(
729        title = _(u'Allocated Bed'),
730        required = False,
731        readonly = True,
732        )
733
734    bed_coordinates = schema.TextLine(
735        title = u'',
736        required = True,
737        readonly = False,
738        )
739
740    bed_type = schema.TextLine(
741        title = _(u'Requested Bed Type'),
742        required = True,
743        readonly = False,
744        )
745
746    booking_session = schema.Choice(
747        title = _(u'Session'),
748        source = academic_sessions_vocab,
749        required = True,
750        readonly = False
751        )
752
753    booking_date = schema.Datetime(
754        title = _(u'Booking Date'),
755        required = False,
756        readonly = False,
757        )
758
759    booking_code = schema.TextLine(
760        title = _(u'Booking Activation Code'),
761        required = False,
762        readonly = False,
763        )
764
765    def getSessionString():
766        """Returns the title of academic_sessions_vocab term of the session
767        when the bed was booked.
768        """
769
770class IStudentPaymentsContainer(IPaymentsContainer):
771    """A container for student payment objects.
772    """
773
774    certificate = Attribute('Certificate to determine the correct p_level value')
775
776class IStudentOnlinePayment(IOnlinePayment):
777    """A student payment via payment gateways.
778    """
779
780    certificate = Attribute('Certificate to determine the correct p_level value')
781    student = Attribute('Student')
782
783    p_current = schema.Bool(
784        title = _(u'Current Session Payment'),
785        default = True,
786        required = False,
787        )
788
789    p_level = schema.Choice(
790        title = _(u'Payment Level'),
791        source = StudyLevelSource(),
792        required = False,
793        )
794
795    def redeemTicket():
796        """Either create an appropriate access code or trigger an action
797        directly.
798        """
799
800    def doAfterStudentPayment():
801        """Process student after payment was made.
802        """
803
804    def doAfterStudentPaymentApproval():
805        """Process student after payment was approved.
806        """
807
808    def approveStudentPayment():
809        """Approve payment and process student.
810        """
811
812IStudentOnlinePayment['p_level'].order = IStudentOnlinePayment[
813    'p_session'].order
814
815class IStudentPreviousPayment(IKofaObject):
816    """An interface for adding previous session payments.
817    """
818
819    p_category = schema.Choice(
820        title = _(u'Payment Category'),
821        default = u'schoolfee',
822        source = PreviousPaymentCategorySource(),
823        required = True,
824        )
825
826    p_session = schema.Choice(
827        title = _(u'Payment Session'),
828        source = academic_sessions_vocab,
829        required = True,
830        )
831
832    p_level = schema.Choice(
833        title = _(u'Payment Level'),
834        source = StudyLevelSource(),
835        required = True,
836        )
837
838class IStudentBalancePayment(IKofaObject):
839    """An interface for adding balances.
840    """
841
842    p_category = schema.Choice(
843        title = _(u'Payment Category'),
844        default = u'schoolfee',
845        required = True,
846        source = BalancePaymentCategorySource(),
847        )
848
849    balance_session = schema.Choice(
850        title = _(u'Payment Session'),
851        source = academic_sessions_vocab,
852        required = True,
853        )
854
855    balance_level = schema.Choice(
856        title = _(u'Payment Level'),
857        source = StudyLevelSource(),
858        required = True,
859        )
860
861    balance_amount = schema.Float(
862        title = _(u'Balance Amount'),
863        default = None,
864        required = True,
865        readonly = False,
866        description = _(
867            u'Balance in Naira '),
868        )
869
870class ICSVStudentExporter(ICSVExporter):
871    """A regular ICSVExporter that additionally supports exporting
872      data from a given student object.
873    """
874    def get_filtered(site, **kw):
875        """Get a filtered set of students.
876        """
877
878    def get_selected(site, selected):
879        """Get set of selected students.
880        """
881
882    def export_student(student, filepath=None):
883        """Export data for a given student.
884        """
885
886    def export_filtered(site, filepath=None, **kw):
887        """Export data for filtered set of students.
888        """
889
890    def export_selected(site, filepath=None, **kw):
891        """Export data for selected set of students.
892        """
Note: See TracBrowser for help on using the repository browser.