## $Id: browser.py 16797 2022-02-10 16:56:19Z 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 datetime import datetime
from zope.i18n import translate
from zope.security import checkPermission
from zope.schema.interfaces import ConstraintNotSatisfied
from zope.formlib.textwidgets import BytesDisplayWidget
from zope.component import getUtility
from hurry.workflow.interfaces import IWorkflowInfo
from waeup.kofa.interfaces import (
    REQUESTED, IExtFileStore, IKofaUtils, IObjectHistory)
from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
from waeup.kofa.browser.layout import action, KofaEditFormPage, UtilityView, KofaPage
from waeup.kofa.students.browser import (
    StudentBaseEditFormPage,
    StudyLevelEditFormPage, StudyLevelDisplayFormPage,
    StudentBasePDFFormPage, ExportPDFCourseRegistrationSlip,
    CourseTicketDisplayFormPage,
    CourseTicketManageFormPage,
    StudentTriggerTransitionFormPage,
    msave, emit_lock_message,
    StudentActivateView, StudentDeactivateView,
    ExportPDFTranscriptSlip,
    PaymentsManageFormPage,
    StartClearancePage,
    StudentFilesUploadPage)
from waeup.kofa.students.workflow import (CREATED, ADMITTED, PAID,
    CLEARANCE, REQUESTED, RETURNING, CLEARED, REGISTERED, VALIDATED,
    GRADUATED, TRANSREQ, TRANSVAL, TRANSREL, FORBIDDEN_POSTGRAD_TRANS)
from waeup.kofa.students.interfaces import IStudentsUtils, ICourseTicket
from waeup.kofa.students.workflow import FORBIDDEN_POSTGRAD_TRANS
from kofacustom.nigeria.students.browser import (
    NigeriaOnlinePaymentDisplayFormPage,
    NigeriaStudentBaseManageFormPage,
    NigeriaStudentClearanceEditFormPage,
    NigeriaOnlinePaymentAddFormPage,
    NigeriaExportPDFPaymentSlip,
    NigeriaExportPDFClearanceSlip,
    NigeriaExportPDFBedTicketSlip,
    NigeriaStudentPersonalDisplayFormPage,
    NigeriaStudentPersonalManageFormPage,
    NigeriaStudentPersonalEditFormPage,
    NigeriaAccommodationManageFormPage,
    NigeriaAccommodationDisplayFormPage,
    NigeriaStudentBaseDisplayFormPage,
    NigeriaStudentFilesUploadPage,
    )
from waeup.uniben.students.interfaces import (
    ICustomStudent,
    ICustomStudentBase,
    ICustomStudentOnlinePayment,
    ICustomStudentStudyCourse,
    ICustomStudentStudyLevel,
    ICustomUGStudentClearance,
    ICustomPGStudentClearance,
    ICustomStudentPersonal,
    ICustomStudentPersonalEdit,
    IMedicalHistory,
    ICustomCourseTicket)
from waeup.uniben.students.deplinks import DEPLINKS
from waeup.uniben.interfaces import MessageFactory as _

class CustomStudentBaseDisplayFormPage(NigeriaStudentBaseDisplayFormPage):
    """ Page to display student base data
    """
    form_fields = grok.AutoFields(ICustomStudentBase).omit(
        'password', 'suspended', 'suspended_comment',
        'flash_notice', 'provisionally_cleared', 'parents_email')
    form_fields[
        'financial_clearance_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')

class CustomStudentBaseManageFormPage(NigeriaStudentBaseManageFormPage):
    """ View to manage student base data
    """
    form_fields = grok.AutoFields(ICustomStudentBase).omit(
        'student_id', 'adm_code', 'suspended',
        'financially_cleared_by', 'financial_clearance_date',
        'parents_email')

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 CustomStartClearancePage(StartClearancePage):

    @property
    def with_ac(self):
        if self.context.faccode == 'DCOEM':
            return False
        return True

    @property
    def portrait_uploaded(self):
        return True


CLEARANCE_FLASH_MESSAGE = """
If you have not presented for physical clearance, scan your WAEC, NECO
and other O level results scratch cards on one document and
attach to the form below (Scans > O Level Results Scratch Card).
Then come back to check for your successful cleared status as from 3 days
after successful clearance request.
If status is cleared, pay your school charges and proceed to the
Dean's Office to collect the signed eligibility form.
"""

