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

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

Revert changes of r16439. We can't customize single actions.

  • Property svn:keywords set to Id
File size: 33.3 KB
RevLine 
[8911]1## $Id: browser.py 16440 2021-03-31 20:52:44Z 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,
[16440]39    StartClearancePage)
[12845]40from waeup.kofa.students.workflow import (CREATED, ADMITTED, PAID,
41    CLEARANCE, REQUESTED, RETURNING, CLEARED, REGISTERED, VALIDATED,
[16171]42    GRADUATED, TRANSREQ, TRANSVAL, TRANSREL, FORBIDDEN_POSTGRAD_TRANS)
[9686]43from waeup.kofa.students.interfaces import IStudentsUtils, ICourseTicket
[9251]44from waeup.kofa.students.workflow import FORBIDDEN_POSTGRAD_TRANS
[8911]45from kofacustom.nigeria.students.browser import (
46    NigeriaOnlinePaymentDisplayFormPage,
[9251]47    NigeriaStudentBaseManageFormPage,
[9380]48    NigeriaStudentClearanceEditFormPage,
[8911]49    NigeriaOnlinePaymentAddFormPage,
[13063]50    NigeriaExportPDFPaymentSlip,
51    NigeriaExportPDFClearanceSlip,
[13297]52    NigeriaExportPDFBedTicketSlip,
[12856]53    NigeriaStudentPersonalDisplayFormPage,
[13085]54    NigeriaStudentPersonalManageFormPage,
[15267]55    NigeriaStudentPersonalEditFormPage,
[15371]56    NigeriaAccommodationManageFormPage,
[15975]57    NigeriaAccommodationDisplayFormPage,
[15371]58    NigeriaStudentBaseDisplayFormPage,
[16361]59    NigeriaStudentFilesUploadPage,
[9281]60    )
[8911]61
[9210]62from waeup.uniben.students.interfaces import (
[12121]63    ICustomStudent,
[15352]64    ICustomStudentBase,
[12856]65    ICustomStudentOnlinePayment,
66    ICustomStudentStudyCourse,
[11552]67    ICustomStudentStudyLevel,
68    ICustomUGStudentClearance,
[12856]69    ICustomPGStudentClearance,
[13085]70    ICustomStudentPersonal,
[16382]71    ICustomStudentPersonalEdit,
72    IMedicalHistory)
[9210]73from waeup.uniben.interfaces import MessageFactory as _
[8911]74
[15371]75class CustomStudentBaseDisplayFormPage(NigeriaStudentBaseDisplayFormPage):
76    """ Page to display student base data
77    """
78    form_fields = grok.AutoFields(ICustomStudentBase).omit(
79        'password', 'suspended', 'suspended_comment',
[16088]80        'flash_notice', 'provisionally_cleared', 'parents_email')
[15371]81    form_fields[
82        'financial_clearance_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
83
[16088]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')
[15371]91
[8911]92class CustomOnlinePaymentDisplayFormPage(NigeriaOnlinePaymentDisplayFormPage):
93    """ Page to view an online payment ticket
94    """
95    grok.context(ICustomStudentOnlinePayment)
[9775]96    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
[9993]97        'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item')
[8911]98    form_fields[
99        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
100    form_fields[
101        'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
102
[15574]103class CustomStartClearancePage(StartClearancePage):
104
105    @property
106    def with_ac(self):
107        if self.context.faccode == 'DCOEM':
108            return False
109        return True
110
[16363]111
112CLEARANCE_FLASH_MESSAGE = """
113If you have not presented for physical clearance, scan your WAEC, NECO
[16364]114and other O level results scratch cards on one document and
115attach to the form below (Scans > O Level Results Scratch Card).
[16363]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
[9380]122class CustomStudentClearanceEditFormPage(NigeriaStudentClearanceEditFormPage):
123    """ View to edit student clearance data by student
124    """
125
[11552]126    @property
127    def form_fields(self):
128        if self.context.is_postgrad:
129            form_fields = grok.AutoFields(ICustomPGStudentClearance).omit(
[12391]130            'clearance_locked', 'nysc_location', 'clr_code', 'officer_comment',
131            'physical_clearance_date')
[11552]132        else:
133            form_fields = grok.AutoFields(ICustomUGStudentClearance).omit(
[12391]134            'clearance_locked', 'clr_code', 'officer_comment',
135            'physical_clearance_date')
[11552]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
[15666]141    def dataNotComplete(self):
[9380]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.')
[9395]151        #if not store.getFileByContext(self.context, attr=u'scd_sit_scan.jpg'):
152        #    return _('No second sitting result uploaded.')
[9380]153        if not store.getFileByContext(self.context, attr=u'secr_cults.jpg'):
[9848]154            return _('No affidavit of non-membership of secret cults uploaded.')
[9380]155        return False
156
[16363]157    def update(self):
158        self.flash(CLEARANCE_FLASH_MESSAGE, type="warning")
159        return super(CustomStudentClearanceEditFormPage, self).update()
160
[8911]161class CustomOnlinePaymentAddFormPage(NigeriaOnlinePaymentAddFormPage):
162    """ Page to add an online payment ticket
163    """
164    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).select(
[15666]165        'p_combi')
[8911]166
[13063]167class CustomExportPDFPaymentSlip(NigeriaExportPDFPaymentSlip):
[8911]168    """Deliver a PDF slip of the context.
169    """
170    grok.context(ICustomStudentOnlinePayment)
[9775]171    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
[15688]172        'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item', 'p_combi')
[8911]173    form_fields['creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
[9205]174    form_fields['payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
175
176
[13063]177class CustomExportPDFClearanceSlip(NigeriaExportPDFClearanceSlip):
[9551]178    """Deliver a PDF slip of the context.
179    """
180
[13303]181    @property
182    def omit_fields(self):
183        omit_fields = ('password', 'suspended', 'suspended_comment',
[13717]184                       'phone', 'adm_code', 'email', 'date_of_birth',
185                       'flash_notice')
[14902]186        if self.context.is_jupeb:
[13303]187            omit_fields += ('faculty', 'department')
188        return omit_fields
[11537]189
[13299]190    @property
191    def label(self):
192        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
[13300]193        line0 = ''
[14902]194        if self.context.is_jupeb:
[13335]195            line0 = 'Joint Universities Preliminary Examinations Board (JUPEB)\n'
[13300]196        line1 = translate(_('Clearance Slip of'),
[13299]197            'waeup.kofa', target_language=portal_language) \
198            + ' %s' % self.context.display_fullname
[13335]199        return '%s%s' % (line0, line1)
[13299]200
[12846]201    def _sigsInFooter(self):
[12845]202        isStudent = getattr(
203            self.request.principal, 'user_type', None) == 'student'
[12852]204        if not isStudent and self.context.state in (CLEARED, RETURNING):
[12846]205            return (_('Date, Student Signature'),
206                    _('Date, Clearance Officer Signature'),
207                    )
208        return ()
[12845]209
[9551]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(),
[10271]217            sigs_in_footer=self._sigsInFooter(), show_scans=False,
218            omit_fields=self.omit_fields)
[9551]219
[12121]220
[13063]221class ExportClearanceInvitationSlip(UtilityView, grok.View):
[12121]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
[12263]231    label = u'Invitation Letter for Physical Clearance'
[12121]232
233    omit_fields = (
234        'suspended', 'phone', 'email',
235        'adm_code', 'suspended_comment',
236        'date_of_birth', 'current_level',
[12150]237        'department', 'current_mode',
[13717]238        'entry_session', 'matric_number', 'sex',
239        'flash_notice')
[12121]240
241    form_fields = []
242
243    @property
244    def note(self):
245        if self.context.physical_clearance_date:
246            return """
[12147]247<br /><br /><br /><br /><font size='12'>
248Dear %s,
249<br /><br /><br />
[12264]250You are invited for your physical clearance on:
[12121]251<br /><br />
[12264]252<strong>%s</strong>.
253<br /><br />
[12265]254Please bring along this letter of invitation to the University Main Auditorium
[12147]255<br /><br />
[12263]256on your clearance date.
[12147]257<br /><br /><br />
[12263]258Signed,
[12147]259<br /><br />
260The Registrar<br />
[12121]261</font>
262
[12147]263""" % (self.context.display_fullname, self.context.physical_clearance_date)
[12121]264        return
265
[12122]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
[12121]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
[13723]283class ExportExaminationScheduleSlip(UtilityView, grok.View):
284    """Deliver a examination schedule slip.
285
[14689]286    This form page is available only in Uniben and AAUE.
[13723]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
[15371]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
[15352]356class ExportJHLIdCard(UtilityView, grok.View):
[15371]357    """Deliver an id card for the John Harris Library.
[15352]358    """
359    grok.context(ICustomStudent)
360    grok.name('jhl_idcard.pdf')
361    grok.require('waeup.viewStudent')
362    prefix = 'form'
363
[15403]364    label = u"John Harris Library Clearance"
[15352]365
366    omit_fields = (
[15371]367        'suspended', 'email', 'phone',
[15352]368        'adm_code', 'suspended_comment',
[15371]369        'date_of_birth',
[15352]370        'current_mode', 'certificate',
371        'entry_session',
372        'flash_notice')
373
374    form_fields = []
375
376    def _sigsInFooter(self):
[15371]377        isStudent = getattr(
378            self.request.principal, 'user_type', None) == 'student'
379        if isStudent:
380            return ''
[15352]381        return (_("Date, Reader's Signature"),
382                _("Date, Circulation Librarian's Signature"),
383                )
384
[15371]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
[15352]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
[14834]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):
[14902]440        if not self.context.flash_notice or not self.context.is_jupeb \
[14835]441            or not 'results' in self.context.flash_notice.lower():
[14834]442            self.flash(_('Forbidden'), type="warning")
443            self.redirect(self.url(self.context))
444
[12856]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
[13085]466class CstomStudentPersonalEditFormPage(NigeriaStudentPersonalEditFormPage):
467    """ Page to edit personal data
468    """
469    form_fields = grok.AutoFields(
470        ICustomStudentPersonalEdit).omit('personal_updated')
471
[9210]472class StudyCourseCOEditFormPage(KofaEditFormPage):
[9281]473    """ Page to edit the student study course data by clearance officers.
[9210]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
[16440]501        #notify(grok.ObjectModifiedEvent(self.context.__parent__))
[9281]502        return
503
504class CustomStudyLevelEditFormPage(StudyLevelEditFormPage):
505    """ Page to edit the student study level data by students.
506
507    """
[9686]508    grok.template('studyleveleditpage')
[9281]509
[9686]510class CustomStudyLevelDisplayFormPage(StudyLevelDisplayFormPage):
511    """ Page to display student study levels
512    """
513    grok.template('studylevelpage')
514
[16427]515    @property
516    def view_scores_allowed(self):
517        return checkPermission('waeup.manageStudent', self.context)
518
[13063]519class CustomExportPDFCourseRegistrationSlip(
520    ExportPDFCourseRegistrationSlip):
[9686]521    """Deliver a PDF slip of the context.
522    """
523
[9921]524    form_fields = grok.AutoFields(ICustomStudentStudyLevel).omit(
[15404]525        'level_verdict', 'gpa', 'level', 'transcript_remark')
[9921]526
[12855]527    def update(self):
528        if self.context.student.state != REGISTERED \
529            or self.context.student.current_level != self.context.level:
530            self.flash(_('Forbidden'), type="warning")
531            self.redirect(self.url(self.context))
532
[10441]533    @property
534    def tabletitle(self):
535        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
536        tabletitle = []
537        tabletitle.append(translate(_('1st Semester Courses'), 'waeup.kofa',
538            target_language=portal_language))
539        tabletitle.append(translate(_('2nd Semester Courses'), 'waeup.kofa',
540            target_language=portal_language))
541        tabletitle.append(translate(_('Level Courses'), 'waeup.kofa',
542            target_language=portal_language))
543        tabletitle.append(translate(_('1st Trimester Courses'), 'waeup.kofa',
544            target_language=portal_language))
545        tabletitle.append(translate(_('2nd Trimester Courses'), 'waeup.kofa',
546            target_language=portal_language))
547        tabletitle.append(translate(_('3rd Trimester Courses'), 'waeup.kofa',
548            target_language=portal_language))
549        return tabletitle
550
[9686]551    def render(self):
552        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
[9909]553        Code = translate('Code', 'waeup.kofa', target_language=portal_language)
554        Title = translate('Title', 'waeup.kofa', target_language=portal_language)
555        Dept = translate('Dept.', 'waeup.kofa', target_language=portal_language)
556        Faculty = translate('Faculty', 'waeup.kofa', target_language=portal_language)
557        Cred = translate(_('Credits'), 'waeup.uniben', target_language=portal_language)
[9686]558        studentview = StudentBasePDFFormPage(self.context.student,
559            self.request, self.omit_fields)
560        students_utils = getUtility(IStudentsUtils)
[10441]561
562        tabledata = []
563        tableheader = []
564        for i in range(1,7):
565            tabledata.append(sorted(
566                [value for value in self.context.values() if value.semester == i],
567                key=lambda value: str(value.semester) + value.code))
568            tableheader.append([(Code,'code', 2.5),
569                             (Title,'title', 5),
570                             (Dept,'dcode', 1.5), (Faculty,'fcode', 1.5),
571                             (Cred, 'credits', 1.5),
572                             ])
[9686]573        return students_utils.renderPDF(
574            self, 'course_registration_slip.pdf',
575            self.context.student, studentview,
[10441]576            tableheader=tableheader,
577            tabledata=tabledata,
[10271]578            omit_fields=self.omit_fields
[9908]579            )
[9848]580
[15401]581class ExportPDFCourseResultSlip(ExportPDFCourseRegistrationSlip):
[9848]582    """Deliver a PDF slip of the context.
583    """
584
585    grok.name('course_result_slip.pdf')
586
[15401]587    form_fields = grok.AutoFields(ICustomStudentStudyLevel).omit('level')
588
[9848]589    @property
[10441]590    def tabletitle(self):
591        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
592        tabletitle = []
593        tabletitle.append(translate(_('1st Semester Courses'), 'waeup.kofa',
594            target_language=portal_language))
595        tabletitle.append(translate(_('2nd Semester Courses'), 'waeup.kofa',
596            target_language=portal_language))
597        tabletitle.append(translate(_('Level Courses'), 'waeup.kofa',
598            target_language=portal_language))
599        tabletitle.append(translate(_('1st Trimester Courses'), 'waeup.kofa',
600            target_language=portal_language))
601        tabletitle.append(translate(_('2nd Trimester Courses'), 'waeup.kofa',
602            target_language=portal_language))
603        tabletitle.append(translate(_('3rd Trimester Courses'), 'waeup.kofa',
604            target_language=portal_language))
605        return tabletitle
606
607    @property
[9848]608    def label(self):
609        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
610        lang = self.request.cookies.get('kofa.language', portal_language)
611        level_title = translate(self.context.level_title, 'waeup.kofa',
612            target_language=lang)
613        return translate(_('Course Result Slip'),
614            'waeup.uniben', target_language=portal_language) \
615            + ' %s' % level_title
616
617    def render(self):
618        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
[9909]619        Code = translate('Code', 'waeup.kofa', target_language=portal_language)
620        Title = translate('Title', 'waeup.kofa', target_language=portal_language)
621        Dept = translate('Dept.', 'waeup.kofa', target_language=portal_language)
622        Faculty = translate('Faculty', 'waeup.kofa', target_language=portal_language)
623        Cred = translate(_('Credits'), 'waeup.uniben', target_language=portal_language)
624        Grade = translate('Grade', 'waeup.kofa', target_language=portal_language)
[9848]625        studentview = StudentBasePDFFormPage(self.context.student,
626            self.request, self.omit_fields)
627        students_utils = getUtility(IStudentsUtils)
[10441]628
629        tabledata = []
630        tableheader = []
631        for i in range(1,7):
632            tabledata.append(sorted(
633                [value for value in self.context.values() if value.semester == i],
634                key=lambda value: str(value.semester) + value.code))
635            tableheader.append([(Code,'code', 2.5),
636                             (Title,'title', 5),
637                             (Dept,'dcode', 1.5), (Faculty,'fcode', 1.5),
638                             (Cred, 'credits', 1.5),
639                             (Grade, 'grade', 1.5),
640                             ])
[9908]641        return students_utils.renderPDF(
[15401]642            self, 'course_result_slip.pdf',
[9908]643            self.context.student, studentview,
[10441]644            tableheader=tableheader,
645            tabledata=tabledata,
[10271]646            omit_fields=self.omit_fields
[9908]647            )
[9686]648
649class CustomCourseTicketDisplayFormPage(CourseTicketDisplayFormPage):
650    """ Page to display course tickets
651    """
652    form_fields = grok.AutoFields(ICourseTicket).omit('score')
[11069]653
[13063]654class CustomStudentActivateView(StudentActivateView):
[11069]655    """ Activate student account
656    """
657
658    def update(self):
659        self.context.suspended = False
660        self.context.writeLogMessage(self, 'account activated')
661        history = IObjectHistory(self.context)
662        history.addMessage('Student account activated', user='undisclosed')
663        self.flash(_('Student account has been activated.'))
664        self.redirect(self.url(self.context))
665        return
666
[13063]667class CustomStudentDeactivateView(StudentDeactivateView):
[11069]668    """ Deactivate student account
669    """
670    def update(self):
671        self.context.suspended = True
672        self.context.writeLogMessage(self, 'account deactivated')
673        history = IObjectHistory(self.context)
674        history.addMessage('Student account deactivated', user='undisclosed')
675        self.flash(_('Student account has been deactivated.'))
676        self.redirect(self.url(self.context))
677        return
[12845]678
[13063]679class CustomExportPDFTranscriptSlip(ExportPDFTranscriptSlip):
[12845]680    """Deliver a PDF slip of the context.
681    """
682
[16171]683    def _sigsInFooter(self):
684        isStudent = getattr(
685            self.request.principal, 'user_type', None) == 'student'
686        if not isStudent and self.context.student.state in (TRANSVAL, TRANSREL):
687            return (_('D. R. (Exams & Records)'),_('Current Dean of Faculty'),)
688        return ()
[12845]689
[14689]690    #def _signatures(self):
691    #    return ([(
692    #        'Current HD<br /> D. R. (Exams & Records)<br /> '
693    #        'For: Registrar')],)
[12845]694
695    def render(self):
696        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
697        Term = translate(_('Term'), 'waeup.kofa', target_language=portal_language)
698        Code = translate(_('Code'), 'waeup.kofa', target_language=portal_language)
699        Title = translate(_('Title'), 'waeup.kofa', target_language=portal_language)
700        Cred = translate(_('Credits'), 'waeup.kofa', target_language=portal_language)
701        #Score = translate(_('Score'), 'waeup.kofa', target_language=portal_language)
702        Grade = translate(_('Grade'), 'waeup.kofa', target_language=portal_language)
703        studentview = StudentBasePDFFormPage(self.context.student,
704            self.request, self.omit_fields)
705        students_utils = getUtility(IStudentsUtils)
706
707        tableheader = [(Code,'code', 2.5),
708                         (Title,'title', 8.5),
709                         (Term, 'semester', 1.5),
710                         (Cred, 'credits', 1.5),
711                         #(Score, 'score', 1.5),
712                         (Grade, 'grade', 1.5),
713                         ]
714
[15164]715        pdfstream = students_utils.renderPDFTranscript(
[12845]716            self, 'transcript.pdf',
717            self.context.student, studentview,
718            omit_fields=self.omit_fields,
719            tableheader=tableheader,
720            signatures=self._signatures(),
721            sigs_in_footer=self._sigsInFooter(),
[15164]722            digital_sigs=self._digital_sigs(),
723            save_file=self._save_file(),
[13297]724            )
[15164]725        if not pdfstream:
726            self.redirect(self.url(self.context.student))
727            return
728        return pdfstream
[13297]729
730class CustomExportPDFBedTicketSlip(NigeriaExportPDFBedTicketSlip):
731    """Deliver a PDF slip of the context.
732    """
[13317]733    omit_fields = ('password', 'suspended', 'suspended_comment',
[13717]734        'phone', 'adm_code', 'email', 'date_of_birth', 'flash_notice')
[13297]735
[13719]736class CustomPaymentsManageFormPage(PaymentsManageFormPage):
737    """ Page to manage the student payments. This manage form page is for
738    both students and students officers. Uniben does not allow students
739    to remove any payment ticket.
740    """
741    @property
742    def manage_payments_allowed(self):
[13723]743        return checkPermission('waeup.manageStudent', self.context)
[15267]744
[15975]745class CustomAccommodationDisplayFormPage(NigeriaAccommodationDisplayFormPage):
746    """ Page to view bed tickets.
747    """
748    with_hostel_selection = True
749
[15267]750class CustomAccommodationManageFormPage(NigeriaAccommodationManageFormPage):
751    """ Page to manage bed tickets.
752    This manage form page is for both students and students officers.
753    """
[15352]754    with_hostel_selection = True
755
756class CustomStudentBaseEditFormPage(StudentBaseEditFormPage):
757    """ View to edit student base data
758    """
759    form_fields = grok.AutoFields(ICustomStudentBase).select(
760        'email', 'phone')
761    form_fields['email'].field.required = True
[16361]762
763class CustomStudentFilesUploadPage(NigeriaStudentFilesUploadPage):
764    """ View to upload passport picture.
765
766    Students are not allowed to change the picture if they
767    passed the regular Kofa application.
768    """
769
770    def update(self):
[16362]771        # Uniben: Only 2020 session students are allowed to edit the picture.
772        if self.context.entry_session != 2020:
773            emit_lock_message(self)
774            return
[16361]775        # Passport pictures must not be editable if application slip
776        # exists.
777        slip = getUtility(IExtFileStore).getFileByContext(
778            self.context, 'application_slip')
779        PORTRAIT_CHANGE_STATES = getUtility(IStudentsUtils).PORTRAIT_CHANGE_STATES
780        if self.context.state not in PORTRAIT_CHANGE_STATES or slip is not None:
781            emit_lock_message(self)
782            return
783        super(StudentFilesUploadPage, self).update()
[16382]784        return
785
[16385]786
787
788
789from zope.schema.vocabulary import SimpleVocabulary
790from zope.formlib.itemswidgets import RadioWidget
791from zope.formlib.itemswidgets import SelectWidget, DropdownWidget
792
793def CustomBooleanRadioWidget(field, request, true=_('yes'), false=_('no')):
794    vocabulary = SimpleVocabulary.fromItems( ((true, True), (false, False)) )
795    widget = RadioWidget(field, vocabulary, request)
796    widget.required = False
797    return widget
798
[16382]799class StudentMedicalHistoryEditFormPage(KofaEditFormPage):
[16383]800    """ Page to edit medical data
[16382]801    """
802    grok.context(ICustomStudent)
803    grok.name('edit_medical')
804    grok.require('waeup.handleStudent')
[16385]805    label = _('Medical Questionnaire')
[16382]806    pnav = 4
807
[16386]808    def _medicalQuestPaymentMade(self, student, session):
809        if len(student['payments']):
810            for ticket in student['payments'].values():
811                if ticket.p_state == 'paid' and \
812                    ticket.p_category == 'medical_quest' and \
813                    ticket.p_session == session:
814                    return True
815        return False
816
817    def update(self):
818        if not self._medicalQuestPaymentMade(
819            self.context, self.context.current_session):
820            self.flash('Please pay medical questionnaire payment first.',
821                type="warning")
822            self.redirect(self.url(self.context))
823            return
824        return super(StudentMedicalHistoryEditFormPage, self).update()
825
[16382]826    @property
[16385]827    def form_fields(self):
828        form_fields = grok.AutoFields(IMedicalHistory)
829        form_fields['medical_updated'].for_display = True
830        for field in ('fever', 'headaches', 'catarrh', 'cough', 'sore_throat',
831                      'breathing', 'sneezing', 'weakness', 'body_pains',
832                      'smell', 'taste', 'asthma', 'hypertension', 'diabetes',
833                      'obesity', 'lagos_abuja', 'outside', 'company_suspected',
834                      'company_confirmed', 'positive', 'negative',
835                      'vaccination'):
836            form_fields[field].custom_widget = CustomBooleanRadioWidget
837        return form_fields
838
839    @property
[16382]840    def separators(self):
841        return getUtility(IStudentsUtils).SEPARATORS_DICT
842
843    @action(_('Save/Confirm'), style='primary')
844    def save(self, **data):
845        msave(self, **data)
846        self.context.medical_updated = datetime.utcnow()
847        return
848
[16383]849class StudentMedicalHistoryManageFormPage(StudentMedicalHistoryEditFormPage):
850    """ Page to manage medical data
851    """
852    grok.name('manage_medical')
853    grok.require('waeup.manageStudent')
[16385]854    label = _('Manage medical questionnaire data')
[16383]855
[16405]856    def update(self):
857        return super(StudentMedicalHistoryEditFormPage, self).update()
858
[16382]859class ExportPDFMedicalHistorySlip(grok.View):
860    """Deliver a PDF slip of the context.
861    """
862    grok.context(ICustomStudent)
[16385]863    grok.name('medical_questionnaire_slip.pdf')
[16382]864    grok.require('waeup.viewStudent')
865    prefix = 'form'
866    form_fields = grok.AutoFields(IMedicalHistory)
867
868    omit_fields = ('password', 'suspended', 'suspended_comment',
869                   'adm_code', 'date_of_birth',
870                   'flash_notice', 'current_mode', 'entry_mode',
871                   'entry_session', 'parents_email', 'study_course',
872                   'current_level', 'reg_number', 'sex',
873                   'certificate')
874
875    @property
876    def title(self):
877        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
[16385]878        return translate(_('Medical Questionnaire'), 'waeup.kofa',
[16382]879            target_language=portal_language)
880
881    @property
882    def label(self):
883        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
[16385]884        return translate(_('Medical Questionnaire Slip of'),
[16382]885            'waeup.kofa', target_language=portal_language) \
886            + ' %s' % self.context.display_fullname
887
888    def render(self):
889        studentview = StudentBasePDFFormPage(self.context.student,
890            self.request, self.omit_fields)
891        students_utils = getUtility(IStudentsUtils)
892        return students_utils.renderPDF(
[16385]893            self, 'medical_questionnaire_slip.pdf',
[16382]894            self.context.student, studentview,
895            omit_fields=self.omit_fields,)
Note: See TracBrowser for help on using the repository browser.