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

Last change on this file since 17238 was 17141, checked in by Henrik Bettermann, 2 years ago

NigeriaStudentFilesUploadPage? replace StudentFilesUploadPage? completely.

  • Property svn:keywords set to Id
File size: 16.1 KB
RevLine 
[8862]1## $Id: browser.py 17141 2022-10-26 09:36:00Z 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
[13620]266        return
267
268class ClearStudentFinancially(UtilityView, grok.View):
[13634]269    """ Clear student financially by financial clearance officer
[13620]270    """
271    grok.context(INigeriaStudent)
272    grok.name('clear_financially')
273    grok.require('waeup.clearStudentFinancially')
274
275    def update(self):
276        if self.context.financially_cleared_by:
277            self.flash(_('This student has already been financially cleared.'),
278                       type="danger")
279            self.redirect(self.url(self.context))
280            return
281        user = get_current_principal()
282        if user is None:
283            usertitle = 'system'
284        else:
285            usertitle = getattr(user, 'public_name', None)
286            if not usertitle:
287                usertitle = user.title
288        self.context.financially_cleared_by = usertitle
289        self.context.financial_clearance_date = datetime.utcnow()
290        self.context.writeLogMessage(self,'financially cleared')
291        history = IObjectHistory(self.context)
292        history.addMessage('Financially cleared')
293        self.flash(_('Student has been financially cleared.'))
294        self.redirect(self.url(self.context))
295        return
296
297    def render(self):
298        return
299
300class WithdrawFinancialClearance(UtilityView, grok.View):
[13634]301    """ Withdraw financial clearance by financial clearance officer
[13620]302    """
303    grok.context(INigeriaStudent)
304    grok.name('withdraw_financial_clearance')
305    grok.require('waeup.clearStudentFinancially')
306
307    def update(self):
308        if not self.context.financially_cleared_by:
309            self.flash(_('This student has not yet been financially cleared.'),
310                       type="danger")
311            self.redirect(self.url(self.context))
312            return
313        self.context.financially_cleared_by = None
314        self.context.financial_clearance_date = None
315        self.context.writeLogMessage(self,'financial clearance withdrawn')
316        history = IObjectHistory(self.context)
317        history.addMessage('Financial clearance withdrawn')
318        self.flash(_('Financial clearance withdrawn.'))
319        self.redirect(self.url(self.context))
320        return
321
322    def render(self):
[13623]323        return
324
325cleared_note = """
326<br /><br /><br />
327<strong>Financially cleared on %s by %s.</strong>
328
329"""
330
[13634]331class NigeriaExportPDFFinancialClearancePage(UtilityView, grok.View):
332    """Deliver a PDF financial clearance slip.
[13623]333    """
334    grok.context(INigeriaStudent)
[13781]335    grok.name('fee_payment_history.pdf')
[13623]336    grok.require('waeup.viewStudent')
337    prefix = 'form'
338
339    omit_fields = (
340        'suspended', 'phone',
341        'adm_code', 'suspended_comment',
[13712]342        'date_of_birth', 'current_level',
343        'flash_notice')
[13623]344
345    form_fields = None
346
347    @property
348    def label(self):
349        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
[13787]350        return translate(_('Fee Payment History for'),
[13623]351            'waeup.kofa', target_language=portal_language) \
352            + ' %s' % self.context.display_fullname
353
354    def _sigsInFooter(self):
[14163]355        if not checkPermission('waeup.clearStudentFinancially', self.context):
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()
[15842]400             if value.p_state in ('paid', 'waived', 'scholarship')],
401             key=lambda value: value.p_session))
[13634]402        tableheader.append([(P_ID,'p_id', 4.2),
[13623]403                         #(CD,'creation_date', 3),
404                         (PD,'formatted_p_date', 3),
405                         (CAT,'category', 3),
406                         (ITEM, 'p_item', 3),
407                         (AMT, 'amount_auth', 2),
408                         (SSS, 'p_session', 2),
409                         ])
410        return students_utils.renderPDF(
[13634]411            self, 'financial_clearance_slip.pdf',
[13623]412            self.context.student, studentview,
413            tableheader=tableheader,
414            tabledata=tabledata,
415            signatures=None,
416            sigs_in_footer=self._sigsInFooter(),
417            omit_fields=self.omit_fields,
418            note=self.note
419            )
Note: See TracBrowser for help on using the repository browser.