class CustomStudentClearanceEditFormPage(NigeriaStudentClearanceEditFormPage):
    """ View to edit student clearance data by student
    """

    @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')
            form_fields['date_of_birth'].for_display = True
            form_fields['nationality'].for_display = True
            form_fields['lga'].for_display = True
        return form_fields

    def dataNotComplete(self):
        store = getUtility(IExtFileStore)
        if self.context.entry_mode in ('ug_ft', 'de_ft') and \
            not store.getFileByContext(self.context, attr=u'passport.jpg'):
            return _('No red background passport picture uploaded.')
        if not store.getFileByContext(self.context, attr=u'birth_certificate.jpg'):
            return _('No birth certificate uploaded.')
        if not store.getFileByContext(self.context, attr=u'ref_let.jpg'):
            return _('No guarantor/referee letter uploaded.')
        if not store.getFileByContext(self.context, attr=u'acc_let.jpg'):
            return _('No acceptance letter uploaded.')
        if not store.getFileByContext(self.context, attr=u'fst_sit_scan.jpg'):
            return _('No first sitting result uploaded.')
        if not store.getFileByContext(self.context, attr=u'secr_cults.jpg'):
            return _('No affidavit of non-membership of secret cults uploaded.')
        if not store.getFileByContext(self.context, attr=u'olevel_sc.jpg'):
            return _('No O level results scratch card uploaded.')
        return False

    #def update(self):
    #    self.flash(CLEARANCE_FLASH_MESSAGE, type="warning")
    #    return super(CustomStudentClearanceEditFormPage, self).update()

