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

Last change on this file since 16406 was 16405, checked in by Henrik Bettermann, 4 years ago

Allow managers to edit medical history.

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