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

Last change on this file since 18066 was 18066, checked in by Henrik Bettermann, 2 days ago

List all students.

  • Property svn:keywords set to Id
File size: 48.3 KB
Line 
1## $Id: browser.py 18066 2025-04-23 13:26:33Z 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
19import os
20import csv
21import pytz
22import textwrap
23from datetime import datetime
24from zope.i18n import translate
25from zope.security import checkPermission
26from zope.schema.interfaces import ConstraintNotSatisfied
27from zope.formlib.textwidgets import BytesDisplayWidget
28from zope.component import getUtility, queryUtility
29from zope.catalog.interfaces import ICatalog
30from hurry.workflow.interfaces import IWorkflowInfo
31from waeup.kofa.interfaces import (
32    REQUESTED, IExtFileStore, IKofaUtils, IObjectHistory)
33from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
34from waeup.kofa.browser.layout import action, KofaEditFormPage, UtilityView, KofaPage
35from waeup.kofa.browser.pages import LocalRoleAssignmentUtilityView
36from waeup.kofa.university.interfaces import ICourse
37from waeup.kofa.students.browser import (
38    StudentBaseEditFormPage,
39    StudyLevelEditFormPage, StudyLevelDisplayFormPage,
40    StudentBasePDFFormPage, ExportPDFCourseRegistrationSlip,
41    CourseTicketDisplayFormPage,
42    CourseTicketManageFormPage,
43    StudentTriggerTransitionFormPage,
44    msave, emit_lock_message,
45    StudentActivateView, StudentDeactivateView,
46    ExportPDFTranscriptSlip,
47    PaymentsManageFormPage,
48    StartClearancePage,
49    StudentFilesUploadPage,
50    StudyCourseTranscriptPage,
51    ExportPDFAdmissionSlip)
52from waeup.kofa.students.workflow import (CREATED, ADMITTED, PAID,
53    CLEARANCE, REQUESTED, RETURNING, CLEARED, REGISTERED, VALIDATED,
54    GRADUATED, TRANSREQ, TRANSVAL, TRANSREL, FORBIDDEN_POSTGRAD_TRANS)
55from waeup.kofa.students.interfaces import IStudentsUtils, ICourseTicket
56from waeup.kofa.students.workflow import FORBIDDEN_POSTGRAD_TRANS
57from kofacustom.nigeria.students.browser import (
58    NigeriaOnlinePaymentDisplayFormPage,
59    NigeriaStudentBaseManageFormPage,
60    NigeriaStudentClearanceEditFormPage,
61    NigeriaOnlinePaymentAddFormPage,
62    NigeriaExportPDFPaymentSlip,
63    NigeriaExportPDFClearanceSlip,
64    NigeriaExportPDFBedTicketSlip,
65    NigeriaStudentPersonalDisplayFormPage,
66    NigeriaStudentPersonalManageFormPage,
67    NigeriaStudentPersonalEditFormPage,
68    NigeriaAccommodationManageFormPage,
69    NigeriaAccommodationDisplayFormPage,
70    NigeriaStudentBaseDisplayFormPage,
71    NigeriaExportPDFFinancialClearancePage,
72    )
73from waeup.uniben.students.interfaces import (
74    ICustomStudent,
75    ICustomStudentBase,
76    ICustomStudentOnlinePayment,
77    ICustomStudentStudyCourse,
78    ICustomStudentStudyLevel,
79    ICustomUGStudentClearance,
80    ICustomPGStudentClearance,
81    ICustomStudentPersonal,
82    ICustomStudentPersonalEdit,
83    IMedicalHistory,
84    ITiship,
85    INYSC,
86    ICustomCourseTicket)
87from waeup.uniben.interfaces import MessageFactory as _
88
89deplinks_path = os.path.join(
90    os.path.dirname(__file__), 'deplinks.csv')
91reader = csv.DictReader(open(deplinks_path, 'rb'))
92DEPLINKS = {line['code']:line['url'] for line in reader}
93
94class CustomStudentBaseDisplayFormPage(NigeriaStudentBaseDisplayFormPage):
95    """ Page to display student base data
96    """
97    grok.template('basepage')
98
99    form_fields = grok.AutoFields(ICustomStudentBase).omit(
100        'password', 'suspended', 'suspended_comment',
101        'flash_notice', 'provisionally_cleared', 'parents_email')
102    form_fields[
103        'financial_clearance_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
104    form_fields[
105        'final_clearance_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
106
107class CustomStudentBaseManageFormPage(NigeriaStudentBaseManageFormPage):
108    """ View to manage student base data
109    """
110    form_fields = grok.AutoFields(ICustomStudentBase).omit(
111        'student_id', 'adm_code', 'suspended',
112        'financially_cleared_by', 'financial_clearance_date',
113        'finally_cleared_by', 'final_clearance_date',
114        'parents_email')
115
116class CustomOnlinePaymentDisplayFormPage(NigeriaOnlinePaymentDisplayFormPage):
117    """ Page to view an online payment ticket
118    """
119    grok.context(ICustomStudentOnlinePayment)
120    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
121        'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item')
122    form_fields[
123        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
124    form_fields[
125        'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
126
127class CustomStartClearancePage(StartClearancePage):
128
129    @property
130    def with_ac(self):
131        if self.context.faccode == 'DCOEM':
132            return False
133        return True
134
135    @property
136    def portrait_uploaded(self):
137        return True
138
139
140CLEARANCE_FLASH_MESSAGE = """
141If you have not presented for physical clearance, scan your WAEC, NECO
142and other O level results scratch cards on one document and
143attach to the form below (Scans > O Level Results Scratch Card).
144Then come back to check for your successful cleared status as from 3 days
145after successful clearance request.
146If status is cleared, pay your school charges and proceed to the
147Dean's Office to collect the signed eligibility form.
148"""
149
150class CustomStudentClearanceEditFormPage(NigeriaStudentClearanceEditFormPage):
151    """ View to edit student clearance data by student
152    """
153
154    @property
155    def form_fields(self):
156        if self.context.is_postgrad:
157            form_fields = grok.AutoFields(ICustomPGStudentClearance).omit(
158            'clearance_locked', 'nysc_location', 'clr_code', 'officer_comment',
159            'physical_clearance_date')
160        else:
161            form_fields = grok.AutoFields(ICustomUGStudentClearance).omit(
162            'clearance_locked', 'clr_code', 'officer_comment',
163            'physical_clearance_date')
164            form_fields['date_of_birth'].for_display = True
165            form_fields['nationality'].for_display = True
166            form_fields['lga'].for_display = True
167        return form_fields
168
169    def dataNotComplete(self):
170        store = getUtility(IExtFileStore)
171        if self.context.entry_mode in ('ug_ft', 'de_ft') and \
172            not store.getFileByContext(self.context, attr=u'passport.jpg'):
173            return _('No red background passport picture uploaded.')
174        if not store.getFileByContext(self.context, attr=u'birth_certificate.jpg'):
175            return _('No birth certificate uploaded.')
176        if not store.getFileByContext(self.context, attr=u'ref_let.jpg'):
177            return _('No guarantor/referee letter uploaded.')
178        if not store.getFileByContext(self.context, attr=u'acc_let.jpg'):
179            return _('No acceptance letter uploaded.')
180        if not store.getFileByContext(self.context, attr=u'fst_sit_scan.jpg'):
181            return _('No first sitting result uploaded.')
182        if not store.getFileByContext(self.context, attr=u'secr_cults.jpg'):
183            return _('No affidavit of non-membership of secret cults uploaded.')
184        if not store.getFileByContext(self.context, attr=u'olevel_sc.jpg'):
185            return _('No O level results scratch card uploaded.')
186        return False
187
188    #def update(self):
189    #    self.flash(CLEARANCE_FLASH_MESSAGE, type="warning")
190    #    return super(CustomStudentClearanceEditFormPage, self).update()
191
192class CustomOnlinePaymentAddFormPage(NigeriaOnlinePaymentAddFormPage):
193    """ Page to add an online payment ticket
194    """
195    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).select(
196        'p_combi')
197
198class CustomExportPDFPaymentSlip(NigeriaExportPDFPaymentSlip):
199    """Deliver a PDF slip of the context.
200    """
201    grok.context(ICustomStudentOnlinePayment)
202    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
203        'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item', 'p_combi')
204    form_fields['creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
205    form_fields['payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
206
207
208class CustomExportPDFClearanceSlip(NigeriaExportPDFClearanceSlip):
209    """Deliver a PDF slip of the context.
210    """
211
212    @property
213    def omit_fields(self):
214        omit_fields = ('password', 'suspended', 'suspended_comment',
215                       'phone', 'adm_code', 'email', 'date_of_birth',
216                       'flash_notice')
217        if self.context.is_jupeb:
218            omit_fields += ('faculty', 'department')
219        return omit_fields
220
221    @property
222    def label(self):
223        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
224        line0 = ''
225        if self.context.is_jupeb:
226            line0 = 'Joint Universities Preliminary Examinations Board (JUPEB)\n'
227        line1 = translate(_('Clearance Slip of'),
228            'waeup.kofa', target_language=portal_language) \
229            + ' %s' % self.context.display_fullname
230        return '%s%s' % (line0, line1)
231
232    def _sigsInFooter(self):
233        isStudent = getattr(
234            self.request.principal, 'user_type', None) == 'student'
235        if not isStudent and self.context.state in (CLEARED, RETURNING):
236            return (_('Date, Student Signature'),
237                    _('Date, Clearance Officer Signature'),
238                    )
239        return ()
240
241    def render(self):
242        studentview = StudentBasePDFFormPage(self.context.student,
243            self.request, self.omit_fields)
244        students_utils = getUtility(IStudentsUtils)
245        return students_utils.renderPDF(
246            self, 'clearance_slip.pdf',
247            self.context.student, studentview, signatures=self._signatures(),
248            sigs_in_footer=self._sigsInFooter(), show_scans=False,
249            omit_fields=self.omit_fields)
250
251
252class ExportClearanceInvitationSlip(UtilityView, grok.View):
253    """Deliver an invitation letter to physical clearance.
254
255    This form page is available only in Uniben.
256    """
257    grok.context(ICustomStudent)
258    grok.name('clearance_invitation_slip.pdf')
259    grok.require('waeup.viewStudent')
260    prefix = 'form'
261
262    label = u'Invitation Letter for Physical Clearance'
263
264    omit_fields = (
265        'suspended', 'phone', 'email',
266        'adm_code', 'suspended_comment',
267        'date_of_birth', 'current_level',
268        'department', 'current_mode',
269        'entry_session', 'matric_number', 'sex',
270        'flash_notice')
271
272    form_fields = []
273
274    @property
275    def note(self):
276        if self.context.physical_clearance_date:
277            return """
278<br /><br /><br /><br /><font size='12'>
279Dear %s,
280<br /><br /><br />
281You are invited for your Health Centre clearance on:
282<br /><br />
283<strong>%s</strong>.
284<br /><br />
285Please bring along your downloaded Health Centre Form to the University Health Centre
286on your Health Centre clearance date.
287<br /><br /><br />
288Signed,
289<br /><br />
290The Registrar<br />
291</font>
292
293""" % (self.context.display_fullname, self.context.physical_clearance_date)
294        return
295
296
297    def update(self):
298        if self.context.student.state != REQUESTED \
299            or not  self.context.student.physical_clearance_date:
300            self.flash(_('Forbidden'), type="warning")
301            self.redirect(self.url(self.context))
302
303    def render(self):
304        studentview = StudentBasePDFFormPage(self.context.student,
305            self.request, self.omit_fields)
306        students_utils = getUtility(IStudentsUtils)
307        return students_utils.renderPDF(
308            self, 'clearance_invitation_slip',
309            self.context.student, studentview,
310            omit_fields=self.omit_fields,
311            note=self.note)
312
313class ExportMedicalExaminationSlip(UtilityView, grok.View):
314    """Deliver an .
315
316    This form page is available only in Uniben.
317    """
318    grok.context(ICustomStudent)
319    grok.name('medical_examination_slip.pdf')
320    grok.require('waeup.viewStudent')
321    prefix = 'form'
322
323    label = u'Uniben Medical Examination Form'
324
325    omit_fields = (
326        'suspended',
327        'adm_code', 'suspended_comment',
328        'current_level',
329        'department', 'current_mode',
330        'entry_session', 'matric_number',
331        'flash_notice', 'parents_email',
332        'faculty', 'department')
333
334    form_fields = grok.AutoFields(ICustomStudentPersonal).select(
335        'marit_stat', 'perm_address', 'next_kin_phone')
336    form_fields['perm_address'].custom_widget = BytesDisplayWidget
337
338    def _medicalClearancePaymentMade(self, student, session):
339        if len(student['payments']):
340            for ticket in student['payments'].values():
341                if ticket.p_state == 'paid' and \
342                    ticket.p_category == 'medical_clearance' and \
343                    ticket.p_session == session:
344                    return True
345        return False
346
347    def update(self):
348        if self.context.student.state != CLEARED \
349            or not  self.context.student.physical_clearance_date:
350            self.flash(_('Forbidden'), type="warning")
351            self.redirect(self.url(self.context))
352        if not self._medicalClearancePaymentMade(
353            self.context, self.context.current_session):
354            self.flash('Please pay medical clearance fee first.',
355                type="warning")
356            self.redirect(self.url(self.context))
357        return
358
359    def render(self):
360        studentview = StudentBasePDFFormPage(self.context.student,
361            self.request, self.omit_fields)
362        students_utils = getUtility(IStudentsUtils)
363        file_path = os.path.join(
364            os.path.dirname(__file__), 'static', 'medical_examination_form.pdf')
365        file = open(file_path, 'rb')
366        mergefiles = [file,]
367        return students_utils.renderPDF(
368            self, 'medical_examination_slip',
369            self.context.student, studentview,
370            omit_fields=self.omit_fields,
371            mergefiles=mergefiles,
372            )
373
374
375class ExportExaminationScheduleSlip(UtilityView, grok.View):
376    """Deliver a examination schedule slip.
377
378    This form page is available only in Uniben and AAUE.
379    """
380    grok.context(ICustomStudent)
381    grok.name('examination_schedule_slip.pdf')
382    grok.require('waeup.viewStudent')
383    prefix = 'form'
384
385    label = u'Examination Schedule Slip'
386
387    omit_fields = (
388        'suspended', 'phone', 'email',
389        'adm_code', 'suspended_comment',
390        'date_of_birth', 'current_level',
391        'current_mode',
392        'entry_session',
393        'flash_notice')
394
395    form_fields = []
396
397    @property
398    def note(self):
399        return """
400<br /><br /><br /><br /><font size='12'>
401Your examination date, time and venue is scheduled as follows:
402<br /><br />
403<strong>%s</strong>
404</font>
405
406""" % self.context.flash_notice
407        return
408
409
410    def update(self):
411        if not self.context.flash_notice \
412            or not 'exam' in self.context.flash_notice.lower():
413            self.flash(_('Forbidden'), type="warning")
414            self.redirect(self.url(self.context))
415
416    def render(self):
417        studentview = StudentBasePDFFormPage(self.context.student,
418            self.request, self.omit_fields)
419        students_utils = getUtility(IStudentsUtils)
420        return students_utils.renderPDF(
421            self, 'examination_schedule_slip',
422            self.context.student, studentview,
423            omit_fields=self.omit_fields,
424            note=self.note)
425
426class SwitchLibraryAccessView(UtilityView, grok.View):
427    """ Switch the library attribute
428    """
429    grok.context(ICustomStudent)
430    grok.name('switch_library_access')
431    grok.require('waeup.switchLibraryAccess')
432
433    def update(self):
434        if self.context.library:
435            self.context.library = False
436            self.context.writeLogMessage(self, 'library access disabled')
437            self.flash(_('Library access disabled'))
438        else:
439            self.context.library = True
440            self.context.writeLogMessage(self, 'library access enabled')
441            self.flash(_('Library access enabled'))
442        self.redirect(self.url(self.context))
443        return
444
445    def render(self):
446        return
447
448class ExportJHLIdCard(UtilityView, grok.View):
449    """Deliver an id card for the John Harris Library.
450    """
451    grok.context(ICustomStudent)
452    grok.name('jhl_idcard.pdf')
453    grok.require('waeup.viewStudent')
454    prefix = 'form'
455
456    label = u"John Harris Library Clearance"
457
458    omit_fields = (
459        'suspended', 'email', 'phone',
460        'adm_code', 'suspended_comment',
461        'date_of_birth',
462        'current_mode', 'certificate',
463        'entry_session',
464        'flash_notice')
465
466    form_fields = []
467
468    def _sigsInFooter(self):
469        isStudent = getattr(
470            self.request.principal, 'user_type', None) == 'student'
471        if isStudent:
472            return ''
473        return (_("Date, Reader's Signature"),
474                _("Date, Circulation Librarian's Signature"),
475                )
476
477    def update(self):
478        if not self.context.library:
479            self.flash(_('Forbidden!'), type="danger")
480            self.redirect(self.url(self.context))
481        return
482
483    @property
484    def note(self):
485        return """
486<br /><br /><br /><br /><font size='12'>
487This is to certify that the bearer whose photograph and other details appear
488 overleaf is a registered user of <b>John Harris Library, University of Benin</b>.
489 The card is not transferable. A replacement fee is charged for a loss,
490 mutilation or otherwise. If found, please, return to John Harris Library,
491 University of Benin, Benin City.
492</font>
493
494"""
495        return
496
497    def render(self):
498        studentview = StudentBasePDFFormPage(self.context.student,
499            self.request, self.omit_fields)
500        students_utils = getUtility(IStudentsUtils)
501        return students_utils.renderPDF(
502            self, 'jhl_idcard',
503            self.context.student, studentview,
504            omit_fields=self.omit_fields,
505            sigs_in_footer=self._sigsInFooter(),
506            note=self.note)
507
508class ExportJUPEBResultSlip(ExportExaminationScheduleSlip):
509    """Deliver a JUPEB result slip.
510
511    This form page is available only in Uniben.
512    """
513
514    grok.name('jupeb_result_slip.pdf')
515    label = u'JUPEB Result Slip'
516
517    @property
518    def note(self):
519        return """
520<br /><br /><br /><br /><font size='12'>
521<strong>%s</strong>
522</font>
523<br /><br /><br /><br />
524<font size='8'>
525Key: A = 5, B = 4, C = 3, D = 2, E = 1, F = 0, X = Absent, Q = Cancelled
526</font>
527
528""" % self.context.flash_notice
529        return
530
531    def update(self):
532        if not self.context.flash_notice or not self.context.is_jupeb \
533            or not 'results' in self.context.flash_notice.lower():
534            self.flash(_('Forbidden'), type="warning")
535            self.redirect(self.url(self.context))
536
537class CustomStudentPersonalDisplayFormPage(
538    NigeriaStudentPersonalDisplayFormPage):
539    """ Page to display student personal data
540    """
541
542    form_fields = grok.AutoFields(ICustomStudentPersonal) + grok.AutoFields(ITiship)
543    form_fields['perm_address'].custom_widget = BytesDisplayWidget
544    form_fields['next_kin_address'].custom_widget = BytesDisplayWidget
545    form_fields[
546        'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
547
548class CustomStudentPersonalManageFormPage(
549    NigeriaStudentPersonalManageFormPage):
550    """ Page to manage personal data
551    """
552
553    form_fields = grok.AutoFields(ICustomStudentPersonal) + grok.AutoFields(ITiship)
554    form_fields['personal_updated'].for_display = True
555    form_fields[
556        'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
557
558class CstomStudentPersonalEditFormPage(NigeriaStudentPersonalEditFormPage):
559    """ Page to edit personal data
560    """
561
562    @property
563    def form_fields(self):
564        form_fields = grok.AutoFields(
565            ICustomStudentPersonalEdit).omit('personal_updated') + grok.AutoFields(ITiship)
566        return form_fields
567
568class StudyCourseCOEditFormPage(KofaEditFormPage):
569    """ Page to edit the student study course data by clearance officers.
570
571    This form page is available only in Uniben.
572    """
573    grok.context(ICustomStudentStudyCourse)
574    grok.name('edit_level')
575    grok.require('waeup.clearStudent')
576    label = _('Edit current level')
577    pnav = 4
578    form_fields = grok.AutoFields(
579        ICustomStudentStudyCourse).select('current_level')
580
581    def update(self):
582        if not (self.context.is_current and
583            self.context.student.state == REQUESTED):
584            emit_lock_message(self)
585            return
586        super(StudyCourseCOEditFormPage, self).update()
587        return
588
589    @action(_('Save'), style='primary')
590    def save(self, **data):
591        try:
592            msave(self, **data)
593        except ConstraintNotSatisfied:
594            # The selected level might not exist in certificate
595            self.flash(_('Current level not available for certificate.'))
596            return
597        #notify(grok.ObjectModifiedEvent(self.context.__parent__))
598        return
599
600class CustomStudyLevelEditFormPage(StudyLevelEditFormPage):
601    """ Page to edit the student study level data by students.
602
603    """
604    grok.template('studyleveleditpage')
605
606class CustomStudyLevelDisplayFormPage(StudyLevelDisplayFormPage):
607    """ Page to display student study levels
608    """
609    grok.template('studylevelpage')
610
611    @property
612    def view_scores_allowed(self):
613        return checkPermission('waeup.manageStudent', self.context)
614
615class CustomExportPDFCourseRegistrationSlip(
616    ExportPDFCourseRegistrationSlip):
617    """Deliver a PDF slip of the context.
618    """
619
620    form_fields = grok.AutoFields(ICustomStudentStudyLevel).omit(
621        'level_verdict', 'gpa', 'level', 'transcript_remark')
622
623    def update(self):
624        if self.context.student.state != REGISTERED \
625            or self.context.student.current_level != self.context.level:
626            self.flash(_('Forbidden'), type="warning")
627            self.redirect(self.url(self.context))
628
629    @property
630    def tabletitle(self):
631        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
632        tabletitle = []
633        tabletitle.append(translate(_('1st Semester Courses'), 'waeup.kofa',
634            target_language=portal_language))
635        tabletitle.append(translate(_('2nd Semester Courses'), 'waeup.kofa',
636            target_language=portal_language))
637        tabletitle.append(translate(_('Level Courses'), 'waeup.kofa',
638            target_language=portal_language))
639        tabletitle.append(translate(_('1st Trimester Courses'), 'waeup.kofa',
640            target_language=portal_language))
641        tabletitle.append(translate(_('2nd Trimester Courses'), 'waeup.kofa',
642            target_language=portal_language))
643        tabletitle.append(translate(_('3rd Trimester Courses'), 'waeup.kofa',
644            target_language=portal_language))
645        return tabletitle
646
647    def render(self):
648        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
649        Code = translate('Code', 'waeup.kofa', target_language=portal_language)
650        Title = translate('Title', 'waeup.kofa', target_language=portal_language)
651        Dept = translate('Dept.', 'waeup.kofa', target_language=portal_language)
652        Faculty = translate('Faculty', 'waeup.kofa', target_language=portal_language)
653        Cred = translate(_('Credits'), 'waeup.uniben', target_language=portal_language)
654        studentview = StudentBasePDFFormPage(self.context.student,
655            self.request, self.omit_fields)
656        students_utils = getUtility(IStudentsUtils)
657
658        tabledata = []
659        tableheader = []
660        for i in range(1,7):
661            tabledata.append(sorted(
662                [value for value in self.context.values() if value.semester == i],
663                key=lambda value: str(value.semester) + value.code))
664            tableheader.append([(Code,'code', 2.5),
665                             (Title,'title', 5),
666                             (Dept,'dcode', 1.5), (Faculty,'fcode', 1.5),
667                             (Cred, 'credits', 1.5),
668                             ])
669        return students_utils.renderPDF(
670            self, 'course_registration_slip.pdf',
671            self.context.student, studentview,
672            tableheader=tableheader,
673            tabledata=tabledata,
674            omit_fields=self.omit_fields
675            )
676
677class ExportPDFCourseResultSlip(ExportPDFCourseRegistrationSlip):
678    """Deliver a PDF slip of the context.
679    """
680
681    grok.name('course_result_slip.pdf')
682
683    form_fields = grok.AutoFields(ICustomStudentStudyLevel).omit('level')
684
685    @property
686    def tabletitle(self):
687        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
688        tabletitle = []
689        tabletitle.append(translate(_('1st Semester Courses'), 'waeup.kofa',
690            target_language=portal_language))
691        tabletitle.append(translate(_('2nd Semester Courses'), 'waeup.kofa',
692            target_language=portal_language))
693        tabletitle.append(translate(_('Level Courses'), 'waeup.kofa',
694            target_language=portal_language))
695        tabletitle.append(translate(_('1st Trimester Courses'), 'waeup.kofa',
696            target_language=portal_language))
697        tabletitle.append(translate(_('2nd Trimester Courses'), 'waeup.kofa',
698            target_language=portal_language))
699        tabletitle.append(translate(_('3rd Trimester Courses'), 'waeup.kofa',
700            target_language=portal_language))
701        return tabletitle
702
703    @property
704    def label(self):
705        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
706        lang = self.request.cookies.get('kofa.language', portal_language)
707        level_title = translate(self.context.level_title, 'waeup.kofa',
708            target_language=lang)
709        return translate(_('Course Result Slip'),
710            'waeup.uniben', target_language=portal_language) \
711            + ' %s' % level_title
712
713    def render(self):
714        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
715        Code = translate('Code', 'waeup.kofa', target_language=portal_language)
716        Title = translate('Title', 'waeup.kofa', target_language=portal_language)
717        Dept = translate('Dept.', 'waeup.kofa', target_language=portal_language)
718        Faculty = translate('Faculty', 'waeup.kofa', target_language=portal_language)
719        Cred = translate(_('Credits'), 'waeup.uniben', target_language=portal_language)
720        Grade = translate('Grade', 'waeup.kofa', target_language=portal_language)
721        studentview = StudentBasePDFFormPage(self.context.student,
722            self.request, self.omit_fields)
723        students_utils = getUtility(IStudentsUtils)
724
725        tabledata = []
726        tableheader = []
727        for i in range(1,7):
728            tabledata.append(sorted(
729                [value for value in self.context.values() if value.semester == i],
730                key=lambda value: str(value.semester) + value.code))
731            tableheader.append([(Code,'code', 2.5),
732                             (Title,'title', 5),
733                             (Dept,'dcode', 1.5), (Faculty,'fcode', 1.5),
734                             (Cred, 'credits', 1.5),
735                             (Grade, 'grade', 1.5),
736                             ])
737        return students_utils.renderPDF(
738            self, 'course_result_slip.pdf',
739            self.context.student, studentview,
740            tableheader=tableheader,
741            tabledata=tabledata,
742            omit_fields=self.omit_fields
743            )
744
745class CustomCourseTicketDisplayFormPage(CourseTicketDisplayFormPage):
746    """ Page to display course tickets
747    """
748    form_fields = grok.AutoFields(ICustomCourseTicket).omit('score')
749
750class CustomCourseTicketManageFormPage(CourseTicketManageFormPage):
751    """ Page to manage course tickets
752    """
753
754    form_fields = grok.AutoFields(ICustomCourseTicket).omit('course_category')
755    form_fields['title'].for_display = True
756    form_fields['fcode'].for_display = True
757    form_fields['dcode'].for_display = True
758    form_fields['semester'].for_display = True
759    form_fields['passmark'].for_display = True
760    form_fields['credits'].for_display = True
761    form_fields['mandatory'].for_display = False
762    form_fields['automatic'].for_display = True
763    form_fields['carry_over'].for_display = True
764    form_fields['ticket_session'].for_display = True
765
766class CustomStudentActivateView(StudentActivateView):
767    """ Activate student account
768    """
769
770    def update(self):
771        self.context.suspended = False
772        self.context.writeLogMessage(self, 'account activated')
773        history = IObjectHistory(self.context)
774        history.addMessage('Student account activated', user='undisclosed')
775        self.flash(_('Student account has been activated.'))
776        self.redirect(self.url(self.context))
777        return
778
779class CustomStudentDeactivateView(StudentDeactivateView):
780    """ Deactivate student account
781    """
782    def update(self):
783        self.context.suspended = True
784        self.context.writeLogMessage(self, 'account deactivated')
785        history = IObjectHistory(self.context)
786        history.addMessage('Student account deactivated', user='undisclosed')
787        self.flash(_('Student account has been deactivated.'))
788        self.redirect(self.url(self.context))
789        return
790
791class CustomStudyCourseTranscriptPage(StudyCourseTranscriptPage):
792    """ Page to display the student's transcript.
793    """
794#    grok.require('waeup.viewStudent')
795
796class CustomExportPDFTranscriptSlip(ExportPDFTranscriptSlip):
797    """Deliver a PDF slip of the context.
798    """
799#    grok.require('waeup.viewStudent')
800
801    def _sigsInFooter(self):
802        isStudent = getattr(
803            self.request.principal, 'user_type', None) == 'student'
804        if not isStudent and self.context.student.state in (TRANSVAL, TRANSREL):
805            return (_('D. R. (Exams & Records)'),_('Current Dean of Faculty'),)
806        return ()
807
808    #def _signatures(self):
809    #    return ([(
810    #        'Current HD<br /> D. R. (Exams & Records)<br /> '
811    #        'For: Registrar')],)
812
813    def render(self):
814        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
815        Term = translate(_('Sem.'), 'waeup.kofa', target_language=portal_language)
816        Code = translate(_('Course'), 'waeup.kofa', target_language=portal_language)
817        Title = translate(_('Subject/Course (Title)'), 'waeup.kofa', target_language=portal_language)
818        Cred = translate(_('Credit'), 'waeup.kofa', target_language=portal_language)
819        #Score = translate(_('Score'), 'waeup.kofa', target_language=portal_language)
820        Grade = translate(_('Grade'), 'waeup.kofa', target_language=portal_language)
821        studentview = StudentBasePDFFormPage(self.context.student,
822            self.request, self.omit_fields)
823        students_utils = getUtility(IStudentsUtils)
824
825        tableheader = [(Code,'code', 2.5),
826                         (Title,'title', 8.5),
827                         (Term, 'semester', 1.5),
828                         (Cred, 'credits', 1.5),
829                         #(Score, 'score', 1.5),
830                         (Grade, 'grade', 1.5),
831                         ]
832
833        pdfstream = students_utils.renderPDFTranscript(
834            self, 'transcript.pdf',
835            self.context.student, studentview,
836            omit_fields=self.omit_fields,
837            tableheader=tableheader,
838            signatures=self._signatures(),
839            sigs_in_footer=self._sigsInFooter(),
840            digital_sigs=self._digital_sigs(),
841            save_file=self._save_file(),
842            )
843        if not pdfstream:
844            self.redirect(self.url(self.context.student))
845            return
846        return pdfstream
847
848class CustomExportPDFBedTicketSlip(NigeriaExportPDFBedTicketSlip):
849    """Deliver a PDF slip of the context.
850    """
851    omit_fields = ('password', 'suspended', 'suspended_comment',
852        'phone', 'adm_code', 'email', 'date_of_birth', 'flash_notice')
853
854class CustomPaymentsManageFormPage(PaymentsManageFormPage):
855    """ Page to manage the student payments. This manage form page is for
856    both students and students officers. Uniben does not allow students
857    to remove any payment ticket.
858    """
859    @property
860    def manage_payments_allowed(self):
861        return checkPermission('waeup.manageStudent', self.context)
862
863class CustomAccommodationDisplayFormPage(NigeriaAccommodationDisplayFormPage):
864    """ Page to view bed tickets.
865    """
866    with_hostel_selection = True
867
868class CustomAccommodationManageFormPage(NigeriaAccommodationManageFormPage):
869    """ Page to manage bed tickets.
870    This manage form page is for both students and students officers.
871    """
872    with_hostel_selection = True
873
874class CustomStudentBaseEditFormPage(StudentBaseEditFormPage):
875    """ View to edit student base data
876    """
877    form_fields = grok.AutoFields(ICustomStudentBase).select(
878        'email', 'phone')
879    form_fields['email'].field.required = True
880
881class ExportMarkSheetSlip(UtilityView, grok.View,
882    LocalRoleAssignmentUtilityView):
883    """Deliver a PDF slip of course tickets in attendance sheet format.
884    """
885    grok.context(ICourse)
886    grok.name('marksheet.pdf')
887    grok.require('waeup.showStudents')
888
889    def update(self):
890        self.current_academic_session = grok.getSite()[
891            'configuration'].current_academic_session
892        if not self.current_academic_session:
893            self.flash(_('Current academic session not set.'), type="danger")
894            self.redirect(self.url(self.context))
895            return
896
897    @property
898    def note(self):
899        return
900
901    def data(self, session):
902        cat = queryUtility(ICatalog, name='coursetickets_catalog')
903        # Attention: Also tickets of previous studycourses are found
904        coursetickets = cat.searchResults(
905            session=(session, session),
906            code=(self.context.code, self.context.code)
907            )
908        header = [[_('S/N'),
909                   _('Matric No.'),
910                   _('Name'),
911                   _('Level'),
912                   _('Course of\nStudies'),
913                   _('CA'),
914                   _('Exam'),
915                   _('Total'),
916                   ],]
917        tickets = []
918        sn = 1
919        ctlist = sorted(list(coursetickets),
920                        key=lambda value: str(value.student.faccode) +
921                                          str(value.student.depcode) +
922                                          str(value.student.certcode) +
923                                          str(value.student.matric_number))
924        # In AAUE only editable appear on the attendance sheet. Hopefully
925        # this holds for other universities too.
926        #editable_tickets = [ticket for ticket in ctlist
927        #    if ticket.editable_by_lecturer]
928        for ticket in ctlist:
929            name = textwrap.fill(ticket.student.display_fullname, 20)
930            row = [sn,
931                  ticket.student.matric_number,
932                  name,
933                  ticket.level,
934                  ticket.student.certcode,
935                  20 * ' ',
936                  20 * ' ',
937                  20 * ' ',
938                  ]
939            tickets.append(row)
940            sn += 1
941        return header + tickets, None
942
943    def render(self):
944        lecturers = [i['user_title'] for i in self.getUsersWithLocalRoles()
945                     if i['local_role'] == 'waeup.local.Lecturer']
946        lecturers =  ', '.join(lecturers)
947        students_utils = getUtility(IStudentsUtils)
948        return students_utils.renderPDFCourseticketsOverview(
949            self, 'marksheet', self.current_academic_session,
950            self.data(self.current_academic_session),
951            lecturers, '', 65, self.note)
952
953
954
955
956from zope.schema.vocabulary import SimpleVocabulary
957from zope.formlib.itemswidgets import RadioWidget
958from zope.formlib.itemswidgets import SelectWidget, DropdownWidget
959
960def CustomBooleanRadioWidget(field, request, true=_('yes'), false=_('no')):
961    vocabulary = SimpleVocabulary.fromItems( ((true, True), (false, False)) )
962    widget = RadioWidget(field, vocabulary, request)
963    widget.required = False
964    return widget
965
966class StudentMedicalHistoryEditFormPage(KofaEditFormPage):
967    """ Page to edit medical data
968    """
969    grok.context(ICustomStudent)
970    grok.name('edit_medical')
971    grok.require('waeup.handleStudent')
972    label = _('Medical Questionnaire')
973    pnav = 4
974
975    def _medicalQuestPaymentMade(self, student, session):
976        if len(student['payments']):
977            for ticket in student['payments'].values():
978                if ticket.p_state == 'paid' and \
979                    ticket.p_category == 'medical_quest' and \
980                    ticket.p_session == session:
981                    return True
982        return False
983
984    def update(self):
985        if not self._medicalQuestPaymentMade(
986            self.context, self.context.current_session):
987            self.flash('Please pay medical questionnaire payment first.',
988                type="warning")
989            self.redirect(self.url(self.context))
990            return
991        return super(StudentMedicalHistoryEditFormPage, self).update()
992
993    @property
994    def form_fields(self):
995        form_fields = grok.AutoFields(IMedicalHistory) + grok.AutoFields(ITiship)
996        form_fields['medical_updated'].for_display = True
997        for field in ('fever', 'headaches', 'catarrh', 'cough', 'sore_throat',
998                      'breathing', 'sneezing', 'weakness', 'body_pains',
999                      'smell', 'taste', 'asthma', 'hypertension', 'diabetes',
1000                      'obesity', 'lagos_abuja', 'outside', 'company_suspected',
1001                      'company_confirmed', 'positive', 'negative',
1002                      'vaccination'):
1003            form_fields[field].custom_widget = CustomBooleanRadioWidget
1004        return form_fields
1005
1006    @property
1007    def separators(self):
1008        return getUtility(IStudentsUtils).SEPARATORS_DICT
1009
1010    @action(_('Save/Confirm'), style='primary')
1011    def save(self, **data):
1012        msave(self, **data)
1013        self.context.medical_updated = datetime.utcnow()
1014        return
1015
1016class StudentMedicalHistoryManageFormPage(StudentMedicalHistoryEditFormPage):
1017    """ Page to manage medical data
1018    """
1019    grok.name('manage_medical')
1020    grok.require('waeup.manageStudent')
1021    label = _('Manage medical questionnaire data')
1022
1023    def update(self):
1024        return super(StudentMedicalHistoryEditFormPage, self).update()
1025
1026
1027class ExportPDFMedicalHistorySlip(grok.View):
1028    """Deliver a PDF slip of the context.
1029    """
1030    grok.context(ICustomStudent)
1031    grok.name('medical_questionnaire_slip.pdf')
1032    grok.require('waeup.viewStudent')
1033    prefix = 'form'
1034    form_fields = grok.AutoFields(IMedicalHistory)
1035
1036    omit_fields = ('password', 'suspended', 'suspended_comment',
1037                   'adm_code', 'date_of_birth',
1038                   'flash_notice', 'current_mode', 'entry_mode',
1039                   'entry_session', 'parents_email',
1040                   'current_level', 'reg_number', 'sex',
1041                   'certificate')
1042
1043    @property
1044    def title(self):
1045        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
1046        return translate(_('Medical Questionnaire'), 'waeup.kofa',
1047            target_language=portal_language)
1048
1049    @property
1050    def label(self):
1051        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
1052        return translate(_('Medical Questionnaire Slip of'),
1053            'waeup.kofa', target_language=portal_language) \
1054            + ' %s' % self.context.display_fullname
1055
1056    def render(self):
1057        studentview = StudentBasePDFFormPage(self.context.student,
1058            self.request, self.omit_fields)
1059        students_utils = getUtility(IStudentsUtils)
1060        return students_utils.renderPDF(
1061            self, 'medical_questionnaire_slip.pdf',
1062            self.context.student, studentview,
1063            omit_fields=self.omit_fields,)
1064
1065class ExportPDFTishipSlip(grok.View):
1066    """Deliver a PDF slip of the context.
1067    """
1068    grok.context(ICustomStudent)
1069    grok.name('tiship_slip.pdf')
1070    grok.require('waeup.viewStudent')
1071    prefix = 'form'
1072    form_fields = grok.AutoFields(ITiship)
1073    title = ''
1074
1075    omit_fields = ('password', 'suspended', 'suspended_comment',
1076                   'adm_code',
1077                   'flash_notice', 'current_mode', 'entry_mode',
1078                   'parents_email',
1079                   )
1080
1081    @property
1082    def label(self):
1083        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
1084        return translate(_('TISHIP Registration Slip of'),
1085            'waeup.kofa', target_language=portal_language) \
1086            + ' %s' % self.context.display_fullname
1087
1088
1089    def _sigsInFooter(self):
1090        return (_('Year of Graduation'),
1091                    _('Signature'),
1092                    _('Date'),
1093                    )
1094
1095    def render(self):
1096        studentview = StudentBasePDFFormPage(self.context.student,
1097            self.request, self.omit_fields)
1098        students_utils = getUtility(IStudentsUtils)
1099        return students_utils.renderPDF(
1100            self, 'tiship_slip.pdf',
1101            self.context.student, studentview,
1102            sigs_in_footer=self._sigsInFooter(),
1103            omit_fields=self.omit_fields,)
1104
1105class PlagTestInfoPage(KofaPage):
1106    "Landing page after plagiation test payment"
1107    grok.context(ICustomStudentOnlinePayment)
1108    grok.name('plagtestinfo')
1109    grok.require('waeup.viewStudent')
1110
1111    def update(self):
1112        if self.context.p_state != 'paid' \
1113            or self.context.p_category != 'plag_test':
1114            self.flash(_('Forbidden'), type="danger")
1115            self.redirect(self.url(self.context))
1116        return super(PlagTestInfoPage, self).update()
1117
1118    @property
1119    def facdep(self):
1120        facdepkey = "%s-%s" % (self.context.student.faccode,
1121                               self.context.student.depcode)
1122        return DEPLINKS.get(facdepkey, None)
1123
1124class CustomExportPDFAdmissionSlip(ExportPDFAdmissionSlip):
1125    """Deliver a PDF Admission slip.
1126    """
1127
1128    @property
1129    def post_text_pt(self):
1130        datelist = self.context.history.messages[0].split()[0].split('-')
1131        creation_date = u'%s/%s/%s' % (datelist[2], datelist[1], datelist[0])
1132        return (
1133            'Your Kofa student record was created on %s. <br/><br/>'
1134            'Please Note: This admission for '
1135            'Undergraduate Part-Time and Undergraduate Sandwich is incomplete '
1136            'until you have successfully applied on the <b>JAMB CAPS PORTAL</b>.  '
1137            'Ignore this if you have completed your own <b>pre-admission</b> '
1138            'activities on the JAMB website.' % creation_date)
1139
1140    def render(self):
1141        students_utils = getUtility(IStudentsUtils)
1142        letterhead_path = os.path.join(
1143            os.path.dirname(__file__), 'static', 'letterhead_admission.jpg')
1144        if not os.path.exists(letterhead_path):
1145            letterhead_path = None
1146        if self.context.current_mode in ('ug_pt', 'ug_sw'):
1147            return students_utils.renderPDFAdmissionLetter(self,
1148                self.context.student, omit_fields=self.omit_fields,
1149                letterhead_path=letterhead_path, post_text=self.post_text_pt)
1150        return students_utils.renderPDFAdmissionLetter(self,
1151            self.context.student, omit_fields=self.omit_fields,
1152            letterhead_path=letterhead_path, post_text=None)
1153
1154class StudentNYSCEditFormPage(KofaEditFormPage):
1155    """ Page to edit NYSC data
1156    """
1157    grok.context(ICustomStudent)
1158    grok.name('edit_nysc')
1159    grok.require('waeup.handleStudent')
1160    label = _('NYSC Request')
1161    pnav = 4
1162
1163    def update(self):
1164        if not self.context.eligible_for_nysc:
1165            self.flash('You are not allowed to apply for NYSC.',
1166                type="warning")
1167            self.redirect(self.url(self.context))
1168            return
1169        return super(StudentNYSCEditFormPage, self).update()
1170
1171    @property
1172    def form_fields(self):
1173        form_fields = grok.AutoFields(INYSC)
1174        form_fields['nysc_updated'].for_display = True
1175        #form_fields['nysc_senate_info'].for_display = True
1176        form_fields['nysc'].field.description = u'Ensure that all your school charges are paid up to date to your graduating session before making this nysc application.'
1177        form_fields['nysc'].field.title = u'Do you want to apply for NYSC?'
1178        form_fields[
1179            'nysc_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
1180        form_fields['nysc'].custom_widget = CustomBooleanRadioWidget
1181        form_fields['nysc_processed'].for_display = True
1182        #form_fields['nysc_senate_info'].field.description = u''
1183        return form_fields
1184
1185    @action(_('Save'), style='primary')
1186    def save(self, **data):
1187        msave(self, **data)
1188        self.context.nysc_updated = datetime.utcnow()
1189        self.context.nysc_processed = False
1190        return
1191
1192class StudentNYSCManageFormPage(KofaEditFormPage):
1193    """ Page to manage NYSC data
1194    """
1195    grok.context(ICustomStudent)
1196    grok.name('manage_nysc')
1197    grok.require('waeup.manageStudent')
1198    label = _('Manage NYSC request data')
1199
1200    @property
1201    def form_fields(self):
1202        form_fields = grok.AutoFields(INYSC)
1203        form_fields['nysc_updated'].for_display = True
1204        form_fields['nysc'].field.description = u''
1205        form_fields['nysc'].field.title = u'NYSC requested'
1206        form_fields[
1207            'nysc_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
1208        return form_fields
1209
1210    @action(_('Save'), style='primary')
1211    def save(self, **data):
1212        msave(self, **data)
1213        return
1214
1215class CustomNigeriaExportPDFFinancialClearancePage(NigeriaExportPDFFinancialClearancePage):
1216    """Deliver a PDF financial clearance slip.
1217    """
1218
1219    grok.context(ICustomStudent)
1220
1221    @property
1222    def note(self):
1223        if self.context.nysc and self.context.nysc_updated:
1224            nysc_updated = self.context.nysc_updated.strftime('%d/%m/%Y')
1225            return """
1226NYSC requested on %s.
1227
1228Senate Info: %s
1229""" % (nysc_updated, self.context.nysc_senate_info)
1230        else:
1231            return
1232
1233    form_fields = grok.AutoFields(ICustomStudent).select('email2')
1234
1235    omit_fields = (
1236        'suspended', 'phone', 'email', 'parents_email',
1237        'adm_code', 'suspended_comment',
1238        'date_of_birth', 'entry_session', 'current_mode',
1239        'flash_notice')
1240
1241class StudentAffidavitUploadPage(KofaPage):
1242    """View to upload scanned affidavit of good behavior by student.
1243    """
1244    grok.context(ICustomStudent)
1245    grok.name('affidavit_upload')
1246    grok.require('waeup.uploadStudentFile')
1247    grok.template('affidavituploadpage')
1248    label = _('Upload affidavit of good conduct')
1249    deletion_warning = _('Are you sure?')
1250    pnav = 4
1251
1252class ExportPDFAffidavitSlip(UtilityView, grok.View):
1253    """Deliver a affidavit PDF template.
1254    """
1255    grok.context(ICustomStudent)
1256    grok.name('affidavit_good_conduct.pdf')
1257    grok.require('waeup.viewStudent')
1258    prefix = 'form'
1259
1260    omit_fields = ('date_of_birth', 'current_level', 'certificate',
1261        'current_mode', 'entry_session')
1262
1263    form_fields = grok.AutoFields(ICustomStudentBase).select('student_id', 'matric_number', 'reg_number', 'sex')
1264
1265    pre_text = ' '
1266
1267    post_text = '''To undertake as follows:
1268
1269(i) to abide by the arrangement(s) put in place by the University Management for the
1270supply, distribution and utilization of electricity on the campuses of the
1271University of Benin;
1272
1273(ii) to pay outstanding school charges upon resumption as eligibility for examinations
1274will henceforth be strictly based on presentation of evidence of payment of approved
1275school charges;
1276
1277(iii) not to bring any prohibited appliances, such as hot plate, ring boiler,
1278gas cooker etc into the Halls of Residence, as violation of this rule shall attract
1279rustication of such a Student;
1280
1281(iv) not to be involved in any unruly conduct that is against the Rules and
1282Regulations of the University; and
1283
1284(v) to be of good conduct, and not to sponsor or participate in any unauthorized
1285assembly or demonstration within the campuses and their precincts.
1286
1287
1288________________________________
1289(Deponent)
1290
1291Sworn at ________________________________
1292
1293This Day ________________________________
1294
1295Before Me _______________________________
1296
1297
1298
1299Commissioner of Oaths
1300
1301
1302
1303
1304'''
1305
1306    @property
1307    def label(self):
1308        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
1309        return 'Affidavit of Undertaking to be of Good Conduct'
1310           
1311    def render(self):
1312        students_utils = getUtility(IStudentsUtils)
1313        letterhead_path = os.path.join(
1314            os.path.dirname(__file__), 'static', 'letterhead.jpg')
1315        if not os.path.exists(letterhead_path):
1316            letterhead_path = None
1317        return students_utils.renderPDFAdmissionLetter(self,
1318            self.context.student, omit_fields=self.omit_fields,
1319            letterhead_path=letterhead_path,
1320            pre_text=self.pre_text, post_text=self.post_text)
Note: See TracBrowser for help on using the repository browser.