source: main/waeup.uniben/trunk/src/waeup/uniben/students/browser.py @ 13583

Last change on this file since 13583 was 13583, checked in by Henrik Bettermann, 9 years ago

Implement first draft of bursary clearance slip.

  • Property svn:keywords set to Id
File size: 23.5 KB
Line 
1## $Id: browser.py 13583 2016-01-10 22:18:06Z henrik $
2##
3## Copyright (C) 2012 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##
18import grok
19from zope.i18n import translate
20from zope.schema.interfaces import ConstraintNotSatisfied
21from zope.formlib.textwidgets import BytesDisplayWidget
22from zope.component import getUtility
23from hurry.workflow.interfaces import IWorkflowInfo
24from waeup.kofa.interfaces import (
25    REQUESTED, IExtFileStore, IKofaUtils, IObjectHistory)
26from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
27from waeup.kofa.browser.layout import action, KofaEditFormPage, UtilityView
28from waeup.kofa.students.browser import (
29    StudyLevelEditFormPage, StudyLevelDisplayFormPage,
30    StudentBasePDFFormPage, ExportPDFCourseRegistrationSlip,
31    CourseTicketDisplayFormPage, StudentTriggerTransitionFormPage,
32    msave, emit_lock_message,
33    StudentActivateView, StudentDeactivateView,
34    ExportPDFTranscriptSlip)
35from waeup.kofa.students.workflow import (CREATED, ADMITTED, PAID,
36    CLEARANCE, REQUESTED, RETURNING, CLEARED, REGISTERED, VALIDATED,
37    GRADUATED, TRANSCRIPT, FORBIDDEN_POSTGRAD_TRANS)
38from waeup.kofa.students.interfaces import IStudentsUtils, ICourseTicket
39from waeup.kofa.students.workflow import FORBIDDEN_POSTGRAD_TRANS
40from kofacustom.nigeria.students.browser import (
41    NigeriaOnlinePaymentDisplayFormPage,
42    NigeriaStudentBaseManageFormPage,
43    NigeriaStudentClearanceEditFormPage,
44    NigeriaOnlinePaymentAddFormPage,
45    NigeriaExportPDFPaymentSlip,
46    NigeriaExportPDFClearanceSlip,
47    NigeriaExportPDFBedTicketSlip,
48    NigeriaStudentPersonalDisplayFormPage,
49    NigeriaStudentPersonalManageFormPage,
50    NigeriaStudentPersonalEditFormPage
51    )
52
53from waeup.uniben.students.interfaces import (
54    ICustomStudent,
55    ICustomStudentOnlinePayment,
56    ICustomStudentStudyCourse,
57    ICustomStudentStudyLevel,
58    ICustomUGStudentClearance,
59    ICustomPGStudentClearance,
60    ICustomStudentPersonal,
61    ICustomStudentPersonalEdit)
62from waeup.uniben.interfaces import MessageFactory as _
63
64class CustomOnlinePaymentDisplayFormPage(NigeriaOnlinePaymentDisplayFormPage):
65    """ Page to view an online payment ticket
66    """
67    grok.context(ICustomStudentOnlinePayment)
68    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
69        'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item')
70    form_fields[
71        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
72    form_fields[
73        'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
74
75class CustomStudentClearanceEditFormPage(NigeriaStudentClearanceEditFormPage):
76    """ View to edit student clearance data by student
77    """
78
79    @property
80    def form_fields(self):
81        if self.context.is_postgrad:
82            form_fields = grok.AutoFields(ICustomPGStudentClearance).omit(
83            'clearance_locked', 'nysc_location', 'clr_code', 'officer_comment',
84            'physical_clearance_date')
85        else:
86            form_fields = grok.AutoFields(ICustomUGStudentClearance).omit(
87            'clearance_locked', 'clr_code', 'officer_comment',
88            'physical_clearance_date')
89            form_fields['date_of_birth'].for_display = True
90            form_fields['nationality'].for_display = True
91            form_fields['lga'].for_display = True
92        return form_fields
93
94    def dataNotComplete(self):
95        store = getUtility(IExtFileStore)
96        if not store.getFileByContext(self.context, attr=u'birth_certificate.jpg'):
97            return _('No birth certificate uploaded.')
98        if not store.getFileByContext(self.context, attr=u'ref_let.jpg'):
99            return _('No guarantor/referee letter uploaded.')
100        if not store.getFileByContext(self.context, attr=u'acc_let.jpg'):
101            return _('No acceptance letter uploaded.')
102        if not store.getFileByContext(self.context, attr=u'fst_sit_scan.jpg'):
103            return _('No first sitting result uploaded.')
104        #if not store.getFileByContext(self.context, attr=u'scd_sit_scan.jpg'):
105        #    return _('No second sitting result uploaded.')
106        if not store.getFileByContext(self.context, attr=u'secr_cults.jpg'):
107            return _('No affidavit of non-membership of secret cults uploaded.')
108        return False
109
110class CustomOnlinePaymentAddFormPage(NigeriaOnlinePaymentAddFormPage):
111    """ Page to add an online payment ticket
112    """
113    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).select(
114        'p_category')
115
116class CustomExportPDFPaymentSlip(NigeriaExportPDFPaymentSlip):
117    """Deliver a PDF slip of the context.
118    """
119    grok.context(ICustomStudentOnlinePayment)
120    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
121        'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item')
122    form_fields['creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
123    form_fields['payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
124
125
126class CustomExportPDFClearanceSlip(NigeriaExportPDFClearanceSlip):
127    """Deliver a PDF slip of the context.
128    """
129
130    @property
131    def omit_fields(self):
132        omit_fields = ('password', 'suspended', 'suspended_comment',
133                       'phone', 'adm_code', 'email', 'date_of_birth')
134        if self.context.faccode == 'JUPEB':
135            omit_fields += ('faculty', 'department')
136        return omit_fields
137
138    @property
139    def label(self):
140        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
141        line0 = ''
142        if self.context.faccode == 'JUPEB':
143            line0 = 'Joint Universities Preliminary Examinations Board (JUPEB)\n'
144        line1 = translate(_('Clearance Slip of'),
145            'waeup.kofa', target_language=portal_language) \
146            + ' %s' % self.context.display_fullname
147        return '%s%s' % (line0, line1)
148
149    def _sigsInFooter(self):
150        isStudent = getattr(
151            self.request.principal, 'user_type', None) == 'student'
152        if not isStudent and self.context.state in (CLEARED, RETURNING):
153            return (_('Date, Student Signature'),
154                    _('Date, Clearance Officer Signature'),
155                    )
156        return ()
157
158    def render(self):
159        studentview = StudentBasePDFFormPage(self.context.student,
160            self.request, self.omit_fields)
161        students_utils = getUtility(IStudentsUtils)
162        return students_utils.renderPDF(
163            self, 'clearance_slip.pdf',
164            self.context.student, studentview, signatures=self._signatures(),
165            sigs_in_footer=self._sigsInFooter(), show_scans=False,
166            omit_fields=self.omit_fields)
167
168
169class ExportClearanceInvitationSlip(UtilityView, grok.View):
170    """Deliver an invitation letter to physical clearance.
171
172    This form page is available only in Uniben.
173    """
174    grok.context(ICustomStudent)
175    grok.name('clearance_invitation_slip.pdf')
176    grok.require('waeup.viewStudent')
177    prefix = 'form'
178
179    label = u'Invitation Letter for Physical Clearance'
180
181    omit_fields = (
182        'suspended', 'phone', 'email',
183        'adm_code', 'suspended_comment',
184        'date_of_birth', 'current_level',
185        'department', 'current_mode',
186        'entry_session', 'matric_number', 'sex')
187
188    form_fields = []
189
190    @property
191    def note(self):
192        if self.context.physical_clearance_date:
193            return """
194<br /><br /><br /><br /><font size='12'>
195Dear %s,
196<br /><br /><br />
197You are invited for your physical clearance on:
198<br /><br />
199<strong>%s</strong>.
200<br /><br />
201Please bring along this letter of invitation to the University Main Auditorium
202<br /><br />
203on your clearance date.
204<br /><br /><br />
205Signed,
206<br /><br />
207The Registrar<br />
208</font>
209
210""" % (self.context.display_fullname, self.context.physical_clearance_date)
211        return
212
213
214    def update(self):
215        if self.context.student.state != REQUESTED \
216            or not  self.context.student.physical_clearance_date:
217            self.flash(_('Forbidden'), type="warning")
218            self.redirect(self.url(self.context))
219
220    def render(self):
221        studentview = StudentBasePDFFormPage(self.context.student,
222            self.request, self.omit_fields)
223        students_utils = getUtility(IStudentsUtils)
224        return students_utils.renderPDF(
225            self, 'clearance_invitation_slip',
226            self.context.student, studentview,
227            omit_fields=self.omit_fields,
228            note=self.note)
229
230class CustomStudentPersonalDisplayFormPage(
231    NigeriaStudentPersonalDisplayFormPage):
232    """ Page to display student personal data
233    """
234
235    form_fields = grok.AutoFields(ICustomStudentPersonal)
236    form_fields['perm_address'].custom_widget = BytesDisplayWidget
237    form_fields['next_kin_address'].custom_widget = BytesDisplayWidget
238    form_fields[
239        'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
240
241class CustomStudentPersonalManageFormPage(
242    NigeriaStudentPersonalManageFormPage):
243    """ Page to manage personal data
244    """
245
246    form_fields = grok.AutoFields(ICustomStudentPersonal)
247    form_fields['personal_updated'].for_display = True
248    form_fields[
249        'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
250
251class CstomStudentPersonalEditFormPage(NigeriaStudentPersonalEditFormPage):
252    """ Page to edit personal data
253    """
254    form_fields = grok.AutoFields(
255        ICustomStudentPersonalEdit).omit('personal_updated')
256
257class StudyCourseCOEditFormPage(KofaEditFormPage):
258    """ Page to edit the student study course data by clearance officers.
259
260    This form page is available only in Uniben.
261    """
262    grok.context(ICustomStudentStudyCourse)
263    grok.name('edit_level')
264    grok.require('waeup.clearStudent')
265    label = _('Edit current level')
266    pnav = 4
267    form_fields = grok.AutoFields(
268        ICustomStudentStudyCourse).select('current_level')
269
270    def update(self):
271        if not (self.context.is_current and
272            self.context.student.state == REQUESTED):
273            emit_lock_message(self)
274            return
275        super(StudyCourseCOEditFormPage, self).update()
276        return
277
278    @action(_('Save'), style='primary')
279    def save(self, **data):
280        try:
281            msave(self, **data)
282        except ConstraintNotSatisfied:
283            # The selected level might not exist in certificate
284            self.flash(_('Current level not available for certificate.'))
285            return
286        #notify(grok.ObjectModifiedEvent(self.context.__parent__))
287        return
288
289class CustomStudyLevelEditFormPage(StudyLevelEditFormPage):
290    """ Page to edit the student study level data by students.
291
292    """
293    grok.template('studyleveleditpage')
294
295class CustomStudyLevelDisplayFormPage(StudyLevelDisplayFormPage):
296    """ Page to display student study levels
297    """
298    grok.template('studylevelpage')
299
300class CustomExportPDFCourseRegistrationSlip(
301    ExportPDFCourseRegistrationSlip):
302    """Deliver a PDF slip of the context.
303    """
304
305    form_fields = grok.AutoFields(ICustomStudentStudyLevel).omit(
306        'level_verdict', 'gpa', 'level')
307
308    def update(self):
309        if self.context.student.state != REGISTERED \
310            or self.context.student.current_level != self.context.level:
311            self.flash(_('Forbidden'), type="warning")
312            self.redirect(self.url(self.context))
313
314    @property
315    def tabletitle(self):
316        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
317        tabletitle = []
318        tabletitle.append(translate(_('1st Semester Courses'), 'waeup.kofa',
319            target_language=portal_language))
320        tabletitle.append(translate(_('2nd Semester Courses'), 'waeup.kofa',
321            target_language=portal_language))
322        tabletitle.append(translate(_('Level Courses'), 'waeup.kofa',
323            target_language=portal_language))
324        tabletitle.append(translate(_('1st Trimester Courses'), 'waeup.kofa',
325            target_language=portal_language))
326        tabletitle.append(translate(_('2nd Trimester Courses'), 'waeup.kofa',
327            target_language=portal_language))
328        tabletitle.append(translate(_('3rd Trimester Courses'), 'waeup.kofa',
329            target_language=portal_language))
330        return tabletitle
331
332    def render(self):
333        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
334        Code = translate('Code', 'waeup.kofa', target_language=portal_language)
335        Title = translate('Title', 'waeup.kofa', target_language=portal_language)
336        Dept = translate('Dept.', 'waeup.kofa', target_language=portal_language)
337        Faculty = translate('Faculty', 'waeup.kofa', target_language=portal_language)
338        Cred = translate(_('Credits'), 'waeup.uniben', target_language=portal_language)
339        studentview = StudentBasePDFFormPage(self.context.student,
340            self.request, self.omit_fields)
341        students_utils = getUtility(IStudentsUtils)
342
343        tabledata = []
344        tableheader = []
345        for i in range(1,7):
346            tabledata.append(sorted(
347                [value for value in self.context.values() if value.semester == i],
348                key=lambda value: str(value.semester) + value.code))
349            tableheader.append([(Code,'code', 2.5),
350                             (Title,'title', 5),
351                             (Dept,'dcode', 1.5), (Faculty,'fcode', 1.5),
352                             (Cred, 'credits', 1.5),
353                             ])
354        return students_utils.renderPDF(
355            self, 'course_registration_slip.pdf',
356            self.context.student, studentview,
357            tableheader=tableheader,
358            tabledata=tabledata,
359            omit_fields=self.omit_fields
360            )
361
362class UnibenExportPDFCourseResultSlip(ExportPDFCourseRegistrationSlip):
363    """Deliver a PDF slip of the context.
364    """
365
366    grok.name('course_result_slip.pdf')
367
368    @property
369    def tabletitle(self):
370        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
371        tabletitle = []
372        tabletitle.append(translate(_('1st Semester Courses'), 'waeup.kofa',
373            target_language=portal_language))
374        tabletitle.append(translate(_('2nd Semester Courses'), 'waeup.kofa',
375            target_language=portal_language))
376        tabletitle.append(translate(_('Level Courses'), 'waeup.kofa',
377            target_language=portal_language))
378        tabletitle.append(translate(_('1st Trimester Courses'), 'waeup.kofa',
379            target_language=portal_language))
380        tabletitle.append(translate(_('2nd Trimester Courses'), 'waeup.kofa',
381            target_language=portal_language))
382        tabletitle.append(translate(_('3rd Trimester Courses'), 'waeup.kofa',
383            target_language=portal_language))
384        return tabletitle
385
386    @property
387    def label(self):
388        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
389        lang = self.request.cookies.get('kofa.language', portal_language)
390        level_title = translate(self.context.level_title, 'waeup.kofa',
391            target_language=lang)
392        return translate(_('Course Result Slip'),
393            'waeup.uniben', target_language=portal_language) \
394            + ' %s' % level_title
395
396    def render(self):
397        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
398        Code = translate('Code', 'waeup.kofa', target_language=portal_language)
399        Title = translate('Title', 'waeup.kofa', target_language=portal_language)
400        Dept = translate('Dept.', 'waeup.kofa', target_language=portal_language)
401        Faculty = translate('Faculty', 'waeup.kofa', target_language=portal_language)
402        Cred = translate(_('Credits'), 'waeup.uniben', target_language=portal_language)
403        Grade = translate('Grade', 'waeup.kofa', target_language=portal_language)
404        studentview = StudentBasePDFFormPage(self.context.student,
405            self.request, self.omit_fields)
406        students_utils = getUtility(IStudentsUtils)
407
408        tabledata = []
409        tableheader = []
410        for i in range(1,7):
411            tabledata.append(sorted(
412                [value for value in self.context.values() if value.semester == i],
413                key=lambda value: str(value.semester) + value.code))
414            tableheader.append([(Code,'code', 2.5),
415                             (Title,'title', 5),
416                             (Dept,'dcode', 1.5), (Faculty,'fcode', 1.5),
417                             (Cred, 'credits', 1.5),
418                             (Grade, 'grade', 1.5),
419                             ])
420        return students_utils.renderPDF(
421            self, 'course_registration_slip.pdf',
422            self.context.student, studentview,
423            tableheader=tableheader,
424            tabledata=tabledata,
425            omit_fields=self.omit_fields
426            )
427
428class UnibenExportPDFBursaryClearancePage(UtilityView, grok.View):
429    """Deliver a PDF bursary clearance slip.
430    """
431    grok.context(ICustomStudent)
432    grok.name('bursary_clearance_slip.pdf')
433    grok.require('waeup.viewStudent')
434    prefix = 'form'
435
436    omit_fields = () # ('date_of_birth', 'current_level')
437
438    form_fields = None
439
440    @property
441    def label(self):
442        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
443        return translate(_('Bursary Clearance Slip of'),
444            'waeup.kofa', target_language=portal_language) \
445            + ' %s' % self.context.display_fullname
446
447    def _sigsInFooter(self):
448        return (_('Date, Student Signature'),
449                _('Date, Bursary Signature'),
450                )
451
452    @property
453    def tabletitle(self):
454        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
455        tabletitle = []
456        tabletitle.append(translate(_('Successful Payments'), 'waeup.kofa',
457            target_language=portal_language))
458        return tabletitle
459
460    def render(self):
461        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
462        P_ID = translate(_('Payment Id'), 'waeup.kofa', target_language=portal_language)
463        #CD = translate(_('Creation Date'), 'waeup.kofa', target_language=portal_language)
464        PD = translate(_('Payment Date'), 'waeup.kofa', target_language=portal_language)
465        CAT = translate(_('Payment Category'), 'waeup.kofa', target_language=portal_language)
466        ITEM = translate(_('Payment Item'), 'waeup.kofa', target_language=portal_language)
467        AMT = translate(_('Amount (Naira)'), 'waeup.kofa', target_language=portal_language)
468        SSS = translate(_('Payment Session'), 'waeup.kofa', target_language=portal_language)
469        studentview = StudentBasePDFFormPage(self.context.student,
470            self.request, self.omit_fields)
471        students_utils = getUtility(IStudentsUtils)
472
473        tabledata = []
474        tableheader = []
475        tabledata.append(sorted(
476            [value for value in self.context['payments'].values()
477             if value.p_state == 'paid'], key=lambda value: value.p_id))
478        tableheader.append([(P_ID,'p_id', 3),
479                         #(CD,'creation_date', 3),
480                         (PD,'formatted_p_date', 3),
481                         (CAT,'category', 3),
482                         (ITEM, 'p_item', 3),
483                         (AMT, 'amount_auth', 2),
484                         (SSS, 'p_session', 2),
485                         ])
486        return students_utils.renderPDF(
487            self, 'bursary_clearance_slip.pdf',
488            self.context.student, studentview,
489            tableheader=tableheader,
490            tabledata=tabledata,
491            signatures=None,
492            sigs_in_footer=self._sigsInFooter(),
493            omit_fields=self.omit_fields
494            )
495
496class CustomCourseTicketDisplayFormPage(CourseTicketDisplayFormPage):
497    """ Page to display course tickets
498    """
499    form_fields = grok.AutoFields(ICourseTicket).omit('score')
500
501class CustomStudentActivateView(StudentActivateView):
502    """ Activate student account
503    """
504
505    def update(self):
506        self.context.suspended = False
507        self.context.writeLogMessage(self, 'account activated')
508        history = IObjectHistory(self.context)
509        history.addMessage('Student account activated', user='undisclosed')
510        self.flash(_('Student account has been activated.'))
511        self.redirect(self.url(self.context))
512        return
513
514class CustomStudentDeactivateView(StudentDeactivateView):
515    """ Deactivate student account
516    """
517    def update(self):
518        self.context.suspended = True
519        self.context.writeLogMessage(self, 'account deactivated')
520        history = IObjectHistory(self.context)
521        history.addMessage('Student account deactivated', user='undisclosed')
522        self.flash(_('Student account has been deactivated.'))
523        self.redirect(self.url(self.context))
524        return
525
526class CustomExportPDFTranscriptSlip(ExportPDFTranscriptSlip):
527    """Deliver a PDF slip of the context.
528    """
529
530    def _sigsInFooter(self):
531        return []
532        #return (_('CERTIFIED TRUE COPY'),)
533
534    def _signatures(self):
535        return ([(
536            'Current HD<br /> D. R. (Exams & Records)<br /> '
537            'For: Registrar')],)
538
539    def render(self):
540        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
541        Term = translate(_('Term'), 'waeup.kofa', target_language=portal_language)
542        Code = translate(_('Code'), 'waeup.kofa', target_language=portal_language)
543        Title = translate(_('Title'), 'waeup.kofa', target_language=portal_language)
544        Cred = translate(_('Credits'), 'waeup.kofa', target_language=portal_language)
545        #Score = translate(_('Score'), 'waeup.kofa', target_language=portal_language)
546        Grade = translate(_('Grade'), 'waeup.kofa', target_language=portal_language)
547        studentview = StudentBasePDFFormPage(self.context.student,
548            self.request, self.omit_fields)
549        students_utils = getUtility(IStudentsUtils)
550
551        tableheader = [(Code,'code', 2.5),
552                         (Title,'title', 8.5),
553                         (Term, 'semester', 1.5),
554                         (Cred, 'credits', 1.5),
555                         #(Score, 'score', 1.5),
556                         (Grade, 'grade', 1.5),
557                         ]
558
559        return students_utils.renderPDFTranscript(
560            self, 'transcript.pdf',
561            self.context.student, studentview,
562            omit_fields=self.omit_fields,
563            tableheader=tableheader,
564            signatures=self._signatures(),
565            sigs_in_footer=self._sigsInFooter(),
566            )
567
568class CustomExportPDFBedTicketSlip(NigeriaExportPDFBedTicketSlip):
569    """Deliver a PDF slip of the context.
570    """
571
572    omit_fields = ('password', 'suspended', 'suspended_comment',
573        'phone', 'adm_code', 'email', 'date_of_birth')
574
575    def render(self):
576        studentview = StudentBasePDFFormPage(self.context.student,
577            self.request, self.omit_fields)
578        students_utils = getUtility(IStudentsUtils)
579
580        note = """
581<br /><br /><br /><br /><br /><font size="14">
582Please endeavour to pay your hostel maintenance charge within <br /><br />
5834 days of being allocated a space or else you are deemed to have <br /><br />
584voluntarily forfeited it and it goes back into circulation to be <br /><br />
585available for booking afresh!</font>
586"""
587
588        return students_utils.renderPDF(
589            self, 'bed_allocation_slip.pdf',
590            self.context.student, studentview,
591            omit_fields=self.omit_fields,
592            note=note)
Note: See TracBrowser for help on using the repository browser.