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

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

Rename bursary.

  • Property svn:keywords set to Id
File size: 16.2 KB
Line 
1## $Id: browser.py 13634 2016-01-18 17:22:05Z 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
22from datetime import datetime
23from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
24from waeup.kofa.interfaces import IExtFileStore, IObjectHistory, IKofaUtils
25from waeup.kofa.browser.layout import action, UtilityView
26from waeup.kofa.utils.helpers import get_current_principal, to_timezone
27from waeup.kofa.students.browser import (
28    StudentPersonalDisplayFormPage, StudentPersonalManageFormPage,
29    StudentClearanceManageFormPage, StudentClearanceEditFormPage,
30    StudentClearanceDisplayFormPage, OnlinePaymentFakeApproveView,
31    ExportPDFClearanceSlip, StudentBaseManageFormPage,
32    StudentBaseDisplayFormPage,
33    StudentBasePDFFormPage,
34    StudentBaseEditFormPage, StudentPersonalEditFormPage,
35    OnlinePaymentDisplayFormPage, OnlinePaymentAddFormPage,
36    OnlinePaymentBreadcrumb, ExportPDFPaymentSlip,
37    ExportPDFCourseRegistrationSlip,
38    ExportPDFBedTicketSlip,
39    StudentFilesUploadPage, emit_lock_message,
40    AccommodationManageFormPage)
41from waeup.kofa.students.interfaces import IStudentsUtils
42from waeup.kofa.students.viewlets import (
43    PaymentReceiptActionButton, StudentPassportActionButton)
44from kofacustom.nigeria.students.interfaces import (
45    INigeriaStudentBase, INigeriaStudent, INigeriaStudentPersonal,
46    INigeriaStudentPersonalEdit,
47    INigeriaUGStudentClearance,INigeriaPGStudentClearance,
48    INigeriaStudentOnlinePayment
49    )
50from waeup.kofa.students.workflow import ADMITTED
51from kofacustom.nigeria.interfaces import MessageFactory as _
52
53class NigeriaOnlinePaymentBreadcrumb(OnlinePaymentBreadcrumb):
54    """A breadcrumb for payments.
55    """
56    grok.context(INigeriaStudentOnlinePayment)
57
58class PaymentReceiptActionButton(PaymentReceiptActionButton):
59    grok.order(4)
60    grok.context(INigeriaStudentOnlinePayment)
61
62class NigeriaStudentBaseDisplayFormPage(StudentBaseDisplayFormPage):
63    """ Page to display student base data
64    """
65    form_fields = grok.AutoFields(INigeriaStudentBase).omit(
66        'password', 'suspended', 'suspended_comment')
67    form_fields[
68        'financial_clearance_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
69
70class NigeriaStudentBaseManageFormPage(StudentBaseManageFormPage):
71    """ View to manage student base data
72    """
73    form_fields = grok.AutoFields(INigeriaStudentBase).omit(
74        'student_id', 'adm_code', 'suspended',
75        'financially_cleared_by', 'financial_clearance_date')
76
77class NigeriaStudentBaseEditFormPage(StudentBaseEditFormPage):
78    """ View to edit student base data
79    """
80    form_fields = grok.AutoFields(INigeriaStudentBase).select(
81        'email', 'phone')
82
83class NigeriaStudentPersonalDisplayFormPage(StudentPersonalDisplayFormPage):
84    """ Page to display student personal data
85    """
86    form_fields = grok.AutoFields(INigeriaStudentPersonal)
87    form_fields['perm_address'].custom_widget = BytesDisplayWidget
88    form_fields['next_kin_address'].custom_widget = BytesDisplayWidget
89    form_fields[
90        'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
91
92class NigeriaStudentPersonalEditFormPage(StudentPersonalEditFormPage):
93    """ Page to edit personal data
94    """
95    form_fields = grok.AutoFields(INigeriaStudentPersonalEdit).omit('personal_updated')
96
97class NigeriaStudentPersonalManageFormPage(StudentPersonalManageFormPage):
98    """ Page to edit personal data
99    """
100    form_fields = grok.AutoFields(INigeriaStudentPersonal)
101    form_fields['personal_updated'].for_display = True
102    form_fields[
103        'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
104
105class NigeriaStudentClearanceDisplayFormPage(StudentClearanceDisplayFormPage):
106    """ Page to display student clearance data
107    """
108
109    @property
110    def form_fields(self):
111        if self.context.is_postgrad:
112            form_fields = grok.AutoFields(
113                INigeriaPGStudentClearance).omit('clearance_locked')
114        else:
115            form_fields = grok.AutoFields(
116                INigeriaUGStudentClearance).omit('clearance_locked')
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
121        return form_fields
122
123class NigeriaExportPDFClearanceSlip(ExportPDFClearanceSlip):
124    """Deliver a PDF slip of the context.
125    """
126    omit_fields = ('password', 'suspended', 'suspended_comment',
127        'phone', 'adm_code', 'email', 'date_of_birth', 'current_level')
128
129    @property
130    def form_fields(self):
131        if self.context.is_postgrad:
132            form_fields = grok.AutoFields(
133                INigeriaPGStudentClearance).omit('clearance_locked')
134        else:
135            form_fields = grok.AutoFields(
136                INigeriaUGStudentClearance).omit('clearance_locked')
137        if not getattr(self.context, 'officer_comment'):
138            form_fields = form_fields.omit('officer_comment')
139        return form_fields
140
141class NigeriaStudentClearanceManageFormPage(StudentClearanceManageFormPage):
142    """ Page to edit student clearance data
143    """
144
145    @property
146    def form_fields(self):
147        if self.context.is_postgrad:
148            form_fields = grok.AutoFields(
149                INigeriaPGStudentClearance).omit('clr_code')
150        else:
151            form_fields = grok.AutoFields(
152                INigeriaUGStudentClearance).omit('clr_code')
153        return form_fields
154
155class NigeriaStudentClearanceEditFormPage(StudentClearanceEditFormPage):
156    """ View to edit student clearance data by student
157    """
158
159    @property
160    def form_fields(self):
161        if self.context.is_postgrad:
162            form_fields = grok.AutoFields(INigeriaPGStudentClearance).omit(
163            'clearance_locked', 'nysc_location', 'clr_code', 'officer_comment',
164            'physical_clearance_date')
165        else:
166            form_fields = grok.AutoFields(INigeriaUGStudentClearance).omit(
167            'clearance_locked', 'clr_code', 'officer_comment',
168            'physical_clearance_date')
169        return form_fields
170
171class NigeriaExportPDFCourseRegistrationSlip(ExportPDFCourseRegistrationSlip):
172    """Deliver a PDF slip of the context.
173    """
174    omit_fields = ('password', 'suspended', 'suspended_comment',
175        'phone', 'adm_code', 'sex', 'email', 'date_of_birth', 'current_level')
176
177class NigeriaOnlinePaymentDisplayFormPage(OnlinePaymentDisplayFormPage):
178    """ Page to view an online payment ticket
179    """
180    grok.context(INigeriaStudentOnlinePayment)
181    form_fields = grok.AutoFields(INigeriaStudentOnlinePayment).omit(
182        'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item')
183    form_fields[
184        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
185    form_fields[
186        'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
187
188class NigeriaOnlinePaymentAddFormPage(OnlinePaymentAddFormPage):
189    """ Page to add an online payment ticket
190    """
191    form_fields = grok.AutoFields(INigeriaStudentOnlinePayment).select(
192        'p_category')
193
194class NigeriaOnlinePaymentFakeApproveView(OnlinePaymentFakeApproveView):
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
206class NigeriaExportPDFPaymentSlip(ExportPDFPaymentSlip):
207    """Deliver a PDF slip of the context.
208    """
209    grok.context(INigeriaStudentOnlinePayment)
210    form_fields = grok.AutoFields(INigeriaStudentOnlinePayment).omit(
211        'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item')
212    form_fields['creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
213    form_fields['payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
214    omit_fields = ('password', 'suspended', 'suspended_comment', 'phone',
215        'adm_code', 'sex', 'email', 'date_of_birth', 'current_level')
216
217class NigeriaAccommodationManageFormPage(AccommodationManageFormPage):
218    """ Page to manage bed tickets.
219    This manage form page is for both students and students officers.
220    """
221    with_hostel_selection = False
222
223class NigeriaExportPDFBedTicketSlip(ExportPDFBedTicketSlip):
224    """Deliver a PDF slip of the context.
225    """
226    omit_fields = ('password', 'suspended', 'suspended_comment',
227        'phone', 'adm_code', 'email', 'date_of_birth', 'current_level')
228
229class StudentPassportActionButton(StudentPassportActionButton):
230
231    @property
232    def target_url(self):
233        # Passport pictures must not be editable if application slip
234        # exists.
235        slip = getUtility(IExtFileStore).getFileByContext(
236            self.context, 'application_slip')
237        PORTRAIT_CHANGE_STATES = getUtility(IStudentsUtils).PORTRAIT_CHANGE_STATES
238        if self.context.state not in PORTRAIT_CHANGE_STATES or slip is not None:
239            return ''
240        return self.view.url(self.view.context, self.target)
241
242class NigeriaStudentFilesUploadPage(StudentFilesUploadPage):
243    """ View to upload passport picture.
244
245    Students are not allowed to change the picture if they
246    passed the regular Kofa application.
247    """
248
249    def update(self):
250        # Passport pictures must not be editable if application slip
251        # exists.
252        slip = getUtility(IExtFileStore).getFileByContext(
253            self.context, 'application_slip')
254        PORTRAIT_CHANGE_STATES = getUtility(IStudentsUtils).PORTRAIT_CHANGE_STATES
255        if self.context.state not in PORTRAIT_CHANGE_STATES or slip is not None:
256            emit_lock_message(self)
257            return
258        super(StudentFilesUploadPage, self).update()
259        return
260
261class ClearStudentFinancially(UtilityView, grok.View):
262    """ Clear student financially by financial clearance officer
263    """
264    grok.context(INigeriaStudent)
265    grok.name('clear_financially')
266    grok.require('waeup.clearStudentFinancially')
267
268    def update(self):
269        if self.context.financially_cleared_by:
270            self.flash(_('This student has already been financially cleared.'),
271                       type="danger")
272            self.redirect(self.url(self.context))
273            return
274        user = get_current_principal()
275        if user is None:
276            usertitle = 'system'
277        else:
278            usertitle = getattr(user, 'public_name', None)
279            if not usertitle:
280                usertitle = user.title
281        self.context.financially_cleared_by = usertitle
282        self.context.financial_clearance_date = datetime.utcnow()
283        self.context.writeLogMessage(self,'financially cleared')
284        history = IObjectHistory(self.context)
285        history.addMessage('Financially cleared')
286        self.flash(_('Student has been financially cleared.'))
287        self.redirect(self.url(self.context))
288        return
289
290    def render(self):
291        return
292
293class WithdrawFinancialClearance(UtilityView, grok.View):
294    """ Withdraw financial clearance by financial clearance officer
295    """
296    grok.context(INigeriaStudent)
297    grok.name('withdraw_financial_clearance')
298    grok.require('waeup.clearStudentFinancially')
299
300    def update(self):
301        if not self.context.financially_cleared_by:
302            self.flash(_('This student has not yet been financially cleared.'),
303                       type="danger")
304            self.redirect(self.url(self.context))
305            return
306        self.context.financially_cleared_by = None
307        self.context.financial_clearance_date = None
308        self.context.writeLogMessage(self,'financial clearance withdrawn')
309        history = IObjectHistory(self.context)
310        history.addMessage('Financial clearance withdrawn')
311        self.flash(_('Financial clearance withdrawn.'))
312        self.redirect(self.url(self.context))
313        return
314
315    def render(self):
316        return
317
318cleared_note = """
319<br /><br /><br />
320<strong>Financially cleared on %s by %s.</strong>
321
322"""
323
324not_cleared_note = """
325<br /><br /><br />
326<strong>Not yet financially cleared.</strong>
327
328"""
329
330class NigeriaExportPDFFinancialClearancePage(UtilityView, grok.View):
331    """Deliver a PDF financial clearance slip.
332    """
333    grok.context(INigeriaStudent)
334    grok.name('financial_clearance_slip.pdf')
335    grok.require('waeup.viewStudent')
336    prefix = 'form'
337
338    omit_fields = (
339        'suspended', 'phone',
340        'adm_code', 'suspended_comment',
341        'date_of_birth', 'current_level')
342
343    form_fields = None
344
345    @property
346    def label(self):
347        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
348        return translate(_('Financial Clearance Slip of'),
349            'waeup.kofa', target_language=portal_language) \
350            + ' %s' % self.context.display_fullname
351
352    def _sigsInFooter(self):
353
354        isStudent = getattr(
355            self.request.principal, 'user_type', None) == 'student'
356        if isStudent:
357            return ()
358        return (_('Date, Student Signature'),
359                _('Date, Financial Clearance Officer Signature'),
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:
371                return not_cleared_note
372            return cleared_note % (
373                timestamp, self.context.financially_cleared_by)
374        return not_cleared_note
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()
401             if value.p_state == 'paid'], key=lambda value: value.p_session))
402        tableheader.append([(P_ID,'p_id', 4.2),
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(
411            self, 'financial_clearance_slip.pdf',
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.