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

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

Show upload button.

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