## $Id: test_browser.py 9154 2012-09-04 07:07:44Z 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
##
import os
import shutil
import tempfile
from StringIO import StringIO
from hurry.workflow.interfaces import IWorkflowState
from zope.component.hooks import setSite, clearSite
from zope.component import getUtility, createObject
from zope.interface import verify
from waeup.kofa.app import University
from waeup.kofa.students.tests.test_browser import StudentsFullSetup
from waeup.kofa.testing import FunctionalTestCase
from waeup.kofa.interfaces import (
    IExtFileStore, IFileStoreNameChooser)
from waeup.kofa.students.interfaces import IStudentsUtils
from waeup.aaue.testing import FunctionalLayer


class StudentProcessorTest(FunctionalTestCase):
    """Perform some batching tests.
    """

    layer = FunctionalLayer

    def setUp(self):
        super(StudentProcessorTest, self).setUp()
        # Setup a sample site for each test
        app = University()
        self.dc_root = tempfile.mkdtemp()
        app['datacenter'].setStoragePath(self.dc_root)

        # Prepopulate the ZODB...
        self.getRootFolder()['app'] = app
        # we add the site immediately after creation to the
        # ZODB. Catalogs and other local utilities are not setup
        # before that step.
        self.app = self.getRootFolder()['app']
        # Set site here. Some of the following setup code might need
        # to access grok.getSite() and should get our new app then
        setSite(app)


    def tearDown(self):
        super(StudentProcessorTest, self).tearDown()
        shutil.rmtree(self.workdir)
        shutil.rmtree(self.dc_root)
        clearSite()
        return

