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

Last change on this file since 17711 was 17542, checked in by Henrik Bettermann, 15 months ago

Implement medical examination form.

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