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

Last change on this file since 16189 was 15974, checked in by Henrik Bettermann, 5 years ago

Do not allow to submit forms to other companies than payment.r_company.

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