## $Id: browser.py 15436 2019-05-29 12:06:23Z henrik $
##
## Copyright (C) 2012 Uli Fouquet & Henrik Bettermann
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##
import grok
from zope.i18n import translate
from zope.formlib.textwidgets import BytesDisplayWidget
from zope.component import getUtility, getMultiAdapter
from zope.viewlet.interfaces import IViewletManager
from waeup.kofa.interfaces import IKofaUtils
from waeup.kofa.browser.layout import UtilityView
from waeup.kofa.students.interfaces import IStudentsUtils
from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
from waeup.kofa.students.browser import (
StartClearancePage, BedTicketAddPage, ExportPDFAdmissionSlip,
StudentBasePDFFormPage)
from waeup.kwarapoly.students.interfaces import (
ICustomStudent, ICustomStudentBase, ICustomStudentStudyLevel,
ICustomUGStudentClearance, ICustomPGStudentClearance)
from waeup.kwarapoly.interfaces import MessageFactory as _
from waeup.kofa.students.workflow import (
ADMITTED, PAID, REQUESTED, RETURNING, CLEARED, REGISTERED,
VALIDATED, GRADUATED, CREATED, CLEARANCE)
from kofacustom.nigeria.students.browser import (
NigeriaOnlinePaymentDisplayFormPage,
NigeriaOnlinePaymentAddFormPage,
NigeriaExportPDFPaymentSlip,
NigeriaStudentClearanceDisplayFormPage,
NigeriaExportPDFClearanceSlip,
NigeriaStudentClearanceEditFormPage,
NigeriaExportPDFCourseRegistrationSlip,
NigeriaStudentPersonalDisplayFormPage,
NigeriaStudentClearanceManageFormPage,
NigeriaStudentPersonalEditFormPage,
NigeriaStudentPersonalManageFormPage,
NigeriaStudentBaseEditFormPage,
NigeriaExportPDFFinancialClearancePage
)
from kofacustom.nigeria.students.viewlets import show_viewlet
from waeup.kwarapoly.students.interfaces import (
ICustomStudent,
ICustomStudentOnlinePayment,
ICustomStudentPersonal,
ICustomStudentPersonalEdit
)
class CustomStudentBaseEditFormPage(NigeriaStudentBaseEditFormPage):
""" View to edit student base data
"""
form_fields = grok.AutoFields(ICustomStudentBase).select(
'email', 'phone', 'sex')
class CustomStudentPersonalDisplayFormPage(
NigeriaStudentPersonalDisplayFormPage):
""" Page to display student personal data
"""
form_fields = grok.AutoFields(ICustomStudentPersonal)
form_fields['perm_address'].custom_widget = BytesDisplayWidget
form_fields['next_kin_address'].custom_widget = BytesDisplayWidget
form_fields['corr_address'].custom_widget = BytesDisplayWidget
form_fields['sponsor_address'].custom_widget = BytesDisplayWidget
form_fields[
'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
class CustomStudentPersonalEditFormPage(NigeriaStudentPersonalEditFormPage):
""" Page to edit personal data
"""
form_fields = grok.AutoFields(ICustomStudentPersonalEdit).omit(
'personal_updated')
class CustomStudentPersonalManageFormPage(
NigeriaStudentPersonalManageFormPage):
""" Page to edit personal data
"""
form_fields = grok.AutoFields(ICustomStudentPersonal)
form_fields['personal_updated'].for_display = True
form_fields[
'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
class CustomOnlinePaymentDisplayFormPage(NigeriaOnlinePaymentDisplayFormPage):
""" Page to view an online payment ticket
"""
grok.context(ICustomStudentOnlinePayment)
form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item')
form_fields[
'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
form_fields[
'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
class CustomOnlinePaymentAddFormPage(NigeriaOnlinePaymentAddFormPage):
""" Page to add an online payment ticket
"""
form_fields = grok.AutoFields(ICustomStudentOnlinePayment).select(
'p_category')
class CustomExportPDFPaymentSlip(NigeriaExportPDFPaymentSlip):
"""Deliver a PDF slip of the context.
"""
grok.context(ICustomStudentOnlinePayment)
form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item')
form_fields['creation_date'].custom_widget = FriendlyDatetimeDisplayWidget(
'le')
form_fields['payment_date'].custom_widget = FriendlyDatetimeDisplayWidget(
'le')
class CustomStartClearancePage(StartClearancePage):
with_ac = True
class CustomStudentClearanceDisplayFormPage(
NigeriaStudentClearanceDisplayFormPage):
""" Page to display student clearance data
"""
@property
def form_fields(self):
if self.context.is_postgrad:
form_fields = grok.AutoFields(
ICustomPGStudentClearance).omit('clearance_locked')
else:
form_fields = grok.AutoFields(
ICustomUGStudentClearance).omit('clearance_locked')
if not getattr(self.context, 'officer_comment'):
form_fields = form_fields.omit('officer_comment')
else:
form_fields['officer_comment'].custom_widget = BytesDisplayWidget
return form_fields
class CustomExportPDFClearanceSlip(NigeriaExportPDFClearanceSlip):
"""Deliver a PDF slip of the context.
"""
@property
def form_fields(self):
if self.context.is_postgrad:
form_fields = grok.AutoFields(
ICustomPGStudentClearance).omit('clearance_locked')
else:
form_fields = grok.AutoFields(
ICustomUGStudentClearance).omit('clearance_locked')
if not getattr(self.context, 'officer_comment'):
form_fields = form_fields.omit('officer_comment')
return form_fields
class CustomStudentClearanceManageFormPage(
NigeriaStudentClearanceManageFormPage):
""" Page to edit student clearance data
"""
@property
def form_fields(self):
if self.context.is_postgrad:
form_fields = grok.AutoFields(
ICustomPGStudentClearance).omit('clr_code')
else:
form_fields = grok.AutoFields(
ICustomUGStudentClearance).omit('clr_code')
return form_fields
class CustomStudentClearanceEditFormPage(NigeriaStudentClearanceEditFormPage):
""" View to edit student clearance data by student
"""
# deactivated on 5/11/15, see ticket 129
def xxx_dataNotComplete(self):
mgr = getMultiAdapter(
(self.context, self.request, self), IViewletManager,'files')
mgr.update()
missing_files = []
required = (
'birthcertificateupload',
'acceptanceletterupload',
'lgaidentificationupload',
'firstsittingresultupload',
'resultstatementupload',
'refereeletterupload',
'statutorydeclarationupload',
)
for viewlet in mgr.viewlets:
if viewlet.__name__ not in required:
continue
if viewlet.show_viewlet and not viewlet.file_exists:
missing_files += (viewlet.label, )
if missing_files:
return "Missing: %s" % ', '.join(missing_files)
return False
@property
def form_fields(self):
if self.context.is_postgrad:
form_fields = grok.AutoFields(ICustomPGStudentClearance).omit(
'clearance_locked', 'nysc_location', 'clr_code', 'officer_comment',
'physical_clearance_date')
else:
form_fields = grok.AutoFields(ICustomUGStudentClearance).omit(
'clearance_locked', 'clr_code', 'officer_comment',
'physical_clearance_date')
return form_fields
class BedTicketAddPage(BedTicketAddPage):
""" Page to add an online payment ticket
"""
buttonname = _('Create bed ticket')
notice = ''
with_ac = False
class CustomExportPDFAdmissionSlip(ExportPDFAdmissionSlip):
"""Deliver a PDF Admission slip.
"""
grok.context(ICustomStudent)
omit_fields = ('date_of_birth', 'current_level', 'flash_notice')
form_fields = grok.AutoFields(ICustomStudent).select(
'student_id', 'reg_number')
@property
def label(self):
line0 = 'Registration Bio Data - B'
line1 = 'Admission Letter of %s' % self.context.display_fullname
return '%s\n%s' % (line0, line1)
def render(self):
if self.context.state in (CREATED, ADMITTED,
CLEARANCE, REQUESTED, CLEARED):
self.flash('Not allowed.')
self.redirect(self.url(self.context))
return
students_utils = getUtility(IStudentsUtils)
return students_utils.renderPDFAdmissionLetter(self,
self.context.student, omit_fields=self.omit_fields)
class ExportPDFAdmissionNotificationPage(UtilityView, grok.View):
"""Deliver a PDF Admission notification slip.
"""
grok.context(ICustomStudent)
grok.name('admission_notification.pdf')
grok.require('waeup.viewStudent')
prefix = 'form'
label = 'Registration Bio Data - A\nNotification of Provisional Admission'
omit_fields = ('date_of_birth', 'current_level')
form_fields = grok.AutoFields(ICustomStudent).select(
'student_id', 'reg_number', 'sex', 'lga')
def render(self):
if self.context.state not in (ADMITTED, CLEARANCE, REQUESTED, CLEARED):
self.flash('Not allowed.')
self.redirect(self.url(self.context))
return
students_utils = getUtility(IStudentsUtils)
pre_text = ''
post_text = post_text_freshers
return students_utils.renderPDFAdmissionLetter(self,
self.context.student, omit_fields=self.omit_fields,
pre_text=pre_text, post_text=post_text)
# copied from waeup.aaue
class CustomExportPDFCourseRegistrationSlip(
NigeriaExportPDFCourseRegistrationSlip):
"""Deliver a PDF slip of the context.
"""
grok.context(ICustomStudentStudyLevel)
form_fields = grok.AutoFields(ICustomStudentStudyLevel).omit(
'level_session', 'level_verdict',
'validated_by', 'validation_date', 'gpa', 'level')
omit_fields = ('password', 'suspended', 'suspended_comment',
'phone', 'adm_code', 'sex', 'email', 'date_of_birth',
'department', 'current_mode', 'current_level')
@property
def title(self):
portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
return translate(_('Credits Registered'), 'waeup.kofa',
target_language=portal_language)
def _signatures(self):
"""Signatures as inserted at document bottom.
As Kwarapoly requires a fancy 'certificate' there, the pre-
and post-fields of signatures are quite large and unusual
here.
This is also a workaround, as we cannot easily insert text
with signature fields in documents using reportlab platypus.
The signature boxes we return here contain context infos
(therefore this has to be a method) and return the following
layout:
+-----------------------------------------+
| (Empty pre text) |
+-------------+---------------------------+
|Date | Students Signature |
+-------------+---------------------------+
| (Empty post text) |
+=========================================+
| Certification |
+-------------+---------------------------+
|Date | Director Signature, etc. |
+-------------+---------------------------+
|NOTE: This form is the ... |
+-----------------------------------------+
"""
return (
[
('', _('Student\'s Signature'), ''),
],
[((
"
"
+ " " * 70 +
"Certification
"
"
"
"This is to certify that "
""
+ self.context.student.display_fullname +
""
" has paid the full School Fees, duly registered and "
"therefore, is cleared to sit for examination in the "
"courses listed above."
"
"
),
"Institute Director\'s Signature and Official Stamp",
(
"NOTE: This form is the property of "
"Kwara State Polytechnic, it is not transferable "
"and students must properly fill it, get it duly "
"endorsed and present it before they can be admitted "
"into Examination Venues."
)), ]
)
def render(self):
portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
Code = translate('Code', 'waeup.kofa', target_language=portal_language)
Title = translate('Title', 'waeup.kofa',
target_language=portal_language)
Cred = translate(
'Cred.', 'waeup.kofa', target_language=portal_language)
Score = translate('Score', 'waeup.kofa',
target_language=portal_language)
Grade = translate('Grade', 'waeup.kofa',
target_language=portal_language)
Signature = translate(_('HOD\'s Signature'), 'waeup.kwarapoly',
target_language=portal_language)
studentview = StudentBasePDFFormPage(self.context.student,
self.request, self.omit_fields)
students_utils = getUtility(IStudentsUtils)
tabledata = []
tableheader = []
for i in range(1, 7):
tabledata.append(sorted(
[value for value in self.context.values()
if value.semester == i],
key=lambda value: str(value.semester) + value.code))
tableheader.append([(Code, 'code', 2.0),
(Title, 'title', 7),
(Cred, 'credits', 1.5),
(Score, 'score', 1.4),
(Grade, 'grade', 1.4),
(Signature, 'dummy', 3),
])
topMargin = 1.5 + (self.label.count('\n') * 0.2)
return students_utils.renderPDF(
self, 'course_registration_slip.pdf',
self.context.student, studentview,
tableheader=tableheader,
tabledata=tabledata,
signatures=self._signatures(),
topMargin=topMargin,
omit_fields=self.omit_fields,
)
class ExportPDFRegistrationSlip(grok.View):
"""Deliver a PDF slip of the context.
"""
grok.context(ICustomStudent)
grok.name('registration_slip.pdf')
grok.require('waeup.viewStudent')
prefix = 'form'
omit_fields = (
'suspended', 'phone',
'adm_code', 'suspended_comment', 'email',
'current_mode', 'matric_number', 'date_of_birth', 'current_level')
title = 'Clearance and Personal Data'
label = 'Registration Bio Data - C\nProfile Data Slip'
form_fields = grok.AutoFields(ICustomStudent).select(
'date_of_birth', 'lga', 'nationality',
'perm_address', 'corr_address',
'marit_stat', 'sponsor_name', 'sponsor_address',
)
def render(self):
if self.context.state in (CREATED, ADMITTED,
CLEARANCE, REQUESTED, CLEARED):
self.flash('Not allowed.')
self.redirect(self.url(self.context))
return
studentview = StudentBasePDFFormPage(self.context.student,
self.request, self.omit_fields)
students_utils = getUtility(IStudentsUtils)
return students_utils.renderPDF(
self, 'registration_slip.pdf',
self.context.student, studentview, signatures=None,
omit_fields=self.omit_fields,
note=post_text_registration)
post_text_registration = """
IMPORTANT NOTICE
This registration slip must be supplied before attendance of lectures. Note that:
1. All fees due must be paid in full.
2. All information required must be available on the Registration Form.
3. The Signature of all appropriate Polytechnic Authority must be obtained.
4. The endorsed Registration Form should be returned to the respective
Institutes and Administrative Offices.
5. No student may change his subject or course of study as shown in the
signed Registration Form without clearance from the Admissions Office
and the Director of the appropriate Institute.
6. All candidates admitted into the HND I programmes should submit the
photocopies of their original certificates of ND and SSCE with scratch
card online for clearance latest a week after the admission is offered.
Failure to comply with this directive may lead to the forfeiture of
the admission.
M.O. Adebayo
Admission Officer
For: Registrar
"""
post_text_freshers = """
INSTRUCTIONS TO FRESHERS
You are hereby offered a provisional admission for the current academic
session subject to the conditions that:
1. The information given in your Application Form is correct.
2. The original of your Credentials are presented for scrutiny.
3. If at any time the Credentials submitted are found to be false/fake
or incorrect, your admission shall be withdrawn.
4. The name by which you are admitted and registered shall remain same
throughout the duration of your programme.
5. You are to fill and submit the Undertaking Form at the point of
registration failure which your admission will be forfeited.
6. You will dress decently covering your nakedness at all times.
7. Payment of school fees will be once and in full and should be by
Interswitch to the designated Banks. Failure to pay fees by the
mode mentioned above by the closing date means you have declined
the offer and your place will be given to another eligible
candidate immediately.
8. You present a Certificate of medical fitness from the Polytechnic
Clinic.
9. All indigenes of Kwara State are required to present Certificate of
Citizenship.
10. The Polytechnic reserves the right to withdraw your admission at
any stage, if you are found to be a cultist or an expelled
individual from any tertiary institution. In addition, it should be
noted that the Polytechnic will not entertain any change of name
different from the one filled by the candidate on his/her Application
Form.
11. You are prepared to take up accommodation provided on the campuses
by the authority.
12. There will be no refund of school fees once paid.
13. If you accept this offer with the above stated conditions, please
make a photocopy of this document and return it to the Admission
Office immediately.
14. You possess the entry requirement for the programme you are admitted.
M.O. Adebayo
Admission Officer
For: Registrar
"""
# XXX: a note for tag used here (from reportlab docs):
# The valign attribute may be set to a css like value from "baseline", "sub",
# "super", "top", "text-top", "middle", "bottom", "text-bottom";
# the value may also be a numeric percentage or an absolute value.
#
# Burn this remark after reading.
class StudentGetMatricNumberView(UtilityView, grok.View):
""" Construct and set the matriculation number.
"""
grok.context(ICustomStudent)
grok.name('get_matric_number')
grok.require('waeup.viewStudent')
def update(self):
students_utils = getUtility(IStudentsUtils)
msg, mnumber = students_utils.setMatricNumber(self.context)
if msg:
self.flash(msg, type="danger")
else:
self.flash(_('Matriculation number %s assigned.' % mnumber))
self.context.writeLogMessage(self, '%s assigned' % mnumber)
self.redirect(self.url(self.context))
return
def render(self):
return
class CustomExportPDFFinancialClearancePage(NigeriaExportPDFFinancialClearancePage):
"""Deliver a PDF financial clearance slip.
"""
def _sigsInFooter(self):
return (_('Date, Checking Officer Signature'),
_('Date, Approving Officer Signature'),
)