## $Id: browser.py 14696 2017-06-19 11:48:37Z henrik $
##
## Copyright (C) 2011 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
##
"""UI components for basic applicants and related components.
"""
import grok
import os
from zope.component import getUtility, getAdapter
from zope.i18n import translate
from hurry.workflow.interfaces import IWorkflowState
from waeup.kofa.interfaces import (
IExtFileStore, IFileStoreNameChooser, IKofaUtils)
from zope.formlib.textwidgets import BytesDisplayWidget
from waeup.kofa.utils.helpers import string_from_bytes, file_size
from waeup.kofa.applicants.browser import (
ApplicantCheckStatusPage, ApplicantBaseDisplayFormPage)
from waeup.kofa.applicants.workflow import STARTED, PAID
from waeup.kofa.applicants.viewlets import PDFActionButton
from waeup.kofa.applicants.interfaces import IApplicantRegisterUpdate
from waeup.kofa.browser.layout import UtilityView
from waeup.kofa.students.interfaces import IStudentsUtils
from waeup.kofa.interfaces import IPDF
from waeup.kofa.browser.viewlets import ManageActionButton
from waeup.aaue.interfaces import MessageFactory as _
from kofacustom.nigeria.applicants.browser import (
NigeriaApplicantDisplayFormPage,
NigeriaApplicantManageFormPage,
NigeriaApplicantEditFormPage,
NigeriaPDFApplicationSlip,
NigeriaApplicantRegistrationPage,
NigeriaExportPDFPaymentSlipPage,
)
from kofacustom.nigeria.applicants.interfaces import OMIT_DISPLAY_FIELDS
from waeup.aaue.applicants.interfaces import (
ICustomUGApplicant,
ICustomUGApplicantEdit,
ITranscriptApplicant,
ICertificateRequest,
ICustomApplicant
)
UG_OMIT_FIELDS = (
'hq_type', 'hq_fname', 'hq_matric_no',
'hq_degree', 'hq_school', 'hq_session', 'hq_disc',
'hq_type2', 'hq_fname2', 'hq_matric_no2',
'hq_degree2', 'hq_school2', 'hq_session2', 'hq_disc2',
'hq_type3', 'hq_fname3', 'hq_matric_no3',
'hq_degree3', 'hq_school3', 'hq_session3', 'hq_disc3',
'nysc_year',
'nysc_location',
'nysc_lga',
'employer',
'emp_position',
'emp_start',
'emp_end',
'emp_reason',
'employer2',
'emp2_position',
'emp2_start',
'emp2_end',
'emp2_reason',
'former_matric',
)
UG_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
'jamb_subjects_list', 'master_sheet_number') + UG_OMIT_FIELDS
UG_OMIT_PDF_FIELDS = UG_OMIT_DISPLAY_FIELDS + UG_OMIT_FIELDS + (
'alr_fname', 'alr_no', 'alr_date',
'alr_results', 'notice')
UG_OMIT_MANAGE_FIELDS = (
'special_application','jamb_subjects_list',) + UG_OMIT_FIELDS
UG_OMIT_EDIT_FIELDS = UG_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
'student_id',
'notice',
'jamb_age',
'jamb_subjects',
'jamb_score',
'jamb_reg_number',
'aggregate',
'master_sheet_number',
'screening_venue',
'screening_score',
'screening_date'
)
UDE_OMIT_FIELDS = (
'nysc_year',
'nysc_location',
'nysc_lga',
'employer',
'emp_position',
'emp_start',
'emp_end',
'emp_reason',
'employer2',
'emp2_position',
'emp2_start',
'emp2_end',
'emp2_reason',
'former_matric',
)
UDE_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
'jamb_subjects_list', 'master_sheet_number') + UDE_OMIT_FIELDS
UDE_OMIT_PDF_FIELDS = UDE_OMIT_DISPLAY_FIELDS + UDE_OMIT_FIELDS + (
'alr_fname', 'alr_no', 'alr_date',
'alr_results', 'notice')
UDE_OMIT_MANAGE_FIELDS = (
'special_application','jamb_subjects_list',) + UDE_OMIT_FIELDS
UDE_OMIT_EDIT_FIELDS = UDE_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
'student_id',
'notice',
'jamb_age',
'jamb_subjects',
'jamb_score',
'jamb_reg_number',
'aggregate',
'master_sheet_number',
'screening_venue',
'screening_score',
'screening_date'
)
#UG_OMIT_PDF_FIELDS = tuple([
# element for element in UG_OMIT_PDF_FIELDS if not element == 'phone'])
#UG_OMIT_PDF_FIELDS += (
# 'reg_number','alr_fname', 'alr_no', 'alr_date',
# 'alr_results', 'notice'
# )
PG_OMIT_FIELDS = (
'fst_sit_fname',
'fst_sit_no',
'fst_sit_date',
'fst_sit_type',
'fst_sit_results',
'scd_sit_fname',
'scd_sit_no',
'scd_sit_date',
'scd_sit_type',
'scd_sit_results',
#'programme_type',
'jamb_age',
'jamb_subjects',
'jamb_score',
'jamb_reg_number',
'aggregate'
)
PG_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
'jamb_subjects_list',) + PG_OMIT_FIELDS
PG_OMIT_PDF_FIELDS = PG_OMIT_DISPLAY_FIELDS + PG_OMIT_FIELDS + (
'reg_number','alr_fname', 'alr_no', 'alr_date',
'alr_results', 'notice',
'nysc_year',
'nysc_location',
'nysc_lga',
'former_matric',
)
PG_OMIT_MANAGE_FIELDS = (
'special_application','jamb_subjects_list',) + PG_OMIT_FIELDS
PG_OMIT_EDIT_FIELDS = PG_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
'student_id',
'notice',
)
PTEE_OMIT_FIELDS = (
'jamb_age',
'jamb_subjects',
'jamb_score',
'jamb_reg_number',
'aggregate'
)
PTEE_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
'jamb_subjects_list',) + PTEE_OMIT_FIELDS
PTEE_OMIT_PDF_FIELDS = PTEE_OMIT_DISPLAY_FIELDS + PTEE_OMIT_FIELDS + (
'reg_number','alr_fname', 'alr_no', 'alr_date',
'alr_results', 'notice',
'nysc_year',
'nysc_location',
'nysc_lga',
'employer',
'emp_position',
'emp_start',
'emp_end',
'emp_reason',
'employer2',
'emp2_position',
'emp2_start',
'emp2_end',
'emp2_reason',
'former_matric',
)
PTEE_OMIT_MANAGE_FIELDS = (
'special_application','jamb_subjects_list',) + PTEE_OMIT_FIELDS
PTEE_OMIT_EDIT_FIELDS = PTEE_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
'student_id',
'notice',
)
UPDATE_OMIT_FIELDS = (
'firstname',
'middlename',
'lastname',
'sex',
'lga',
'course1',
)
class CustomApplicantDisplayFormPage(NigeriaApplicantDisplayFormPage):
"""A display view for applicant data.
"""
@property
def form_fields(self):
if self.target is not None and self.target == 'trans':
form_fields = grok.AutoFields(ITranscriptApplicant).omit(
'locked', 'suspended')
form_fields['dispatch_address'].custom_widget = BytesDisplayWidget
form_fields['perm_address'].custom_widget = BytesDisplayWidget
return form_fields
if self.target is not None and self.target == 'cert':
form_fields = grok.AutoFields(ICertificateRequest).omit(
'locked', 'suspended')
form_fields['dispatch_address'].custom_widget = BytesDisplayWidget
form_fields['perm_address'].custom_widget = BytesDisplayWidget
return form_fields
# AAUE is using the same interface for all regular applications.
form_fields = grok.AutoFields(ICustomUGApplicant)
if self.target is not None and self.target.startswith('pg'):
for field in PG_OMIT_DISPLAY_FIELDS:
form_fields = form_fields.omit(field)
elif self.target is not None and self.target in ('ptee',):
for field in PTEE_OMIT_DISPLAY_FIELDS:
form_fields = form_fields.omit(field)
elif self.target is not None and self.target in ('ude',):
for field in UDE_OMIT_DISPLAY_FIELDS:
form_fields = form_fields.omit(field)
else:
for field in UG_OMIT_DISPLAY_FIELDS:
form_fields = form_fields.omit(field)
form_fields['perm_address'].custom_widget = BytesDisplayWidget
form_fields['notice'].custom_widget = BytesDisplayWidget
if not getattr(self.context, 'student_id'):
form_fields = form_fields.omit('student_id')
if not getattr(self.context, 'screening_score'):
form_fields = form_fields.omit('screening_score')
if not getattr(self.context, 'screening_venue'):
form_fields = form_fields.omit('screening_venue')
if not getattr(self.context, 'screening_date'):
form_fields = form_fields.omit('screening_date')
return form_fields
def getCourseAdmitted(self):
"""Return link, title and code in html format to the certificate
admitted.
"""
if self.layout.isApplicant():
return ''
course_admitted = self.context.course_admitted
if getattr(course_admitted, '__parent__',None):
url = self.url(course_admitted)
title = course_admitted.title
code = course_admitted.code
return '%s - %s' %(url,code,title)
return ''
class CustomPDFActionButton(PDFActionButton):
@property
def target_url(self):
if self.context.state in ('initialized', 'started', 'paid') \
or self.context.special or self.view.target in ('trans', 'cert'):
return
return self.view.url(self.view.context, self.target)
class CustomPDFApplicationSlip(NigeriaPDFApplicationSlip):
column_two_fields = ('applicant_id', 'reg_number',
'firstname', 'middlename', 'lastname', 'sex', 'date_of_birth')
#two_columns_design_fields = [
# 'fst_sit_fname', 'fst_sit_no', 'fst_sit_date',
# 'fst_sit_type', 'fst_sit_results',
# 'scd_sit_fname', 'scd_sit_no', 'scd_sit_date',
# 'scd_sit_type', 'scd_sit_results']
def _getCourseAdmittedLink(self, view):
return None
def _getDeptAndFaculty(self):
return [None, None]
@property
def note(self):
note = getattr(self.context.__parent__, 'application_slip_notice', None)
if note:
return '
' + note
if self.context.sex == 'm':
pronoun = 'he'
else:
pronoun = 'she'
return '''
The applicant has acknowledged that, if discovered at any time that %s does not possess
any of the qualifications which %s claims %s has obtained, %s will be expelled from the
University not be re-admitted for the same or any other programme, even if %s has
upgraded previous qualifications or possess additional qualifications.
''' % (
pronoun, pronoun, pronoun, pronoun, pronoun)
@property
def form_fields(self):
# AAUE is using the same interface for all regular applications.
form_fields = grok.AutoFields(ICustomUGApplicant)
if self.target is not None and self.target.startswith('pg'):
for field in PG_OMIT_PDF_FIELDS:
form_fields = form_fields.omit(field)
elif self.target is not None and self.target in ('ptee',):
for field in PTEE_OMIT_PDF_FIELDS:
form_fields = form_fields.omit(field)
elif self.target is not None and self.target in ('ude',):
for field in UDE_OMIT_PDF_FIELDS:
form_fields = form_fields.omit(field)
else:
for field in UG_OMIT_PDF_FIELDS:
form_fields = form_fields.omit(field)
if not getattr(self.context, 'student_id'):
form_fields = form_fields.omit('student_id')
if not getattr(self.context, 'screening_score'):
form_fields = form_fields.omit('screening_score')
if not getattr(self.context, 'screening_venue'):
form_fields = form_fields.omit('screening_venue')
if not getattr(self.context, 'screening_date'):
form_fields = form_fields.omit('screening_date')
return form_fields
class CustomApplicantManageFormPage(NigeriaApplicantManageFormPage):
"""A full edit view for applicant data.
"""
@property
def form_fields(self):
if self.target is not None and self.target == 'trans':
form_fields = grok.AutoFields(ITranscriptApplicant)
form_fields['applicant_id'].for_display = True
return form_fields
if self.target is not None and self.target == 'cert':
form_fields = grok.AutoFields(ICertificateRequest)
form_fields['applicant_id'].for_display = True
return form_fields
# AAUE is using the same interface for all regular applications.
form_fields = grok.AutoFields(ICustomUGApplicant)
if self.target is not None and self.target.startswith('pg'):
for field in PG_OMIT_MANAGE_FIELDS:
form_fields = form_fields.omit(field)
elif self.target is not None and self.target in ('ptee',):
for field in PTEE_OMIT_MANAGE_FIELDS:
form_fields = form_fields.omit(field)
elif self.target is not None and self.target in ('ude',):
for field in UDE_OMIT_MANAGE_FIELDS:
form_fields = form_fields.omit(field)
else:
for field in UG_OMIT_MANAGE_FIELDS:
form_fields = form_fields.omit(field)
form_fields['student_id'].for_display = True
form_fields['applicant_id'].for_display = True
return form_fields
class CustomApplicantEditFormPage(NigeriaApplicantEditFormPage):
"""An applicant-centered edit view for applicant data.
"""
def unremovable(self, ticket):
return True
# AAUE applicants never see the 'Remove Selected Tickets' button.
@property
def display_actions(self):
state = IWorkflowState(self.context).getState()
# If the form is unlocked, applicants are allowed to save the form
# and remove unused tickets.
actions = [[_('Save')], []]
# Only in state started they can also add tickets.
if state == STARTED:
actions = [[_('Save')],
[_('Add online payment ticket')]]
# In state paid, they can submit the data and further add tickets
# if the application is special.
elif self.context.special and state == PAID:
actions = [[_('Save'), _('Finally Submit')],
[_('Add online payment ticket')]]
elif state == PAID:
actions = [[_('Save'), _('Finally Submit')], []]
return actions
@property
def form_fields(self):
if self.target is not None and self.target == 'trans':
form_fields = grok.AutoFields(ITranscriptApplicant).omit(
'locked', 'suspended')
form_fields['applicant_id'].for_display = True
form_fields['reg_number'].for_display = True
return form_fields
if self.target is not None and self.target == 'cert':
form_fields = grok.AutoFields(ICertificateRequest).omit(
'locked', 'suspended')
form_fields['applicant_id'].for_display = True
form_fields['reg_number'].for_display = True
# Additional omissions
if self.context.__parent__.code == 'cert5':
for field in ('firstname', 'middlename', 'lastname'):
form_fields[field].for_display = True
return form_fields
# AAUE is using the same interface for all regular applications.
form_fields = grok.AutoFields(ICustomUGApplicantEdit)
if self.target is not None and self.target.startswith('pg'):
for field in PG_OMIT_EDIT_FIELDS:
form_fields = form_fields.omit(field)
elif self.target is not None and self.target in ('ptee',):
for field in PTEE_OMIT_EDIT_FIELDS:
form_fields = form_fields.omit(field)
elif self.target is not None and self.target in ('ude',):
for field in UDE_OMIT_EDIT_FIELDS:
form_fields = form_fields.omit(field)
else:
for field in UG_OMIT_EDIT_FIELDS:
form_fields = form_fields.omit(field)
# Additional omissions
if self.target is not None and self.target in ('ude', 'utme'):
for field in UPDATE_OMIT_FIELDS:
form_fields[field].for_display = True
form_fields['applicant_id'].for_display = True
form_fields['reg_number'].for_display = True
return form_fields
class CustomApplicantRegistrationPage(NigeriaApplicantRegistrationPage):
"""Captcha'd registration page for applicants.
"""
@property
def form_fields(self):
form_fields = None
if self.context.mode == 'update':
form_fields = grok.AutoFields(IApplicantRegisterUpdate).select(
'lastname','reg_number','email')
target = getattr(self.context, 'prefix', None)
if target in ('trans', 'cert'):
form_fields.get('reg_number').field.title = u'Matriculation Number'
else: #if self.context.mode == 'create':
form_fields = grok.AutoFields(ICustomUGApplicantEdit).select(
'firstname', 'middlename', 'lastname', 'email', 'phone')
return form_fields
def _redirect(self, email, password, applicant_id):
# Forward email and credentials to landing page.
self.redirect(self.url(self.context, 'registration_complete',
data = dict(email=email, password=password,
applicant_id=applicant_id)))
return
@property
def _postfix(self):
"""Alumni records have to be imported into several containers.
Therefore a string must be added to their registration number
to make it unique.
"""
if self.context.prefix in ('trans', 'cert'):
return self.context.code
return ''
class CustomExportPDFPaymentSlipPage(NigeriaExportPDFPaymentSlipPage):
@property
def payment_slip_download_warning(self):
return ''
class CustomApplicantCheckStatusPage(ApplicantCheckStatusPage):
"""Captcha'd status checking page for applicants.
"""
grok.template('applicantcheckstatus')
class PaymentReceiptActionButton(ManageActionButton):
grok.order(8) # This button should always be the last one.
grok.context(ICustomApplicant)
grok.view(CustomApplicantDisplayFormPage)
grok.require('waeup.viewApplication')
icon = 'actionicon_pdf.png'
text = _('Download screening invitation letter')
target = 'screening_invitation.pdf'
@property
def target_url(self):
if not self.context.screening_date:
return ''
return self.view.url(self.view.context, self.target)
class ExportScreeningInvitationLetter(UtilityView, grok.View):
"""Deliver a slip with only screening data.
This form page is available only in AAUE.
"""
grok.context(ICustomApplicant)
grok.name('screening_invitation.pdf')
grok.require('waeup.viewApplication')
prefix = 'form'
label = u'Screening Invitation Letter'
form_fields = []
@property
def note(self):
if self.context.screening_date:
year = self.context.__parent__.year
session = '%s/%s' % (year, year + 1)
sdate = self.context.screening_date
stime = ''
if '@' in self.context.screening_date:
sdate = self.context.screening_date.split('@')[0].strip()
stime = self.context.screening_date.split('@')[1].strip()
return """
Dear %s,
You are invited to the Ambrose Alli University %s Admissions Screening Exercise.
Date: %s
Time: %s
Venue: %s
Please bring this letter of invitation and the downloaded application form along with you on your screening date.
You are expected to be available 30 minutes before the commencement of your Screening.
""" % (
self.context.display_fullname,
session,
sdate,
stime,
self.context.screening_venue)
return
@property
def title(self):
return None
def update(self):
if not self.context.screening_date:
self.flash(_('Forbidden'), type="warning")
self.redirect(self.url(self.context))
def render(self):
applicantview = ApplicantBaseDisplayFormPage(self.context, self.request)
students_utils = getUtility(IStudentsUtils)
return students_utils.renderPDF(self,'screening_data.pdf',
self.context, applicantview, note=self.note)