source: main/waeup.kwarapoly/trunk/src/waeup/kwarapoly/students/browser.py @ 11905

Last change on this file since 11905 was 11905, checked in by uli, 10 years ago

pep8.

  • Property svn:keywords set to Id
File size: 19.0 KB
Line 
1## $Id: browser.py 11905 2014-10-29 12:38:50Z uli $
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.i18n import translate
20from zope.formlib.textwidgets import BytesDisplayWidget
21from zope.component import getUtility
22from hurry.workflow.interfaces import IWorkflowInfo
23from waeup.kofa.interfaces import ADMITTED, IKofaUtils
24from waeup.kofa.browser.layout import UtilityView
25from waeup.kofa.students.interfaces import IStudentsUtils
26from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
27from waeup.kofa.students.browser import (
28    StartClearancePage, BedTicketAddPage, ExportPDFAdmissionSlipPage,
29    StudentBasePDFFormPage)
30from waeup.kwarapoly.students.interfaces import (
31    ICustomStudent, ICustomStudentBase, ICustomStudentStudyLevel,
32    ICustomUGStudentClearance, ICustomPGStudentClearance)
33from waeup.kwarapoly.interfaces import MessageFactory as _
34from waeup.kofa.students.workflow import (
35    ADMITTED, PAID, REQUESTED, RETURNING, CLEARED, REGISTERED,
36    VALIDATED, GRADUATED, TRANSCRIPT, CREATED, CLEARANCE)
37from kofacustom.nigeria.students.browser import (
38    NigeriaOnlinePaymentDisplayFormPage,
39    NigeriaOnlinePaymentAddFormPage,
40    NigeriaExportPDFPaymentSlipPage,
41    NigeriaStudentClearanceDisplayFormPage,
42    NigeriaExportPDFClearanceSlipPage,
43    NigeriaStudentClearanceEditFormPage,
44    NigeriaExportPDFCourseRegistrationSlipPage,
45    NigeriaStudentPersonalDisplayFormPage,
46    NigeriaStudentClearanceManageFormPage,
47    NigeriaStudentPersonalEditFormPage,
48    NigeriaStudentPersonalManageFormPage,
49    NigeriaStudentBaseEditFormPage
50    )
51
52from waeup.kwarapoly.students.interfaces import (
53    ICustomStudentOnlinePayment,
54    ICustomStudentPersonal,
55    ICustomStudentPersonalEdit
56    )
57
58
59class CustomStudentBaseEditFormPage(NigeriaStudentBaseEditFormPage):
60    """ View to edit student base data
61    """
62    form_fields = grok.AutoFields(ICustomStudentBase).select(
63        'email', 'phone', 'sex')
64
65
66class CustomStudentPersonalDisplayFormPage(
67    NigeriaStudentPersonalDisplayFormPage):
68    """ Page to display student personal data
69    """
70    form_fields = grok.AutoFields(ICustomStudentPersonal)
71    form_fields['perm_address'].custom_widget = BytesDisplayWidget
72    form_fields['next_kin_address'].custom_widget = BytesDisplayWidget
73    form_fields['corr_address'].custom_widget = BytesDisplayWidget
74    form_fields['sponsor_address'].custom_widget = BytesDisplayWidget
75    form_fields[
76        'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
77
78
79class CustomStudentPersonalEditFormPage(NigeriaStudentPersonalEditFormPage):
80    """ Page to edit personal data
81    """
82    form_fields = grok.AutoFields(ICustomStudentPersonalEdit).omit(
83        'personal_updated')
84
85
86class CustomStudentPersonalManageFormPage(
87    NigeriaStudentPersonalManageFormPage):
88    """ Page to edit personal data
89    """
90    form_fields = grok.AutoFields(ICustomStudentPersonal)
91    form_fields['personal_updated'].for_display = True
92    form_fields[
93        'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
94
95
96class CustomOnlinePaymentDisplayFormPage(NigeriaOnlinePaymentDisplayFormPage):
97    """ Page to view an online payment ticket
98    """
99    grok.context(ICustomStudentOnlinePayment)
100    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
101        'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item')
102    form_fields[
103        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
104    form_fields[
105        'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
106
107
108class CustomOnlinePaymentAddFormPage(NigeriaOnlinePaymentAddFormPage):
109    """ Page to add an online payment ticket
110    """
111    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).select(
112        'p_category')
113
114
115class CustomExportPDFPaymentSlipPage(NigeriaExportPDFPaymentSlipPage):
116    """Deliver a PDF slip of the context.
117    """
118    grok.context(ICustomStudentOnlinePayment)
119    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
120        'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item')
121    form_fields['creation_date'].custom_widget = FriendlyDatetimeDisplayWidget(
122        'le')
123    form_fields['payment_date'].custom_widget = FriendlyDatetimeDisplayWidget(
124        'le')
125
126
127class CustomStartClearancePage(StartClearancePage):
128
129    with_ac = False
130
131
132class CustomStudentClearanceDisplayFormPage(
133    NigeriaStudentClearanceDisplayFormPage):
134    """ Page to display student clearance data
135    """
136
137    @property
138    def form_fields(self):
139        if self.context.is_postgrad:
140            form_fields = grok.AutoFields(
141                ICustomPGStudentClearance).omit('clearance_locked')
142        else:
143            form_fields = grok.AutoFields(
144                ICustomUGStudentClearance).omit('clearance_locked')
145        if not getattr(self.context, 'officer_comment'):
146            form_fields = form_fields.omit('officer_comment')
147        else:
148            form_fields['officer_comment'].custom_widget = BytesDisplayWidget
149        return form_fields
150
151
152class CustomExportPDFClearanceSlipPage(NigeriaExportPDFClearanceSlipPage):
153    """Deliver a PDF slip of the context.
154    """
155
156    @property
157    def form_fields(self):
158        if self.context.is_postgrad:
159            form_fields = grok.AutoFields(
160                ICustomPGStudentClearance).omit('clearance_locked')
161        else:
162            form_fields = grok.AutoFields(
163                ICustomUGStudentClearance).omit('clearance_locked')
164        if not getattr(self.context, 'officer_comment'):
165            form_fields = form_fields.omit('officer_comment')
166        return form_fields
167
168
169class CustomStudentClearanceManageFormPage(
170    NigeriaStudentClearanceManageFormPage):
171    """ Page to edit student clearance data
172    """
173
174    @property
175    def form_fields(self):
176        if self.context.is_postgrad:
177            form_fields = grok.AutoFields(
178                ICustomPGStudentClearance).omit('clr_code')
179        else:
180            form_fields = grok.AutoFields(
181                ICustomUGStudentClearance).omit('clr_code')
182        return form_fields
183
184
185class CustomStudentClearanceEditFormPage(NigeriaStudentClearanceEditFormPage):
186    """ View to edit student clearance data by student
187    """
188
189    def dataNotComplete(self):
190        return False
191
192    @property
193    def form_fields(self):
194        if self.context.is_postgrad:
195            form_fields = grok.AutoFields(ICustomPGStudentClearance).omit(
196            'clearance_locked', 'nysc_location', 'clr_code', 'officer_comment')
197        else:
198            form_fields = grok.AutoFields(ICustomUGStudentClearance).omit(
199            'clearance_locked', 'clr_code', 'officer_comment')
200        return form_fields
201
202
203class BedTicketAddPage(BedTicketAddPage):
204    """ Page to add an online payment ticket
205    """
206    buttonname = _('Create bed ticket')
207    notice = ''
208    with_ac = False
209
210
211class CustomExportPDFAdmissionSlipPage(ExportPDFAdmissionSlipPage):
212    """Deliver a PDF Admission slip.
213    """
214    grok.context(ICustomStudent)
215
216    omit_fields = ('date_of_birth', 'current_level')
217
218    form_fields = grok.AutoFields(ICustomStudent).select(
219        'student_id', 'reg_number')
220
221    def render(self):
222        if self.context.state in (CREATED, ADMITTED,
223                                  CLEARANCE, REQUESTED, CLEARED):
224            self.flash('Not allowed.')
225            self.redirect(self.url(self.context))
226            return
227        students_utils = getUtility(IStudentsUtils)
228        return students_utils.renderPDFAdmissionLetter(self,
229            self.context.student, omit_fields=self.omit_fields)
230
231
232class ExportPDFAdmissionNotificationPage(UtilityView, grok.View):
233    """Deliver a PDF Admission notification slip.
234    """
235    grok.context(ICustomStudent)
236    grok.name('admission_notification.pdf')
237    grok.require('waeup.viewStudent')
238    prefix = 'form'
239    label = 'Notification of Provisional Admission'
240
241    omit_fields = ('date_of_birth', 'current_level')
242
243    form_fields = grok.AutoFields(ICustomStudent).select(
244        'student_id', 'reg_number', 'sex', 'lga')
245
246    def render(self):
247        if self.context.state not in (ADMITTED, CLEARANCE, REQUESTED, CLEARED):
248            self.flash('Not allowed.')
249            self.redirect(self.url(self.context))
250            return
251        students_utils = getUtility(IStudentsUtils)
252        pre_text = ''
253        post_text = post_text_freshers
254        return students_utils.renderPDFAdmissionLetter(self,
255            self.context.student, omit_fields=self.omit_fields,
256            pre_text=pre_text, post_text=post_text)
257
258
259# copied from waeup.aaue
260class CustomExportPDFCourseRegistrationSlipPage(
261    NigeriaExportPDFCourseRegistrationSlipPage):
262    """Deliver a PDF slip of the context.
263    """
264    grok.context(ICustomStudentStudyLevel)
265    form_fields = grok.AutoFields(ICustomStudentStudyLevel).omit(
266        'level_session', 'level_verdict',
267        'validated_by', 'validation_date', 'gpa')
268
269    omit_fields = ('password', 'suspended', 'suspended_comment',
270        'phone', 'adm_code', 'sex', 'email', 'date_of_birth',
271        'department', 'current_mode', 'current_level')
272
273    @property
274    def title(self):
275        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
276        return translate(_('Credits Registered'), 'waeup.kofa',
277            target_language=portal_language)
278
279    def _signatures(self):
280        """Signatures as inserted at document bottom.
281
282        As Kwarapoly requires a fancy 'certificate' there, the pre-
283        and post-fields of signatures are quite large and unusual
284        here.
285
286        This is also a workaround, as we cannot easily insert text
287        with signature fields in documents using reportlab platypus.
288
289        The signature boxes we return here contain context infos
290        (therefore this has to be a method) and return the following
291        layout:
292
293            +-----------------------------------------+
294            | (Empty pre text)                        |
295            +-------------+---------------------------+
296            |Date         | Students Signature        |
297            +-------------+---------------------------+
298            | (Empty post text)                       |
299            +=========================================+
300            |            Certification                |
301            +-------------+---------------------------+
302            |Date         | Director Signature, etc.  |
303            +-------------+---------------------------+
304            |NOTE: This form is the ...               |
305            +-----------------------------------------+
306
307
308        """
309        return (
310            [
311                ('', _('Student\'s Signature'), ''),
312                ],
313            [((
314                    "<br/>"
315                    + "&nbsp;" * 70 +
316                    "<u><b><font size='14'>Certification</font></b></u><br/>"
317                    "<br/><b><i>"
318                    "This is to certify that "
319                    "<font size='13'>"
320                    + self.context.student.display_fullname +
321                    "</font>"
322                    " has paid the full School Fees, duly registered and "
323                    "therefore, is cleared to sit for examination in the "
324                    "courses listed above."
325                    "</i></b><br/><br/>"
326                    ),
327              "Institute Director\'s Signature and Official Stamp",
328              (
329                    "<b><u>NOTE:</u></b> This form is the property of "
330                    "Kwara State Polytechnic, it is not transferable "
331                    "and students must properly fill it, get it duly "
332                    "endorsed and present it before they can be admitted "
333                    "into Examination Venues."
334                    )), ]
335            )
336
337    def render(self):
338        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
339        Sem = translate('Sem.', 'waeup.kofa', target_language=portal_language)
340        Code = translate('Code', 'waeup.kofa', target_language=portal_language)
341        Title = translate('Title', 'waeup.kofa',
342                          target_language=portal_language)
343        Cred = translate(
344            'Cred.', 'waeup.kofa', target_language=portal_language)
345        Score = translate('Score', 'waeup.kofa',
346                          target_language=portal_language)
347        Grade = translate('Grade', 'waeup.kofa',
348                          target_language=portal_language)
349        Signature = translate(_('HOD\'s Signature'), 'waeup.kwarapoly',
350            target_language=portal_language)
351        studentview = StudentBasePDFFormPage(self.context.student,
352            self.request, self.omit_fields)
353        students_utils = getUtility(IStudentsUtils)
354
355        tabledata = []
356        tableheader = []
357        contenttitle = []
358        for i in range(1, 7):
359            tabledata.append(sorted(
360                [value for value in self.context.values()
361                 if value.semester == i],
362                key=lambda value: str(value.semester) + value.code))
363            tableheader.append([(Code, 'code', 2.0),
364                               (Title, 'title', 7),
365                               (Cred, 'credits', 1.5),
366                               (Score, 'score', 1.4),
367                               (Grade, 'grade', 1.4),
368                               (Signature, 'dummy', 3),
369                               ])
370        topMargin = 1.5 + (self.label.count('\n') * 0.2)
371        return students_utils.renderPDF(
372            self, 'course_registration_slip.pdf',
373            self.context.student, studentview,
374            tableheader=tableheader,
375            tabledata=tabledata,
376            signatures=self._signatures(),
377            topMargin=topMargin,
378            omit_fields=self.omit_fields,
379            )
380
381
382class ExportPDFRegistrationSlipPage(grok.View):
383    """Deliver a PDF slip of the context.
384    """
385    grok.context(ICustomStudent)
386    grok.name('registration_slip.pdf')
387    grok.require('waeup.viewStudent')
388    prefix = 'form'
389    omit_fields = (
390        'suspended', 'phone',
391        'adm_code', 'suspended_comment', 'email',
392        'current_mode', 'matric_number', 'date_of_birth', 'current_level')
393    title = 'Clearance and Personal Data'
394    label = 'Profile Registration Slip'
395
396    form_fields = grok.AutoFields(ICustomStudent).select(
397        'date_of_birth', 'lga', 'nationality',
398        'perm_address', 'corr_address',
399        'marit_stat', 'sponsor_name', 'sponsor_address',
400        )
401
402    def render(self):
403        studentview = StudentBasePDFFormPage(self.context.student,
404            self.request, self.omit_fields)
405        students_utils = getUtility(IStudentsUtils)
406        return students_utils.renderPDF(
407            self, 'registration_slip.pdf',
408            self.context.student, studentview, signatures=None,
409            omit_fields=self.omit_fields,
410            note=post_text_registration)
411
412post_text_registration = """<br /><br />
413<strong>IMPORTANT NOTICE</strong>
414<br /><br />
415This registration slip must be supplied before attendance of lectures.
416Note that:
417<br /><br />
4181. All fees due must be paid in full.
419<br /><br />
4202. All information required must be available on the Registration Form.
421<br /><br />
4223. The Signature of all appropriate Polytechnic Authority must be obtained.
423<br /><br />
4244. The endorsed Registration Form should be returned to the respective
425   Institutes and Administrative Offices.
426<br /><br />
4275. No student may change his subject or course of study as shown in the
428   signed Registration Form without clearance from the Admissions Office
429   and the Director of the appropriate Institute.
430<br /><br />
4316. All candidates admitted into the HND I programmes should submit the
432   photocopies of their original certificates of ND and SSCE with scratch
433   card online for clearance latest a week after the admission is offered.
434   Failure to comply with this directive may lead to the forfeiture of
435   the admission.
436<br /><br />
437<!-- image size: 229x100 pixels; ratio (2.29:1) must be kept -->
438<img src="${signature_img_path}" valign="-30"
439     height="75" width="172" />
440<br />
441M.O. Adebayo<br />
442Admission Officer<br />
443For: Registrar
444"""
445
446post_text_freshers = """
447<strong>INSTRUCTIONS TO FRESHERS</strong>
448<br /><br />
449You are hereby offered a provisional admission for the 2014/2015 session
450subject to the conditions that:
451<br /><br />
4521. The information given in your Application Form is correct.
453<br /><br />
4542. The original of your Credentials are presented for scrutiny.
455<br /><br />
4563. If at any time the Credentials submitted are found to be false/fake
457   or incorrect, your admission shall be withdrawn.
458<br /><br />
4594. The name by which you are admitted and registered shall remain same
460   throughout the duration of your programme.
461<br /><br />
4625. You are to fill and submit the Undertaking Form at the point of
463   registration failure which your admission will be forfeited.
464<br /><br />
4656. You will dress decently covering your nakedness at all times.
466<br /><br />
4677. Payment of school fees will be once and in full and should be by
468   Interswitch to the designated Banks. Failure to pay fees by the
469   mode mentioned above by the closing date means you have declined
470   the offer and your place will be given to another eligible
471   candidate immediately.
472<br /><br />
4738. You present a Certificate of medical fitness from the Polytechnic
474   Clinic.
475<br /><br />
4769. All indigenes of Kwara State are required to present Certificate of
477   Citizenship.
478<br /><br />
47910. The Polytechnic reserves the right to withdraw your admission at
480    any stage, if you are found to be a cultist or an expelled
481    individual from any tertiary institution.
482<br /><br />
48311. You are prepared to take up accommodation provided on the campuses
484    by the authority.
485<br /><br />
48612. There will be no refund of school fees once paid.
487<br /><br />
48813. If you accept this offer with the above stated conditions, please
489    make a photocopy of this document and return it to the Admission
490    Office immediately.
491<br /><br />
49214. You possess the entry requirement for the programme you are admitted.
493<br /><br />
494
495<!-- image size: 229x100 pixels; ratio (2.29:1) must be kept -->
496<img src="${signature_img_path}" valign="-30"
497     height="75" width="172" />
498<br />
499M.O. Adebayo<br />
500Admission Officer<br />
501For: Registrar
502"""
503# XXX: a note for <img /> tag used here (from reportlab docs):
504#   The valign attribute may be set to a css like value from "baseline", "sub",
505#   "super", "top", "text-top", "middle", "bottom", "text-bottom";
506#   the value may also be a numeric percentage or an absolute value.
507#
508# Burn this remark after reading.
Note: See TracBrowser for help on using the repository browser.