source: main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/students/browser.py @ 13823

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

Change slip title.

  • Property svn:keywords set to Id
File size: 16.2 KB
RevLine 
[8862]1## $Id: browser.py 13787 2016-03-24 08:35:27Z 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.formlib.textwidgets import BytesDisplayWidget
20from zope.component import getUtility
21from zope.i18n import translate
[13620]22from datetime import datetime
[8862]23from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
[13623]24from waeup.kofa.interfaces import IExtFileStore, IObjectHistory, IKofaUtils
[13620]25from waeup.kofa.browser.layout import action, UtilityView
[13623]26from waeup.kofa.utils.helpers import get_current_principal, to_timezone
[8862]27from waeup.kofa.students.browser import (
[8904]28    StudentPersonalDisplayFormPage, StudentPersonalManageFormPage,
[8862]29    StudentClearanceManageFormPage, StudentClearanceEditFormPage,
[13058]30    StudentClearanceDisplayFormPage, OnlinePaymentFakeApproveView,
31    ExportPDFClearanceSlip, StudentBaseManageFormPage,
[8966]32    StudentBaseDisplayFormPage,
[13623]33    StudentBasePDFFormPage,
[8862]34    StudentBaseEditFormPage, StudentPersonalEditFormPage,
35    OnlinePaymentDisplayFormPage, OnlinePaymentAddFormPage,
[13058]36    OnlinePaymentBreadcrumb, ExportPDFPaymentSlip,
37    ExportPDFCourseRegistrationSlip,
38    ExportPDFBedTicketSlip,
[13458]39    StudentFilesUploadPage, emit_lock_message,
40    AccommodationManageFormPage)
[10707]41from waeup.kofa.students.interfaces import IStudentsUtils
[8862]42from waeup.kofa.students.viewlets import (
43    PaymentReceiptActionButton, StudentPassportActionButton)
44from kofacustom.nigeria.students.interfaces import (
[8863]45    INigeriaStudentBase, INigeriaStudent, INigeriaStudentPersonal,
[9564]46    INigeriaStudentPersonalEdit,
[8863]47    INigeriaUGStudentClearance,INigeriaPGStudentClearance,
[8904]48    INigeriaStudentOnlinePayment
[8862]49    )
50from waeup.kofa.students.workflow import ADMITTED
51from kofacustom.nigeria.interfaces import MessageFactory as _
52
[8863]53class NigeriaOnlinePaymentBreadcrumb(OnlinePaymentBreadcrumb):
[8862]54    """A breadcrumb for payments.
55    """
[8863]56    grok.context(INigeriaStudentOnlinePayment)
[8862]57
58class PaymentReceiptActionButton(PaymentReceiptActionButton):
59    grok.order(4)
[8863]60    grok.context(INigeriaStudentOnlinePayment)
[8862]61
[8966]62class NigeriaStudentBaseDisplayFormPage(StudentBaseDisplayFormPage):
63    """ Page to display student base data
64    """
[9704]65    form_fields = grok.AutoFields(INigeriaStudentBase).omit(
[13712]66        'password', 'suspended', 'suspended_comment', 'flash_notice')
[13620]67    form_fields[
68        'financial_clearance_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
[8966]69
[8863]70class NigeriaStudentBaseManageFormPage(StudentBaseManageFormPage):
[8862]71    """ View to manage student base data
72    """
[9144]73    form_fields = grok.AutoFields(INigeriaStudentBase).omit(
[13620]74        'student_id', 'adm_code', 'suspended',
75        'financially_cleared_by', 'financial_clearance_date')
[8862]76
[8863]77class NigeriaStudentBaseEditFormPage(StudentBaseEditFormPage):
[8862]78    """ View to edit student base data
79    """
[8863]80    form_fields = grok.AutoFields(INigeriaStudentBase).select(
[8862]81        'email', 'phone')
82
[8863]83class NigeriaStudentPersonalDisplayFormPage(StudentPersonalDisplayFormPage):
[8862]84    """ Page to display student personal data
85    """
[9562]86    form_fields = grok.AutoFields(INigeriaStudentPersonal)
[8862]87    form_fields['perm_address'].custom_widget = BytesDisplayWidget
[9053]88    form_fields['next_kin_address'].custom_widget = BytesDisplayWidget
[9562]89    form_fields[
90        'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
[8862]91
[8863]92class NigeriaStudentPersonalEditFormPage(StudentPersonalEditFormPage):
[8862]93    """ Page to edit personal data
94    """
[9564]95    form_fields = grok.AutoFields(INigeriaStudentPersonalEdit).omit('personal_updated')
[8862]96
[8904]97class NigeriaStudentPersonalManageFormPage(StudentPersonalManageFormPage):
98    """ Page to edit personal data
99    """
100    form_fields = grok.AutoFields(INigeriaStudentPersonal)
[9554]101    form_fields['personal_updated'].for_display = True
[9572]102    form_fields[
103        'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
[8904]104
[8863]105class NigeriaStudentClearanceDisplayFormPage(StudentClearanceDisplayFormPage):
[8862]106    """ Page to display student clearance data
107    """
108
109    @property
110    def form_fields(self):
[9248]111        if self.context.is_postgrad:
[8862]112            form_fields = grok.AutoFields(
[8863]113                INigeriaPGStudentClearance).omit('clearance_locked')
[8862]114        else:
115            form_fields = grok.AutoFields(
[8863]116                INigeriaUGStudentClearance).omit('clearance_locked')
[9535]117        if not getattr(self.context, 'officer_comment'):
118            form_fields = form_fields.omit('officer_comment')
119        else:
120            form_fields['officer_comment'].custom_widget = BytesDisplayWidget
[8862]121        return form_fields
122
[13058]123class NigeriaExportPDFClearanceSlip(ExportPDFClearanceSlip):
[8862]124    """Deliver a PDF slip of the context.
125    """
[9704]126    omit_fields = ('password', 'suspended', 'suspended_comment',
[13712]127        'phone', 'adm_code', 'email', 'date_of_birth', 'current_level',
128        'flash_notice')
[8862]129
130    @property
131    def form_fields(self):
[9248]132        if self.context.is_postgrad:
[8862]133            form_fields = grok.AutoFields(
[8863]134                INigeriaPGStudentClearance).omit('clearance_locked')
[8862]135        else:
136            form_fields = grok.AutoFields(
[8863]137                INigeriaUGStudentClearance).omit('clearance_locked')
[9535]138        if not getattr(self.context, 'officer_comment'):
139            form_fields = form_fields.omit('officer_comment')
[8862]140        return form_fields
141
[8863]142class NigeriaStudentClearanceManageFormPage(StudentClearanceManageFormPage):
[8862]143    """ Page to edit student clearance data
144    """
145
146    @property
147    def form_fields(self):
[9248]148        if self.context.is_postgrad:
[9249]149            form_fields = grok.AutoFields(
150                INigeriaPGStudentClearance).omit('clr_code')
[8862]151        else:
[9249]152            form_fields = grok.AutoFields(
153                INigeriaUGStudentClearance).omit('clr_code')
[8862]154        return form_fields
155
[8863]156class NigeriaStudentClearanceEditFormPage(StudentClearanceEditFormPage):
[8862]157    """ View to edit student clearance data by student
158    """
159
160    @property
161    def form_fields(self):
[9248]162        if self.context.is_postgrad:
[8946]163            form_fields = grok.AutoFields(INigeriaPGStudentClearance).omit(
[12107]164            'clearance_locked', 'nysc_location', 'clr_code', 'officer_comment',
[12120]165            'physical_clearance_date')
[8862]166        else:
[8946]167            form_fields = grok.AutoFields(INigeriaUGStudentClearance).omit(
[12107]168            'clearance_locked', 'clr_code', 'officer_comment',
[12120]169            'physical_clearance_date')
[8862]170        return form_fields
171
[13058]172class NigeriaExportPDFCourseRegistrationSlip(ExportPDFCourseRegistrationSlip):
[9376]173    """Deliver a PDF slip of the context.
174    """
[9704]175    omit_fields = ('password', 'suspended', 'suspended_comment',
[13712]176        'phone', 'adm_code', 'sex', 'email', 'date_of_birth', 'current_level',
177        'flash_notice')
[9376]178
[8863]179class NigeriaOnlinePaymentDisplayFormPage(OnlinePaymentDisplayFormPage):
[8862]180    """ Page to view an online payment ticket
181    """
[8863]182    grok.context(INigeriaStudentOnlinePayment)
[9774]183    form_fields = grok.AutoFields(INigeriaStudentOnlinePayment).omit(
[9985]184        'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item')
[8862]185    form_fields[
186        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
187    form_fields[
188        'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
189
[8863]190class NigeriaOnlinePaymentAddFormPage(OnlinePaymentAddFormPage):
[8862]191    """ Page to add an online payment ticket
192    """
[8863]193    form_fields = grok.AutoFields(INigeriaStudentOnlinePayment).select(
[8862]194        'p_category')
195
[13058]196class NigeriaOnlinePaymentFakeApproveView(OnlinePaymentFakeApproveView):
[8862]197    """ Disable payment approval view for students.
198
199    This view is used for browser tests only and
200    has to be neutralized here!
201    """
202    grok.name('fake_approve')
203    grok.require('waeup.managePortal')
204
205    def update(self):
206        return
207
[13058]208class NigeriaExportPDFPaymentSlip(ExportPDFPaymentSlip):
[8862]209    """Deliver a PDF slip of the context.
210    """
[8863]211    grok.context(INigeriaStudentOnlinePayment)
[9774]212    form_fields = grok.AutoFields(INigeriaStudentOnlinePayment).omit(
[9985]213        'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item')
[8862]214    form_fields['creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
215    form_fields['payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
[9704]216    omit_fields = ('password', 'suspended', 'suspended_comment', 'phone',
[13712]217        'adm_code', 'sex', 'email', 'date_of_birth', 'current_level',
218        'flash_notice')
[8862]219
[13458]220class NigeriaAccommodationManageFormPage(AccommodationManageFormPage):
221    """ Page to manage bed tickets.
222    This manage form page is for both students and students officers.
223    """
224    with_hostel_selection = False
225
[13058]226class NigeriaExportPDFBedTicketSlip(ExportPDFBedTicketSlip):
[9376]227    """Deliver a PDF slip of the context.
228    """
[9704]229    omit_fields = ('password', 'suspended', 'suspended_comment',
[13712]230        'phone', 'adm_code', 'email', 'date_of_birth', 'current_level',
231        'flash_notice')
[9376]232
[8862]233class StudentPassportActionButton(StudentPassportActionButton):
234
235    @property
236    def target_url(self):
[10707]237        # Passport pictures must not be editable if application slip
238        # exists.
[8862]239        slip = getUtility(IExtFileStore).getFileByContext(
240            self.context, 'application_slip')
[13130]241        PORTRAIT_CHANGE_STATES = getUtility(IStudentsUtils).PORTRAIT_CHANGE_STATES
242        if self.context.state not in PORTRAIT_CHANGE_STATES or slip is not None:
[8862]243            return ''
244        return self.view.url(self.view.context, self.target)
245
[8863]246class NigeriaStudentFilesUploadPage(StudentFilesUploadPage):
[8862]247    """ View to upload passport picture.
248
249    Students are not allowed to change the picture if they
250    passed the regular Kofa application.
251    """
252
253    def update(self):
[10707]254        # Passport pictures must not be editable if application slip
255        # exists.
[8862]256        slip = getUtility(IExtFileStore).getFileByContext(
257            self.context, 'application_slip')
[13130]258        PORTRAIT_CHANGE_STATES = getUtility(IStudentsUtils).PORTRAIT_CHANGE_STATES
259        if self.context.state not in PORTRAIT_CHANGE_STATES or slip is not None:
[8862]260            emit_lock_message(self)
261            return
262        super(StudentFilesUploadPage, self).update()
[13620]263        return
264
265class ClearStudentFinancially(UtilityView, grok.View):
[13634]266    """ Clear student financially by financial clearance officer
[13620]267    """
268    grok.context(INigeriaStudent)
269    grok.name('clear_financially')
270    grok.require('waeup.clearStudentFinancially')
271
272    def update(self):
273        if self.context.financially_cleared_by:
274            self.flash(_('This student has already been financially cleared.'),
275                       type="danger")
276            self.redirect(self.url(self.context))
277            return
278        user = get_current_principal()
279        if user is None:
280            usertitle = 'system'
281        else:
282            usertitle = getattr(user, 'public_name', None)
283            if not usertitle:
284                usertitle = user.title
285        self.context.financially_cleared_by = usertitle
286        self.context.financial_clearance_date = datetime.utcnow()
287        self.context.writeLogMessage(self,'financially cleared')
288        history = IObjectHistory(self.context)
289        history.addMessage('Financially cleared')
290        self.flash(_('Student has been financially cleared.'))
291        self.redirect(self.url(self.context))
292        return
293
294    def render(self):
295        return
296
297class WithdrawFinancialClearance(UtilityView, grok.View):
[13634]298    """ Withdraw financial clearance by financial clearance officer
[13620]299    """
300    grok.context(INigeriaStudent)
301    grok.name('withdraw_financial_clearance')
302    grok.require('waeup.clearStudentFinancially')
303
304    def update(self):
305        if not self.context.financially_cleared_by:
306            self.flash(_('This student has not yet been financially cleared.'),
307                       type="danger")
308            self.redirect(self.url(self.context))
309            return
310        self.context.financially_cleared_by = None
311        self.context.financial_clearance_date = None
312        self.context.writeLogMessage(self,'financial clearance withdrawn')
313        history = IObjectHistory(self.context)
314        history.addMessage('Financial clearance withdrawn')
315        self.flash(_('Financial clearance withdrawn.'))
316        self.redirect(self.url(self.context))
317        return
318
319    def render(self):
[13623]320        return
321
322cleared_note = """
323<br /><br /><br />
324<strong>Financially cleared on %s by %s.</strong>
325
326"""
327
[13634]328class NigeriaExportPDFFinancialClearancePage(UtilityView, grok.View):
329    """Deliver a PDF financial clearance slip.
[13623]330    """
331    grok.context(INigeriaStudent)
[13781]332    grok.name('fee_payment_history.pdf')
[13623]333    grok.require('waeup.viewStudent')
334    prefix = 'form'
335
336    omit_fields = (
337        'suspended', 'phone',
338        'adm_code', 'suspended_comment',
[13712]339        'date_of_birth', 'current_level',
340        'flash_notice')
[13623]341
342    form_fields = None
343
344    @property
345    def label(self):
346        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
[13787]347        return translate(_('Fee Payment History for'),
[13623]348            'waeup.kofa', target_language=portal_language) \
349            + ' %s' % self.context.display_fullname
350
351    def _sigsInFooter(self):
352
353        isStudent = getattr(
354            self.request.principal, 'user_type', None) == 'student'
355        if isStudent:
356            return ()
[13642]357        return (_('Date, Checking Officer Signature'),
358                _('Date, Approving Officer Signature'),
[13623]359                )
360
361    @property
362    def note(self):
363        if self.context.financially_cleared_by:
364            tz = getUtility(IKofaUtils).tzinfo
365            try:
366                timestamp = to_timezone(
367                    self.context.financial_clearance_date, tz).strftime(
368                        "%Y-%m-%d %H:%M:%S")
369            except ValueError:
[13760]370                return
[13623]371            return cleared_note % (
372                timestamp, self.context.financially_cleared_by)
[13760]373        return
[13623]374
375    @property
376    def tabletitle(self):
377        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
378        tabletitle = []
379        tabletitle.append(translate(_('Successful Payments'), 'waeup.kofa',
380            target_language=portal_language))
381        return tabletitle
382
383    def render(self):
384        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
385        P_ID = translate(_('Payment Id'), 'waeup.kofa', target_language=portal_language)
386        #CD = translate(_('Creation Date'), 'waeup.kofa', target_language=portal_language)
387        PD = translate(_('Payment Date'), 'waeup.kofa', target_language=portal_language)
388        CAT = translate(_('Payment Category'), 'waeup.kofa', target_language=portal_language)
389        ITEM = translate(_('Payment Item'), 'waeup.kofa', target_language=portal_language)
390        AMT = translate(_('Amount (Naira)'), 'waeup.kofa', target_language=portal_language)
391        SSS = translate(_('Payment Session'), 'waeup.kofa', target_language=portal_language)
392        studentview = StudentBasePDFFormPage(self.context.student,
393            self.request, self.omit_fields)
394        students_utils = getUtility(IStudentsUtils)
395
396        tabledata = []
397        tableheader = []
398        tabledata.append(sorted(
399            [value for value in self.context['payments'].values()
[13634]400             if value.p_state == 'paid'], key=lambda value: value.p_session))
401        tableheader.append([(P_ID,'p_id', 4.2),
[13623]402                         #(CD,'creation_date', 3),
403                         (PD,'formatted_p_date', 3),
404                         (CAT,'category', 3),
405                         (ITEM, 'p_item', 3),
406                         (AMT, 'amount_auth', 2),
407                         (SSS, 'p_session', 2),
408                         ])
409        return students_utils.renderPDF(
[13634]410            self, 'financial_clearance_slip.pdf',
[13623]411            self.context.student, studentview,
412            tableheader=tableheader,
413            tabledata=tabledata,
414            signatures=None,
415            sigs_in_footer=self._sigsInFooter(),
416            omit_fields=self.omit_fields,
417            note=self.note
418            )
Note: See TracBrowser for help on using the repository browser.