class CustomOnlinePaymentAddFormPage(NigeriaOnlinePaymentAddFormPage):
    """ Page to add an online payment ticket
    """
    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).select(
        'p_combi')

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', 'p_combi')
    form_fields['creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
    form_fields['payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')


class CustomExportPDFClearanceSlip(NigeriaExportPDFClearanceSlip):
    """Deliver a PDF slip of the context.
    """

    @property
    def omit_fields(self):
        omit_fields = ('password', 'suspended', 'suspended_comment',
                       'phone', 'adm_code', 'email', 'date_of_birth',
                       'flash_notice')
        if self.context.is_jupeb:
            omit_fields += ('faculty', 'department')
        return omit_fields

    @property
    def label(self):
        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
        line0 = ''
        if self.context.is_jupeb:
            line0 = 'Joint Universities Preliminary Examinations Board (JUPEB)\n'
        line1 = translate(_('Clearance Slip of'),
            'waeup.kofa', target_language=portal_language) \
            + ' %s' % self.context.display_fullname
        return '%s%s' % (line0, line1)

    def _sigsInFooter(self):
        isStudent = getattr(
            self.request.principal, 'user_type', None) == 'student'
        if not isStudent and self.context.state in (CLEARED, RETURNING):
            return (_('Date, Student Signature'),
                    _('Date, Clearance Officer Signature'),
                    )
        return ()

    def render(self):
        studentview = StudentBasePDFFormPage(self.context.student,
            self.request, self.omit_fields)
        students_utils = getUtility(IStudentsUtils)
        return students_utils.renderPDF(
            self, 'clearance_slip.pdf',
            self.context.student, studentview, signatures=self._signatures(),
            sigs_in_footer=self._sigsInFooter(), show_scans=False,
            omit_fields=self.omit_fields)


class ExportClearanceInvitationSlip(UtilityView, grok.View):
    """Deliver an invitation letter to physical clearance.

    This form page is available only in Uniben.
    """
    grok.context(ICustomStudent)
    grok.name('clearance_invitation_slip.pdf')
    grok.require('waeup.viewStudent')
    prefix = 'form'

    label = u'Invitation Letter for Physical Clearance'

    omit_fields = (
        'suspended', 'phone', 'email',
        'adm_code', 'suspended_comment',
        'date_of_birth', 'current_level',
        'department', 'current_mode',
        'entry_session', 'matric_number', 'sex',
        'flash_notice')

    form_fields = []

    @property
    def note(self):
        if self.context.physical_clearance_date:
            return """
<br /><br /><br /><br /><font size='12'>
Dear %s,
<br /><br /><br />
You are invited for your physical clearance on:
<br /><br />
<strong>%s</strong>.
<br /><br />
Please bring along this letter of invitation to the University Main Auditorium
<br /><br />
on your clearance date.
<br /><br /><br />
Signed,
<br /><br />
The Registrar<br />
</font>

""" % (self.context.display_fullname, self.context.physical_clearance_date)
        return


    def update(self):
        if self.context.student.state != REQUESTED \
            or not  self.context.student.physical_clearance_date:
            self.flash(_('Forbidden'), type="warning")
            self.redirect(self.url(self.context))

    def render(self):
        studentview = StudentBasePDFFormPage(self.context.student,
            self.request, self.omit_fields)
        students_utils = getUtility(IStudentsUtils)
        return students_utils.renderPDF(
            self, 'clearance_invitation_slip',
            self.context.student, studentview,
            omit_fields=self.omit_fields,
            note=self.note)

class ExportExaminationScheduleSlip(UtilityView, grok.View):
    """Deliver a examination schedule slip.

    This form page is available only in Uniben and AAUE.
    """
    grok.context(ICustomStudent)
    grok.name('examination_schedule_slip.pdf')
    grok.require('waeup.viewStudent')
    prefix = 'form'

    label = u'Examination Schedule Slip'

    omit_fields = (
        'suspended', 'phone', 'email',
        'adm_code', 'suspended_comment',
        'date_of_birth', 'current_level',
        'current_mode',
        'entry_session',
        'flash_notice')

    form_fields = []

    @property
    def note(self):
        return """
<br /><br /><br /><br /><font size='12'>
Your examination date, time and venue is scheduled as follows:
<br /><br />
<strong>%s</strong>
</font>

""" % self.context.flash_notice
        return


    def update(self):
        if not self.context.flash_notice \
            or not 'exam' in self.context.flash_notice.lower():
            self.flash(_('Forbidden'), type="warning")
            self.redirect(self.url(self.context))

    def render(self):
        studentview = StudentBasePDFFormPage(self.context.student,
            self.request, self.omit_fields)
        students_utils = getUtility(IStudentsUtils)
        return students_utils.renderPDF(
            self, 'examination_schedule_slip',
            self.context.student, studentview,
            omit_fields=self.omit_fields,
            note=self.note)

class SwitchLibraryAccessView(UtilityView, grok.View):
    """ Switch the library attribute
    """
    grok.context(ICustomStudent)
    grok.name('switch_library_access')
    grok.require('waeup.switchLibraryAccess')

    def update(self):
        if self.context.library:
            self.context.library = False
            self.context.writeLogMessage(self, 'library access disabled')
            self.flash(_('Library access disabled'))
        else:
            self.context.library = True
            self.context.writeLogMessage(self, 'library access enabled')
            self.flash(_('Library access enabled'))
        self.redirect(self.url(self.context))
        return

    def render(self):
        return

class ExportJHLIdCard(UtilityView, grok.View):
    """Deliver an id card for the John Harris Library.
    """
    grok.context(ICustomStudent)
    grok.name('jhl_idcard.pdf')
    grok.require('waeup.viewStudent')
    prefix = 'form'

    label = u"John Harris Library Clearance"

    omit_fields = (
        'suspended', 'email', 'phone',
        'adm_code', 'suspended_comment',
        'date_of_birth',
        'current_mode', 'certificate',
        'entry_session',
        'flash_notice')

    form_fields = []

    def _sigsInFooter(self):
        isStudent = getattr(
            self.request.principal, 'user_type', None) == 'student'
        if isStudent:
            return ''
        return (_("Date, Reader's Signature"),
                _("Date, Circulation Librarian's Signature"),
                )

    def update(self):
        if not self.context.library:
            self.flash(_('Forbidden!'), type="danger")
            self.redirect(self.url(self.context))
        return

    @property
    def note(self):
        return """
<br /><br /><br /><br /><font size='12'>
This is to certify that the bearer whose photograph and other details appear
 overleaf is a registered user of <b>John Harris Library, University of Benin</b>.
 The card is not transferable. A replacement fee is charged for a loss,
 mutilation or otherwise. If found, please, return to John Harris Library,
 University of Benin, Benin City.
</font>

"""
        return

    def render(self):
        studentview = StudentBasePDFFormPage(self.context.student,
            self.request, self.omit_fields)
        students_utils = getUtility(IStudentsUtils)
        return students_utils.renderPDF(
            self, 'jhl_idcard',
            self.context.student, studentview,
            omit_fields=self.omit_fields,
            sigs_in_footer=self._sigsInFooter(),
            note=self.note)

class ExportJUPEBResultSlip(ExportExaminationScheduleSlip):
    """Deliver a JUPEB result slip.

    This form page is available only in Uniben.
    """

    grok.name('jupeb_result_slip.pdf')
    label = u'JUPEB Result Slip'

    @property
    def note(self):
        return """
<br /><br /><br /><br /><font size='12'>
<strong>%s</strong>
</font>
<br /><br /><br /><br />
<font size='8'>
Key: A = 5, B = 4, C = 3, D = 2, E = 1, F = 0, X = Absent, Q = Cancelled
</font>

""" % self.context.flash_notice
        return

    def update(self):
        if not self.context.flash_notice or not self.context.is_jupeb \
            or not 'results' in self.context.flash_notice.lower():
            self.flash(_('Forbidden'), type="warning")
            self.redirect(self.url(self.context))

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[
        'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')

class CustomStudentPersonalManageFormPage(
    NigeriaStudentPersonalManageFormPage):
    """ Page to manage personal data
    """

    form_fields = grok.AutoFields(ICustomStudentPersonal)
    form_fields['personal_updated'].for_display = True
    form_fields[
        'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')

class CstomStudentPersonalEditFormPage(NigeriaStudentPersonalEditFormPage):
    """ Page to edit personal data
    """
    form_fields = grok.AutoFields(
        ICustomStudentPersonalEdit).omit('personal_updated')

class StudyCourseCOEditFormPage(KofaEditFormPage):
    """ Page to edit the student study course data by clearance officers.

    This form page is available only in Uniben.
    """
    grok.context(ICustomStudentStudyCourse)
    grok.name('edit_level')
    grok.require('waeup.clearStudent')
    label = _('Edit current level')
    pnav = 4
    form_fields = grok.AutoFields(
        ICustomStudentStudyCourse).select('current_level')

    def update(self):
        if not (self.context.is_current and
            self.context.student.state == REQUESTED):
            emit_lock_message(self)
            return
        super(StudyCourseCOEditFormPage, self).update()
        return

    @action(_('Save'), style='primary')
    def save(self, **data):
        try:
            msave(self, **data)
        except ConstraintNotSatisfied:
            # The selected level might not exist in certificate
            self.flash(_('Current level not available for certificate.'))
            return
        #notify(grok.ObjectModifiedEvent(self.context.__parent__))
        return

class CustomStudyLevelEditFormPage(StudyLevelEditFormPage):
    """ Page to edit the student study level data by students.

    """
    grok.template('studyleveleditpage')

class CustomStudyLevelDisplayFormPage(StudyLevelDisplayFormPage):
    """ Page to display student study levels
    """
    grok.template('studylevelpage')

    @property
    def view_scores_allowed(self):
        return checkPermission('waeup.manageStudent', self.context)

class CustomExportPDFCourseRegistrationSlip(
    ExportPDFCourseRegistrationSlip):
    """Deliver a PDF slip of the context.
    """

    form_fields = grok.AutoFields(ICustomStudentStudyLevel).omit(
        'level_verdict', 'gpa', 'level', 'transcript_remark')

    def update(self):
        if self.context.student.state != REGISTERED \
            or self.context.student.current_level != self.context.level:
            self.flash(_('Forbidden'), type="warning")
            self.redirect(self.url(self.context))

    @property
    def tabletitle(self):
        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
        tabletitle = []
        tabletitle.append(translate(_('1st Semester Courses'), 'waeup.kofa',
            target_language=portal_language))
        tabletitle.append(translate(_('2nd Semester Courses'), 'waeup.kofa',
            target_language=portal_language))
        tabletitle.append(translate(_('Level Courses'), 'waeup.kofa',
            target_language=portal_language))
        tabletitle.append(translate(_('1st Trimester Courses'), 'waeup.kofa',
            target_language=portal_language))
        tabletitle.append(translate(_('2nd Trimester Courses'), 'waeup.kofa',
            target_language=portal_language))
        tabletitle.append(translate(_('3rd Trimester Courses'), 'waeup.kofa',
            target_language=portal_language))
        return tabletitle

    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)
        Dept = translate('Dept.', 'waeup.kofa', target_language=portal_language)
        Faculty = translate('Faculty', 'waeup.kofa', target_language=portal_language)
        Cred = translate(_('Credits'), 'waeup.uniben', 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.5),
                             (Title,'title', 5),
                             (Dept,'dcode', 1.5), (Faculty,'fcode', 1.5),
                             (Cred, 'credits', 1.5),
                             ])
        return students_utils.renderPDF(
            self, 'course_registration_slip.pdf',
            self.context.student, studentview,
            tableheader=tableheader,
            tabledata=tabledata,
            omit_fields=self.omit_fields
            )

