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

Last change on this file since 14403 was 14279, checked in by Henrik Bettermann, 8 years ago

Add waived payments to fee_payment_history.pdf.

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