## $Id: browser.py 15711 2019-10-29 06:06:52Z 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.formlib.textwidgets import BytesDisplayWidget
from zope.component import getUtility
from zope.security import checkPermission
from zope.i18n import translate
from datetime import datetime
from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
from waeup.kofa.interfaces import IExtFileStore, IObjectHistory, IKofaUtils
from waeup.kofa.browser.layout import action, UtilityView
from waeup.kofa.utils.helpers import get_current_principal, to_timezone
from waeup.kofa.students.browser import (
StudentPersonalDisplayFormPage, StudentPersonalManageFormPage,
StudentClearanceManageFormPage, StudentClearanceEditFormPage,
StudentClearanceDisplayFormPage, OnlinePaymentFakeApproveView,
ExportPDFClearanceSlip, StudentBaseManageFormPage,
StudentBaseDisplayFormPage,
StudentBasePDFFormPage,
StudentBaseEditFormPage, StudentPersonalEditFormPage,
OnlinePaymentDisplayFormPage, OnlinePaymentAddFormPage,
OnlinePaymentBreadcrumb, ExportPDFPaymentSlip,
ExportPDFCourseRegistrationSlip,
ExportPDFBedTicketSlip,
StudentFilesUploadPage, emit_lock_message,
AccommodationManageFormPage,
BedTicketAddPage)
from waeup.kofa.students.interfaces import IStudentsUtils
from waeup.kofa.students.viewlets import (
PaymentReceiptActionButton, StudentPassportActionButton)
from kofacustom.nigeria.students.interfaces import (
INigeriaStudentBase, INigeriaStudent, INigeriaStudentPersonal,
INigeriaStudentPersonalEdit,
INigeriaUGStudentClearance,INigeriaPGStudentClearance,
INigeriaStudentOnlinePayment
)
from waeup.kofa.students.workflow import ADMITTED
from kofacustom.nigeria.interfaces import MessageFactory as _
class NigeriaOnlinePaymentBreadcrumb(OnlinePaymentBreadcrumb):
"""A breadcrumb for payments.
"""
grok.context(INigeriaStudentOnlinePayment)
class PaymentReceiptActionButton(PaymentReceiptActionButton):
grok.order(4)
grok.context(INigeriaStudentOnlinePayment)
class NigeriaStudentBaseDisplayFormPage(StudentBaseDisplayFormPage):
""" Page to display student base data
"""
form_fields = grok.AutoFields(INigeriaStudentBase).omit(
'password', 'suspended', 'suspended_comment',
'flash_notice', 'provisionally_cleared')
form_fields[
'financial_clearance_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
class NigeriaStudentBaseManageFormPage(StudentBaseManageFormPage):
""" View to manage student base data
"""
form_fields = grok.AutoFields(INigeriaStudentBase).omit(
'student_id', 'adm_code', 'suspended',
'financially_cleared_by', 'financial_clearance_date')
class NigeriaStudentBaseEditFormPage(StudentBaseEditFormPage):
""" View to edit student base data
"""
form_fields = grok.AutoFields(INigeriaStudentBase).select(
'email', 'phone')
class NigeriaStudentPersonalDisplayFormPage(StudentPersonalDisplayFormPage):
""" Page to display student personal data
"""
form_fields = grok.AutoFields(INigeriaStudentPersonal)
form_fields['perm_address'].custom_widget = BytesDisplayWidget
form_fields['next_kin_address'].custom_widget = BytesDisplayWidget
form_fields[
'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
class NigeriaStudentPersonalEditFormPage(StudentPersonalEditFormPage):
""" Page to edit personal data
"""
form_fields = grok.AutoFields(INigeriaStudentPersonalEdit).omit('personal_updated')
class NigeriaStudentPersonalManageFormPage(StudentPersonalManageFormPage):
""" Page to edit personal data
"""
form_fields = grok.AutoFields(INigeriaStudentPersonal)
form_fields['personal_updated'].for_display = True
form_fields[
'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
class NigeriaStudentClearanceDisplayFormPage(StudentClearanceDisplayFormPage):
""" Page to display student clearance data
"""
@property
def form_fields(self):
if self.context.is_postgrad:
form_fields = grok.AutoFields(
INigeriaPGStudentClearance).omit('clearance_locked')
else:
form_fields = grok.AutoFields(
INigeriaUGStudentClearance).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 NigeriaExportPDFClearanceSlip(ExportPDFClearanceSlip):
"""Deliver a PDF slip of the context.
"""
omit_fields = ('password', 'suspended', 'suspended_comment',
'phone', 'adm_code', 'email', 'date_of_birth', 'current_level',
'flash_notice')
@property
def form_fields(self):
if self.context.is_postgrad:
form_fields = grok.AutoFields(
INigeriaPGStudentClearance).omit('clearance_locked')
else:
form_fields = grok.AutoFields(
INigeriaUGStudentClearance).omit('clearance_locked')
if not getattr(self.context, 'officer_comment'):
form_fields = form_fields.omit('officer_comment')
return form_fields
class NigeriaStudentClearanceManageFormPage(StudentClearanceManageFormPage):
""" Page to edit student clearance data
"""
@property
def form_fields(self):
if self.context.is_postgrad:
form_fields = grok.AutoFields(
INigeriaPGStudentClearance).omit('clr_code')
else:
form_fields = grok.AutoFields(
INigeriaUGStudentClearance).omit('clr_code')
return form_fields
class NigeriaStudentClearanceEditFormPage(StudentClearanceEditFormPage):
""" View to edit student clearance data by student
"""
@property
def form_fields(self):
if self.context.is_postgrad:
form_fields = grok.AutoFields(INigeriaPGStudentClearance).omit(
'clearance_locked', 'nysc_location', 'clr_code', 'officer_comment',
'physical_clearance_date')
else:
form_fields = grok.AutoFields(INigeriaUGStudentClearance).omit(
'clearance_locked', 'clr_code', 'officer_comment',
'physical_clearance_date')
return form_fields
class NigeriaExportPDFCourseRegistrationSlip(ExportPDFCourseRegistrationSlip):
"""Deliver a PDF slip of the context.
"""
omit_fields = ('password', 'suspended', 'suspended_comment',
'phone', 'adm_code', 'sex', 'email', 'date_of_birth', 'current_level',
'flash_notice')
class NigeriaOnlinePaymentDisplayFormPage(OnlinePaymentDisplayFormPage):
""" Page to view an online payment ticket
"""
grok.context(INigeriaStudentOnlinePayment)
form_fields = grok.AutoFields(INigeriaStudentOnlinePayment).omit(
'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item','p_combi')
form_fields[
'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
form_fields[
'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
class NigeriaOnlinePaymentAddFormPage(OnlinePaymentAddFormPage):
""" Page to add an online payment ticket
"""
form_fields = grok.AutoFields(INigeriaStudentOnlinePayment).select(
'p_combi')
class NigeriaOnlinePaymentFakeApproveView(OnlinePaymentFakeApproveView):
""" Disable payment approval view for students.
This view is used for browser tests only and
has to be neutralized here!
"""
grok.name('fake_approve')
grok.require('waeup.managePortal')
def update(self):
return
class NigeriaExportPDFPaymentSlip(ExportPDFPaymentSlip):
"""Deliver a PDF slip of the context.
"""
grok.context(INigeriaStudentOnlinePayment)
form_fields = grok.AutoFields(INigeriaStudentOnlinePayment).omit(
'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item',
'p_split_data','p_combi')
form_fields['creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
form_fields['payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
omit_fields = ('password', 'suspended', 'suspended_comment', 'phone',
'adm_code', 'sex', 'email', 'date_of_birth', 'current_level',
'flash_notice')
class NigeriaAccommodationManageFormPage(AccommodationManageFormPage):
""" Page to manage bed tickets.
This manage form page is for both students and students officers.
"""
with_hostel_selection = False
class NigeriaBedTicketAddPage(BedTicketAddPage):
""" Page to add a bed ticket
"""
with_ac = True
with_bedselection = False
class NigeriaExportPDFBedTicketSlip(ExportPDFBedTicketSlip):
"""Deliver a PDF slip of the context.
"""
omit_fields = ('password', 'suspended', 'suspended_comment',
'phone', 'adm_code', 'email', 'date_of_birth', 'current_level',
'flash_notice')
class StudentPassportActionButton(StudentPassportActionButton):
@property
def target_url(self):
# Passport pictures must not be editable if application slip
# exists.
slip = getUtility(IExtFileStore).getFileByContext(
self.context, 'application_slip')
PORTRAIT_CHANGE_STATES = getUtility(IStudentsUtils).PORTRAIT_CHANGE_STATES
if self.context.state not in PORTRAIT_CHANGE_STATES or slip is not None:
return ''
return self.view.url(self.view.context, self.target)
class NigeriaStudentFilesUploadPage(StudentFilesUploadPage):
""" View to upload passport picture.
Students are not allowed to change the picture if they
passed the regular Kofa application.
"""
def update(self):
# Passport pictures must not be editable if application slip
# exists.
slip = getUtility(IExtFileStore).getFileByContext(
self.context, 'application_slip')
PORTRAIT_CHANGE_STATES = getUtility(IStudentsUtils).PORTRAIT_CHANGE_STATES
if self.context.state not in PORTRAIT_CHANGE_STATES or slip is not None:
emit_lock_message(self)
return
super(StudentFilesUploadPage, self).update()
return
class ClearStudentFinancially(UtilityView, grok.View):
""" Clear student financially by financial clearance officer
"""
grok.context(INigeriaStudent)
grok.name('clear_financially')
grok.require('waeup.clearStudentFinancially')
def update(self):
if self.context.financially_cleared_by:
self.flash(_('This student has already been financially cleared.'),
type="danger")
self.redirect(self.url(self.context))
return
user = get_current_principal()
if user is None:
usertitle = 'system'
else:
usertitle = getattr(user, 'public_name', None)
if not usertitle:
usertitle = user.title
self.context.financially_cleared_by = usertitle
self.context.financial_clearance_date = datetime.utcnow()
self.context.writeLogMessage(self,'financially cleared')
history = IObjectHistory(self.context)
history.addMessage('Financially cleared')
self.flash(_('Student has been financially cleared.'))
self.redirect(self.url(self.context))
return
def render(self):
return
class WithdrawFinancialClearance(UtilityView, grok.View):
""" Withdraw financial clearance by financial clearance officer
"""
grok.context(INigeriaStudent)
grok.name('withdraw_financial_clearance')
grok.require('waeup.clearStudentFinancially')
def update(self):
if not self.context.financially_cleared_by:
self.flash(_('This student has not yet been financially cleared.'),
type="danger")
self.redirect(self.url(self.context))
return
self.context.financially_cleared_by = None
self.context.financial_clearance_date = None
self.context.writeLogMessage(self,'financial clearance withdrawn')
history = IObjectHistory(self.context)
history.addMessage('Financial clearance withdrawn')
self.flash(_('Financial clearance withdrawn.'))
self.redirect(self.url(self.context))
return
def render(self):
return
cleared_note = """
Financially cleared on %s by %s.
"""
class NigeriaExportPDFFinancialClearancePage(UtilityView, grok.View):
"""Deliver a PDF financial clearance slip.
"""
grok.context(INigeriaStudent)
grok.name('fee_payment_history.pdf')
grok.require('waeup.viewStudent')
prefix = 'form'
omit_fields = (
'suspended', 'phone',
'adm_code', 'suspended_comment',
'date_of_birth', 'current_level',
'flash_notice')
form_fields = None
@property
def label(self):
portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
return translate(_('Fee Payment History for'),
'waeup.kofa', target_language=portal_language) \
+ ' %s' % self.context.display_fullname
def _sigsInFooter(self):
if not checkPermission('waeup.clearStudentFinancially', self.context):
return ()
return (_('Date, Checking Officer Signature'),
_('Date, Approving Officer Signature'),
)
@property
def note(self):
if self.context.financially_cleared_by:
tz = getUtility(IKofaUtils).tzinfo
try:
timestamp = to_timezone(
self.context.financial_clearance_date, tz).strftime(
"%Y-%m-%d %H:%M:%S")
except ValueError:
return
return cleared_note % (
timestamp, self.context.financially_cleared_by)
return
@property
def tabletitle(self):
portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
tabletitle = []
tabletitle.append(translate(_('Successful Payments'), 'waeup.kofa',
target_language=portal_language))
return tabletitle
def render(self):
portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
P_ID = translate(_('Payment Id'), 'waeup.kofa', target_language=portal_language)
#CD = translate(_('Creation Date'), 'waeup.kofa', target_language=portal_language)
PD = translate(_('Payment Date'), 'waeup.kofa', target_language=portal_language)
CAT = translate(_('Payment Category'), 'waeup.kofa', target_language=portal_language)
ITEM = translate(_('Payment Item'), 'waeup.kofa', target_language=portal_language)
AMT = translate(_('Amount (Naira)'), 'waeup.kofa', target_language=portal_language)
SSS = translate(_('Payment Session'), 'waeup.kofa', target_language=portal_language)
studentview = StudentBasePDFFormPage(self.context.student,
self.request, self.omit_fields)
students_utils = getUtility(IStudentsUtils)
tabledata = []
tableheader = []
tabledata.append(sorted(
[value for value in self.context['payments'].values()
if value.p_state in ('paid', 'waived')], key=lambda value: value.p_session))
tableheader.append([(P_ID,'p_id', 4.2),
#(CD,'creation_date', 3),
(PD,'formatted_p_date', 3),
(CAT,'category', 3),
(ITEM, 'p_item', 3),
(AMT, 'amount_auth', 2),
(SSS, 'p_session', 2),
])
return students_utils.renderPDF(
self, 'financial_clearance_slip.pdf',
self.context.student, studentview,
tableheader=tableheader,
tabledata=tabledata,
signatures=None,
sigs_in_footer=self._sigsInFooter(),
omit_fields=self.omit_fields,
note=self.note
)