class StudentUITests(StudentsFullSetup):
    """Tests for customized student class views and pages
    """

    layer = FunctionalLayer

    def test_manage_payments(self):
        # Add missing configuration data
        self.app['configuration']['2004'].gown_fee = 150.0
        self.app['configuration']['2004'].transfer_fee = 90.0
        #self.app['configuration']['2004'].clearance_fee = 120.0
        self.app['configuration']['2004'].booking_fee = 150.0
        self.app['configuration']['2004'].maint_fee = 180.0

        # Managers can add online payment tickets
        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
        self.browser.open(self.payments_path)
        self.browser.getControl("Add online payment ticket").click()
        self.browser.getControl("Create ticket").click()
        self.assertMatches('...Wrong state...',
                           self.browser.contents)
        IWorkflowState(self.student).setState('cleared')
        self.browser.open(self.payments_path + '/addop')
        self.browser.getControl("Create ticket").click()
        self.assertMatches('...Amount could not be determined...',
                           self.browser.contents)

        self.app['configuration']['2004'].school_fee_base = 6666.0

        self.browser.getControl("Add online payment ticket").click()
        self.browser.getControl("Create ticket").click()
        self.assertMatches('...ticket created...',
                           self.browser.contents)
        ctrl = self.browser.getControl(name='val_id')
        value = ctrl.options[0]
        self.browser.getLink(value).click()
        self.assertMatches('...Amount Authorized...',
                           self.browser.contents)
        # Managers can open payment slip
        self.browser.getLink("Download payment slip").click()
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
        # Set ticket paid
        ticket = self.student['payments'].items()[0][1]
        ticket.p_state = 'paid'
        self.browser.open(self.payments_path + '/addop')
        self.browser.getControl("Create ticket").click()
        self.assertMatches('...This type of payment has already been made...',
                           self.browser.contents)
        self.browser.open(self.payments_path + '/addop')
        # Also the other payments can be made
        self.browser.getControl(name="form.p_category").value = ['gown']
        self.browser.getControl("Create ticket").click()
        self.assertMatches('...ticket created...',
                           self.browser.contents)
        self.browser.open(self.payments_path + '/addop')
        self.browser.getControl(name="form.p_category").value = ['transfer']
        self.browser.getControl("Create ticket").click()
        self.assertMatches('...ticket created...',
                           self.browser.contents)
        self.browser.open(self.payments_path + '/addop')
        self.browser.getControl(
            name="form.p_category").value = ['bed_allocation']
        self.browser.getControl("Create ticket").click()
        self.assertMatches('...ticket created...',
                           self.browser.contents)
        self.browser.open(self.payments_path + '/addop')
        self.browser.getControl(
            name="form.p_category").value = ['hostel_maintenance']
        self.browser.getControl("Create ticket").click()
        self.assertMatches('...ticket created...',
                           self.browser.contents)
        self.browser.open(self.payments_path + '/addop')
        self.browser.getControl(name="form.p_category").value = ['clearance']
        self.browser.getControl("Create ticket").click()
        self.assertMatches('...ticket created...',
                           self.browser.contents)
        # Remove all payments so that we can add a school fee payment again
        keys = [i for i in self.student['payments'].keys()]
        for payment in keys:
            del self.student['payments'][payment]
        self.browser.open(self.payments_path + '/addop')
        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
        self.browser.getControl("Create ticket").click()
        self.assertMatches('...ticket created...',
                           self.browser.contents)
        # We can't add the 2nd instalment ticket because the
        # first one has not yet been approved.
        self.browser.open(self.payments_path + '/addop')
        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
        self.browser.getControl("Create ticket").click()
        self.assertMatches('...1st school fee instalment has not yet been paid...',
                           self.browser.contents)
        # Ok, then we approve the first instalment ...
        ctrl = self.browser.getControl(name='val_id')
        p_id = ctrl.options[0]
        self.browser.open(self.payments_path + '/' + p_id + '/approve')
        # ... add the second instalment ...
        self.browser.open(self.payments_path + '/addop')
        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
        self.browser.getControl("Create ticket").click()
        self.assertMatches('...ticket created...',
                           self.browser.contents)
        # ... approve the second instalment ...
        ctrl = self.browser.getControl(name='val_id')
        p_id = ctrl.options[1]
        self.browser.open(self.payments_path + '/' + p_id + '/approve')
        # ... and finally add the 1st instalment for the next session
        # provided that student is returning.
        IWorkflowState(self.student).setState('returning')
        self.browser.open(self.payments_path + '/addop')
        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
        self.browser.getControl("Create ticket").click()
        self.assertMatches('...Session configuration object is not...',
                           self.browser.contents)
        # Uups, we forgot to add a session configuration for next session
        configuration = createObject('waeup.SessionConfiguration')
        configuration.academic_session = 2005
        self.app['configuration'].addSessionConfiguration(configuration)
        self.app['configuration']['2005'].school_fee_base = 7777.0
        self.browser.open(self.payments_path + '/addop')
        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
        self.browser.getControl("Create ticket").click()
        self.assertMatches('...ticket created...',
                           self.browser.contents)
        # If the session configuration doesn't exist an error message will
        # be shown. No other requirement is being checked.
        del self.app['configuration']['2004']
        self.browser.open(self.payments_path)
        self.browser.getControl("Add online payment ticket").click()
        self.browser.getControl("Create ticket").click()
        self.assertMatches('...Session configuration object is not...',
                           self.browser.contents)

    def test_get_returning_data(self):
        # Student is in level 100, session 2004 with verdict A
        utils = getUtility(IStudentsUtils)
        self.assertEqual(utils.getReturningData(self.student),(2005, 200))
        self.student['studycourse'].current_verdict = 'C'
        self.assertEqual(utils.getReturningData(self.student),(2005, 110))
        self.student['studycourse'].current_verdict = 'D'
        self.assertEqual(utils.getReturningData(self.student),(2005, 100))
        return

    def test_set_payment_details(self):
        self.app['configuration']['2004'].gown_fee = 150.0
        self.app['configuration']['2004'].transfer_fee = 90.0
        self.app['configuration']['2004'].booking_fee = 150.0
        self.app['configuration']['2004'].maint_fee = 180.0
        self.app['configuration']['2004'].clearance_fee = 1234.0
        self.app['configuration']['2004'].school_fee_base = 6666.0
        utils = getUtility(IStudentsUtils)

        configuration = createObject('waeup.SessionConfiguration')
        configuration.academic_session = 2005
        self.app['configuration'].addSessionConfiguration(configuration)
        self.app['configuration']['2005'].school_fee_base = 7777.0

        error, payment = utils.setPaymentDetails('schoolfee_1',self.student)
        self.assertEqual(payment, None)
        self.assertEqual(error, u'Wrong state.')

        IWorkflowState(self.student).setState('cleared')
        error, payment = utils.setPaymentDetails('schoolfee_1',self.student)
        self.assertEqual(payment.p_level, 100)
        self.assertEqual(payment.p_session, 2004)
        self.assertEqual(payment.amount_auth, 6666.0)
        self.assertEqual(payment.p_item, u'CERT1')
        self.assertEqual(error, None)

        # Add penalty fee ...
        # ... for cleared
        self.app['configuration']['2004'].penalty_ug = 99.0
        # ... for returning
        self.app['configuration']['2005'].penalty_ug = 88.0
        error, payment = utils.setPaymentDetails('schoolfee_1',self.student)
        self.assertEqual(payment.amount_auth, 6765.0)
        IWorkflowState(self.student).setState('returning')
        error, payment = utils.setPaymentDetails('schoolfee_1',self.student)
        self.assertEqual(payment.p_level, 200)
        self.assertEqual(payment.p_session, 2005)
        self.assertEqual(payment.amount_auth, 7865.0)
        self.assertEqual(payment.p_item, u'CERT1')
        self.assertEqual(error, None)

        error, payment = utils.setPaymentDetails('clearance',self.student)
        self.assertEqual(payment.p_level, 100)
        self.assertEqual(payment.p_session, 2004)
        self.assertEqual(payment.amount_auth, 1234.0)
        self.assertEqual(payment.p_item, u'CERT1')
        self.assertEqual(error, None)

        error, payment = utils.setPaymentDetails('gown',self.student)
        self.assertEqual(payment.p_level, 100)
        self.assertEqual(payment.p_session, 2004)
        self.assertEqual(payment.amount_auth, 150.0)
        self.assertEqual(payment.p_item, u'')
        self.assertEqual(error, None)

        error, payment = utils.setPaymentDetails('hostel_maintenance',self.student)
        self.assertEqual(payment.p_level, 100)
        self.assertEqual(payment.p_session, 2004)
        self.assertEqual(payment.amount_auth, 180.0)
        self.assertEqual(payment.p_item, u'')
        self.assertEqual(error, None)

        error, payment = utils.setPaymentDetails('bed_allocation',self.student)
        self.assertEqual(payment.p_level, 100)
        self.assertEqual(payment.p_session, 2004)
        self.assertEqual(payment.amount_auth, 150.0)
        self.assertEqual(payment.p_item, u'')
        self.assertEqual(error, None)

        error, payment = utils.setPaymentDetails('transfer',self.student)
        self.assertEqual(payment.p_level, 100)
        self.assertEqual(payment.p_session, 2004)
        self.assertEqual(payment.amount_auth, 90.0)
        self.assertEqual(payment.p_item, u'')
        self.assertEqual(error, None)

        error, payment = utils.setPaymentDetails('schoolfee',self.student, 2004, 100)
        self.assertEqual(error, u'Previous session payment not yet implemented.')
        return