## $Id: browser.py 14279 2016-11-15 12:41:10Z 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)
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')
    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_category')

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')
    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 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 = """
<br /><br /><br />
<strong>Financially cleared on %s by %s.</strong>

"""

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
            )