class ExportPDFCourseResultSlip(ExportPDFCourseRegistrationSlip):
    """Deliver a PDF slip of the context.
    """

    grok.name('course_result_slip.pdf')

    form_fields = grok.AutoFields(ICustomStudentStudyLevel).omit('level')

    @property
    def tabletitle(self):
        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
        tabletitle = []
        tabletitle.append(translate(_('1st Semester Courses'), 'waeup.kofa',
            target_language=portal_language))
        tabletitle.append(translate(_('2nd Semester Courses'), 'waeup.kofa',
            target_language=portal_language))
        tabletitle.append(translate(_('Level Courses'), 'waeup.kofa',
            target_language=portal_language))
        tabletitle.append(translate(_('1st Trimester Courses'), 'waeup.kofa',
            target_language=portal_language))
        tabletitle.append(translate(_('2nd Trimester Courses'), 'waeup.kofa',
            target_language=portal_language))
        tabletitle.append(translate(_('3rd Trimester Courses'), 'waeup.kofa',
            target_language=portal_language))
        return tabletitle

    @property
    def label(self):
        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
        lang = self.request.cookies.get('kofa.language', portal_language)
        level_title = translate(self.context.level_title, 'waeup.kofa',
            target_language=lang)
        return translate(_('Course Result Slip'),
            'waeup.uniben', target_language=portal_language) \
            + ' %s' % level_title

    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)
        Dept = translate('Dept.', 'waeup.kofa', target_language=portal_language)
        Faculty = translate('Faculty', 'waeup.kofa', target_language=portal_language)
        Cred = translate(_('Credits'), 'waeup.uniben', target_language=portal_language)
        Grade = translate('Grade', 'waeup.kofa', 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.5),
                             (Title,'title', 5),
                             (Dept,'dcode', 1.5), (Faculty,'fcode', 1.5),
                             (Cred, 'credits', 1.5),
                             (Grade, 'grade', 1.5),
                             ])
        return students_utils.renderPDF(
            self, 'course_result_slip.pdf',
            self.context.student, studentview,
            tableheader=tableheader,
            tabledata=tabledata,
            omit_fields=self.omit_fields
            )

