## $Id: test_browser.py 13786 2016-03-22 06:20:49Z 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
import pytz
import grok
from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState
from zope.securitypolicy.interfaces import IPrincipalRoleManager
from datetime import datetime, timedelta, date
from mechanize import LinkNotFoundError
from hurry.workflow.interfaces import IWorkflowState
from zope.event import notify
from zope.component.hooks import setSite, clearSite
from zope.component import getUtility, createObject, queryUtility
from zope.catalog.interfaces import ICatalog
from waeup.kofa.app import University
from waeup.kofa.students.tests.test_browser import StudentsFullSetup
from waeup.kofa.students.accommodation import BedTicket
from waeup.kofa.testing import FunctionalTestCase
from waeup.kofa.authentication import LocalRoleSetEvent
from waeup.kofa.browser.tests.test_pdf import samples_dir
from waeup.aaue.testing import FunctionalLayer

SAMPLE_IMAGE = os.path.join(os.path.dirname(__file__), 'test_image.jpg')


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 OfficerUITests(StudentsFullSetup):
    # Tests for Student class views and pages

    layer = FunctionalLayer

    def test_gpa_calculation(self):
        studylevel = createObject(u'waeup.StudentStudyLevel')
        studylevel.level = 100
        studylevel.level_session = 2005
        self.student['studycourse'].entry_mode = 'ug_ft'
        self.student['studycourse'].addStudentStudyLevel(
            self.certificate, studylevel)
        # First course has been added automatically.
        # Set score. 
        studylevel['COURSE1'].score = 55
        # GPA is 3.0.
        self.assertEqual(studylevel.gpa_params[0], 3.0)
        courseticket = createObject('waeup.CourseTicket')
        courseticket.code = 'ANYCODE'
        courseticket.title = u'Any TITLE'
        courseticket.credits = 13
        courseticket.score = 66
        courseticket.semester = 1
        courseticket.dcode = u'ANYDCODE'
        courseticket.fcode = u'ANYFCODE'
        studylevel['COURSE2'] = courseticket
        # total credits
        self.assertEqual(self.student['studycourse']['100'].gpa_params[1], 23)
        # weigheted credits = 3 * 10 + 4 * 13
        self.assertEqual(self.student['studycourse']['100'].gpa_params[2], 82.0)
        # sgpa = 82 / 23
        self.assertEqual(self.student['studycourse']['100'].gpa_params[0], 3.565)
        return

    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'].booking_fee = 150.0
        self.app['configuration']['2004'].maint_fee = 180.0
        self.app['configuration']['2004'].late_fee = 80.0

        # Managers can add online payment tickets
        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
        self.browser.open(self.payments_path)
        self.browser.getLink("Add current session payment ticket").click()
        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
        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.browser.getControl(name="form.p_category").value = ['schoolfee']
        # Accepotance fee must be paid first
        #self.browser.getControl("Create ticket").click()
        #self.assertMatches('...Please pay acceptance fee first...',
        #                   self.browser.contents)
        self.app['configuration']['2004'].clearance_fee = 666.0
        self.browser.getControl(name="form.p_category").value = ['clearance_incl']
        self.browser.getControl("Create ticket").click()
        ctrl = self.browser.getControl(name='val_id')
        cpt_value = ctrl.options[0]
        # School fee payment ticket can be added ...
        self.student['studycourse'].certificate.school_fee_1 = 6666.0
        self.student.nationality = u'NG'
        self.browser.open(self.payments_path + '/addop')
        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
        self.browser.getControl("Create ticket").click()
        self.assertMatches('...ticket created...',
                           self.browser.contents)
        # ... but not paid through the query_history page.
        ctrl = self.browser.getControl(name='val_id')
        sfpt_value = ctrl.options[1]
        self.student['studycourse'].entry_session = 2013
        self.browser.open(self.payments_path + '/' + sfpt_value)
        self.browser.getLink("Query eTranzact History").click()
        self.assertMatches('...alert-danger">Please pay acceptance fee first...',
                           self.browser.contents)
        # If clearance/acceptance fee is paid ...
        self.student['payments'][cpt_value].approveStudentPayment()
        self.browser.getLink("Query eTranzact History").click()
        # ... query_history page is accessible.
        self.assertMatches(
            '...<h1 class="kofa-content-label">Requery eTranzact History</h1>...',
            self.browser.contents)
        # Managers can open school fee payment slip
        self.browser.open(self.payments_path + '/' + sfpt_value)
        self.browser.getLink("Download payment slip").click()
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
        # If school fee ticket is paid, the student is automatically set to
        # school fee paid...
        ticket = self.student['payments'][sfpt_value].approveStudentPayment()
        self.assertEqual(self.student.state, 'school fee paid')
        # ... no further school fee ticket can be added.
        self.browser.open(self.payments_path + '/addop')
        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
        self.browser.getControl("Create ticket").click()
        self.assertMatches('...Wrong state...',
                           self.browser.contents)
        self.browser.open(self.payments_path + '/addop')
        self.browser.getControl(name="form.p_category").value = ['late_registration']
        self.browser.getControl("Create ticket").click()
        self.assertMatches('...ticket created...',
                           self.browser.contents)
        return

    def test_for_instalment_payments(self):
        self.student['studycourse'].certificate.study_mode = 'ug_pt'
        self.student['studycourse'].certificate.school_fee_1 = 6666.0
        self.app['configuration']['2004'].union_fee = 1250.0
        self.app['configuration']['2004'].welfare_fee = 750.0
        self.student.nationality = u'NG'
        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
        self.browser.open(self.payments_path + '/addop')
        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
        self.browser.getControl("Create ticket").click()
        self.assertTrue(
            'Part-time students are not allowed' in self.browser.contents)
        self.student['studycourse'].certificate.study_mode = 'ug_ft'
        self.browser.open(self.payments_path + '/addop')
        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
        self.browser.getControl("Create ticket").click()
        self.assertTrue(
            'Wrong state. Only students in state \'cleared\' are allowed to pay by instalments'
            in self.browser.contents)
        IWorkflowState(self.student).setState('cleared')
        self.browser.open(self.payments_path + '/addop')
        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
        self.browser.getControl("Create ticket").click()
        self.assertTrue('ticket created' in 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 ...
        self.browser.open(self.payments_path)
        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.assertTrue('ticket created' in 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')
        self.assertEqual(self.student['payments'].values()[0].p_category, 'schoolfee_1')
        self.assertEqual(self.student['payments'].values()[1].p_category, 'schoolfee_2')
        # (6666-250)/2 + 1250 + 750 - 500 + 250
        self.assertEqual(self.student['payments'].values()[0].amount_auth, 4958.0)
        # (6666-250)/2 + 250
        self.assertEqual(self.student['payments'].values()[1].amount_auth, 3458.0)
        return

    def test_manage_payments_bypass_ac_creation(self):
        self.student['studycourse'].certificate.school_fee_1 = 6666.0
        self.student.nationality = u'NG'
        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
        self.browser.open(self.payments_path)
        IWorkflowState(self.student).setState('cleared')
        self.browser.getLink("Add current session payment ticket").click()
        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
        self.browser.getControl("Create ticket").click()
        ctrl = self.browser.getControl(name='val_id')
        value = ctrl.options[0]
        self.browser.getLink(value).click()
        payment_url = self.browser.url
        logfile = os.path.join(
            self.app['datacenter'].storage, 'logs', 'students.log')
        # The ticket can be found in the payments_catalog
        cat = queryUtility(ICatalog, name='payments_catalog')
        results = list(cat.searchResults(p_state=('unpaid', 'unpaid')))
        self.assertTrue(len(results), 1)
        self.assertTrue(results[0] is self.student['payments'][value])
        # Managers can approve the payment
        self.browser.open(payment_url)
        self.browser.getLink("Approve payment").click()
        self.assertMatches('...Payment approved...',
                          self.browser.contents)
        # Approval is logged in students.log ...
        logcontent = open(logfile).read()
        self.assertTrue(
            'zope.mgr - students.browser.OnlinePaymentApproveView '
            '- E1000000 - schoolfee_incl payment approved'
            in logcontent)
        # ... and in payments.log
        logfile = os.path.join(
            self.app['datacenter'].storage, 'logs', 'payments.log')
        logcontent = open(logfile).read()
        self.assertTrue(
            '"zope.mgr",E1000000,%s,schoolfee_incl,6666.0,AP,,,,,,\n' % value
            in logcontent)
        # Student is in state school fee paid, no activation
        # code was necessary.
        self.assertEqual(self.student.state, 'school fee paid')
        self.assertEqual(len(self.app['accesscodes']['SFE-0']),0)
        return

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

    layer = FunctionalLayer

    def setUp(self):
        super(StudentUITests, self).setUp()

        bedticket = BedTicket()
        bedticket.booking_session = 2004
        bedticket.bed_type = u'any bed type'
        bedticket.bed = self.app['hostels']['hall-1']['hall-1_A_101_A']
        bedticket.bed_coordinates = u'My bed coordinates'
        self.student['accommodation'].addBedTicket(bedticket)

    def test_student_payments(self):
        self.certificate.study_mode = 'ug_ft'
        self.student['studycourse'].entry_session = 2013
        self.student['studycourse'].certificate.school_fee_1 = 50250.0
        self.app['configuration']['2004'].union_fee = 1250.0
        self.app['configuration']['2004'].welfare_fee = 750.0
        self.student.nationality = u'NG'
        # Login
        IWorkflowState(self.student).setState('cleared')
        self.browser.open(self.login_path)
        self.browser.getControl(name="form.login").value = self.student_id
        self.browser.getControl(name="form.password").value = 'spwd'
        self.browser.getControl("Login").click()
        # Test school fee payments
        self.browser.open(self.student_path + '/payments')
        self.browser.getLink("Add current session payment ticket").click()
        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
        self.browser.getControl("Create ticket").click()
        self.assertTrue('ticket created' in self.browser.contents)
        value = self.student['payments'].keys()[0]
        self.browser.getLink(value).click()
        self.assertTrue('Amount Authorized' in self.browser.contents)
        self.assertEqual(self.student['payments'][value].amount_auth, 51750.0)
        self.browser.open(self.browser.url + '/payment_slip.pdf')
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
        path = os.path.join(samples_dir(), 'payment_slip.pdf')
        open(path, 'wb').write(self.browser.contents)
        print "Sample PDF payment_slip.pdf written to %s" % path
        # Another school fee payment cannot be added
        self.student['payments'][value].approve()
        self.browser.open(self.student_path + '/payments')
        self.browser.getLink("Add current session payment ticket").click()
        self.browser.getControl(name="form.p_category").value = ['schoolfee']
        self.browser.getControl("Create ticket").click()
        self.assertTrue(
            'Another school fee payment for this session has already been made'
            in self.browser.contents)
        # Test hostel maintenance payments
        self.browser.open(self.student_path + '/payments')
        self.browser.getLink("Add current session payment ticket").click()
        self.browser.getControl(name="form.p_category").value = ['hostel_maintenance']
        self.browser.getControl("Create ticket").click()
        self.assertTrue('ticket created' in self.browser.contents)
        value = self.student['payments'].keys()[1]
        self.browser.getLink(value).click()
        self.assertTrue('<span>My bed coordinates</span>' in self.browser.contents)
        self.assertEqual(self.student['payments'][value].amount_auth, 876.0)
        return

    def test_late_registration(self):
        # Login
        delta = timedelta(days=10)
        self.app['configuration'][
            '2004'].coursereg_deadline = datetime.now(pytz.utc) - delta
        IWorkflowState(self.student).setState('school fee paid')
        # Current session is 2004. Here we test course registration for
        # returning students.
        self.student['studycourse'].entry_session = 2003
        self.browser.open(self.login_path)
        self.browser.getControl(name="form.login").value = self.student_id
        self.browser.getControl(name="form.password").value = 'spwd'
        self.browser.getControl("Login").click()
        self.browser.open(self.payments_path)
        self.browser.open(self.payments_path + '/addop')
        self.browser.getControl(name="form.p_category").value = ['late_registration']
        self.browser.getControl("Create ticket").click()
        self.assertMatches('...ticket created...',
                           self.browser.contents)
        self.browser.getLink("Study Course").click()
        self.browser.getLink("Add course list").click()
        self.assertMatches('...Add current level 100 (Year 1)...',
                           self.browser.contents)
        self.browser.getControl("Create course list now").click()
        self.browser.getLink("100").click()
        self.browser.getLink("Edit course list").click()
        self.browser.getControl("Register course list").click()
        self.assertTrue('Course registration has ended. Please pay' in self.browser.contents)
        self.student['payments'].values()[0].approve()
        self.browser.getControl("Register course list").click()
        self.assertTrue('Course list has been registered' in self.browser.contents)
        self.assertEqual(self.student.state, 'courses registered')
        # Reset student and check if fresh students are always allowed to
        # register courses.
        self.student['studycourse'].entry_session = 2004
        del self.student['payments'][self.student['payments'].keys()[0]]
        IWorkflowState(self.student).setState('school fee paid')
        self.browser.open(self.studycourse_path + '/100/edit')
        self.browser.getControl("Register course list").click()
        self.assertTrue('Course list has been registered' in self.browser.contents)
        return


    def deactivated_test_student_course_registration(self):
        # Add more courses
        self.course2 = createObject('waeup.Course')
        self.course2.code = 'COURSE2'
        self.course2.semester = 2
        self.course2.credits = 10
        self.course2.passmark = 40
        self.app['faculties']['fac1']['dep1'].courses.addCourse(
            self.course2)
        self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCertCourse(
            self.course2, level=100)
        self.course3 = createObject('waeup.Course')
        self.course3.code = 'COURSE3'
        self.course3.semester = 3
        self.course3.credits = 10
        self.course3.passmark = 40
        self.app['faculties']['fac1']['dep1'].courses.addCourse(
            self.course3)
        self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCertCourse(
            self.course3, level=100)

        # Login as student
        self.browser.open(self.login_path)
        IWorkflowState(self.student).setState('school fee paid')
        self.browser.open(self.login_path)
        self.browser.getControl(name="form.login").value = self.student_id
        self.browser.getControl(name="form.password").value = 'spwd'
        self.browser.getControl("Login").click()
        # Students can add the current study level
        self.browser.getLink("Study Course").click()
        self.browser.getLink("Add course list").click()
        self.assertMatches('...Add current level 100 (Year 1)...',
                           self.browser.contents)
        self.browser.getControl("Create course list now").click()
        # Student has not paid second instalment, therefore a level
        # with two course ticket was created (semester 1 and combined)
        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 2)
        self.browser.getLink("100").click()
        self.browser.getLink("Edit course list").click()
        self.browser.getControl("Add course ticket").click()
        # Student can't add second semester course
        self.assertTrue('<option value="COURSE1">' in self.browser.contents)
        self.assertTrue('<option value="COURSE3">' in self.browser.contents)
        self.assertFalse('<option value="COURSE2">' in self.browser.contents)

        # Let's remove level and see what happens after 2nd instalment payment
        del(self.student['studycourse']['100'])
        payment2 = createObject('waeup.StudentOnlinePayment')
        payment2.p_category = u'schoolfee_2'
        payment2.p_session = self.student.current_session
        self.student['payments']['anykey'] = payment2
        self.browser.open(self.studycourse_path)
        self.browser.getLink("Add course list").click()
        self.browser.getControl("Create course list now").click()
        # Still only 2 tickets have been created since payment ticket
        # was not paid
        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 2)
        payment2.p_state = u'paid'
        del(self.student['studycourse']['100'])
        self.browser.open(self.studycourse_path)
        self.browser.getLink("Add course list").click()
        self.browser.getControl("Create course list now").click()
        # Now 2nd semester course has been added
        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 3)
        # Student can add second semester course
        self.browser.getLink("100").click()
        self.browser.getLink("Edit course list").click()
        self.browser.getControl("Add course ticket").click()
        self.assertTrue('<option value="COURSE1">' in self.browser.contents)
        self.assertTrue('<option value="COURSE2">' in self.browser.contents)
        self.assertTrue('<option value="COURSE3">' in self.browser.contents)
        return

    def test_set_matric_number(self):
        #payment = createObject('waeup.StudentOnlinePayment')
        #payment.p_category = u'concessional'
        #payment.p_id = u'anyid'
        #payment.p_state = u'paid'
        #self.student['payments']['anykey'] = payment
        # Login as student
        self.browser.open(self.login_path)
        IWorkflowState(self.student).setState('school fee paid')
        self.browser.open(self.login_path)
        self.browser.getControl(name="form.login").value = self.student_id
        self.browser.getControl(name="form.password").value = 'spwd'
        self.browser.getControl("Login").click()
        self.assertRaises(
            LinkNotFoundError,
            self.browser.getLink, 'Get Matriculation Number')
        self.student.matric_number = None
        site = grok.getSite()
        site['configuration'].next_matric_integer = 1
        self.student['studycourse'].certificate.study_mode = 'ug_pt'
        self.browser.open(self.student_path)
        self.assertRaises(
            LinkNotFoundError,
            self.browser.getLink, 'Download matriculation number slip')
        self.browser.getLink("Get Matriculation Number").click()
        self.assertTrue('Matriculation number PTP/fac1/dep1/04/00001 assigned.'
            in self.browser.contents)
        self.assertEqual(self.student.matric_number, 'PTP/fac1/dep1/04/00001')
        self.assertRaises(
            LinkNotFoundError,
            self.browser.getLink, 'Get Matriculation Number')
        # Setting matric number is logged.
        logfile = os.path.join(
            self.app['datacenter'].storage, 'logs', 'students.log')
        logcontent = open(logfile).read()
        self.assertTrue('E1000000 - waeup.aaue.students.browser.StudentGetMatricNumberPage - '
                        'E1000000 - PTP/fac1/dep1/04/00001 assigned' in logcontent)
        # Matric Number Slip can be downloaded
        self.browser.getLink("Download matriculation number slip").click()
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
        path = os.path.join(samples_dir(), 'matric_number_slip.pdf')
        open(path, 'wb').write(self.browser.contents)
        print "Sample PDF matric_number_slip.pdf written to %s" % path
        return

    def test_personal_data_slip(self):
        # Login as student
        self.browser.open(self.login_path)
        IWorkflowState(self.student).setState('school fee paid')
        self.browser.open(self.login_path)
        self.browser.getControl(name="form.login").value = self.student_id
        self.browser.getControl(name="form.password").value = 'spwd'
        self.browser.getControl("Login").click()
        self.browser.getLink("Personal Data").click()
        self.assertRaises(
            LinkNotFoundError,
            self.browser.getLink, 'Download personal data slip')
        self.student.father_name = u'Rudolf'
        self.browser.open(self.personal_path)
        self.browser.getLink("Download personal data slip").click()
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
        path = os.path.join(samples_dir(), 'personal_data_slip.pdf')
        open(path, 'wb').write(self.browser.contents)
        print "Sample PDF personal_data_slip.pdf written to %s" % path
        return

    def test_student_course_registration(self):
        IWorkflowState(self.student).setState('school fee paid')
        self.browser.open(self.login_path)
        self.browser.getControl(name="form.login").value = self.student_id
        self.browser.getControl(name="form.password").value = 'spwd'
        self.browser.getControl("Login").click()
        # Now students can add the current study level
        self.browser.getLink("Study Course").click()
        self.browser.getLink("Add course list").click()
        self.assertMatches('...Add current level 100 (Year 1)...',
                           self.browser.contents)
        self.browser.getControl("Create course list now").click()
        # Students can't open the customized pdf course registration slip
        self.browser.open(
            self.student_path + '/studycourse/100/course_registration_slip.pdf')
        self.assertTrue('Forbidden' in self.browser.contents)
        # They can open slips from the previous session ...
        self.student['studycourse'].current_level = 200
        self.browser.open(self.student_path + '/studycourse/100')
        self.browser.getLink("Download course registration slip").click()
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
        # or if they have registered their course list
        self.student['studycourse'].current_level = 200
        IWorkflowState(self.student).setState('courses registered')
        self.browser.open(self.student_path + '/studycourse/100')
        self.browser.getLink("Download course registration slip").click()
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
        path = os.path.join(samples_dir(), 'ft_course_registration_slip.pdf')
        open(path, 'wb').write(self.browser.contents)
        print "Sample PDF ft_course_registration_slip.pdf written to %s" % path

        self.certificate.study_mode = 'ug_pt'
        self.browser.open(self.student_path + '/studycourse/100')
        self.browser.getLink("Download course registration slip").click()
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
        path = os.path.join(samples_dir(), 'pt_course_registration_slip.pdf')
        open(path, 'wb').write(self.browser.contents)
        print "Sample PDF pt_course_registration_slip.pdf written to %s" % path

        self.certificate.study_mode = 'special_pg_ft'
        self.student.matric_number = u'AAU/SPS/FLW/LAW/15/PHD/09504'
        self.browser.open(self.student_path + '/studycourse/100')
        self.browser.getLink("Download course registration slip").click()
        self.assertEqual(self.browser.headers['Status'], '200 Ok')
        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
        path = os.path.join(samples_dir(), 'pg_course_registration_slip.pdf')
        open(path, 'wb').write(self.browser.contents)
        print "Sample PDF pg_course_registration_slip.pdf written to %s" % path

    def test_student_clearance(self):
        # Student cant login if their password is not set
        IWorkflowInfo(self.student).fireTransition('admit')
        self.browser.open(self.login_path)
        self.browser.getControl(name="form.login").value = self.student_id
        self.browser.getControl(name="form.password").value = 'spwd'
        self.browser.getControl("Login").click()
        self.assertMatches(
            '...You logged in...', self.browser.contents)
        # Admitted student can upload a passport picture
        self.browser.open(self.student_path + '/change_portrait')
        ctrl = self.browser.getControl(name='passportuploadedit')
        file_obj = open(SAMPLE_IMAGE, 'rb')
        file_ctrl = ctrl.mech_control
        file_ctrl.add_file(file_obj, filename='my_photo.jpg')
        self.browser.getControl(
            name='upload_passportuploadedit').click()
        self.assertTrue(
            'src="http://localhost/app/students/E1000000/passport.jpg"'
            in self.browser.contents)
        # Student is redirected to the personal data form because
        # personal data form is not properly filled.
        self.browser.open(self.student_path + '/start_clearance')
        self.assertMatches('...Personal data form is not properly filled...',
                           self.browser.contents)
        self.assertEqual(self.browser.url, self.student_path + '/edit_personal')
        self.student.father_name = u'Rudolf'
        self.browser.open(self.student_path + '/start_clearance')
        self.assertMatches(
            '...<h1 class="kofa-content-label">Start clearance</h1>...',
            self.browser.contents)

    def test_student_accommodation(self):
        del self.student['accommodation']['2004']
        self.student['studycourse'].certificate.study_mode = 'dp_ft'
        # All beds can be assigned
        bed1 = self.app['hostels']['hall-1']['hall-1_A_101_A']
        bed1.bed_type = u'regular_male_all'
        bed2 = self.app['hostels']['hall-1']['hall-1_A_101_B']
        bed2.bed_type = u'regular_female_all'
        notify(grok.ObjectModifiedEvent(bed1))
        notify(grok.ObjectModifiedEvent(bed2))
        # Login
        self.browser.open(self.login_path)
        self.browser.getControl(name="form.login").value = self.student_id
        self.browser.getControl(name="form.password").value = 'spwd'
        self.browser.getControl("Login").click()
        # Students can book accommodation without AC ...
        self.browser.open(self.acco_path)
        IWorkflowInfo(self.student).fireTransition('admit')
        self.browser.getControl("Book accommodation").click()
        self.assertTrue(
            'You are not eligible to book accommodation.'
            in self.browser.contents)
        self.student['studycourse'].certificate.study_mode = 'ug_ft'
        self.browser.getControl("Book accommodation").click()
        self.assertFalse('Activation Code:' in self.browser.contents)
        self.browser.getControl("Create bed ticket").click()
        # Bed is randomly selected but, since there is only
        # one bed for this student, we know that
        self.assertEqual(self.student['accommodation']['2004'].bed_coordinates,
            'Hall 1, Block A, Room 101, Bed A (regular_male_all)')
        # Only the hall name is displayed
        self.assertEqual(self.student[
            'accommodation']['2004'].display_coordinates,
            'Hall 1')
        self.assertFalse('Hall 1, Block A, Room 101, Bed A'
            in self.browser.contents)
        self.assertTrue('<td>Hall 1</td>'
            in self.browser.contents)
        return

    def test_handle_courses_by_lecturer(self):
        self.app['users'].addUser('mrslecturer', 'mrslecturersecret')
        self.app['users']['mrslecturer'].email = 'mrslecturer@foo.ng'
        self.app['users']['mrslecturer'].title = u'Mercedes Benz'
        # Add course ticket
        studylevel = createObject(u'waeup.StudentStudyLevel')
        studylevel.level = 100
        studylevel.level_session = 2004
        self.student['studycourse'].addStudentStudyLevel(
            self.certificate, studylevel)
        # Assign local Lecturer role for a certificate.
        course = self.app['faculties']['fac1']['dep1'].courses['COURSE1']
        prmlocal = IPrincipalRoleManager(course)
        prmlocal.assignRoleToPrincipal('waeup.local.Lecturer', 'mrslecturer')
        notify(LocalRoleSetEvent(
            course, 'waeup.local.Lecturer', 'mrslecturer', granted=True))
        # Login as lecturer.
        self.browser.open(self.login_path)
        self.browser.getControl(name="form.login").value = 'mrslecturer'
        self.browser.getControl(name="form.password").value = 'mrslecturersecret'
        self.browser.getControl("Login").click()
        self.browser.getLink("My Roles").click()
        self.browser.getLink(
            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1").click()
        # Course results can be batch edited via the edit_courses view.
        self.app['faculties']['fac1']['dep1'].score_editing_disabled = False
        self.app['configuration'].current_academic_session = 2004
        IWorkflowState(self.student).setState('courses validated')
        self.browser.open(
            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1/edit_scores")
        self.assertTrue(
            'input type="text" name="scores"'
            in self.browser.contents)
        self.browser.getControl(name="scores", index=0).value = '55'
        self.browser.getControl(name="cas", index=0).value = '66'
        self.browser.getControl("Update scores").click()
        # New score and ca has been set.
        self.assertEqual(
            self.student['studycourse']['100']['COURSE1'].score, 55)
        self.assertEqual(
            self.student['studycourse']['100']['COURSE1'].ca, 66)
        # Score editing has been logged.
        logfile = os.path.join(
            self.app['datacenter'].storage, 'logs', 'students.log')
        logcontent = open(logfile).read()
        self.assertTrue('mrslecturer - waeup.aaue.students.browser.CustomEditScoresPage - '
                        'E1000000 100/COURSE1 score updated (55)' in logcontent)
        self.assertTrue('mrslecturer - waeup.aaue.students.browser.CustomEditScoresPage - '
                        'E1000000 100/COURSE1 ca updated (66)' in logcontent)
        # Non-integer scores won't be accepted.
        self.browser.open(
            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1/edit_scores")
        self.assertTrue('value="55" />' in self.browser.contents)
        self.browser.getControl(name="scores", index=0).value = 'abc'
        self.browser.getControl("Update scores").click()
        self.assertTrue('Error: Score(s) and CA(s) of Anna Tester have not be updated.'
            in self.browser.contents)
        # Scores can be removed.
        self.browser.open(
            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1/edit_scores")
        self.browser.getControl(name="scores", index=0).value = ''
        self.browser.getControl("Update scores").click()
        self.assertEqual(
            self.student['studycourse']['100']['COURSE1'].score, None)
        logcontent = open(logfile).read()
        self.assertTrue('mrslecturer - waeup.aaue.students.browser.CustomEditScoresPage - '
                        'E1000000 100/COURSE1 score updated (None)' in logcontent)