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

Last change on this file since 15185 was 15173, checked in by Henrik Bettermann, 6 years ago

Remove redundant manage page (and ITranscript interface).

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