class CustomCourseTicketDisplayFormPage(CourseTicketDisplayFormPage):
    """ Page to display course tickets
    """
    form_fields = grok.AutoFields(ICustomCourseTicket).omit('score')

class CustomCourseTicketManageFormPage(CourseTicketManageFormPage):
    """ Page to manage course tickets
    """

    form_fields = grok.AutoFields(ICustomCourseTicket).omit('course_category')
    form_fields['title'].for_display = True
    form_fields['fcode'].for_display = True
    form_fields['dcode'].for_display = True
    form_fields['semester'].for_display = True
    form_fields['passmark'].for_display = True
    form_fields['credits'].for_display = True
    form_fields['mandatory'].for_display = False
    form_fields['automatic'].for_display = True
    form_fields['carry_over'].for_display = True
    form_fields['ticket_session'].for_display = True

class CustomStudentActivateView(StudentActivateView):
    """ Activate student account
    """

    def update(self):
        self.context.suspended = False
        self.context.writeLogMessage(self, 'account activated')
        history = IObjectHistory(self.context)
        history.addMessage('Student account activated', user='undisclosed')
        self.flash(_('Student account has been activated.'))
        self.redirect(self.url(self.context))
        return

class CustomStudentDeactivateView(StudentDeactivateView):
    """ Deactivate student account
    """
    def update(self):
        self.context.suspended = True
        self.context.writeLogMessage(self, 'account deactivated')
        history = IObjectHistory(self.context)
        history.addMessage('Student account deactivated', user='undisclosed')
        self.flash(_('Student account has been deactivated.'))
        self.redirect(self.url(self.context))
        return

