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

Last change on this file since 16489 was 16489, checked in by Henrik Bettermann, 3 years ago

Add study_mode.

  • Property svn:keywords set to Id
File size: 24.3 KB
Line 
1## $Id: browser.py 16489 2021-05-21 06:52:16Z 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        if not self.context.minimumStudentPayments():
184            self.redirect(self.url(self.context))
185            return
186        studentview = StudentBasePDFFormPage(self.context.student,
187            self.request, self.omit_fields)
188        students_utils = getUtility(IStudentsUtils)
189
190        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
191        P_ID = translate(_('Payment Id'), 'waeup.kofa', target_language=portal_language)
192        #CD = translate(_('Creation Date'), 'waeup.kofa', target_language=portal_language)
193        PD = translate(_('Payment Date'), 'waeup.kofa', target_language=portal_language)
194        CAT = translate(_('Payment Category'), 'waeup.kofa', target_language=portal_language)
195        ITEM = translate(_('Payment Item'), 'waeup.kofa', target_language=portal_language)
196        AMT = translate(_('Amount (Naira)'), 'waeup.kofa', target_language=portal_language)
197        SSS = translate(_('Payment Session'), 'waeup.kofa', target_language=portal_language)
198        tabledata = []
199        tableheader = []
200        tabledata.append(sorted(
201            [value for value in self.context['payments'].values()
202             if value.p_state in ('paid', 'waived', 'scholarship')
203             and value.p_session >= value.student.current_session],
204             key=lambda value: value.p_session))
205        tableheader.append([(P_ID,'p_id', 4.2),
206                         #(CD,'creation_date', 3),
207                         (PD,'formatted_p_date', 3),
208                         (CAT,'category', 3),
209                         (ITEM, 'p_item', 3),
210                         (AMT, 'amount_auth', 2),
211                         (SSS, 'p_session', 2),
212                         ])
213
214        #watermark_path = os.path.join(
215        #    os.path.dirname(__file__), 'static', 'watermark.pdf')
216        #watermark = open(watermark_path, 'rb')
217        #file_path = os.path.join(
218        #    os.path.dirname(__file__), 'static', 'biodataPage2.pdf')
219        #file = open(file_path, 'rb')
220        #mergefiles = [file,]
221
222        return students_utils.renderPDF(
223            self, 'course_registration_clearance.pdf',
224            self.context.student, studentview,
225            omit_fields=self.omit_fields,
226            signatures=self._signatures(),
227
228            tableheader=tableheader,
229            tabledata=tabledata,
230
231            pagebreak=True,
232        #    mergefiles=mergefiles,
233        #    watermark=watermark
234            )
235
236class CustomAccommodationDisplayFormPage(NigeriaAccommodationDisplayFormPage):
237    """ Page to view bed tickets.
238    """
239    with_hostel_selection = True
240
241class CustomAccommodationManageFormPage(NigeriaAccommodationManageFormPage):
242    """ Page to manage bed tickets.
243    This manage form page is for both students and students officers.
244    """
245    with_hostel_selection = True
246
247class CustomBedTicketAddPage(NigeriaBedTicketAddPage):
248    """ Page to add a bed ticket
249    """
250    with_ac = False
251    with_bedselection = True
252
253class StudentGetMatricNumberPage(UtilityView, grok.View):
254    """ Construct and set the matriculation number.
255    """
256    grok.context(IStudent)
257    grok.name('get_matric_number')
258    grok.require('waeup.manageStudent')
259
260    def update(self):
261        students_utils = getUtility(IStudentsUtils)
262        msg, mnumber = students_utils.setMatricNumber(self.context)
263        if msg:
264            self.flash(msg, type="danger")
265        else:
266            self.flash(_('Matriculation number %s assigned.' % mnumber))
267            self.context.writeLogMessage(self, '%s assigned' % mnumber)
268        self.redirect(self.url(self.context))
269        return
270
271    def render(self):
272        return
273
274class SwitchLibraryAccessView(UtilityView, grok.View):
275    """ Switch the library attribute
276    """
277    grok.context(ICustomStudent)
278    grok.name('switch_library_access')
279    grok.require('waeup.switchLibraryAccess')
280
281    def update(self):
282        if self.context.library:
283            self.context.library = False
284            self.context.writeLogMessage(self, 'library access disabled')
285            self.flash(_('Library access disabled'))
286        else:
287            self.context.library = True
288            self.context.writeLogMessage(self, 'library access enabled')
289            self.flash(_('Library access enabled'))
290        self.redirect(self.url(self.context))
291        return
292
293    def render(self):
294        return
295
296class ExportLibIdCard(UtilityView, grok.View):
297    """Deliver an id card for the library.
298    """
299    grok.context(ICustomStudent)
300    grok.name('lib_idcard.pdf')
301    grok.require('waeup.viewStudent')
302    prefix = 'form'
303
304    label = u"Library Clearance"
305
306    omit_fields = (
307        'suspended', 'email', 'phone',
308        'adm_code', 'suspended_comment',
309        'date_of_birth',
310        'current_mode', 'certificate',
311        'entry_session',
312        'flash_notice')
313
314    form_fields = []
315
316    def _sigsInFooter(self):
317        isStudent = getattr(
318            self.request.principal, 'user_type', None) == 'student'
319        if isStudent:
320            return ''
321        return (_("Date, Reader's Signature"),
322                _("Date, Circulation Librarian's Signature"),
323                )
324
325    def update(self):
326        if not self.context.library:
327            self.flash(_('Forbidden!'), type="danger")
328            self.redirect(self.url(self.context))
329        return
330
331    @property
332    def note(self):
333        return """
334<br /><br /><br /><br /><font size='12'>
335This is to certify that the bearer whose photograph and other details appear
336 overleaf is a registered user of the <b>University Library</b>.
337 The card is not transferable. A replacement fee is charged for a loss,
338 mutilation or otherwise. If found, please, return to the University Library,
339 Igbinedion University, Okada.
340</font>
341
342"""
343        return
344
345    def render(self):
346        studentview = StudentBasePDFFormPage(self.context.student,
347            self.request, self.omit_fields)
348        students_utils = getUtility(IStudentsUtils)
349        return students_utils.renderPDF(
350            self, 'lib_idcard',
351            self.context.student, studentview,
352            omit_fields=self.omit_fields,
353            sigs_in_footer=self._sigsInFooter(),
354            note=self.note)
355
356class CustomStartClearancePage(StartClearancePage):
357    with_ac = False
358
359class CustomBalancePaymentAddFormPage(BalancePaymentAddFormPage):
360    grok.require('waeup.payStudent')
361
362class CustomExportPDFAdmissionSlip(ExportPDFAdmissionSlip):
363    """Deliver a PDF Admission slip.
364    """
365
366    omit_fields = ('date_of_birth',
367                   #'current_level',
368                   #'current_mode',
369                   #'entry_session'
370                   )
371
372    @property
373    def session(self):
374        return academic_sessions_vocab.getTerm(
375            self.context.entry_session).title
376
377    @property
378    def level(self):
379        studylevelsource = StudyLevelSource()
380        return studylevelsource.factory.getTitle(
381            self.context['studycourse'].certificate, self.context.current_level)
382
383    @property
384    def label(self):
385        return 'OFFER OF PROVISIONAL ADMISSION \nFOR %s SESSION' % self.session
386
387    @property
388    def pre_text_ug(self):
389        return (
390            'Following your performance in the screening exercise '
391            'for the %s academic session, I am pleased to inform '
392            'you that you have been offered provisional admission into the '
393            'Igbinedion University, Okada as follows:' % self.session)
394
395    @property
396    def pre_text_pg(self):
397        return (
398            'I am pleased to inform you that your application for admission'
399            ' into the Igbinedion University, Okada was successful. You have'
400            ' been admitted as follows:')
401
402    @property
403    def basic_medical_only_text(self):
404        return"""
405Progression to 200 Level MBBS programmes is highly competitive and strictly based on merit/approved quota. Students who are unable to make the cut off point will have the option of joining allied courses such as BSc Nursing, BSc Anatomy, BSc Biochemistry, BSc Physiology, Bachelor of Medical Laboratory Science, including Computer Science and engineering courses at 200 Level provided they have the relevant O/L credits.
406"""
407
408    @property
409    def post_text_ug(self):
410        return """
411Please 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.
412
413All 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.
414
415You are required to show evidence of the result / credentials you presented on application for admission.
416
417Fees can be paid using any of the following options:
418
419Fees 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
420
421Kindly note the following:
422
423Fees indicated on the Fee Structure page are valid for the current session only.
424Your Student Id (indicated above) Is your logln to the University portal.
425As 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.
426All 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.
427Fees once paid are not refundable.
428It is advisable that you keep the original receipts of fees paid and present them on demand.
429
430Accommodation: 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.
431
432Food: Food is available in cafeteria on "pay-as-you-eat" basis.
433
434Resumption 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.
435
436Registration/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.
437
438Transport Facility: The University provides a compulsory shuttle bus service to all students at a fee already included in the other charges.
439
440Kindly note that fresh students are not allowed the use of private vehicles.
441
442Conduct: 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.
443
444We wish you a successful academic career in Igbinedion University.
445
446Congratulations!
447
448
449
450<img src="${signature_benji_img_path}" valign="-20" height="38" width="86" />
451
452Friday Benji Bakare Esq.
453Registrar
454registrar@iuokada.edu.ng
45508035902949
456"""
457
458    @property
459    def post_text_pg(self):
460        return """
4611. Details of your programme will be made available to you by the Head of your Department on your arrival at the Igbinedion University.
462
4632. 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.
464
4653. If you accept this offer of admission upon the conditions above, you should please:
466
467(a) Complete the enclosed Acceptance Form of Provisional Offer of Admission in duplicate and send  by registered mail or by hand to the
468
469Secretary
470School of Postgraduate Studies and Research
471Igbinedion University,
472P.M.B. 0006,
473Benin City, Edo State,
474Nigeria
475
476(b)     Forward the following along with the Acceptance Form of Provisional Offer of Admission.
477
478(i) A non-refundable deposit of N100,000.00 (One Hundred Thousand Naira Only) which is part of the School fees: Payable Online.
479
480(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.
481
4824. The following will be required for Registration:
483
484(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.
485
486(b) The original copies of all credentials listed in your application form (including NYSC discharge/exemption certificate) should be brought for sighting.
487
4885. 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.
489
4906. Please find attached:
491
492(a) A copy of School fees Regime
493(b) A copy of Acceptance Forms
494
4957. Note:
496
497(a) All Tuition fees are to be paid online
498(b) Post-graduate dues and other charges are to be paid into ABC Microfinance Bank Okada, Account No: 30125
499
5008.  CONGRATULATIONS!!!
501
502Yours faithfully,
503
504<img src="${signature_olaoke_img_path}" valign="-20" height="38" width="86" />
505
506Mr. Olaoke, Olasoji Oluwole
507Secretary, School of Postgraduate Studies & Research
508"""
509
510    def render(self):
511        students_utils = getUtility(IStudentsUtils)
512        watermark_path = os.path.join(
513            os.path.dirname(__file__), 'static', 'watermark.pdf')
514        watermark = open(watermark_path, 'rb')
515        if self.context.is_postgrad:
516            file_path = os.path.join(
517                os.path.dirname(__file__), 'static', 'admission_letter_pg.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_pg, post_text=self.post_text_pg,
523                mergefiles=mergefiles,
524                watermark=watermark)
525        file_path = os.path.join(
526            os.path.dirname(__file__), 'static', 'admission_letter_ug.pdf')
527        file = open(file_path, 'rb')
528        mergefiles = [file,]
529        if self.context.certcode == 'BBMS' and self.context.current_level == 100:
530            post_text = self.basic_medical_only_text + self.post_text_ug
531        else:
532            post_text = self.post_text_ug
533        return students_utils.renderPDFAdmissionLetter(self,
534            self.context.student, omit_fields=self.omit_fields,
535            pre_text=self.pre_text_ug, post_text=post_text,
536            mergefiles=mergefiles,
537            watermark=watermark)
538
539class CustomOnlinePaymentDisplayFormPage(NigeriaOnlinePaymentDisplayFormPage):
540    """ Page to view an online payment ticket. We do not omit provider_amt.
541    """
542    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
543        'gateway_amt', 'thirdparty_amt', 'p_item','p_combi', 'provider_amt')
544    form_fields[
545        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
546    form_fields[
547        'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
548
549class CustomExportPDFPaymentSlip(NigeriaExportPDFPaymentSlip):
550    """Deliver a PDF slip of the context. We do not omit provider_amt.
551    """
552    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
553        'gateway_amt', 'thirdparty_amt', 'p_item',
554        'p_split_data','p_combi', 'provider_amt')
555    form_fields['creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
556    form_fields['payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
Note: See TracBrowser for help on using the repository browser.