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

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

Passport picture is not required when starting clearance.

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