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

Last change on this file since 16458 was 16458, checked in by Henrik Bettermann, 3 years ago

Only ug_ft students must upload picture.

  • Property svn:keywords set to Id
File size: 33.5 KB
Line 
1## $Id: browser.py 16458 2021-04-14 06:07:09Z 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 datetime import datetime
20from zope.i18n import translate
21from zope.security import checkPermission
22from zope.schema.interfaces import ConstraintNotSatisfied
23from zope.formlib.textwidgets import BytesDisplayWidget
24from zope.component import getUtility
25from hurry.workflow.interfaces import IWorkflowInfo
26from waeup.kofa.interfaces import (
27    REQUESTED, IExtFileStore, IKofaUtils, IObjectHistory)
28from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
29from waeup.kofa.browser.layout import action, KofaEditFormPage, UtilityView
30from waeup.kofa.students.browser import (
31    StudentBaseEditFormPage,
32    StudyLevelEditFormPage, StudyLevelDisplayFormPage,
33    StudentBasePDFFormPage, ExportPDFCourseRegistrationSlip,
34    CourseTicketDisplayFormPage, StudentTriggerTransitionFormPage,
35    msave, emit_lock_message,
36    StudentActivateView, StudentDeactivateView,
37    ExportPDFTranscriptSlip,
38    PaymentsManageFormPage,
39    StartClearancePage,
40    StudentFilesUploadPage)
41from waeup.kofa.students.workflow import (CREATED, ADMITTED, PAID,
42    CLEARANCE, REQUESTED, RETURNING, CLEARED, REGISTERED, VALIDATED,
43    GRADUATED, TRANSREQ, TRANSVAL, TRANSREL, FORBIDDEN_POSTGRAD_TRANS)
44from waeup.kofa.students.interfaces import IStudentsUtils, ICourseTicket
45from waeup.kofa.students.workflow import FORBIDDEN_POSTGRAD_TRANS
46from kofacustom.nigeria.students.browser import (
47    NigeriaOnlinePaymentDisplayFormPage,
48    NigeriaStudentBaseManageFormPage,
49    NigeriaStudentClearanceEditFormPage,
50    NigeriaOnlinePaymentAddFormPage,
51    NigeriaExportPDFPaymentSlip,
52    NigeriaExportPDFClearanceSlip,
53    NigeriaExportPDFBedTicketSlip,
54    NigeriaStudentPersonalDisplayFormPage,
55    NigeriaStudentPersonalManageFormPage,
56    NigeriaStudentPersonalEditFormPage,
57    NigeriaAccommodationManageFormPage,
58    NigeriaAccommodationDisplayFormPage,
59    NigeriaStudentBaseDisplayFormPage,
60    NigeriaStudentFilesUploadPage,
61    )
62
63from waeup.uniben.students.interfaces import (
64    ICustomStudent,
65    ICustomStudentBase,
66    ICustomStudentOnlinePayment,
67    ICustomStudentStudyCourse,
68    ICustomStudentStudyLevel,
69    ICustomUGStudentClearance,
70    ICustomPGStudentClearance,
71    ICustomStudentPersonal,
72    ICustomStudentPersonalEdit,
73    IMedicalHistory)
74from waeup.uniben.interfaces import MessageFactory as _
75
76class CustomStudentBaseDisplayFormPage(NigeriaStudentBaseDisplayFormPage):
77    """ Page to display student base data
78    """
79    form_fields = grok.AutoFields(ICustomStudentBase).omit(
80        'password', 'suspended', 'suspended_comment',
81        'flash_notice', 'provisionally_cleared', 'parents_email')
82    form_fields[
83        'financial_clearance_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
84
85class CustomStudentBaseManageFormPage(NigeriaStudentBaseManageFormPage):
86    """ View to manage student base data
87    """
88    form_fields = grok.AutoFields(ICustomStudentBase).omit(
89        'student_id', 'adm_code', 'suspended',
90        'financially_cleared_by', 'financial_clearance_date',
91        'parents_email')
92
93class CustomOnlinePaymentDisplayFormPage(NigeriaOnlinePaymentDisplayFormPage):
94    """ Page to view an online payment ticket
95    """
96    grok.context(ICustomStudentOnlinePayment)
97    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
98        'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item')
99    form_fields[
100        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
101    form_fields[
102        'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
103
104class CustomStartClearancePage(StartClearancePage):
105
106    @property
107    def with_ac(self):
108        if self.context.faccode == 'DCOEM':
109            return False
110        return True
111
112    @property
113    def portrait_uploaded(self):
114        return True
115
116
117CLEARANCE_FLASH_MESSAGE = """
118If you have not presented for physical clearance, scan your WAEC, NECO
119and other O level results scratch cards on one document and
120attach to the form below (Scans > O Level Results Scratch Card).
121Then come back to check for your successful cleared status as from 3 days
122after successful clearance request.
123If status is cleared, pay your school charges and proceed to the
124Dean's Office to collect the signed eligibility form.
125"""
126
127class CustomStudentClearanceEditFormPage(NigeriaStudentClearanceEditFormPage):
128    """ View to edit student clearance data by student
129    """
130
131    @property
132    def form_fields(self):
133        if self.context.is_postgrad:
134            form_fields = grok.AutoFields(ICustomPGStudentClearance).omit(
135            'clearance_locked', 'nysc_location', 'clr_code', 'officer_comment',
136            'physical_clearance_date')
137        else:
138            form_fields = grok.AutoFields(ICustomUGStudentClearance).omit(
139            'clearance_locked', 'clr_code', 'officer_comment',
140            'physical_clearance_date')
141            form_fields['date_of_birth'].for_display = True
142            form_fields['nationality'].for_display = True
143            form_fields['lga'].for_display = True
144        return form_fields
145
146    def dataNotComplete(self):
147        store = getUtility(IExtFileStore)
148        if self.context.entry_mode in ('ug_ft', 'de_ft') and \
149            not store.getFileByContext(self.context, attr=u'passport.jpg'):
150            return _('No red background passport picture uploaded.')
151        if not store.getFileByContext(self.context, attr=u'birth_certificate.jpg'):
152            return _('No birth certificate uploaded.')
153        if not store.getFileByContext(self.context, attr=u'ref_let.jpg'):
154            return _('No guarantor/referee letter uploaded.')
155        if not store.getFileByContext(self.context, attr=u'acc_let.jpg'):
156            return _('No acceptance letter uploaded.')
157        if not store.getFileByContext(self.context, attr=u'fst_sit_scan.jpg'):
158            return _('No first sitting result uploaded.')
159        if not store.getFileByContext(self.context, attr=u'secr_cults.jpg'):
160            return _('No affidavit of non-membership of secret cults uploaded.')
161        if not store.getFileByContext(self.context, attr=u'olevel_sc.jpg'):
162            return _('No O level results scratch card uploaded.')
163        return False
164
165    #def update(self):
166    #    self.flash(CLEARANCE_FLASH_MESSAGE, type="warning")
167    #    return super(CustomStudentClearanceEditFormPage, self).update()
168
169class CustomOnlinePaymentAddFormPage(NigeriaOnlinePaymentAddFormPage):
170    """ Page to add an online payment ticket
171    """
172    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).select(
173        'p_combi')
174
175class CustomExportPDFPaymentSlip(NigeriaExportPDFPaymentSlip):
176    """Deliver a PDF slip of the context.
177    """
178    grok.context(ICustomStudentOnlinePayment)
179    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
180        'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item', 'p_combi')
181    form_fields['creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
182    form_fields['payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
183
184
185class CustomExportPDFClearanceSlip(NigeriaExportPDFClearanceSlip):
186    """Deliver a PDF slip of the context.
187    """
188
189    @property
190    def omit_fields(self):
191        omit_fields = ('password', 'suspended', 'suspended_comment',
192                       'phone', 'adm_code', 'email', 'date_of_birth',
193                       'flash_notice')
194        if self.context.is_jupeb:
195            omit_fields += ('faculty', 'department')
196        return omit_fields
197
198    @property
199    def label(self):
200        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
201        line0 = ''
202        if self.context.is_jupeb:
203            line0 = 'Joint Universities Preliminary Examinations Board (JUPEB)\n'
204        line1 = translate(_('Clearance Slip of'),
205            'waeup.kofa', target_language=portal_language) \
206            + ' %s' % self.context.display_fullname
207        return '%s%s' % (line0, line1)
208
209    def _sigsInFooter(self):
210        isStudent = getattr(
211            self.request.principal, 'user_type', None) == 'student'
212        if not isStudent and self.context.state in (CLEARED, RETURNING):
213            return (_('Date, Student Signature'),
214                    _('Date, Clearance Officer Signature'),
215                    )
216        return ()
217
218    def render(self):
219        studentview = StudentBasePDFFormPage(self.context.student,
220            self.request, self.omit_fields)
221        students_utils = getUtility(IStudentsUtils)
222        return students_utils.renderPDF(
223            self, 'clearance_slip.pdf',
224            self.context.student, studentview, signatures=self._signatures(),
225            sigs_in_footer=self._sigsInFooter(), show_scans=False,
226            omit_fields=self.omit_fields)
227
228
229class ExportClearanceInvitationSlip(UtilityView, grok.View):
230    """Deliver an invitation letter to physical clearance.
231
232    This form page is available only in Uniben.
233    """
234    grok.context(ICustomStudent)
235    grok.name('clearance_invitation_slip.pdf')
236    grok.require('waeup.viewStudent')
237    prefix = 'form'
238
239    label = u'Invitation Letter for Physical Clearance'
240
241    omit_fields = (
242        'suspended', 'phone', 'email',
243        'adm_code', 'suspended_comment',
244        'date_of_birth', 'current_level',
245        'department', 'current_mode',
246        'entry_session', 'matric_number', 'sex',
247        'flash_notice')
248
249    form_fields = []
250
251    @property
252    def note(self):
253        if self.context.physical_clearance_date:
254            return """
255<br /><br /><br /><br /><font size='12'>
256Dear %s,
257<br /><br /><br />
258You are invited for your physical clearance on:
259<br /><br />
260<strong>%s</strong>.
261<br /><br />
262Please bring along this letter of invitation to the University Main Auditorium
263<br /><br />
264on your clearance date.
265<br /><br /><br />
266Signed,
267<br /><br />
268The Registrar<br />
269</font>
270
271""" % (self.context.display_fullname, self.context.physical_clearance_date)
272        return
273
274
275    def update(self):
276        if self.context.student.state != REQUESTED \
277            or not  self.context.student.physical_clearance_date:
278            self.flash(_('Forbidden'), type="warning")
279            self.redirect(self.url(self.context))
280
281    def render(self):
282        studentview = StudentBasePDFFormPage(self.context.student,
283            self.request, self.omit_fields)
284        students_utils = getUtility(IStudentsUtils)
285        return students_utils.renderPDF(
286            self, 'clearance_invitation_slip',
287            self.context.student, studentview,
288            omit_fields=self.omit_fields,
289            note=self.note)
290
291class ExportExaminationScheduleSlip(UtilityView, grok.View):
292    """Deliver a examination schedule slip.
293
294    This form page is available only in Uniben and AAUE.
295    """
296    grok.context(ICustomStudent)
297    grok.name('examination_schedule_slip.pdf')
298    grok.require('waeup.viewStudent')
299    prefix = 'form'
300
301    label = u'Examination Schedule Slip'
302
303    omit_fields = (
304        'suspended', 'phone', 'email',
305        'adm_code', 'suspended_comment',
306        'date_of_birth', 'current_level',
307        'current_mode',
308        'entry_session',
309        'flash_notice')
310
311    form_fields = []
312
313    @property
314    def note(self):
315        return """
316<br /><br /><br /><br /><font size='12'>
317Your examination date, time and venue is scheduled as follows:
318<br /><br />
319<strong>%s</strong>
320</font>
321
322""" % self.context.flash_notice
323        return
324
325
326    def update(self):
327        if not self.context.flash_notice \
328            or not 'exam' in self.context.flash_notice.lower():
329            self.flash(_('Forbidden'), type="warning")
330            self.redirect(self.url(self.context))
331
332    def render(self):
333        studentview = StudentBasePDFFormPage(self.context.student,
334            self.request, self.omit_fields)
335        students_utils = getUtility(IStudentsUtils)
336        return students_utils.renderPDF(
337            self, 'examination_schedule_slip',
338            self.context.student, studentview,
339            omit_fields=self.omit_fields,
340            note=self.note)
341
342class SwitchLibraryAccessView(UtilityView, grok.View):
343    """ Switch the library attribute
344    """
345    grok.context(ICustomStudent)
346    grok.name('switch_library_access')
347    grok.require('waeup.switchLibraryAccess')
348
349    def update(self):
350        if self.context.library:
351            self.context.library = False
352            self.context.writeLogMessage(self, 'library access disabled')
353            self.flash(_('Library access disabled'))
354        else:
355            self.context.library = True
356            self.context.writeLogMessage(self, 'library access enabled')
357            self.flash(_('Library access enabled'))
358        self.redirect(self.url(self.context))
359        return
360
361    def render(self):
362        return
363
364class ExportJHLIdCard(UtilityView, grok.View):
365    """Deliver an id card for the John Harris Library.
366    """
367    grok.context(ICustomStudent)
368    grok.name('jhl_idcard.pdf')
369    grok.require('waeup.viewStudent')
370    prefix = 'form'
371
372    label = u"John Harris Library Clearance"
373
374    omit_fields = (
375        'suspended', 'email', 'phone',
376        'adm_code', 'suspended_comment',
377        'date_of_birth',
378        'current_mode', 'certificate',
379        'entry_session',
380        'flash_notice')
381
382    form_fields = []
383
384    def _sigsInFooter(self):
385        isStudent = getattr(
386            self.request.principal, 'user_type', None) == 'student'
387        if isStudent:
388            return ''
389        return (_("Date, Reader's Signature"),
390                _("Date, Circulation Librarian's Signature"),
391                )
392
393    def update(self):
394        if not self.context.library:
395            self.flash(_('Forbidden!'), type="danger")
396            self.redirect(self.url(self.context))
397        return
398
399    @property
400    def note(self):
401        return """
402<br /><br /><br /><br /><font size='12'>
403This is to certify that the bearer whose photograph and other details appear
404 overleaf is a registered user of <b>John Harris Library, University of Benin</b>.
405 The card is not transferable. A replacement fee is charged for a loss,
406 mutilation or otherwise. If found, please, return to John Harris Library,
407 University of Benin, Benin City.
408</font>
409
410"""
411        return
412
413    def render(self):
414        studentview = StudentBasePDFFormPage(self.context.student,
415            self.request, self.omit_fields)
416        students_utils = getUtility(IStudentsUtils)
417        return students_utils.renderPDF(
418            self, 'jhl_idcard',
419            self.context.student, studentview,
420            omit_fields=self.omit_fields,
421            sigs_in_footer=self._sigsInFooter(),
422            note=self.note)
423
424class ExportJUPEBResultSlip(ExportExaminationScheduleSlip):
425    """Deliver a JUPEB result slip.
426
427    This form page is available only in Uniben.
428    """
429
430    grok.name('jupeb_result_slip.pdf')
431    label = u'JUPEB Result Slip'
432
433    @property
434    def note(self):
435        return """
436<br /><br /><br /><br /><font size='12'>
437<strong>%s</strong>
438</font>
439<br /><br /><br /><br />
440<font size='8'>
441Key: A = 5, B = 4, C = 3, D = 2, E = 1, F = 0, X = Absent, Q = Cancelled
442</font>
443
444""" % self.context.flash_notice
445        return
446
447    def update(self):
448        if not self.context.flash_notice or not self.context.is_jupeb \
449            or not 'results' in self.context.flash_notice.lower():
450            self.flash(_('Forbidden'), type="warning")
451            self.redirect(self.url(self.context))
452
453class CustomStudentPersonalDisplayFormPage(
454    NigeriaStudentPersonalDisplayFormPage):
455    """ Page to display student personal data
456    """
457
458    form_fields = grok.AutoFields(ICustomStudentPersonal)
459    form_fields['perm_address'].custom_widget = BytesDisplayWidget
460    form_fields['next_kin_address'].custom_widget = BytesDisplayWidget
461    form_fields[
462        'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
463
464class CustomStudentPersonalManageFormPage(
465    NigeriaStudentPersonalManageFormPage):
466    """ Page to manage personal data
467    """
468
469    form_fields = grok.AutoFields(ICustomStudentPersonal)
470    form_fields['personal_updated'].for_display = True
471    form_fields[
472        'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
473
474class CstomStudentPersonalEditFormPage(NigeriaStudentPersonalEditFormPage):
475    """ Page to edit personal data
476    """
477    form_fields = grok.AutoFields(
478        ICustomStudentPersonalEdit).omit('personal_updated')
479
480class StudyCourseCOEditFormPage(KofaEditFormPage):
481    """ Page to edit the student study course data by clearance officers.
482
483    This form page is available only in Uniben.
484    """
485    grok.context(ICustomStudentStudyCourse)
486    grok.name('edit_level')
487    grok.require('waeup.clearStudent')
488    label = _('Edit current level')
489    pnav = 4
490    form_fields = grok.AutoFields(
491        ICustomStudentStudyCourse).select('current_level')
492
493    def update(self):
494        if not (self.context.is_current and
495            self.context.student.state == REQUESTED):
496            emit_lock_message(self)
497            return
498        super(StudyCourseCOEditFormPage, self).update()
499        return
500
501    @action(_('Save'), style='primary')
502    def save(self, **data):
503        try:
504            msave(self, **data)
505        except ConstraintNotSatisfied:
506            # The selected level might not exist in certificate
507            self.flash(_('Current level not available for certificate.'))
508            return
509        #notify(grok.ObjectModifiedEvent(self.context.__parent__))
510        return
511
512class CustomStudyLevelEditFormPage(StudyLevelEditFormPage):
513    """ Page to edit the student study level data by students.
514
515    """
516    grok.template('studyleveleditpage')
517
518class CustomStudyLevelDisplayFormPage(StudyLevelDisplayFormPage):
519    """ Page to display student study levels
520    """
521    grok.template('studylevelpage')
522
523    @property
524    def view_scores_allowed(self):
525        return checkPermission('waeup.manageStudent', self.context)
526
527class CustomExportPDFCourseRegistrationSlip(
528    ExportPDFCourseRegistrationSlip):
529    """Deliver a PDF slip of the context.
530    """
531
532    form_fields = grok.AutoFields(ICustomStudentStudyLevel).omit(
533        'level_verdict', 'gpa', 'level', 'transcript_remark')
534
535    def update(self):
536        if self.context.student.state != REGISTERED \
537            or self.context.student.current_level != self.context.level:
538            self.flash(_('Forbidden'), type="warning")
539            self.redirect(self.url(self.context))
540
541    @property
542    def tabletitle(self):
543        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
544        tabletitle = []
545        tabletitle.append(translate(_('1st Semester Courses'), 'waeup.kofa',
546            target_language=portal_language))
547        tabletitle.append(translate(_('2nd Semester Courses'), 'waeup.kofa',
548            target_language=portal_language))
549        tabletitle.append(translate(_('Level Courses'), 'waeup.kofa',
550            target_language=portal_language))
551        tabletitle.append(translate(_('1st Trimester Courses'), 'waeup.kofa',
552            target_language=portal_language))
553        tabletitle.append(translate(_('2nd Trimester Courses'), 'waeup.kofa',
554            target_language=portal_language))
555        tabletitle.append(translate(_('3rd Trimester Courses'), 'waeup.kofa',
556            target_language=portal_language))
557        return tabletitle
558
559    def render(self):
560        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
561        Code = translate('Code', 'waeup.kofa', target_language=portal_language)
562        Title = translate('Title', 'waeup.kofa', target_language=portal_language)
563        Dept = translate('Dept.', 'waeup.kofa', target_language=portal_language)
564        Faculty = translate('Faculty', 'waeup.kofa', target_language=portal_language)
565        Cred = translate(_('Credits'), 'waeup.uniben', target_language=portal_language)
566        studentview = StudentBasePDFFormPage(self.context.student,
567            self.request, self.omit_fields)
568        students_utils = getUtility(IStudentsUtils)
569
570        tabledata = []
571        tableheader = []
572        for i in range(1,7):
573            tabledata.append(sorted(
574                [value for value in self.context.values() if value.semester == i],
575                key=lambda value: str(value.semester) + value.code))
576            tableheader.append([(Code,'code', 2.5),
577                             (Title,'title', 5),
578                             (Dept,'dcode', 1.5), (Faculty,'fcode', 1.5),
579                             (Cred, 'credits', 1.5),
580                             ])
581        return students_utils.renderPDF(
582            self, 'course_registration_slip.pdf',
583            self.context.student, studentview,
584            tableheader=tableheader,
585            tabledata=tabledata,
586            omit_fields=self.omit_fields
587            )
588
589class ExportPDFCourseResultSlip(ExportPDFCourseRegistrationSlip):
590    """Deliver a PDF slip of the context.
591    """
592
593    grok.name('course_result_slip.pdf')
594
595    form_fields = grok.AutoFields(ICustomStudentStudyLevel).omit('level')
596
597    @property
598    def tabletitle(self):
599        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
600        tabletitle = []
601        tabletitle.append(translate(_('1st Semester Courses'), 'waeup.kofa',
602            target_language=portal_language))
603        tabletitle.append(translate(_('2nd Semester Courses'), 'waeup.kofa',
604            target_language=portal_language))
605        tabletitle.append(translate(_('Level Courses'), 'waeup.kofa',
606            target_language=portal_language))
607        tabletitle.append(translate(_('1st Trimester Courses'), 'waeup.kofa',
608            target_language=portal_language))
609        tabletitle.append(translate(_('2nd Trimester Courses'), 'waeup.kofa',
610            target_language=portal_language))
611        tabletitle.append(translate(_('3rd Trimester Courses'), 'waeup.kofa',
612            target_language=portal_language))
613        return tabletitle
614
615    @property
616    def label(self):
617        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
618        lang = self.request.cookies.get('kofa.language', portal_language)
619        level_title = translate(self.context.level_title, 'waeup.kofa',
620            target_language=lang)
621        return translate(_('Course Result Slip'),
622            'waeup.uniben', target_language=portal_language) \
623            + ' %s' % level_title
624
625    def render(self):
626        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
627        Code = translate('Code', 'waeup.kofa', target_language=portal_language)
628        Title = translate('Title', 'waeup.kofa', target_language=portal_language)
629        Dept = translate('Dept.', 'waeup.kofa', target_language=portal_language)
630        Faculty = translate('Faculty', 'waeup.kofa', target_language=portal_language)
631        Cred = translate(_('Credits'), 'waeup.uniben', target_language=portal_language)
632        Grade = translate('Grade', 'waeup.kofa', target_language=portal_language)
633        studentview = StudentBasePDFFormPage(self.context.student,
634            self.request, self.omit_fields)
635        students_utils = getUtility(IStudentsUtils)
636
637        tabledata = []
638        tableheader = []
639        for i in range(1,7):
640            tabledata.append(sorted(
641                [value for value in self.context.values() if value.semester == i],
642                key=lambda value: str(value.semester) + value.code))
643            tableheader.append([(Code,'code', 2.5),
644                             (Title,'title', 5),
645                             (Dept,'dcode', 1.5), (Faculty,'fcode', 1.5),
646                             (Cred, 'credits', 1.5),
647                             (Grade, 'grade', 1.5),
648                             ])
649        return students_utils.renderPDF(
650            self, 'course_result_slip.pdf',
651            self.context.student, studentview,
652            tableheader=tableheader,
653            tabledata=tabledata,
654            omit_fields=self.omit_fields
655            )
656
657class CustomCourseTicketDisplayFormPage(CourseTicketDisplayFormPage):
658    """ Page to display course tickets
659    """
660    form_fields = grok.AutoFields(ICourseTicket).omit('score')
661
662class CustomStudentActivateView(StudentActivateView):
663    """ Activate student account
664    """
665
666    def update(self):
667        self.context.suspended = False
668        self.context.writeLogMessage(self, 'account activated')
669        history = IObjectHistory(self.context)
670        history.addMessage('Student account activated', user='undisclosed')
671        self.flash(_('Student account has been activated.'))
672        self.redirect(self.url(self.context))
673        return
674
675class CustomStudentDeactivateView(StudentDeactivateView):
676    """ Deactivate student account
677    """
678    def update(self):
679        self.context.suspended = True
680        self.context.writeLogMessage(self, 'account deactivated')
681        history = IObjectHistory(self.context)
682        history.addMessage('Student account deactivated', user='undisclosed')
683        self.flash(_('Student account has been deactivated.'))
684        self.redirect(self.url(self.context))
685        return
686
687class CustomExportPDFTranscriptSlip(ExportPDFTranscriptSlip):
688    """Deliver a PDF slip of the context.
689    """
690
691    def _sigsInFooter(self):
692        isStudent = getattr(
693            self.request.principal, 'user_type', None) == 'student'
694        if not isStudent and self.context.student.state in (TRANSVAL, TRANSREL):
695            return (_('D. R. (Exams & Records)'),_('Current Dean of Faculty'),)
696        return ()
697
698    #def _signatures(self):
699    #    return ([(
700    #        'Current HD<br /> D. R. (Exams & Records)<br /> '
701    #        'For: Registrar')],)
702
703    def render(self):
704        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
705        Term = translate(_('Term'), 'waeup.kofa', target_language=portal_language)
706        Code = translate(_('Code'), 'waeup.kofa', target_language=portal_language)
707        Title = translate(_('Title'), 'waeup.kofa', target_language=portal_language)
708        Cred = translate(_('Credits'), 'waeup.kofa', target_language=portal_language)
709        #Score = translate(_('Score'), 'waeup.kofa', target_language=portal_language)
710        Grade = translate(_('Grade'), 'waeup.kofa', target_language=portal_language)
711        studentview = StudentBasePDFFormPage(self.context.student,
712            self.request, self.omit_fields)
713        students_utils = getUtility(IStudentsUtils)
714
715        tableheader = [(Code,'code', 2.5),
716                         (Title,'title', 8.5),
717                         (Term, 'semester', 1.5),
718                         (Cred, 'credits', 1.5),
719                         #(Score, 'score', 1.5),
720                         (Grade, 'grade', 1.5),
721                         ]
722
723        pdfstream = students_utils.renderPDFTranscript(
724            self, 'transcript.pdf',
725            self.context.student, studentview,
726            omit_fields=self.omit_fields,
727            tableheader=tableheader,
728            signatures=self._signatures(),
729            sigs_in_footer=self._sigsInFooter(),
730            digital_sigs=self._digital_sigs(),
731            save_file=self._save_file(),
732            )
733        if not pdfstream:
734            self.redirect(self.url(self.context.student))
735            return
736        return pdfstream
737
738class CustomExportPDFBedTicketSlip(NigeriaExportPDFBedTicketSlip):
739    """Deliver a PDF slip of the context.
740    """
741    omit_fields = ('password', 'suspended', 'suspended_comment',
742        'phone', 'adm_code', 'email', 'date_of_birth', 'flash_notice')
743
744class CustomPaymentsManageFormPage(PaymentsManageFormPage):
745    """ Page to manage the student payments. This manage form page is for
746    both students and students officers. Uniben does not allow students
747    to remove any payment ticket.
748    """
749    @property
750    def manage_payments_allowed(self):
751        return checkPermission('waeup.manageStudent', self.context)
752
753class CustomAccommodationDisplayFormPage(NigeriaAccommodationDisplayFormPage):
754    """ Page to view bed tickets.
755    """
756    with_hostel_selection = True
757
758class CustomAccommodationManageFormPage(NigeriaAccommodationManageFormPage):
759    """ Page to manage bed tickets.
760    This manage form page is for both students and students officers.
761    """
762    with_hostel_selection = True
763
764class CustomStudentBaseEditFormPage(StudentBaseEditFormPage):
765    """ View to edit student base data
766    """
767    form_fields = grok.AutoFields(ICustomStudentBase).select(
768        'email', 'phone')
769    form_fields['email'].field.required = True
770
771class CustomStudentFilesUploadPage(NigeriaStudentFilesUploadPage):
772    """ View to upload passport picture.
773
774    Students are not allowed to change the picture if they
775    passed the regular Kofa application.
776    """
777
778    def update(self):
779        # Uniben: Only 2020 session students are allowed to edit the picture.
780        if self.context.entry_session != 2020:
781            emit_lock_message(self)
782            return
783        if self.context.entry_mode not in ('ug_ft', 'de_ft'):
784            emit_lock_message(self)
785            return
786        PORTRAIT_CHANGE_STATES = getUtility(IStudentsUtils).PORTRAIT_CHANGE_STATES
787        if self.context.state not in PORTRAIT_CHANGE_STATES:
788            emit_lock_message(self)
789            return
790        super(StudentFilesUploadPage, self).update()
791        return
792
793
794
795
796from zope.schema.vocabulary import SimpleVocabulary
797from zope.formlib.itemswidgets import RadioWidget
798from zope.formlib.itemswidgets import SelectWidget, DropdownWidget
799
800def CustomBooleanRadioWidget(field, request, true=_('yes'), false=_('no')):
801    vocabulary = SimpleVocabulary.fromItems( ((true, True), (false, False)) )
802    widget = RadioWidget(field, vocabulary, request)
803    widget.required = False
804    return widget
805
806class StudentMedicalHistoryEditFormPage(KofaEditFormPage):
807    """ Page to edit medical data
808    """
809    grok.context(ICustomStudent)
810    grok.name('edit_medical')
811    grok.require('waeup.handleStudent')
812    label = _('Medical Questionnaire')
813    pnav = 4
814
815    def _medicalQuestPaymentMade(self, student, session):
816        if len(student['payments']):
817            for ticket in student['payments'].values():
818                if ticket.p_state == 'paid' and \
819                    ticket.p_category == 'medical_quest' and \
820                    ticket.p_session == session:
821                    return True
822        return False
823
824    def update(self):
825        if not self._medicalQuestPaymentMade(
826            self.context, self.context.current_session):
827            self.flash('Please pay medical questionnaire payment first.',
828                type="warning")
829            self.redirect(self.url(self.context))
830            return
831        return super(StudentMedicalHistoryEditFormPage, self).update()
832
833    @property
834    def form_fields(self):
835        form_fields = grok.AutoFields(IMedicalHistory)
836        form_fields['medical_updated'].for_display = True
837        for field in ('fever', 'headaches', 'catarrh', 'cough', 'sore_throat',
838                      'breathing', 'sneezing', 'weakness', 'body_pains',
839                      'smell', 'taste', 'asthma', 'hypertension', 'diabetes',
840                      'obesity', 'lagos_abuja', 'outside', 'company_suspected',
841                      'company_confirmed', 'positive', 'negative',
842                      'vaccination'):
843            form_fields[field].custom_widget = CustomBooleanRadioWidget
844        return form_fields
845
846    @property
847    def separators(self):
848        return getUtility(IStudentsUtils).SEPARATORS_DICT
849
850    @action(_('Save/Confirm'), style='primary')
851    def save(self, **data):
852        msave(self, **data)
853        self.context.medical_updated = datetime.utcnow()
854        return
855
856class StudentMedicalHistoryManageFormPage(StudentMedicalHistoryEditFormPage):
857    """ Page to manage medical data
858    """
859    grok.name('manage_medical')
860    grok.require('waeup.manageStudent')
861    label = _('Manage medical questionnaire data')
862
863    def update(self):
864        return super(StudentMedicalHistoryEditFormPage, self).update()
865
866class ExportPDFMedicalHistorySlip(grok.View):
867    """Deliver a PDF slip of the context.
868    """
869    grok.context(ICustomStudent)
870    grok.name('medical_questionnaire_slip.pdf')
871    grok.require('waeup.viewStudent')
872    prefix = 'form'
873    form_fields = grok.AutoFields(IMedicalHistory)
874
875    omit_fields = ('password', 'suspended', 'suspended_comment',
876                   'adm_code', 'date_of_birth',
877                   'flash_notice', 'current_mode', 'entry_mode',
878                   'entry_session', 'parents_email', 'study_course',
879                   'current_level', 'reg_number', 'sex',
880                   'certificate')
881
882    @property
883    def title(self):
884        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
885        return translate(_('Medical Questionnaire'), 'waeup.kofa',
886            target_language=portal_language)
887
888    @property
889    def label(self):
890        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
891        return translate(_('Medical Questionnaire Slip of'),
892            'waeup.kofa', target_language=portal_language) \
893            + ' %s' % self.context.display_fullname
894
895    def render(self):
896        studentview = StudentBasePDFFormPage(self.context.student,
897            self.request, self.omit_fields)
898        students_utils = getUtility(IStudentsUtils)
899        return students_utils.renderPDF(
900            self, 'medical_questionnaire_slip.pdf',
901            self.context.student, studentview,
902            omit_fields=self.omit_fields,)
Note: See TracBrowser for help on using the repository browser.