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

Last change on this file since 13719 was 13719, checked in by Henrik Bettermann, 9 years ago

Customize PaymentsManageFormPage?.

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