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

Last change on this file since 17384 was 17362, checked in by Henrik Bettermann, 18 months ago

Add post_text to admission letter.

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