source: main/kofacustom.iuokada/trunk/src/kofacustom/iuokada/students/browser.py @ 16409

Last change on this file since 16409 was 16409, checked in by Henrik Bettermann, 4 years ago

Jite: Acceptance fee of 200k is a part of schoolfees.

Adjust flash message.

  • Property svn:keywords set to Id
File size: 23.5 KB
Line 
1## $Id: browser.py 16409 2021-03-06 21:29:49Z 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
19import os
20from zope.i18n import translate
21from zope.schema.interfaces import ConstraintNotSatisfied
22from zope.component import getUtility
23from zope.formlib.textwidgets import BytesDisplayWidget
24from hurry.workflow.interfaces import IWorkflowInfo
25from waeup.kofa.interfaces import (REQUESTED, ADMITTED, CLEARANCE,
26    IExtFileStore, IKofaUtils, academic_sessions_vocab)
27from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
28from waeup.kofa.browser.layout import (
29    action, jsaction, UtilityView, KofaEditFormPage)
30from waeup.kofa.students.browser import (
31    StudyLevelEditFormPage, StudyLevelDisplayFormPage,
32    StudentBasePDFFormPage, ExportPDFCourseRegistrationSlip,
33    CourseTicketDisplayFormPage, StudentTriggerTransitionFormPage,
34    StartClearancePage, BalancePaymentAddFormPage,
35    ExportPDFAdmissionSlip, ExportPDFPersonalDataSlip,
36    msave, emit_lock_message)
37from waeup.kofa.students.interfaces import (
38    IStudentsUtils, ICourseTicket, IStudent)
39from waeup.kofa.students.vocabularies import StudyLevelSource
40from waeup.kofa.students.workflow import FORBIDDEN_POSTGRAD_TRANS
41from kofacustom.nigeria.students.browser import (
42    NigeriaOnlinePaymentDisplayFormPage,
43    NigeriaStudentBaseDisplayFormPage,
44    NigeriaStudentBaseManageFormPage,
45    NigeriaStudentClearanceEditFormPage,
46    NigeriaOnlinePaymentAddFormPage,
47    NigeriaExportPDFPaymentSlip,
48    NigeriaExportPDFClearanceSlip,
49    NigeriaExportPDFCourseRegistrationSlip,
50    NigeriaStudentBaseEditFormPage,
51    NigeriaBedTicketAddPage,
52    NigeriaAccommodationManageFormPage,
53    NigeriaAccommodationDisplayFormPage,
54    NigeriaStudentPersonalManageFormPage,
55    NigeriaStudentPersonalEditFormPage,
56    NigeriaStudentPersonalDisplayFormPage
57    )
58from kofacustom.iuokada.students.interfaces import (
59    ICustomStudentOnlinePayment, ICustomStudentStudyCourse,
60    ICustomStudentStudyLevel, ICustomStudentBase, ICustomStudent,
61    ICustomStudentPersonal, ICustomStudentPersonalEdit)
62from kofacustom.iuokada.interfaces import MessageFactory as _
63
64class CustomStudentBaseDisplayFormPage(NigeriaStudentBaseDisplayFormPage):
65    """ Page to display student base data
66    """
67    form_fields = grok.AutoFields(ICustomStudentBase).omit(
68        'password', 'suspended', 'suspended_comment', 'flash_notice')
69
70class CustomStudentBaseManageFormPage(NigeriaStudentBaseManageFormPage):
71    """ View to manage student base data
72    """
73    form_fields = grok.AutoFields(ICustomStudentBase).omit(
74        'student_id', 'adm_code', 'suspended',
75        'financially_cleared_by', 'financial_clearance_date')
76
77class StudentBaseEditFormPage(NigeriaStudentBaseEditFormPage):
78    """ View to edit student base data
79    """
80    @property
81    def form_fields(self):
82        form_fields = grok.AutoFields(ICustomStudentBase).select(
83            'email', 'email2', 'parents_email', 'phone',)
84        if not self.context.state in (ADMITTED, CLEARANCE):
85            form_fields['parents_email'].for_display = True
86        return form_fields
87
88class CustomExportPDFCourseRegistrationSlip(
89    NigeriaExportPDFCourseRegistrationSlip):
90    """Deliver a PDF slip of the context.
91    """
92
93    def _signatures(self):
94        return (
95                ['Student Signature'],
96                ['HoD / Course Adviser Signature'],
97                ['College Officer Signature'],
98                ['Dean Signature']
99                )
100
101    #def _sigsInFooter(self):
102    #    return (_('Student'),
103    #            _('HoD / Course Adviser'),
104    #            _('College Officer'),
105    #            _('Dean'),
106    #            )
107    #    return ()
108
109class CustomStudentPersonalDisplayFormPage(NigeriaStudentPersonalDisplayFormPage):
110    """ Page to display student personal data
111    """
112    form_fields = grok.AutoFields(ICustomStudentPersonal)
113    form_fields['perm_address'].custom_widget = BytesDisplayWidget
114    form_fields['postal_address'].custom_widget = BytesDisplayWidget
115    form_fields['hostel_address'].custom_widget = BytesDisplayWidget
116    form_fields['father_address'].custom_widget = BytesDisplayWidget
117    form_fields['mother_address'].custom_widget = BytesDisplayWidget
118    form_fields['guardian_address'].custom_widget = BytesDisplayWidget
119    form_fields[
120        'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
121
122
123class CustomStudentPersonalEditFormPage(NigeriaStudentPersonalEditFormPage):
124    """ Page to edit personal data
125    """
126    form_fields = grok.AutoFields(ICustomStudentPersonalEdit).omit(
127        'personal_updated')
128
129    def update(self):
130        #if not self.context.is_fresh:
131        #    self.flash('Not allowed.', type="danger")
132        #    self.redirect(self.url(self.context))
133        #    return
134        if not self.context.minimumStudentPayments():
135            self.flash('Please make 40% of your tution fee payments first.',
136                       type="warning")
137            self.redirect(self.url(self.context, 'view_personal'))
138            return
139        super(CustomStudentPersonalEditFormPage, self).update()
140        return
141
142
143class CustomStudentPersonalManageFormPage(NigeriaStudentPersonalManageFormPage):
144    """ Page to manage personal data
145    """
146    form_fields = grok.AutoFields(ICustomStudentPersonal)
147    form_fields['personal_updated'].for_display = True
148    form_fields[
149        'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
150
151class CustomExportPDFPersonalDataSlip(ExportPDFPersonalDataSlip):
152    """Deliver a PDF base and personal data slip.
153    """
154    grok.name('course_registration_clearance.pdf')
155    omit_fields = (
156        'phone', 'email',
157        'suspended',
158        'adm_code', 'suspended_comment',
159        'current_level',
160        'flash_notice', 'entry_session',
161        'parents_email')
162
163    form_fields = grok.AutoFields(ICustomStudentPersonal)
164
165    def _signatures(self):
166        return ([('I certify that the above named student has satisfied the financial requirements for registration.', 'Name and Signature of Bursary Staff', '<br><br>')],
167                [('I certify that the credentials of the student have been screened by me and the student is hereby cleared.', 'Name and Signature of Registry Staff', '<br><br>')],
168                [('I certify that the above named student has registered with the Library.', 'Name and Signature of Library Staff', '<br><br>')],
169                [('I certify that the above named student has been registered with the college. ', 'Name and Signature of College Officer', '<br><br>')],
170                [('I certify that the above named student has completed his/her ICT registration. ', 'Name and Signature of ICT Staff', '<br><br>')],
171                [('Eligibility/Congratulation Station', 'Name and Signature of Registrar', '')],
172                )
173
174    @property
175    def tabletitle(self):
176        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
177        tabletitle = []
178        session = self.context.student.current_session
179        tabletitle.append('_PB_Successful %s/%s Session Payments' %(session, session+1))
180        return tabletitle
181
182    def render(self):
183        studentview = StudentBasePDFFormPage(self.context.student,
184            self.request, self.omit_fields)
185        students_utils = getUtility(IStudentsUtils)
186
187        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
188        P_ID = translate(_('Payment Id'), 'waeup.kofa', target_language=portal_language)
189        #CD = translate(_('Creation Date'), 'waeup.kofa', target_language=portal_language)
190        PD = translate(_('Payment Date'), 'waeup.kofa', target_language=portal_language)
191        CAT = translate(_('Payment Category'), 'waeup.kofa', target_language=portal_language)
192        ITEM = translate(_('Payment Item'), 'waeup.kofa', target_language=portal_language)
193        AMT = translate(_('Amount (Naira)'), 'waeup.kofa', target_language=portal_language)
194        SSS = translate(_('Payment Session'), 'waeup.kofa', target_language=portal_language)
195        tabledata = []
196        tableheader = []
197        tabledata.append(sorted(
198            [value for value in self.context['payments'].values()
199             if value.p_state in ('paid', 'waived', 'scholarship')
200             and value.p_session >= value.student.current_session],
201             key=lambda value: value.p_session))
202        tableheader.append([(P_ID,'p_id', 4.2),
203                         #(CD,'creation_date', 3),
204                         (PD,'formatted_p_date', 3),
205                         (CAT,'category', 3),
206                         (ITEM, 'p_item', 3),
207                         (AMT, 'amount_auth', 2),
208                         (SSS, 'p_session', 2),
209                         ])
210
211        #watermark_path = os.path.join(
212        #    os.path.dirname(__file__), 'static', 'watermark.pdf')
213        #watermark = open(watermark_path, 'rb')
214        #file_path = os.path.join(
215        #    os.path.dirname(__file__), 'static', 'biodataPage2.pdf')
216        #file = open(file_path, 'rb')
217        #mergefiles = [file,]
218
219        return students_utils.renderPDF(
220            self, 'course_registration_clearance.pdf',
221            self.context.student, studentview,
222            omit_fields=self.omit_fields,
223            signatures=self._signatures(),
224
225            tableheader=tableheader,
226            tabledata=tabledata,
227
228            pagebreak=True,
229        #    mergefiles=mergefiles,
230        #    watermark=watermark
231            )
232
233class CustomAccommodationDisplayFormPage(NigeriaAccommodationDisplayFormPage):
234    """ Page to view bed tickets.
235    """
236    with_hostel_selection = True
237
238class CustomAccommodationManageFormPage(NigeriaAccommodationManageFormPage):
239    """ Page to manage bed tickets.
240    This manage form page is for both students and students officers.
241    """
242    with_hostel_selection = True
243
244class CustomBedTicketAddPage(NigeriaBedTicketAddPage):
245    """ Page to add a bed ticket
246    """
247    with_ac = False
248    with_bedselection = True
249
250class StudentGetMatricNumberPage(UtilityView, grok.View):
251    """ Construct and set the matriculation number.
252    """
253    grok.context(IStudent)
254    grok.name('get_matric_number')
255    grok.require('waeup.manageStudent')
256
257    def update(self):
258        students_utils = getUtility(IStudentsUtils)
259        msg, mnumber = students_utils.setMatricNumber(self.context)
260        if msg:
261            self.flash(msg, type="danger")
262        else:
263            self.flash(_('Matriculation number %s assigned.' % mnumber))
264            self.context.writeLogMessage(self, '%s assigned' % mnumber)
265        self.redirect(self.url(self.context))
266        return
267
268    def render(self):
269        return
270
271class SwitchLibraryAccessView(UtilityView, grok.View):
272    """ Switch the library attribute
273    """
274    grok.context(ICustomStudent)
275    grok.name('switch_library_access')
276    grok.require('waeup.switchLibraryAccess')
277
278    def update(self):
279        if self.context.library:
280            self.context.library = False
281            self.context.writeLogMessage(self, 'library access disabled')
282            self.flash(_('Library access disabled'))
283        else:
284            self.context.library = True
285            self.context.writeLogMessage(self, 'library access enabled')
286            self.flash(_('Library access enabled'))
287        self.redirect(self.url(self.context))
288        return
289
290    def render(self):
291        return
292
293class ExportLibIdCard(UtilityView, grok.View):
294    """Deliver an id card for the library.
295    """
296    grok.context(ICustomStudent)
297    grok.name('lib_idcard.pdf')
298    grok.require('waeup.viewStudent')
299    prefix = 'form'
300
301    label = u"Library Clearance"
302
303    omit_fields = (
304        'suspended', 'email', 'phone',
305        'adm_code', 'suspended_comment',
306        'date_of_birth',
307        'current_mode', 'certificate',
308        'entry_session',
309        'flash_notice')
310
311    form_fields = []
312
313    def _sigsInFooter(self):
314        isStudent = getattr(
315            self.request.principal, 'user_type', None) == 'student'
316        if isStudent:
317            return ''
318        return (_("Date, Reader's Signature"),
319                _("Date, Circulation Librarian's Signature"),
320                )
321
322    def update(self):
323        if not self.context.library:
324            self.flash(_('Forbidden!'), type="danger")
325            self.redirect(self.url(self.context))
326        return
327
328    @property
329    def note(self):
330        return """
331<br /><br /><br /><br /><font size='12'>
332This is to certify that the bearer whose photograph and other details appear
333 overleaf is a registered user of the <b>University Library</b>.
334 The card is not transferable. A replacement fee is charged for a loss,
335 mutilation or otherwise. If found, please, return to the University Library,
336 Igbinedion University, Okada.
337</font>
338
339"""
340        return
341
342    def render(self):
343        studentview = StudentBasePDFFormPage(self.context.student,
344            self.request, self.omit_fields)
345        students_utils = getUtility(IStudentsUtils)
346        return students_utils.renderPDF(
347            self, 'lib_idcard',
348            self.context.student, studentview,
349            omit_fields=self.omit_fields,
350            sigs_in_footer=self._sigsInFooter(),
351            note=self.note)
352
353class CustomStartClearancePage(StartClearancePage):
354    with_ac = False
355
356class CustomBalancePaymentAddFormPage(BalancePaymentAddFormPage):
357    grok.require('waeup.payStudent')
358
359class CustomExportPDFAdmissionSlip(ExportPDFAdmissionSlip):
360    """Deliver a PDF Admission slip.
361    """
362
363    omit_fields = ('date_of_birth',
364                   #'current_level',
365                   'current_mode',
366                   #'entry_session'
367                   )
368
369    @property
370    def session(self):
371        return academic_sessions_vocab.getTerm(
372            self.context.entry_session).title
373
374    @property
375    def level(self):
376        studylevelsource = StudyLevelSource()
377        return studylevelsource.factory.getTitle(
378            self.context['studycourse'].certificate, self.context.current_level)
379
380    @property
381    def label(self):
382        return 'OFFER OF PROVISIONAL ADMISSION \nFOR %s SESSION' % self.session
383
384    @property
385    def pre_text_ug(self):
386        return (
387            'Following your performance in the screening exercise '
388            'for the %s academic session, I am pleased to inform '
389            'you that you have been offered provisional admission into the '
390            'Igbinedion University, Okada as follows:' % self.session)
391
392    @property
393    def pre_text_pg(self):
394        return (
395            'I am pleased to inform you that your application for admission'
396            ' into the Igbinedion University, Okada was successful. You have'
397            ' been admitted as follows:')
398
399    @property
400    def post_text_ug(self):
401        return """
402Please note that at the point of registration for your programme of study (course), you will be required to present the following documents: Current UTME result slip, WAEC/NECO (0' Level) result, Birth certificate or sworn affidavit of age, and health certificate from a recognized Medical Centre.
403
404All credentials (original) will be checked during registration. This admission will be cancelled at any point in time it is found that your claims in the application form are false.
405
406You are required to show evidence of the result / credentials you presented on application for admission.
407
408Fees can be paid using any of the following options:
409
410Fees can be paid through your portal page. INSTRUCTIONS can be found below "FEES PAYMENT PROCEDURE" for the options you have to make your payment, as well as instructions on how to use your preferred payment option. If you choose to use the bank payment option, you can pay at any branch of the following banks through Etranzact platform only: Access Bank, First Bank, Zenith Bank
411
412Kindly note the following:
413
414Fees indicated on the Fee Structure page are valid for the current session only.
415Your Student Id (indicated above) Is your logln to the University portal.
416As an indication of your acceptance of this offer of admission, you should pay a non-refundable Acceptance deposit of 200,000. Further note that the 200,000 deposit is part of the tuition fee for the session. Failure to pay after the expiration of two weeks may lead to forfeiture of admission.
417All fees must be paid in full at the beginning of the session, as basis for accommodation, registration and attendance of lectures. This is the rule for all students at all levels. Install mental payments of not more than two installments, may be allowed under exceptional circumstances.
418Fees once paid are not refundable.
419It is advisable that you keep the original receipts of fees paid and present them on demand.
420
421Accommodation: Accommodation in University hostels is compulsory for every student. No student Is allowed to live outside the hostels. Any student who does so will be expelled from the University.
422
423Food: Food is available in cafeteria on "pay-as-you-eat" basis.
424
425Resumption Date: The University opens for fresh students with online registration starting from Monday 28th September, 2020. The date for physical resumption is 14th November, 2020.
426
427Registration/Orientation Programme: Orientation programme/registration for fresh students will start on Monday, 16th November 2020. Registration ends on 2020-11-30. A late registration fee of N50,000 will be charged after this date. All credentials, O'Level Results, Birth Certificate/Age Declaration, UTME Result Slip (Original) will be checked during registration. This admission will be cancelled at any point in time it is found that any of your claims in the application form is false.
428
429Transport Facility: The University provides a compulsory shuttle bus service to all students at a fee already included in the other charges.
430
431Kindly note that fresh students are not allowed the use of private vehicles.
432
433Conduct: All students are expected to conduct themselves properly and dress decently on campus, as well as obey all rules and regulations as failure to comply will attract appropriate sanctions.
434
435We wish you a successful academic career in Igbinedion University.
436
437Congratulations!
438
439
440
441<img src="${signature_benji_img_path}" valign="-20" height="38" width="86" />
442
443Friday Benji Bakare Esq.
444Registrar
445registrar@iuokada.edu.ng
44608035902949
447"""
448
449    @property
450    def post_text_pg(self):
451        return """
4521. Details of your programme will be made available to you by the Head of your Department on your arrival at the Igbinedion University.
453
4542. This offer is conditional upon the confirmation of your qualifications as listed by you in your application form. You will be required to produce the ORIGINAL COPIES of all your certificates for verification during registration. If at any time after admission, it is discovered that you do not possess any of the qualifications upon which this offer of admission was made, you will be required to withdraw from the University.
455
4563. If you accept this offer of admission upon the conditions above, you should please:
457
458(a) Complete the enclosed Acceptance Form of Provisional Offer of Admission in duplicate and send  by registered mail or by hand to the
459
460Secretary
461School of Postgraduate Studies and Research
462Igbinedion University,
463P.M.B. 0006,
464Benin City, Edo State,
465Nigeria
466
467(b)     Forward the following along with the Acceptance Form of Provisional Offer of Admission.
468
469(i) A non-refundable deposit of N100,000.00 (One Hundred Thousand Naira Only) which is part of the School fees: Payable Online.
470
471(ii) Four recent passport-size photograph of yourself with your full-names (surname first in BLOCK LETTERS) written on the reverse side of the photograph and pinned to the Acceptance Form.
472
4734. The following will be required for Registration:
474
475(a) A medical examination to be conducted by an approved medical practitioner. On your arrival at the Igbinedion University, you should submit the enclosed Igbinedion University Medical Examination Form duly completed and signed by an approved medical practitioner together with your chest X-ray film to Director of Health Service at the Igbinedion University, Okada.
476
477(b) The original copies of all credentials listed in your application form (including NYSC discharge/exemption certificate) should be brought for sighting.
478
4795. You are required to pay the necessary fees and register for your degree programme not later than three weeks from the beginning of the Academic Session. Late registration may be allowed during an additional period of five weeks on payment of a late registration fees. Please note that you will be allowed to register after two months have elapsed from the beginning of the sessions.
480
4816. Please find attached:
482
483(a) A copy of School fees Regime
484(b) A copy of Acceptance Forms
485
4867. Note:
487
488(a) All Tuition fees are to be paid online
489(b) Post-graduate dues and other charges are to be paid into ABC Microfinance Bank Okada, Account No: 30125
490
4918.  CONGRATULATIONS!!!
492
493Yours faithfully,
494
495<img src="${signature_olaoke_img_path}" valign="-20" height="38" width="86" />
496
497Mr. Olaoke, Olasoji Oluwole
498Secretary, School of Postgraduate Studies & Research
499"""
500
501    def render(self):
502        students_utils = getUtility(IStudentsUtils)
503        watermark_path = os.path.join(
504            os.path.dirname(__file__), 'static', 'watermark.pdf')
505        watermark = open(watermark_path, 'rb')
506        if self.context.is_postgrad:
507            file_path = os.path.join(
508                os.path.dirname(__file__), 'static', 'admission_letter_pg.pdf')
509            file = open(file_path, 'rb')
510            mergefiles = [file,]
511            return students_utils.renderPDFAdmissionLetter(self,
512                self.context.student, omit_fields=self.omit_fields,
513                pre_text=self.pre_text_pg, post_text=self.post_text_pg,
514                mergefiles=mergefiles,
515                watermark=watermark)
516        file_path = os.path.join(
517            os.path.dirname(__file__), 'static', 'admission_letter_ug.pdf')
518        file = open(file_path, 'rb')
519        mergefiles = [file,]
520        return students_utils.renderPDFAdmissionLetter(self,
521            self.context.student, omit_fields=self.omit_fields,
522            pre_text=self.pre_text_ug, post_text=self.post_text_ug,
523            mergefiles=mergefiles,
524            watermark=watermark)
525
526class CustomOnlinePaymentDisplayFormPage(NigeriaOnlinePaymentDisplayFormPage):
527    """ Page to view an online payment ticket. We do not omit provider_amt.
528    """
529    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
530        'gateway_amt', 'thirdparty_amt', 'p_item','p_combi', 'provider_amt')
531    form_fields[
532        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
533    form_fields[
534        'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
535
536class CustomExportPDFPaymentSlip(NigeriaExportPDFPaymentSlip):
537    """Deliver a PDF slip of the context. We do not omit provider_amt.
538    """
539    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
540        'gateway_amt', 'thirdparty_amt', 'p_item',
541        'p_split_data','p_combi', 'provider_amt')
542    form_fields['creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
543    form_fields['payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
Note: See TracBrowser for help on using the repository browser.