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

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

Add missing import.

  • Property svn:keywords set to Id
File size: 33.5 KB
Line 
1## $Id: browser.py 16448 2021-04-09 10:35:08Z henrik $
2##
3## Copyright (C) 2012 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18import grok
19from datetime import datetime
20from zope.i18n import translate
21from zope.security import checkPermission
22from zope.schema.interfaces import ConstraintNotSatisfied
23from zope.formlib.textwidgets import BytesDisplayWidget
24from zope.component import getUtility
25from hurry.workflow.interfaces import IWorkflowInfo
26from waeup.kofa.interfaces import (
27    REQUESTED, IExtFileStore, IKofaUtils, IObjectHistory)
28from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
29from waeup.kofa.browser.layout import action, KofaEditFormPage, UtilityView
30from waeup.kofa.students.browser import (
31    StudentBaseEditFormPage,
32    StudyLevelEditFormPage, StudyLevelDisplayFormPage,
33    StudentBasePDFFormPage, ExportPDFCourseRegistrationSlip,
34    CourseTicketDisplayFormPage, StudentTriggerTransitionFormPage,
35    msave, emit_lock_message,
36    StudentActivateView, StudentDeactivateView,
37    ExportPDFTranscriptSlip,
38    PaymentsManageFormPage,
39    StartClearancePage,
40    StudentFilesUploadPage)
41from waeup.kofa.students.workflow import (CREATED, ADMITTED, PAID,
42    CLEARANCE, REQUESTED, RETURNING, CLEARED, REGISTERED, VALIDATED,
43    GRADUATED, TRANSREQ, TRANSVAL, TRANSREL, FORBIDDEN_POSTGRAD_TRANS)
44from waeup.kofa.students.interfaces import IStudentsUtils, ICourseTicket
45from waeup.kofa.students.workflow import FORBIDDEN_POSTGRAD_TRANS
46from kofacustom.nigeria.students.browser import (
47    NigeriaOnlinePaymentDisplayFormPage,
48    NigeriaStudentBaseManageFormPage,
49    NigeriaStudentClearanceEditFormPage,
50    NigeriaOnlinePaymentAddFormPage,
51    NigeriaExportPDFPaymentSlip,
52    NigeriaExportPDFClearanceSlip,
53    NigeriaExportPDFBedTicketSlip,
54    NigeriaStudentPersonalDisplayFormPage,
55    NigeriaStudentPersonalManageFormPage,
56    NigeriaStudentPersonalEditFormPage,
57    NigeriaAccommodationManageFormPage,
58    NigeriaAccommodationDisplayFormPage,
59    NigeriaStudentBaseDisplayFormPage,
60    NigeriaStudentFilesUploadPage,
61    )
62
63from waeup.uniben.students.interfaces import (
64    ICustomStudent,
65    ICustomStudentBase,
66    ICustomStudentOnlinePayment,
67    ICustomStudentStudyCourse,
68    ICustomStudentStudyLevel,
69    ICustomUGStudentClearance,
70    ICustomPGStudentClearance,
71    ICustomStudentPersonal,
72    ICustomStudentPersonalEdit,
73    IMedicalHistory)
74from waeup.uniben.interfaces import MessageFactory as _
75
76class CustomStudentBaseDisplayFormPage(NigeriaStudentBaseDisplayFormPage):
77    """ Page to display student base data
78    """
79    form_fields = grok.AutoFields(ICustomStudentBase).omit(
80        'password', 'suspended', 'suspended_comment',
81        'flash_notice', 'provisionally_cleared', 'parents_email')
82    form_fields[
83        'financial_clearance_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
84
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')
92
93class CustomOnlinePaymentDisplayFormPage(NigeriaOnlinePaymentDisplayFormPage):
94    """ Page to view an online payment ticket
95    """
96    grok.context(ICustomStudentOnlinePayment)
97    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
98        'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item')
99    form_fields[
100        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
101    form_fields[
102        'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
103
104class CustomStartClearancePage(StartClearancePage):
105
106    @property
107    def with_ac(self):
108        if self.context.faccode == 'DCOEM':
109            return False
110        return True
111
112
113CLEARANCE_FLASH_MESSAGE = """
114If you have not presented for physical clearance, scan your WAEC, NECO
115and other O level results scratch cards on one document and
116attach to the form below (Scans > O Level Results Scratch Card).
117Then come back to check for your successful cleared status as from 3 days
118after successful clearance request.
119If status is cleared, pay your school charges and proceed to the
120Dean's Office to collect the signed eligibility form.
121"""
122
123class CustomStudentClearanceEditFormPage(NigeriaStudentClearanceEditFormPage):
124    """ View to edit student clearance data by student
125    """
126
127    @property
128    def form_fields(self):
129        if self.context.is_postgrad:
130            form_fields = grok.AutoFields(ICustomPGStudentClearance).omit(
131            'clearance_locked', 'nysc_location', 'clr_code', 'officer_comment',
132            'physical_clearance_date')
133        else:
134            form_fields = grok.AutoFields(ICustomUGStudentClearance).omit(
135            'clearance_locked', 'clr_code', 'officer_comment',
136            'physical_clearance_date')
137            form_fields['date_of_birth'].for_display = True
138            form_fields['nationality'].for_display = True
139            form_fields['lga'].for_display = True
140        return form_fields
141
142    def dataNotComplete(self):
143        store = getUtility(IExtFileStore)
144        if not store.getFileByContext(self.context, attr=u'birth_certificate.jpg'):
145            return _('No birth certificate uploaded.')
146        if not store.getFileByContext(self.context, attr=u'ref_let.jpg'):
147            return _('No guarantor/referee letter uploaded.')
148        if not store.getFileByContext(self.context, attr=u'acc_let.jpg'):
149            return _('No acceptance letter uploaded.')
150        if not store.getFileByContext(self.context, attr=u'fst_sit_scan.jpg'):
151            return _('No first sitting result uploaded.')
152        #if not store.getFileByContext(self.context, attr=u'scd_sit_scan.jpg'):
153        #    return _('No second sitting result uploaded.')
154        if not store.getFileByContext(self.context, attr=u'secr_cults.jpg'):
155            return _('No affidavit of non-membership of secret cults uploaded.')
156        if not store.getFileByContext(self.context, attr=u'olevel_sc.jpg'):
157            return _('No O level results scratch card 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        #notify(grok.ObjectModifiedEvent(self.context.__parent__))
505        return
506
507class CustomStudyLevelEditFormPage(StudyLevelEditFormPage):
508    """ Page to edit the student study level data by students.
509
510    """
511    grok.template('studyleveleditpage')
512
513class CustomStudyLevelDisplayFormPage(StudyLevelDisplayFormPage):
514    """ Page to display student study levels
515    """
516    grok.template('studylevelpage')
517
518    @property
519    def view_scores_allowed(self):
520        return checkPermission('waeup.manageStudent', self.context)
521
522class CustomExportPDFCourseRegistrationSlip(
523    ExportPDFCourseRegistrationSlip):
524    """Deliver a PDF slip of the context.
525    """
526
527    form_fields = grok.AutoFields(ICustomStudentStudyLevel).omit(
528        'level_verdict', 'gpa', 'level', 'transcript_remark')
529
530    def update(self):
531        if self.context.student.state != REGISTERED \
532            or self.context.student.current_level != self.context.level:
533            self.flash(_('Forbidden'), type="warning")
534            self.redirect(self.url(self.context))
535
536    @property
537    def tabletitle(self):
538        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
539        tabletitle = []
540        tabletitle.append(translate(_('1st Semester Courses'), 'waeup.kofa',
541            target_language=portal_language))
542        tabletitle.append(translate(_('2nd Semester Courses'), 'waeup.kofa',
543            target_language=portal_language))
544        tabletitle.append(translate(_('Level Courses'), 'waeup.kofa',
545            target_language=portal_language))
546        tabletitle.append(translate(_('1st Trimester Courses'), 'waeup.kofa',
547            target_language=portal_language))
548        tabletitle.append(translate(_('2nd Trimester Courses'), 'waeup.kofa',
549            target_language=portal_language))
550        tabletitle.append(translate(_('3rd Trimester Courses'), 'waeup.kofa',
551            target_language=portal_language))
552        return tabletitle
553
554    def render(self):
555        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
556        Code = translate('Code', 'waeup.kofa', target_language=portal_language)
557        Title = translate('Title', 'waeup.kofa', target_language=portal_language)
558        Dept = translate('Dept.', 'waeup.kofa', target_language=portal_language)
559        Faculty = translate('Faculty', 'waeup.kofa', target_language=portal_language)
560        Cred = translate(_('Credits'), 'waeup.uniben', target_language=portal_language)
561        studentview = StudentBasePDFFormPage(self.context.student,
562            self.request, self.omit_fields)
563        students_utils = getUtility(IStudentsUtils)
564
565        tabledata = []
566        tableheader = []
567        for i in range(1,7):
568            tabledata.append(sorted(
569                [value for value in self.context.values() if value.semester == i],
570                key=lambda value: str(value.semester) + value.code))
571            tableheader.append([(Code,'code', 2.5),
572                             (Title,'title', 5),
573                             (Dept,'dcode', 1.5), (Faculty,'fcode', 1.5),
574                             (Cred, 'credits', 1.5),
575                             ])
576        return students_utils.renderPDF(
577            self, 'course_registration_slip.pdf',
578            self.context.student, studentview,
579            tableheader=tableheader,
580            tabledata=tabledata,
581            omit_fields=self.omit_fields
582            )
583
584class ExportPDFCourseResultSlip(ExportPDFCourseRegistrationSlip):
585    """Deliver a PDF slip of the context.
586    """
587
588    grok.name('course_result_slip.pdf')
589
590    form_fields = grok.AutoFields(ICustomStudentStudyLevel).omit('level')
591
592    @property
593    def tabletitle(self):
594        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
595        tabletitle = []
596        tabletitle.append(translate(_('1st Semester Courses'), 'waeup.kofa',
597            target_language=portal_language))
598        tabletitle.append(translate(_('2nd Semester Courses'), 'waeup.kofa',
599            target_language=portal_language))
600        tabletitle.append(translate(_('Level Courses'), 'waeup.kofa',
601            target_language=portal_language))
602        tabletitle.append(translate(_('1st Trimester Courses'), 'waeup.kofa',
603            target_language=portal_language))
604        tabletitle.append(translate(_('2nd Trimester Courses'), 'waeup.kofa',
605            target_language=portal_language))
606        tabletitle.append(translate(_('3rd Trimester Courses'), 'waeup.kofa',
607            target_language=portal_language))
608        return tabletitle
609
610    @property
611    def label(self):
612        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
613        lang = self.request.cookies.get('kofa.language', portal_language)
614        level_title = translate(self.context.level_title, 'waeup.kofa',
615            target_language=lang)
616        return translate(_('Course Result Slip'),
617            'waeup.uniben', target_language=portal_language) \
618            + ' %s' % level_title
619
620    def render(self):
621        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
622        Code = translate('Code', 'waeup.kofa', target_language=portal_language)
623        Title = translate('Title', 'waeup.kofa', target_language=portal_language)
624        Dept = translate('Dept.', 'waeup.kofa', target_language=portal_language)
625        Faculty = translate('Faculty', 'waeup.kofa', target_language=portal_language)
626        Cred = translate(_('Credits'), 'waeup.uniben', target_language=portal_language)
627        Grade = translate('Grade', 'waeup.kofa', target_language=portal_language)
628        studentview = StudentBasePDFFormPage(self.context.student,
629            self.request, self.omit_fields)
630        students_utils = getUtility(IStudentsUtils)
631
632        tabledata = []
633        tableheader = []
634        for i in range(1,7):
635            tabledata.append(sorted(
636                [value for value in self.context.values() if value.semester == i],
637                key=lambda value: str(value.semester) + value.code))
638            tableheader.append([(Code,'code', 2.5),
639                             (Title,'title', 5),
640                             (Dept,'dcode', 1.5), (Faculty,'fcode', 1.5),
641                             (Cred, 'credits', 1.5),
642                             (Grade, 'grade', 1.5),
643                             ])
644        return students_utils.renderPDF(
645            self, 'course_result_slip.pdf',
646            self.context.student, studentview,
647            tableheader=tableheader,
648            tabledata=tabledata,
649            omit_fields=self.omit_fields
650            )
651
652class CustomCourseTicketDisplayFormPage(CourseTicketDisplayFormPage):
653    """ Page to display course tickets
654    """
655    form_fields = grok.AutoFields(ICourseTicket).omit('score')
656
657class CustomStudentActivateView(StudentActivateView):
658    """ Activate student account
659    """
660
661    def update(self):
662        self.context.suspended = False
663        self.context.writeLogMessage(self, 'account activated')
664        history = IObjectHistory(self.context)
665        history.addMessage('Student account activated', user='undisclosed')
666        self.flash(_('Student account has been activated.'))
667        self.redirect(self.url(self.context))
668        return
669
670class CustomStudentDeactivateView(StudentDeactivateView):
671    """ Deactivate student account
672    """
673    def update(self):
674        self.context.suspended = True
675        self.context.writeLogMessage(self, 'account deactivated')
676        history = IObjectHistory(self.context)
677        history.addMessage('Student account deactivated', user='undisclosed')
678        self.flash(_('Student account has been deactivated.'))
679        self.redirect(self.url(self.context))
680        return
681
682class CustomExportPDFTranscriptSlip(ExportPDFTranscriptSlip):
683    """Deliver a PDF slip of the context.
684    """
685
686    def _sigsInFooter(self):
687        isStudent = getattr(
688            self.request.principal, 'user_type', None) == 'student'
689        if not isStudent and self.context.student.state in (TRANSVAL, TRANSREL):
690            return (_('D. R. (Exams & Records)'),_('Current Dean of Faculty'),)
691        return ()
692
693    #def _signatures(self):
694    #    return ([(
695    #        'Current HD<br /> D. R. (Exams & Records)<br /> '
696    #        'For: Registrar')],)
697
698    def render(self):
699        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
700        Term = translate(_('Term'), 'waeup.kofa', target_language=portal_language)
701        Code = translate(_('Code'), 'waeup.kofa', target_language=portal_language)
702        Title = translate(_('Title'), 'waeup.kofa', target_language=portal_language)
703        Cred = translate(_('Credits'), 'waeup.kofa', target_language=portal_language)
704        #Score = translate(_('Score'), 'waeup.kofa', target_language=portal_language)
705        Grade = translate(_('Grade'), 'waeup.kofa', target_language=portal_language)
706        studentview = StudentBasePDFFormPage(self.context.student,
707            self.request, self.omit_fields)
708        students_utils = getUtility(IStudentsUtils)
709
710        tableheader = [(Code,'code', 2.5),
711                         (Title,'title', 8.5),
712                         (Term, 'semester', 1.5),
713                         (Cred, 'credits', 1.5),
714                         #(Score, 'score', 1.5),
715                         (Grade, 'grade', 1.5),
716                         ]
717
718        pdfstream = students_utils.renderPDFTranscript(
719            self, 'transcript.pdf',
720            self.context.student, studentview,
721            omit_fields=self.omit_fields,
722            tableheader=tableheader,
723            signatures=self._signatures(),
724            sigs_in_footer=self._sigsInFooter(),
725            digital_sigs=self._digital_sigs(),
726            save_file=self._save_file(),
727            )
728        if not pdfstream:
729            self.redirect(self.url(self.context.student))
730            return
731        return pdfstream
732
733class CustomExportPDFBedTicketSlip(NigeriaExportPDFBedTicketSlip):
734    """Deliver a PDF slip of the context.
735    """
736    omit_fields = ('password', 'suspended', 'suspended_comment',
737        'phone', 'adm_code', 'email', 'date_of_birth', 'flash_notice')
738
739class CustomPaymentsManageFormPage(PaymentsManageFormPage):
740    """ Page to manage the student payments. This manage form page is for
741    both students and students officers. Uniben does not allow students
742    to remove any payment ticket.
743    """
744    @property
745    def manage_payments_allowed(self):
746        return checkPermission('waeup.manageStudent', self.context)
747
748class CustomAccommodationDisplayFormPage(NigeriaAccommodationDisplayFormPage):
749    """ Page to view bed tickets.
750    """
751    with_hostel_selection = True
752
753class CustomAccommodationManageFormPage(NigeriaAccommodationManageFormPage):
754    """ Page to manage bed tickets.
755    This manage form page is for both students and students officers.
756    """
757    with_hostel_selection = True
758
759class CustomStudentBaseEditFormPage(StudentBaseEditFormPage):
760    """ View to edit student base data
761    """
762    form_fields = grok.AutoFields(ICustomStudentBase).select(
763        'email', 'phone')
764    form_fields['email'].field.required = True
765
766class CustomStudentFilesUploadPage(NigeriaStudentFilesUploadPage):
767    """ View to upload passport picture.
768
769    Students are not allowed to change the picture if they
770    passed the regular Kofa application.
771    """
772
773    def update(self):
774        # Uniben: Only 2020 session students are allowed to edit the picture.
775        if self.context.entry_session != 2020:
776            emit_lock_message(self)
777            return
778        # Passport pictures must not be editable if application slip
779        # exists.
780        slip = getUtility(IExtFileStore).getFileByContext(
781            self.context, 'application_slip')
782        PORTRAIT_CHANGE_STATES = getUtility(IStudentsUtils).PORTRAIT_CHANGE_STATES
783        if self.context.state not in PORTRAIT_CHANGE_STATES or slip is not None:
784            emit_lock_message(self)
785            return
786        super(StudentFilesUploadPage, self).update()
787        return
788
789
790
791
792from zope.schema.vocabulary import SimpleVocabulary
793from zope.formlib.itemswidgets import RadioWidget
794from zope.formlib.itemswidgets import SelectWidget, DropdownWidget
795
796def CustomBooleanRadioWidget(field, request, true=_('yes'), false=_('no')):
797    vocabulary = SimpleVocabulary.fromItems( ((true, True), (false, False)) )
798    widget = RadioWidget(field, vocabulary, request)
799    widget.required = False
800    return widget
801
802class StudentMedicalHistoryEditFormPage(KofaEditFormPage):
803    """ Page to edit medical data
804    """
805    grok.context(ICustomStudent)
806    grok.name('edit_medical')
807    grok.require('waeup.handleStudent')
808    label = _('Medical Questionnaire')
809    pnav = 4
810
811    def _medicalQuestPaymentMade(self, student, session):
812        if len(student['payments']):
813            for ticket in student['payments'].values():
814                if ticket.p_state == 'paid' and \
815                    ticket.p_category == 'medical_quest' and \
816                    ticket.p_session == session:
817                    return True
818        return False
819
820    def update(self):
821        if not self._medicalQuestPaymentMade(
822            self.context, self.context.current_session):
823            self.flash('Please pay medical questionnaire payment first.',
824                type="warning")
825            self.redirect(self.url(self.context))
826            return
827        return super(StudentMedicalHistoryEditFormPage, self).update()
828
829    @property
830    def form_fields(self):
831        form_fields = grok.AutoFields(IMedicalHistory)
832        form_fields['medical_updated'].for_display = True
833        for field in ('fever', 'headaches', 'catarrh', 'cough', 'sore_throat',
834                      'breathing', 'sneezing', 'weakness', 'body_pains',
835                      'smell', 'taste', 'asthma', 'hypertension', 'diabetes',
836                      'obesity', 'lagos_abuja', 'outside', 'company_suspected',
837                      'company_confirmed', 'positive', 'negative',
838                      'vaccination'):
839            form_fields[field].custom_widget = CustomBooleanRadioWidget
840        return form_fields
841
842    @property
843    def separators(self):
844        return getUtility(IStudentsUtils).SEPARATORS_DICT
845
846    @action(_('Save/Confirm'), style='primary')
847    def save(self, **data):
848        msave(self, **data)
849        self.context.medical_updated = datetime.utcnow()
850        return
851
852class StudentMedicalHistoryManageFormPage(StudentMedicalHistoryEditFormPage):
853    """ Page to manage medical data
854    """
855    grok.name('manage_medical')
856    grok.require('waeup.manageStudent')
857    label = _('Manage medical questionnaire data')
858
859    def update(self):
860        return super(StudentMedicalHistoryEditFormPage, self).update()
861
862class ExportPDFMedicalHistorySlip(grok.View):
863    """Deliver a PDF slip of the context.
864    """
865    grok.context(ICustomStudent)
866    grok.name('medical_questionnaire_slip.pdf')
867    grok.require('waeup.viewStudent')
868    prefix = 'form'
869    form_fields = grok.AutoFields(IMedicalHistory)
870
871    omit_fields = ('password', 'suspended', 'suspended_comment',
872                   'adm_code', 'date_of_birth',
873                   'flash_notice', 'current_mode', 'entry_mode',
874                   'entry_session', 'parents_email', 'study_course',
875                   'current_level', 'reg_number', 'sex',
876                   'certificate')
877
878    @property
879    def title(self):
880        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
881        return translate(_('Medical Questionnaire'), 'waeup.kofa',
882            target_language=portal_language)
883
884    @property
885    def label(self):
886        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
887        return translate(_('Medical Questionnaire Slip of'),
888            'waeup.kofa', target_language=portal_language) \
889            + ' %s' % self.context.display_fullname
890
891    def render(self):
892        studentview = StudentBasePDFFormPage(self.context.student,
893            self.request, self.omit_fields)
894        students_utils = getUtility(IStudentsUtils)
895        return students_utils.renderPDF(
896            self, 'medical_questionnaire_slip.pdf',
897            self.context.student, studentview,
898            omit_fields=self.omit_fields,)
Note: See TracBrowser for help on using the repository browser.