class CustomExportPDFTranscriptSlip(ExportPDFTranscriptSlip):
    """Deliver a PDF slip of the context.
    """

    def _sigsInFooter(self):
        isStudent = getattr(
            self.request.principal, 'user_type', None) == 'student'
        if not isStudent and self.context.student.state in (TRANSVAL, TRANSREL):
            return (_('D. R. (Exams & Records)'),_('Current Dean of Faculty'),)
        return ()

    #def _signatures(self):
    #    return ([(
    #        'Current HD<br /> D. R. (Exams & Records)<br /> '
    #        'For: Registrar')],)

    def render(self):
        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
        Term = translate(_('Term'), 'waeup.kofa', target_language=portal_language)
        Code = translate(_('Code'), 'waeup.kofa', target_language=portal_language)
        Title = translate(_('Title'), 'waeup.kofa', target_language=portal_language)
        Cred = translate(_('Credits'), 'waeup.kofa', target_language=portal_language)
        #Score = translate(_('Score'), 'waeup.kofa', target_language=portal_language)
        Grade = translate(_('Grade'), 'waeup.kofa', target_language=portal_language)
        studentview = StudentBasePDFFormPage(self.context.student,
            self.request, self.omit_fields)
        students_utils = getUtility(IStudentsUtils)

        tableheader = [(Code,'code', 2.5),
                         (Title,'title', 8.5),
                         (Term, 'semester', 1.5),
                         (Cred, 'credits', 1.5),
                         #(Score, 'score', 1.5),
                         (Grade, 'grade', 1.5),
                         ]

        pdfstream = students_utils.renderPDFTranscript(
            self, 'transcript.pdf',
            self.context.student, studentview,
            omit_fields=self.omit_fields,
            tableheader=tableheader,
            signatures=self._signatures(),
            sigs_in_footer=self._sigsInFooter(),
            digital_sigs=self._digital_sigs(),
            save_file=self._save_file(),
            )
        if not pdfstream:
            self.redirect(self.url(self.context.student))
            return
        return pdfstream

class CustomExportPDFBedTicketSlip(NigeriaExportPDFBedTicketSlip):
    """Deliver a PDF slip of the context.
    """
    omit_fields = ('password', 'suspended', 'suspended_comment',
        'phone', 'adm_code', 'email', 'date_of_birth', 'flash_notice')

class CustomPaymentsManageFormPage(PaymentsManageFormPage):
    """ Page to manage the student payments. This manage form page is for
    both students and students officers. Uniben does not allow students
    to remove any payment ticket.
    """
    @property
    def manage_payments_allowed(self):
        return checkPermission('waeup.manageStudent', self.context)

class CustomAccommodationDisplayFormPage(NigeriaAccommodationDisplayFormPage):
    """ Page to view bed tickets.
    """
    with_hostel_selection = True

class CustomAccommodationManageFormPage(NigeriaAccommodationManageFormPage):
    """ Page to manage bed tickets.
    This manage form page is for both students and students officers.
    """
    with_hostel_selection = True

class CustomStudentBaseEditFormPage(StudentBaseEditFormPage):
    """ View to edit student base data
    """
    form_fields = grok.AutoFields(ICustomStudentBase).select(
        'email', 'phone')
    form_fields['email'].field.required = True

class CustomStudentFilesUploadPage(NigeriaStudentFilesUploadPage):
    """ View to upload passport picture.

    Students are not allowed to change the picture if they
    passed the regular Kofa application.
    """

    def update(self):
        # Uniben: Only 2020 session students are allowed to edit the picture.
        if self.context.entry_session != 2020:
            emit_lock_message(self)
            return
        if self.context.entry_mode not in ('ug_ft', 'de_ft'):
            emit_lock_message(self)
            return
        PORTRAIT_CHANGE_STATES = getUtility(IStudentsUtils).PORTRAIT_CHANGE_STATES
        if self.context.state not in PORTRAIT_CHANGE_STATES:
            emit_lock_message(self)
            return
        super(StudentFilesUploadPage, self).update()
        return




from zope.schema.vocabulary import SimpleVocabulary
from zope.formlib.itemswidgets import RadioWidget
from zope.formlib.itemswidgets import SelectWidget, DropdownWidget

