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

Last change on this file since 13146 was 13085, checked in by Henrik Bettermann, 10 years ago

Allow students to edit parent_email.

  • Property svn:keywords set to Id
File size: 19.2 KB
RevLine 
[8911]1## $Id: browser.py 13085 2015-06-21 11:47:55Z 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 zope.i18n import translate
[9210]20from zope.schema.interfaces import ConstraintNotSatisfied
[12856]21from zope.formlib.textwidgets import BytesDisplayWidget
[9380]22from zope.component import getUtility
[9281]23from hurry.workflow.interfaces import IWorkflowInfo
[11069]24from waeup.kofa.interfaces import (
25    REQUESTED, IExtFileStore, IKofaUtils, IObjectHistory)
[8911]26from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
[12121]27from waeup.kofa.browser.layout import action, KofaEditFormPage, UtilityView
[9205]28from waeup.kofa.students.browser import (
[9686]29    StudyLevelEditFormPage, StudyLevelDisplayFormPage,
[13063]30    StudentBasePDFFormPage, ExportPDFCourseRegistrationSlip,
[10025]31    CourseTicketDisplayFormPage, StudentTriggerTransitionFormPage,
[11069]32    msave, emit_lock_message,
[13063]33    StudentActivateView, StudentDeactivateView,
34    ExportPDFTranscriptSlip)
[12845]35from waeup.kofa.students.workflow import (CREATED, ADMITTED, PAID,
36    CLEARANCE, REQUESTED, RETURNING, CLEARED, REGISTERED, VALIDATED,
37    GRADUATED, TRANSCRIPT, FORBIDDEN_POSTGRAD_TRANS)
[9686]38from waeup.kofa.students.interfaces import IStudentsUtils, ICourseTicket
[9251]39from waeup.kofa.students.workflow import FORBIDDEN_POSTGRAD_TRANS
[8911]40from kofacustom.nigeria.students.browser import (
41    NigeriaOnlinePaymentDisplayFormPage,
[9251]42    NigeriaStudentBaseManageFormPage,
[9380]43    NigeriaStudentClearanceEditFormPage,
[8911]44    NigeriaOnlinePaymentAddFormPage,
[13063]45    NigeriaExportPDFPaymentSlip,
46    NigeriaExportPDFClearanceSlip,
[12856]47    NigeriaStudentPersonalDisplayFormPage,
[13085]48    NigeriaStudentPersonalManageFormPage,
49    NigeriaStudentPersonalEditFormPage
[9281]50    )
[8911]51
[9210]52from waeup.uniben.students.interfaces import (
[12121]53    ICustomStudent,
[12856]54    ICustomStudentOnlinePayment,
55    ICustomStudentStudyCourse,
[11552]56    ICustomStudentStudyLevel,
57    ICustomUGStudentClearance,
[12856]58    ICustomPGStudentClearance,
[13085]59    ICustomStudentPersonal,
60    ICustomStudentPersonalEdit)
[9210]61from waeup.uniben.interfaces import MessageFactory as _
[8911]62
63class CustomOnlinePaymentDisplayFormPage(NigeriaOnlinePaymentDisplayFormPage):
64    """ Page to view an online payment ticket
65    """
66    grok.context(ICustomStudentOnlinePayment)
[9775]67    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
[9993]68        'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item')
[8911]69    form_fields[
70        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
71    form_fields[
72        'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
73
[9380]74class CustomStudentClearanceEditFormPage(NigeriaStudentClearanceEditFormPage):
75    """ View to edit student clearance data by student
76    """
77
[11552]78    @property
79    def form_fields(self):
80        if self.context.is_postgrad:
81            form_fields = grok.AutoFields(ICustomPGStudentClearance).omit(
[12391]82            'clearance_locked', 'nysc_location', 'clr_code', 'officer_comment',
83            'physical_clearance_date')
[11552]84        else:
85            form_fields = grok.AutoFields(ICustomUGStudentClearance).omit(
[12391]86            'clearance_locked', 'clr_code', 'officer_comment',
87            'physical_clearance_date')
[11552]88            form_fields['date_of_birth'].for_display = True
89            form_fields['nationality'].for_display = True
90            form_fields['lga'].for_display = True
91        return form_fields
92
[9380]93    def dataNotComplete(self):
94        store = getUtility(IExtFileStore)
95        if not store.getFileByContext(self.context, attr=u'birth_certificate.jpg'):
96            return _('No birth certificate uploaded.')
97        if not store.getFileByContext(self.context, attr=u'ref_let.jpg'):
98            return _('No guarantor/referee letter uploaded.')
99        if not store.getFileByContext(self.context, attr=u'acc_let.jpg'):
100            return _('No acceptance letter uploaded.')
101        if not store.getFileByContext(self.context, attr=u'fst_sit_scan.jpg'):
102            return _('No first sitting result uploaded.')
[9395]103        #if not store.getFileByContext(self.context, attr=u'scd_sit_scan.jpg'):
104        #    return _('No second sitting result uploaded.')
[9380]105        if not store.getFileByContext(self.context, attr=u'secr_cults.jpg'):
[9848]106            return _('No affidavit of non-membership of secret cults uploaded.')
[9380]107        return False
108
[8911]109class CustomOnlinePaymentAddFormPage(NigeriaOnlinePaymentAddFormPage):
110    """ Page to add an online payment ticket
111    """
112    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).select(
113        'p_category')
114
[13063]115class CustomExportPDFPaymentSlip(NigeriaExportPDFPaymentSlip):
[8911]116    """Deliver a PDF slip of the context.
117    """
118    grok.context(ICustomStudentOnlinePayment)
[9775]119    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
[9993]120        'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item')
[8911]121    form_fields['creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
[9205]122    form_fields['payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
123
124
[13063]125class CustomExportPDFClearanceSlip(NigeriaExportPDFClearanceSlip):
[9551]126    """Deliver a PDF slip of the context.
127    """
128
[11537]129    omit_fields = ('password', 'suspended', 'suspended_comment',
130        'phone', 'adm_code', 'email', 'date_of_birth')
131
[12846]132    def _sigsInFooter(self):
[12845]133        isStudent = getattr(
134            self.request.principal, 'user_type', None) == 'student'
[12852]135        if not isStudent and self.context.state in (CLEARED, RETURNING):
[12846]136            return (_('Date, Student Signature'),
137                    _('Date, Clearance Officer Signature'),
138                    )
139        return ()
[12845]140
[9551]141    def render(self):
142        studentview = StudentBasePDFFormPage(self.context.student,
143            self.request, self.omit_fields)
144        students_utils = getUtility(IStudentsUtils)
145        return students_utils.renderPDF(
146            self, 'clearance_slip.pdf',
147            self.context.student, studentview, signatures=self._signatures(),
[10271]148            sigs_in_footer=self._sigsInFooter(), show_scans=False,
149            omit_fields=self.omit_fields)
[9551]150
[12121]151
[13063]152class ExportClearanceInvitationSlip(UtilityView, grok.View):
[12121]153    """Deliver an invitation letter to physical clearance.
154
155    This form page is available only in Uniben.
156    """
157    grok.context(ICustomStudent)
158    grok.name('clearance_invitation_slip.pdf')
159    grok.require('waeup.viewStudent')
160    prefix = 'form'
161
[12263]162    label = u'Invitation Letter for Physical Clearance'
[12121]163
164    omit_fields = (
165        'suspended', 'phone', 'email',
166        'adm_code', 'suspended_comment',
167        'date_of_birth', 'current_level',
[12150]168        'department', 'current_mode',
[12121]169        'entry_session', 'matric_number', 'sex')
170
171    form_fields = []
172
173    @property
174    def note(self):
175        if self.context.physical_clearance_date:
176            return """
[12147]177<br /><br /><br /><br /><font size='12'>
178Dear %s,
179<br /><br /><br />
[12264]180You are invited for your physical clearance on:
[12121]181<br /><br />
[12264]182<strong>%s</strong>.
183<br /><br />
[12265]184Please bring along this letter of invitation to the University Main Auditorium
[12147]185<br /><br />
[12263]186on your clearance date.
[12147]187<br /><br /><br />
[12263]188Signed,
[12147]189<br /><br />
190The Registrar<br />
[12121]191</font>
192
[12147]193""" % (self.context.display_fullname, self.context.physical_clearance_date)
[12121]194        return
195
[12122]196
197    def update(self):
198        if self.context.student.state != REQUESTED \
199            or not  self.context.student.physical_clearance_date:
200            self.flash(_('Forbidden'), type="warning")
201            self.redirect(self.url(self.context))
202
[12121]203    def render(self):
204        studentview = StudentBasePDFFormPage(self.context.student,
205            self.request, self.omit_fields)
206        students_utils = getUtility(IStudentsUtils)
207        return students_utils.renderPDF(
208            self, 'clearance_invitation_slip',
209            self.context.student, studentview,
210            omit_fields=self.omit_fields,
211            note=self.note)
212
[12856]213class CustomStudentPersonalDisplayFormPage(
214    NigeriaStudentPersonalDisplayFormPage):
215    """ Page to display student personal data
216    """
217
218    form_fields = grok.AutoFields(ICustomStudentPersonal)
219    form_fields['perm_address'].custom_widget = BytesDisplayWidget
220    form_fields['next_kin_address'].custom_widget = BytesDisplayWidget
221    form_fields[
222        'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
223
224class CustomStudentPersonalManageFormPage(
225    NigeriaStudentPersonalManageFormPage):
226    """ Page to manage personal data
227    """
228
229    form_fields = grok.AutoFields(ICustomStudentPersonal)
230    form_fields['personal_updated'].for_display = True
231    form_fields[
232        'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
233
[13085]234class CstomStudentPersonalEditFormPage(NigeriaStudentPersonalEditFormPage):
235    """ Page to edit personal data
236    """
237    form_fields = grok.AutoFields(
238        ICustomStudentPersonalEdit).omit('personal_updated')
239
[9210]240class StudyCourseCOEditFormPage(KofaEditFormPage):
[9281]241    """ Page to edit the student study course data by clearance officers.
[9210]242
243    This form page is available only in Uniben.
244    """
245    grok.context(ICustomStudentStudyCourse)
246    grok.name('edit_level')
247    grok.require('waeup.clearStudent')
248    label = _('Edit current level')
249    pnav = 4
250    form_fields = grok.AutoFields(
251        ICustomStudentStudyCourse).select('current_level')
252
253    def update(self):
254        if not (self.context.is_current and
255            self.context.student.state == REQUESTED):
256            emit_lock_message(self)
257            return
258        super(StudyCourseCOEditFormPage, self).update()
259        return
260
261    @action(_('Save'), style='primary')
262    def save(self, **data):
263        try:
264            msave(self, **data)
265        except ConstraintNotSatisfied:
266            # The selected level might not exist in certificate
267            self.flash(_('Current level not available for certificate.'))
268            return
269        #notify(grok.ObjectModifiedEvent(self.context.__parent__))
[9281]270        return
271
272class CustomStudyLevelEditFormPage(StudyLevelEditFormPage):
273    """ Page to edit the student study level data by students.
274
275    """
[9686]276    grok.template('studyleveleditpage')
[9281]277
[9686]278class CustomStudyLevelDisplayFormPage(StudyLevelDisplayFormPage):
279    """ Page to display student study levels
280    """
281    grok.template('studylevelpage')
282
[13063]283class CustomExportPDFCourseRegistrationSlip(
284    ExportPDFCourseRegistrationSlip):
[9686]285    """Deliver a PDF slip of the context.
286    """
287
[9921]288    form_fields = grok.AutoFields(ICustomStudentStudyLevel).omit(
[12879]289        'level_verdict', 'gpa', 'level')
[9921]290
[12855]291    def update(self):
292        if self.context.student.state != REGISTERED \
293            or self.context.student.current_level != self.context.level:
294            self.flash(_('Forbidden'), type="warning")
295            self.redirect(self.url(self.context))
296
[10441]297    @property
298    def tabletitle(self):
299        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
300        tabletitle = []
301        tabletitle.append(translate(_('1st Semester Courses'), 'waeup.kofa',
302            target_language=portal_language))
303        tabletitle.append(translate(_('2nd Semester Courses'), 'waeup.kofa',
304            target_language=portal_language))
305        tabletitle.append(translate(_('Level Courses'), 'waeup.kofa',
306            target_language=portal_language))
307        tabletitle.append(translate(_('1st Trimester Courses'), 'waeup.kofa',
308            target_language=portal_language))
309        tabletitle.append(translate(_('2nd Trimester Courses'), 'waeup.kofa',
310            target_language=portal_language))
311        tabletitle.append(translate(_('3rd Trimester Courses'), 'waeup.kofa',
312            target_language=portal_language))
313        return tabletitle
314
[9686]315    def render(self):
316        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
[9909]317        Code = translate('Code', 'waeup.kofa', target_language=portal_language)
318        Title = translate('Title', 'waeup.kofa', target_language=portal_language)
319        Dept = translate('Dept.', 'waeup.kofa', target_language=portal_language)
320        Faculty = translate('Faculty', 'waeup.kofa', target_language=portal_language)
321        Cred = translate(_('Credits'), 'waeup.uniben', target_language=portal_language)
[9686]322        studentview = StudentBasePDFFormPage(self.context.student,
323            self.request, self.omit_fields)
324        students_utils = getUtility(IStudentsUtils)
[10441]325
326        tabledata = []
327        tableheader = []
328        contenttitle = []
329        for i in range(1,7):
330            tabledata.append(sorted(
331                [value for value in self.context.values() if value.semester == i],
332                key=lambda value: str(value.semester) + value.code))
333            tableheader.append([(Code,'code', 2.5),
334                             (Title,'title', 5),
335                             (Dept,'dcode', 1.5), (Faculty,'fcode', 1.5),
336                             (Cred, 'credits', 1.5),
337                             ])
[9686]338        return students_utils.renderPDF(
339            self, 'course_registration_slip.pdf',
340            self.context.student, studentview,
[10441]341            tableheader=tableheader,
342            tabledata=tabledata,
[10271]343            omit_fields=self.omit_fields
[9908]344            )
[9848]345
[13063]346class UnibenExportPDFCourseResultSlip(ExportPDFCourseRegistrationSlip):
[9848]347    """Deliver a PDF slip of the context.
348    """
349
350    grok.name('course_result_slip.pdf')
351
352    @property
[10441]353    def tabletitle(self):
354        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
355        tabletitle = []
356        tabletitle.append(translate(_('1st Semester Courses'), 'waeup.kofa',
357            target_language=portal_language))
358        tabletitle.append(translate(_('2nd Semester Courses'), 'waeup.kofa',
359            target_language=portal_language))
360        tabletitle.append(translate(_('Level Courses'), 'waeup.kofa',
361            target_language=portal_language))
362        tabletitle.append(translate(_('1st Trimester Courses'), 'waeup.kofa',
363            target_language=portal_language))
364        tabletitle.append(translate(_('2nd Trimester Courses'), 'waeup.kofa',
365            target_language=portal_language))
366        tabletitle.append(translate(_('3rd Trimester Courses'), 'waeup.kofa',
367            target_language=portal_language))
368        return tabletitle
369
370    @property
[9848]371    def label(self):
372        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
373        lang = self.request.cookies.get('kofa.language', portal_language)
374        level_title = translate(self.context.level_title, 'waeup.kofa',
375            target_language=lang)
376        return translate(_('Course Result Slip'),
377            'waeup.uniben', target_language=portal_language) \
378            + ' %s' % level_title
379
380    def render(self):
381        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
[9909]382        Code = translate('Code', 'waeup.kofa', target_language=portal_language)
383        Title = translate('Title', 'waeup.kofa', target_language=portal_language)
384        Dept = translate('Dept.', 'waeup.kofa', target_language=portal_language)
385        Faculty = translate('Faculty', 'waeup.kofa', target_language=portal_language)
386        Cred = translate(_('Credits'), 'waeup.uniben', target_language=portal_language)
387        Grade = translate('Grade', 'waeup.kofa', target_language=portal_language)
[9848]388        studentview = StudentBasePDFFormPage(self.context.student,
389            self.request, self.omit_fields)
390        students_utils = getUtility(IStudentsUtils)
[10441]391
392        tabledata = []
393        tableheader = []
394        contenttitle = []
395        for i in range(1,7):
396            tabledata.append(sorted(
397                [value for value in self.context.values() if value.semester == i],
398                key=lambda value: str(value.semester) + value.code))
399            tableheader.append([(Code,'code', 2.5),
400                             (Title,'title', 5),
401                             (Dept,'dcode', 1.5), (Faculty,'fcode', 1.5),
402                             (Cred, 'credits', 1.5),
403                             (Grade, 'grade', 1.5),
404                             ])
[9908]405        return students_utils.renderPDF(
406            self, 'course_registration_slip.pdf',
407            self.context.student, studentview,
[10441]408            tableheader=tableheader,
409            tabledata=tabledata,
[10271]410            omit_fields=self.omit_fields
[9908]411            )
[9686]412
413class CustomCourseTicketDisplayFormPage(CourseTicketDisplayFormPage):
414    """ Page to display course tickets
415    """
416    form_fields = grok.AutoFields(ICourseTicket).omit('score')
[11069]417
[13063]418class CustomStudentActivateView(StudentActivateView):
[11069]419    """ Activate student account
420    """
421
422    def update(self):
423        self.context.suspended = False
424        self.context.writeLogMessage(self, 'account activated')
425        history = IObjectHistory(self.context)
426        history.addMessage('Student account activated', user='undisclosed')
427        self.flash(_('Student account has been activated.'))
428        self.redirect(self.url(self.context))
429        return
430
[13063]431class CustomStudentDeactivateView(StudentDeactivateView):
[11069]432    """ Deactivate student account
433    """
434    def update(self):
435        self.context.suspended = True
436        self.context.writeLogMessage(self, 'account deactivated')
437        history = IObjectHistory(self.context)
438        history.addMessage('Student account deactivated', user='undisclosed')
439        self.flash(_('Student account has been deactivated.'))
440        self.redirect(self.url(self.context))
441        return
[12845]442
[13063]443class CustomExportPDFTranscriptSlip(ExportPDFTranscriptSlip):
[12845]444    """Deliver a PDF slip of the context.
445    """
446
447    def _sigsInFooter(self):
448        return []
449        #return (_('CERTIFIED TRUE COPY'),)
450
451    def _signatures(self):
452        return ([(
453            'Current HD<br /> D. R. (Exams & Records)<br /> '
454            'For: Registrar')],)
455
456    def render(self):
457        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
458        Term = translate(_('Term'), 'waeup.kofa', target_language=portal_language)
459        Code = translate(_('Code'), 'waeup.kofa', target_language=portal_language)
460        Title = translate(_('Title'), 'waeup.kofa', target_language=portal_language)
461        Cred = translate(_('Credits'), 'waeup.kofa', target_language=portal_language)
462        #Score = translate(_('Score'), 'waeup.kofa', target_language=portal_language)
463        Grade = translate(_('Grade'), 'waeup.kofa', target_language=portal_language)
464        studentview = StudentBasePDFFormPage(self.context.student,
465            self.request, self.omit_fields)
466        students_utils = getUtility(IStudentsUtils)
467
468        tableheader = [(Code,'code', 2.5),
469                         (Title,'title', 8.5),
470                         (Term, 'semester', 1.5),
471                         (Cred, 'credits', 1.5),
472                         #(Score, 'score', 1.5),
473                         (Grade, 'grade', 1.5),
474                         ]
475
476        return students_utils.renderPDFTranscript(
477            self, 'transcript.pdf',
478            self.context.student, studentview,
479            omit_fields=self.omit_fields,
480            tableheader=tableheader,
481            signatures=self._signatures(),
482            sigs_in_footer=self._sigsInFooter(),
483            )
Note: See TracBrowser for help on using the repository browser.