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

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

Customize CustomStudyCourseManageFormPage?.

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