def CustomBooleanRadioWidget(field, request, true=_('yes'), false=_('no')):
    vocabulary = SimpleVocabulary.fromItems( ((true, True), (false, False)) )
    widget = RadioWidget(field, vocabulary, request)
    widget.required = False
    return widget

class StudentMedicalHistoryEditFormPage(KofaEditFormPage):
    """ Page to edit medical data
    """
    grok.context(ICustomStudent)
    grok.name('edit_medical')
    grok.require('waeup.handleStudent')
    label = _('Medical Questionnaire')
    pnav = 4

    def _medicalQuestPaymentMade(self, student, session):
        if len(student['payments']):
            for ticket in student['payments'].values():
                if ticket.p_state == 'paid' and \
                    ticket.p_category == 'medical_quest' and \
                    ticket.p_session == session:
                    return True
        return False

    def update(self):
        if not self._medicalQuestPaymentMade(
            self.context, self.context.current_session):
            self.flash('Please pay medical questionnaire payment first.',
                type="warning")
            self.redirect(self.url(self.context))
            return
        return super(StudentMedicalHistoryEditFormPage, self).update()

    @property
    def form_fields(self):
        form_fields = grok.AutoFields(IMedicalHistory)
        form_fields['medical_updated'].for_display = True
        for field in ('fever', 'headaches', 'catarrh', 'cough', 'sore_throat',
                      'breathing', 'sneezing', 'weakness', 'body_pains',
                      'smell', 'taste', 'asthma', 'hypertension', 'diabetes',
                      'obesity', 'lagos_abuja', 'outside', 'company_suspected',
                      'company_confirmed', 'positive', 'negative',
                      'vaccination'):
            form_fields[field].custom_widget = CustomBooleanRadioWidget
        return form_fields

    @property
    def separators(self):
        return getUtility(IStudentsUtils).SEPARATORS_DICT

    @action(_('Save/Confirm'), style='primary')
    def save(self, **data):
        msave(self, **data)
        self.context.medical_updated = datetime.utcnow()
        return

class StudentMedicalHistoryManageFormPage(StudentMedicalHistoryEditFormPage):
    """ Page to manage medical data
    """
    grok.name('manage_medical')
    grok.require('waeup.manageStudent')
    label = _('Manage medical questionnaire data')

    def update(self):
        return super(StudentMedicalHistoryEditFormPage, self).update()

class ExportPDFMedicalHistorySlip(grok.View):
    """Deliver a PDF slip of the context.
    """
    grok.context(ICustomStudent)
    grok.name('medical_questionnaire_slip.pdf')
    grok.require('waeup.viewStudent')
    prefix = 'form'
    form_fields = grok.AutoFields(IMedicalHistory)

    omit_fields = ('password', 'suspended', 'suspended_comment',
                   'adm_code', 'date_of_birth',
                   'flash_notice', 'current_mode', 'entry_mode',
                   'entry_session', 'parents_email', 'study_course',
                   'current_level', 'reg_number', 'sex',
                   'certificate')

    @property
    def title(self):
        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
        return translate(_('Medical Questionnaire'), 'waeup.kofa',
            target_language=portal_language)

    @property
    def label(self):
        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
        return translate(_('Medical Questionnaire Slip of'),
            'waeup.kofa', target_language=portal_language) \
            + ' %s' % self.context.display_fullname

    def render(self):
        studentview = StudentBasePDFFormPage(self.context.student,
            self.request, self.omit_fields)
        students_utils = getUtility(IStudentsUtils)
        return students_utils.renderPDF(
            self, 'medical_questionnaire_slip.pdf',
            self.context.student, studentview,
            omit_fields=self.omit_fields,)

class PlagTestInfoPage(KofaPage):
    "Landing page after plagiation test payment"
    grok.context(ICustomStudentOnlinePayment)
    grok.name('plagtestinfo')
    grok.require('waeup.viewStudent')

    def update(self):
        if self.context.p_state != 'paid' \
            or self.context.p_category != 'plag_test':
            self.flash(_('Forbidden'), type="danger")
            self.redirect(self.url(self.context))
        return super(PlagTestInfoPage, self).update()

    @property
    def facdep(self):
        facdepkey = "%s-%s" % (self.context.student.faccode,
                               self.context.student.depcode)
        return DEPLINKS[facdepkey]