source: main/waeup.uniben/trunk/src/waeup/uniben/students/tests/test_browser.py @ 14320

Last change on this file since 14320 was 14237, checked in by Henrik Bettermann, 8 years ago

Clearance fee and provider amount do increase only for students starting in 2016.

  • Property svn:keywords set to Id
File size: 53.6 KB
Line 
1## $Id: test_browser.py 14237 2016-10-27 21:07:05Z henrik $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18import os
19import shutil
20import tempfile
21import pytz
22from datetime import datetime, timedelta, date
23from StringIO import StringIO
24from hurry.workflow.interfaces import IWorkflowState, IWorkflowInfo
25from zope.securitypolicy.interfaces import IPrincipalRoleManager
26from zope.security.interfaces import Unauthorized
27from zope.component.hooks import setSite, clearSite
28from zope.component import getUtility, createObject
29from zope.interface import verify
30from zope.event import notify
31from waeup.kofa.authentication import LocalRoleSetEvent
32from waeup.kofa.app import University
33from waeup.kofa.students.tests.test_browser import StudentsFullSetup
34from waeup.kofa.students.accommodation import BedTicket
35from waeup.kofa.hostels.hostel import Hostel, Bed, NOT_OCCUPIED
36from waeup.kofa.testing import FunctionalTestCase
37from waeup.kofa.browser.tests.test_pdf import samples_dir
38from waeup.kofa.interfaces import (
39    IExtFileStore, IFileStoreNameChooser)
40from waeup.kofa.students.interfaces import IStudentsUtils
41from waeup.uniben.testing import FunctionalLayer
42
43SAMPLE_FPM = os.path.join(os.path.dirname(__file__), 'sample.fpm')
44
45class StudentUITests(StudentsFullSetup):
46    """Tests for customized student class views and pages
47    """
48
49    layer = FunctionalLayer
50
51    def setUp(self):
52        super(StudentUITests, self).setUp()
53
54    def test_next_session_allowed(self):
55        # Let's see if next_session_allowed works as expected
56        # A, ug_ft, 100
57        IWorkflowState(self.student).setState('returning')
58        self.assertTrue(self.student['studycourse'].next_session_allowed)
59        # Uniben special PG programmes have the same workflow
60        # as UG students
61        self.certificate.study_mode = 'special_pg_pt'
62        self.assertTrue(self.student['studycourse'].next_session_allowed)
63        IWorkflowState(self.student).setState('school fee paid')
64        self.assertFalse(self.student['studycourse'].next_session_allowed)
65        # Now we convert the certificate into a 'regular
66        # postgraduate certificate ...
67        self.certificate.study_mode = 'pg_ft'
68        # ... and voila next session registration is allowed
69        self.assertTrue(self.student['studycourse'].next_session_allowed)
70
71    def test_manage_access(self):
72        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
73        # The student created in the base package is a ug student
74        self.browser.open(self.manage_clearance_path)
75        self.assertMatches('...First Sitting Record...',
76                           self.browser.contents)
77        # There is no pg field in the clearance form
78        self.assertFalse('Second Higher Education Record'
79            in self.browser.contents)
80        # Now we change the study mode ...
81        self.certificate.study_mode = 'pg_ft'
82        self.browser.open(self.clearance_path)
83        # ... and additional pg clearance fields appears
84        self.assertMatches('...Second Higher Education Record...',
85                           self.browser.contents)
86        # But also fields from the ug form are displayed
87        self.assertMatches('...First Sitting Record...',
88                           self.browser.contents)
89        # The same holds for Uniben's special pg students
90        self.certificate.study_mode = 'special_pg_pt'
91        self.browser.open(self.clearance_path)
92        self.assertMatches('...Second Higher Education Record...',
93                           self.browser.contents)
94        self.assertMatches('...First Sitting Record...',
95                           self.browser.contents)
96        # We want to see the signature fields.
97        IWorkflowState(self.student).setState('returning')
98        self.browser.open(self.student_path + '/clearance_slip.pdf')
99        self.assertEqual(self.browser.headers['Status'], '200 Ok')
100        self.assertEqual(self.browser.headers['Content-Type'],
101                         'application/pdf')
102        path = os.path.join(samples_dir(), 'clearance_slip.pdf')
103        open(path, 'wb').write(self.browser.contents)
104        print "Sample PDF clearance_slip.pdf written to %s" % path
105
106    def test_student_access(self):
107        # Students can edit clearance data
108        IWorkflowState(self.student).setState('clearance started')
109        self.student.nationality = u'NG'
110        file_store = getUtility(IExtFileStore)
111        self.browser.open(self.login_path)
112        self.browser.getControl(name="form.login").value = self.student_id
113        self.browser.getControl(name="form.password").value = 'spwd'
114        self.browser.getControl("Login").click()
115        self.browser.open(self.edit_clearance_path)
116        # UG students can't edit date_of_birth, nationality and lga
117        self.assertFalse('form.date_of_birth' in self.browser.contents)
118        self.assertFalse('form.nationality' in self.browser.contents)
119        self.assertFalse('form.lga' in self.browser.contents)
120        # Clearance can only be requested if all required documents
121        # have been uploaded.
122        self.browser.getControl("Save and request clearance").click()
123        self.assertTrue('No birth certificate uploaded'
124            in self.browser.contents)
125        birth_certificate = 'My birth certificate'
126        file_id = IFileStoreNameChooser(self.student).chooseName(
127            attr="birth_certificate.jpg")
128        file_store.createFile(file_id, StringIO(birth_certificate))
129        self.browser.open(self.edit_clearance_path)
130        self.browser.getControl("Save and request clearance").click()
131
132        self.assertTrue('No guarantor/referee letter uploaded'
133            in self.browser.contents)
134        ref_let = 'My ref let'
135        file_id = IFileStoreNameChooser(self.student).chooseName(
136            attr="ref_let.jpg")
137        file_store.createFile(file_id, StringIO(ref_let))
138        self.browser.open(self.edit_clearance_path)
139        self.browser.getControl("Save and request clearance").click()
140
141        self.assertTrue('No acceptance letter uploaded'
142            in self.browser.contents)
143        acc_let = 'My acc let'
144        file_id = IFileStoreNameChooser(self.student).chooseName(
145            attr="acc_let.jpg")
146        file_store.createFile(file_id, StringIO(acc_let))
147        self.browser.open(self.edit_clearance_path)
148        self.browser.getControl("Save and request clearance").click()
149
150        self.assertTrue('No first sitting result uploaded'
151            in self.browser.contents)
152        fst_sit_scan = 'My first sitting result'
153        file_id = IFileStoreNameChooser(self.student).chooseName(
154            attr="fst_sit_scan.jpg")
155        file_store.createFile(file_id, StringIO(fst_sit_scan))
156        self.browser.open(self.edit_clearance_path)
157        self.browser.getControl("Save and request clearance").click()
158
159        #self.assertTrue('No second sitting result uploaded'
160        #    in self.browser.contents)
161        #scd_sit_scan = 'My second sitting result'
162        #file_id = IFileStoreNameChooser(self.student).chooseName(
163        #    attr="scd_sit_scan.jpg")
164        #file_store.createFile(file_id, StringIO(scd_sit_scan))
165        #self.browser.open(self.edit_clearance_path)
166        #self.browser.getControl("Save and request clearance").click()
167
168        self.assertTrue('No affidavit of non-membership of secret cults uploaded'
169            in self.browser.contents)
170        secr_cults = 'My non-membership scan'
171        file_id = IFileStoreNameChooser(self.student).chooseName(
172            attr="secr_cults.jpg")
173        file_store.createFile(file_id, StringIO(secr_cults))
174        # Clearance invitation letter is not yet available
175        self.browser.open(self.clearance_path)
176        self.assertFalse('invitation slip' in self.browser.contents)
177        self.browser.open(self.student_path + '/clearance_invitation_slip.pdf')
178        self.assertTrue('Forbidden' in self.browser.contents)
179        self.browser.open(self.edit_clearance_path)
180        self.browser.getControl("Save and request clearance").click()
181        self.assertTrue('Clearance has been requested'
182            in self.browser.contents)
183        # Now student can export physical_clearance.slip
184        self.app['configuration'].name = u'University of Benin'
185        self.student.physical_clearance_date = u'January 5th, 2015'
186        self.browser.getLink("Clearance Data").click()
187        self.browser.getLink("Download clearance invitation slip").click()
188        self.assertEqual(self.browser.headers['Status'], '200 Ok')
189        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
190        path = os.path.join(samples_dir(), 'clearance_invitation_slip.pdf')
191        open(path, 'wb').write(self.browser.contents)
192        print "Sample PDF clearance_invitation_slip.pdf written to %s" % path
193        # Students can open the personal edit page and see the parent_email field.
194        self.browser.open(self.student_path + '/edit_personal')
195        self.assertTrue('parent_email' in self.browser.contents)
196
197    def test_examination_schedule_slip(self):
198        self.student.flash_notice = u'My Examination Date'
199        self.browser.open(self.login_path)
200        self.browser.getControl(name="form.login").value = self.student_id
201        self.browser.getControl(name="form.password").value = 'spwd'
202        self.browser.getControl("Login").click()
203        self.browser.getLink("Download examination schedule slip").click()
204        self.assertEqual(self.browser.headers['Status'], '200 Ok')
205        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
206        path = os.path.join(samples_dir(), 'examination_schedule_slip.pdf')
207        open(path, 'wb').write(self.browser.contents)
208        print "Sample PDF examination_schedule_slip.pdf written to %s" % path
209        # If flash_notive does not contain exam' the button does not show up.
210        self.student.flash_notice = u'anything'
211        self.browser.open(self.student_path)
212        self.assertFalse('examination schedule slip' in self.browser.contents)
213
214    def test_manage_payments(self):
215        # Add missing configuration data
216        self.app['configuration']['2004'].gown_fee = 150.0
217        self.app['configuration']['2004'].transfer_fee = 90.0
218        #self.app['configuration']['2004'].clearance_fee = 120.0
219        self.app['configuration']['2004'].booking_fee = 150.0
220        self.app['configuration']['2004'].maint_fee = 180.0
221
222        # Managers can add online payment tickets
223        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
224        self.browser.open(self.payments_path)
225        self.browser.getLink("Add current session payment ticket").click()
226        self.browser.getControl("Create ticket").click()
227        self.assertMatches('...Amount could not be determined...',
228                           self.browser.contents)
229        IWorkflowState(self.student).setState('cleared')
230        self.student.nationality = u'NG'
231        self.browser.open(self.payments_path + '/addop')
232        self.browser.getControl(name="form.p_category").value = ['schoolfee']
233        self.browser.getControl("Create ticket").click()
234        self.assertMatches('...ticket created...',
235                           self.browser.contents)
236        ctrl = self.browser.getControl(name='val_id')
237        value = ctrl.options[0]
238        self.browser.getLink(value).click()
239        self.assertMatches('...Amount Authorized...',
240                           self.browser.contents)
241        # Managers can open payment slip
242        self.browser.getLink("Download payment slip").click()
243        self.assertEqual(self.browser.headers['Status'], '200 Ok')
244        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
245        # Set ticket paid
246        ticket = self.student['payments'].items()[0][1]
247        ticket.p_state = 'paid'
248        self.browser.open(self.payments_path + '/addop')
249        self.browser.getControl(name="form.p_category").value = ['schoolfee']
250        self.browser.getControl("Create ticket").click()
251        self.assertMatches('...This type of payment has already been made...',
252                           self.browser.contents)
253        # Remove all payments so that we can add a school fee payment again
254        keys = [i for i in self.student['payments'].keys()]
255        for payment in keys:
256            del self.student['payments'][payment]
257        self.browser.open(self.payments_path + '/addop')
258        self.browser.getControl(name="form.p_category").value = ['schoolfee']
259        self.browser.getControl("Create ticket").click()
260        self.assertMatches('...ticket created...',
261                           self.browser.contents)
262        schoolfee_ticket = self.student['payments'].values()[0]
263        self.browser.open(self.payments_path + '/addop')
264        self.browser.getControl(name="form.p_category").value = ['gown']
265        self.browser.getControl("Create ticket").click()
266        self.assertMatches('...ticket created...',
267                           self.browser.contents)
268        self.browser.open(self.payments_path + '/addop')
269        #self.browser.getControl(
270        #    name="form.p_category").value = ['tempmaint_1']
271        #self.browser.getControl("Create ticket").click()
272        #self.assertMatches('...You have not yet paid the hostel application fee...',
273        #                   self.browser.contents)
274        #self.browser.open(self.payments_path + '/addop')
275        #self.browser.getControl(name="form.p_category").value = ['hostel_application']
276        #self.browser.getControl("Create ticket").click()
277        #self.assertMatches('...ticket created...',
278        #                   self.browser.contents)
279        #ha_ticket = self.student['payments'].values()[2]
280        #ha_ticket.approve()
281        #self.browser.open(self.payments_path + '/addop')
282        #self.browser.getControl(
283        #    name="form.p_category").value = ['tempmaint_1']
284        #self.browser.getControl("Create ticket").click()
285        #self.assertMatches('...ticket created...',
286        #                   self.browser.contents)
287        #self.browser.open(self.payments_path + '/addop')
288        #self.browser.getControl(
289        #    name="form.p_category").value = ['tempmaint_2']
290        #self.browser.getControl("Create ticket").click()
291        #self.assertMatches('...ticket created...',
292        #                   self.browser.contents)
293        #self.browser.open(self.payments_path + '/addop')
294        #self.browser.getControl(
295        #    name="form.p_category").value = ['tempmaint_3']
296        #self.browser.getControl("Create ticket").click()
297        #self.assertMatches('...ticket created...',
298        #                   self.browser.contents)
299        #self.browser.open(self.payments_path + '/addop')
300        # We can't test clearance payment ticket creation at the moment,
301        # since Uniben decided to deactivate clearance for ug students.
302        #self.browser.getControl(name="form.p_category").value = ['clearance']
303        #self.browser.getControl("Create ticket").click()
304        #self.assertMatches('...ticket created...',
305        #                   self.browser.contents)
306        self.browser.open(self.payments_path + '/addop')
307        self.browser.getControl(name="form.p_category").value = ['schoolfee']
308        self.browser.getControl("Create ticket").click()
309        self.assertMatches('...ticket created...',
310                           self.browser.contents)
311        # In state returning we can add a new school fee ticket since
312        # p_session and p_level is different
313        IWorkflowState(self.student).setState('returning')
314        self.browser.open(self.payments_path + '/addop')
315        self.browser.getControl(name="form.p_category").value = ['schoolfee']
316        self.browser.getControl("Create ticket").click()
317        # Uups, we forgot to add a session configuration for next session
318        self.assertMatches('...Session configuration object is not...',
319                           self.browser.contents)
320        configuration = createObject('waeup.SessionConfiguration')
321        configuration.academic_session = 2005
322        self.app['configuration'].addSessionConfiguration(configuration)
323        self.browser.open(self.payments_path + '/addop')
324        self.browser.getControl(name="form.p_category").value = ['schoolfee']
325        self.browser.getControl("Create ticket").click()
326
327
328        #self.assertMatches('...You have not yet paid your current/active session...',
329        #                   self.browser.contents)
330        ## Ok, let's pay the first schoolfee ticket.
331        #schoolfee_ticket.approve()
332        #self.browser.open(self.payments_path + '/addop')
333        #self.browser.getControl(name="form.p_category").value = ['schoolfee']
334        #self.browser.getControl("Create ticket").click()
335
336
337        self.assertMatches('...ticket created...',
338                           self.browser.contents)
339        # In state admitted school fee can't be determined
340        IWorkflowState(self.student).setState('admitted')
341        self.browser.open(self.payments_path + '/addop')
342        self.browser.getControl(name="form.p_category").value = ['schoolfee']
343        self.browser.getControl("Create ticket").click()
344        self.assertMatches('...Amount could not be determined...',
345                           self.browser.contents)
346
347        # If the session configuration doesn't exist an error message will
348        # be shown. No other requirement is being checked.
349        del self.app['configuration']['2004']
350        self.browser.open(self.payments_path)
351        self.browser.getLink("Add current session payment ticket").click()
352        self.browser.getControl("Create ticket").click()
353        self.assertMatches('...Session configuration object is not...',
354                           self.browser.contents)
355
356    def test_student_course_registration(self):
357        # Uniben students see grade instead of score on all level pages
358        # and on course ticket page.
359        IWorkflowState(self.student).setState('school fee paid')
360        self.browser.open(self.login_path)
361        self.browser.getControl(name="form.login").value = self.student_id
362        self.browser.getControl(name="form.password").value = 'spwd'
363        self.browser.getControl("Login").click()
364        # Now students can add the current study level
365        self.browser.getLink("Study Course").click()
366        self.browser.getLink("Add course list").click()
367        self.assertMatches('...Add current level 100 (Year 1)...',
368                           self.browser.contents)
369        self.browser.getControl("Create course list now").click()
370        # A level with one course ticket was created
371        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 1)
372        self.student['studycourse']['100']['COURSE1'].score = 55
373        self.browser.getLink("100").click()
374        # GPA has been properly calculated
375        self.assertEqual(self.student['studycourse']['100'].gpa_params[0], 3.0)
376        # Score is not shown but grade
377        self.assertTrue('<th>Grade</th>' in self.browser.contents)
378        self.assertFalse('<th>Score</th>' in self.browser.contents)
379        self.browser.getLink("Edit course list").click()
380        self.assertTrue('<th>Grade</th>' in self.browser.contents)
381        self.assertFalse('<th>Score</th>' in self.browser.contents)
382        self.browser.getLink("COURSE1").click()
383        self.assertFalse('Score' in self.browser.contents)
384        # Students can open the special Uniben pdf course result slip
385        self.browser.open(self.student_path + '/studycourse/100')
386        self.browser.getLink("Download course result slip").click()
387        self.assertEqual(self.browser.headers['Status'], '200 Ok')
388        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
389        # Even if course is mandatory, students can remove the course
390        self.student['studycourse']['100']['COURSE1'].mandatory = True
391        self.browser.open(self.student_path + '/studycourse/100')
392        self.browser.getLink("Edit course list").click()
393        ctrl = self.browser.getControl(name='val_id')
394        ctrl.getControl(value='COURSE1').selected = True
395        self.browser.getControl("Remove selected", index=0).click()
396        self.assertTrue('Successfully removed' in self.browser.contents)
397        # Students can open the customized pdf course registration slip
398        # if they have registered their course list
399        self.browser.open(
400            self.student_path + '/studycourse/100/course_registration_slip.pdf')
401        self.assertTrue('Forbidden' in self.browser.contents)
402        IWorkflowState(self.student).setState('courses registered')
403        self.browser.open(self.student_path + '/studycourse/100')
404        self.browser.getLink("Download course registration slip").click()
405        self.assertEqual(self.browser.headers['Status'], '200 Ok')
406        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
407
408    def test_get_returning_data(self):
409        # Student is in level 100, session 2004 with verdict A
410        utils = getUtility(IStudentsUtils)
411        self.assertEqual(utils.getReturningData(self.student),(2005, 200))
412        self.student['studycourse'].current_verdict = 'C'
413        self.assertEqual(utils.getReturningData(self.student),(2005, 110))
414        self.student['studycourse'].current_verdict = 'D'
415        self.assertEqual(utils.getReturningData(self.student),(2005, 100))
416        return
417
418    def test_set_returning_data(self):
419        # Student is in level 100, session 2004 with verdict A
420        utils = getUtility(IStudentsUtils)
421
422        utils.setReturningData(self.student)
423        self.assertEqual(self.student['studycourse'].current_session, 2005)
424        self.assertEqual(self.student['studycourse'].current_level, 200)
425
426        self.student['studycourse'].current_session = 2004
427        self.student['studycourse'].current_level = 100
428        self.student['studycourse'].current_verdict = 'C'
429        utils.setReturningData(self.student)
430        self.assertEqual(self.student['studycourse'].current_session, 2005)
431        self.assertEqual(self.student['studycourse'].current_level, 110)
432
433        self.student['studycourse'].current_session = 2004
434        self.student['studycourse'].current_level = 100
435        self.student['studycourse'].current_verdict = 'D'
436        utils.setReturningData(self.student)
437        self.assertEqual(self.student['studycourse'].current_session, 2005)
438        self.assertEqual(self.student['studycourse'].current_level, 100)
439        return
440
441    def test_set_payment_details(self):
442        self.app['configuration']['2004'].gown_fee = 150.0
443        self.app['configuration']['2004'].transfer_fee = 90.0
444        self.app['configuration']['2004'].booking_fee = 150.0
445        self.app['configuration']['2004'].maint_fee = 180.0
446
447        configuration = createObject('waeup.SessionConfiguration')
448        configuration.academic_session = 2000
449        self.app['configuration'].addSessionConfiguration(configuration)
450        configuration2 = createObject('waeup.SessionConfiguration')
451        configuration2.academic_session = 2002
452        self.app['configuration'].addSessionConfiguration(configuration2)
453        configuration3 = createObject('waeup.SessionConfiguration')
454        configuration3.academic_session = 2003
455        self.app['configuration'].addSessionConfiguration(configuration3)
456        configuration4 = createObject('waeup.SessionConfiguration')
457        configuration4.academic_session = 2005
458        self.app['configuration'].addSessionConfiguration(configuration4)
459        utils = getUtility(IStudentsUtils)
460        self.student['studycourse'].entry_session = 2002
461        self.student.nationality = u'NG'
462
463        error, payment = utils.setPaymentDetails('schoolfee',
464            self.student, None, None)
465        self.assertEqual(payment, None)
466        # Student is in state 'created' and can thus not pay.
467        self.assertTrue(u'Amount could not be determined.' in error)
468
469        # Previous session must be valid.
470        error, payment = utils.setPaymentDetails('schoolfee',
471            self.student, 2000, 300)
472        self.assertEqual(payment, None)
473        self.assertTrue(u'The previous session must not fall below' in error)
474        error, payment = utils.setPaymentDetails('schoolfee',
475            self.student, 2005, 300)
476        self.assertEqual(payment, None)
477        self.assertTrue(u'This is not a previous session' in error)
478
479        # Previous session schoolfee payment; fresh and returning
480        # are distinguished by their entry_level
481        error, payment = utils.setPaymentDetails('schoolfee',
482            self.student, 2002, 300)
483        self.assertEqual(payment.amount_auth, 40000.0)
484        self.assertEqual(payment.p_session, 2002)
485        self.assertEqual(payment.p_level, 300)
486        self.assertFalse(payment.p_current)
487        error, payment = utils.setPaymentDetails('schoolfee',
488            self.student, 2003, 300)
489        self.assertEqual(payment.amount_auth, 20000.0)
490        self.assertEqual(payment.p_session, 2003)
491        self.assertEqual(payment.p_level, 300)
492        self.assertFalse(payment.p_current)
493
494        # Current schoolfee payment; fresh and returning
495        # are distinguished by their state
496        IWorkflowState(self.student).setState('cleared')
497        error, payment = utils.setPaymentDetails('schoolfee',
498            self.student, None, None)
499        self.assertEqual(payment.p_level, 100)
500        self.assertEqual(payment.p_session, 2004)
501        self.assertEqual(payment.amount_auth, 40000.0)
502        self.assertEqual(payment.p_item, u'CERT1')
503        self.assertEqual(error, None)
504        self.assertTrue(payment.p_current)
505
506        # Add penalty fee ...
507        # ... for cleared
508        self.app['configuration']['2004'].penalty_ug_ft = 99.0
509        # ... for returning
510        self.app['configuration']['2005'].penalty_ug_ft = 88.0
511        error, payment = utils.setPaymentDetails('schoolfee',
512            self.student, None, None)
513        self.assertEqual(payment.amount_auth, 40099.0)
514
515        IWorkflowState(self.student).setState('returning')
516
517
518        #error, payment = utils.setPaymentDetails('schoolfee',
519        #    self.student, None, None)
520        #self.assertTrue(
521        #    u'You have not yet paid your current/active session.' in error)
522        ## Ok, that means we have to add paid payment ticket first.
523        #payment = createObject('waeup.StudentOnlinePayment')
524        #payment.p_category = u'schoolfee'
525        #payment.p_session = self.student.current_session
526        #payment.p_item = u'My Certificate'
527        #payment.p_id = u'anyid'
528        #payment.p_state = u'paid'
529        #self.student['payments']['anykey'] = payment
530
531
532        error, payment = utils.setPaymentDetails('schoolfee',
533            self.student, None, None)
534        self.assertEqual(payment.p_level, 200)
535        self.assertEqual(payment.p_session, 2005)
536        self.assertEqual(payment.amount_auth, 20088.0)
537        self.assertEqual(payment.p_item, u'CERT1')
538        self.assertEqual(error, None)
539
540        # Staff members pay less.
541        self.student.is_staff = True
542        error, payment = utils.setPaymentDetails('schoolfee',
543            self.student, None, None)
544        self.assertEqual(payment.p_level, 200)
545        self.assertEqual(payment.p_session, 2005)
546        self.assertEqual(payment.amount_auth, 10088.0)
547        self.assertEqual(payment.p_item, u'CERT1')
548        self.assertEqual(error, None)
549
550        # Foreigners pay more.
551        IWorkflowState(self.student).setState('cleared')
552        self.student.is_staff = False
553        self.student.nationality = u'DE'
554        self.certificate.school_fee_3 = 60000.0
555        error, payment = utils.setPaymentDetails(
556            'schoolfee', self.student, None, None)
557        self.assertEqual(payment.p_level, 100)
558        self.assertEqual(payment.p_session, 2004)
559        self.assertEqual(payment.amount_auth, 60099.0)
560        self.assertEqual(payment.p_item, u'CERT1')
561        self.assertEqual(error, None)
562        IWorkflowState(self.student).setState('returning')
563        self.student.is_staff = False
564        self.certificate.school_fee_4 = 20000.0
565        error, payment = utils.setPaymentDetails(
566            'schoolfee', self.student, None, None)
567        self.assertEqual(payment.p_level, 200)
568        self.assertEqual(payment.p_session, 2005)
569        self.assertEqual(payment.amount_auth, 20088.0)
570        self.assertEqual(payment.p_item, u'CERT1')
571        self.assertEqual(error, None)
572
573        # In Uniben students can pay school fee in all states no matter
574        # if they are ug or pg students.
575        IWorkflowState(self.student).setState('school fee paid')
576        self.student.is_staff = False
577        self.student.nationality = u'NG'
578        self.certificate.school_fee_2 = 10000.0
579        error, payment = utils.setPaymentDetails(
580            'schoolfee', self.student, None, None)
581        self.assertEqual(payment.p_level, None)
582        self.assertEqual(payment.p_session, 2005)
583        self.assertEqual(payment.amount_auth, 10088.0)
584        self.assertEqual(payment.p_item, u'CERT1')
585        self.assertEqual(error, None)
586        IWorkflowState(self.student).setState('courses registered')
587        self.certificate.study_mode = 'special_pg_pt'
588        error, payment = utils.setPaymentDetails(
589            'schoolfee', self.student, None, None)
590        self.assertEqual(payment.p_level, None)
591        self.assertEqual(payment.p_session, 2005)
592        self.assertEqual(payment.amount_auth, 10000.0)
593        self.assertEqual(payment.p_item, u'CERT1')
594        self.assertEqual(error, None)
595        IWorkflowState(self.student).setState('courses validated')
596        error, payment = utils.setPaymentDetails(
597            'schoolfee', self.student, None, None)
598        self.assertEqual(payment.p_level, None)
599        self.assertEqual(payment.p_session, 2005)
600        self.assertEqual(payment.amount_auth, 10000.0)
601        self.assertEqual(payment.p_item, u'CERT1')
602        self.assertEqual(error, None)
603
604        error, payment = utils.setPaymentDetails('clearance',
605            self.student, None, None)
606        self.assertEqual(payment.p_level, 100)
607        self.assertEqual(payment.p_session, 2004)
608        self.assertEqual(payment.amount_auth, 45000.0)
609        self.assertEqual(payment.p_item, u'CERT1')
610        self.assertEqual(error, None)
611
612        error, payment = utils.setPaymentDetails('gown',
613            self.student, None, None)
614        self.assertEqual(payment.p_level, 100)
615        self.assertEqual(payment.p_session, 2004)
616        self.assertEqual(payment.amount_auth, 150.0)
617        self.assertEqual(payment.p_item, u'')
618        self.assertEqual(error, None)
619
620        bedticket = BedTicket()
621        bedticket.booking_session = 2004
622        bedticket.bed_type = u'any bed type'
623        bedticket.bed = self.app['hostels']['hall-1']['hall-1_A_101_A']
624        bedticket.bed_coordinates = u'My bed coordinates'
625        self.student['accommodation'].addBedTicket(bedticket)
626
627        error, payment = utils.setPaymentDetails('hostel_maintenance',
628            self.student, None, None)
629        self.assertEqual(payment.p_level, 100)
630        self.assertEqual(payment.p_session, 2004)
631        self.assertEqual(payment.amount_auth, 876.0)
632        self.assertEqual(payment.p_item, u'My bed coordinates')
633        self.assertEqual(error, None)
634
635        self.certificate.study_mode = 'ug_ft'
636        error, payment = utils.setPaymentDetails('bed_allocation',
637            self.student, None, None)
638        self.assertTrue(u'Amount could not be determined.' in error)
639        self.student['studycourse'].current_session = 2004
640        self.student['studycourse'].entry_session = 2004
641        self.student['studycourse'].current_level = 100
642        error, payment = utils.setPaymentDetails('bed_allocation',
643            self.student, None, None)
644        self.assertEqual(payment.p_level, 100)
645        self.assertEqual(payment.p_session, 2004)
646        self.assertEqual(payment.amount_auth, 650.0) # plus 500 student union
647        self.assertEqual(payment.p_item, u'regular_male_fr')
648        self.assertEqual(error, None)
649
650        self.certificate.study_mode = 'pg_ft'
651        error, payment = utils.setPaymentDetails('bed_allocation',
652            self.student, None, None)
653        self.assertEqual(payment.p_level, 100)
654        self.assertEqual(payment.p_session, 2004)
655        self.assertEqual(payment.amount_auth, 150.0)
656        self.assertEqual(payment.p_item, u'pg_male_all')
657        self.assertEqual(error, None)
658
659        #error, payment = utils.setPaymentDetails('hostel_application',
660        #    self.student, None, None)
661        #self.assertEqual(payment.p_level, 100)
662        #self.assertEqual(payment.p_session, 2004)
663        #self.assertEqual(payment.amount_auth, 1000.0)
664        #self.assertEqual(payment.p_item, u'')
665        #self.assertEqual(error, None)
666
667        #payment.approve()
668        #self.student['payments'][payment.p_id] = payment
669
670        #error, payment = utils.setPaymentDetails('tempmaint_1',
671        #    self.student, None, None)
672        #self.assertEqual(payment.p_level, 100)
673        #self.assertEqual(payment.p_session, 2004)
674        #self.assertEqual(payment.amount_auth, 8150.0)
675        #self.assertEqual(payment.p_item, u'Hall 1-4 M/F Ekehuan')
676        #self.assertEqual(error, None)
677
678        #error, payment = utils.setPaymentDetails('tempmaint_2',
679        #    self.student, None, None)
680        #self.assertEqual(payment.p_level, 100)
681        #self.assertEqual(payment.p_session, 2004)
682        #self.assertEqual(payment.amount_auth, 12650.0)
683        #self.assertEqual(payment.p_item, u'Hall 5 M/F')
684        #self.assertEqual(error, None)
685
686        #error, payment = utils.setPaymentDetails('tempmaint_3',
687        #    self.student, None, None)
688        #self.assertEqual(payment.p_level, 100)
689        #self.assertEqual(payment.p_session, 2004)
690        #self.assertEqual(payment.amount_auth, 9650.0)
691        #self.assertEqual(payment.p_item, u'Clinical Hostel')
692        #self.assertEqual(error, None)
693
694        error, payment = utils.setPaymentDetails('transfer',
695            self.student, None, None)
696        self.assertEqual(payment.p_level, 100)
697        self.assertEqual(payment.p_session, 2004)
698        self.assertEqual(payment.amount_auth, 90.0)
699        self.assertEqual(payment.p_item, u'')
700        self.assertEqual(error, None)
701        return
702
703    def test_edit_level_by_co(self):
704        # Create clearance officer
705        self.app['users'].addUser('mrclear', 'mrclearsecret')
706        self.app['users']['mrclear'].email = 'mrclear@foo.ng'
707        self.app['users']['mrclear'].title = 'Carlo Pitter'
708        # Assign local ClearanceOfficer role
709        department = self.app['faculties']['fac1']['dep1']
710        prmlocal = IPrincipalRoleManager(department)
711        prmlocal.assignRoleToPrincipal('waeup.local.ClearanceOfficer', 'mrclear')
712        notify(LocalRoleSetEvent(
713            department, 'waeup.local.ClearanceOfficer', 'mrclear', granted=True))
714        IWorkflowState(self.student).setState('clearance started')
715        # Login as clearance officer
716        self.browser.open(self.login_path)
717        self.browser.getControl(name="form.login").value = 'mrclear'
718        self.browser.getControl(name="form.password").value = 'mrclearsecret'
719        self.browser.getControl("Login").click()
720        self.assertMatches('...You logged in...', self.browser.contents)
721        # Only in state clearance requested the CO does see the
722        # 'Edit level' button ...
723        self.browser.open(self.studycourse_path)
724        self.assertFalse('Edit level' in self.browser.contents)
725        # ... and can open the edit_level view
726        self.browser.open(self.studycourse_path + '/edit_level')
727        self.assertMatches('...is locked...', self.browser.contents)
728        self.assertEqual(self.browser.url, self.studycourse_path)
729        IWorkflowInfo(self.student).fireTransition('request_clearance')
730        self.browser.open(self.studycourse_path)
731        self.assertTrue('Edit level' in self.browser.contents)
732        self.browser.getLink("Edit level").click()
733        self.browser.getControl(name="form.current_level").value = ['200']
734        self.browser.getControl("Save").click()
735        self.assertMatches('...has been saved...', self.browser.contents)
736        self.assertEqual(self.student.current_level, 200)
737
738    def test_postgraduate_student_access(self):
739        self.certificate.study_mode = 'special_pg_pt'
740        self.certificate.start_level = 700
741        self.certificate.end_level = 800
742        self.student['studycourse'].current_level = 700
743        IWorkflowState(self.student).setState('school fee paid')
744        self.browser.open(self.login_path)
745        self.browser.getControl(name="form.login").value = self.student_id
746        self.browser.getControl(name="form.password").value = 'spwd'
747        self.browser.getControl("Login").click()
748        self.assertTrue(
749            'You logged in.' in self.browser.contents)
750        # Now students can add the current study level
751        self.browser.getLink("Study Course").click()
752        self.browser.getLink("Add course list").click()
753        self.assertMatches('...Add current level 700...',
754                           self.browser.contents)
755        self.browser.getControl("Create course list now").click()
756        # A level with no course ticket was created
757        self.assertEqual(self.student['studycourse']['700'].number_of_tickets, 0)
758        self.browser.getLink("700").click()
759        self.browser.getLink("Edit course list").click()
760        self.browser.getLink("here").click()
761        self.browser.getControl(name="form.course").value = ['COURSE1']
762        # Non-final year students can't add ticket with 51 credits
763        self.app['faculties']['fac1']['dep1'].courses['COURSE1'].credits = 51
764        self.browser.getControl("Add course ticket").click()
765        self.assertMatches('...Total credits exceed 50...',
766                           self.browser.contents)
767        # Final year students can't add ticket with 52 credits ...
768        self.app['faculties']['fac1']['dep1'].courses['COURSE1'].credits = 52
769        self.student['studycourse'].certificate.end_level = 700
770        self.browser.getControl("Add course ticket").click()
771        self.assertMatches('...Total credits exceed 51...',
772                           self.browser.contents)
773        # ... but with 51 credits
774        self.app['faculties']['fac1']['dep1'].courses['COURSE1'].credits = 51
775        self.browser.getControl("Add course ticket").click()
776        self.assertMatches('...Successfully added COURSE1...',
777                           self.browser.contents)
778        # Non-final year special postgraduate students can't register
779        # course lists if their total credits are 51 and thus exceed 50 ...
780        self.student['studycourse'].certificate.end_level = 800
781        self.browser.getControl("Register course list").click()
782        self.assertMatches('...Maximum credits of 50 exceeded...',
783            self.browser.contents)
784        # ... but final year students can
785        self.student['studycourse'].certificate.end_level = 700
786        self.browser.getControl("Register course list").click()
787        self.assertMatches('...Course list has been registered...',
788            self.browser.contents)
789        self.assertEqual(self.student.state, 'courses registered')
790        return
791
792    def test_login(self):
793        # If suspended_comment is set this message will be flashed instead
794        self.student.suspended_comment = u'Aetsch baetsch!'
795        self.student.suspended = True
796        self.browser.open(self.login_path)
797        self.browser.getControl(name="form.login").value = self.student_id
798        self.browser.getControl(name="form.password").value = 'spwd'
799        self.browser.getControl("Login").click()
800        # Uniben does not display suspended_comment
801        self.assertMatches(
802            '...<div class="alert alert-warning">Your account has been deactivated.</div>...',
803            self.browser.contents)
804        self.student.suspended = False
805
806    def test_activate_deactivate_buttons(self):
807        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
808        self.browser.open(self.student_path)
809        self.browser.getLink("Deactivate").click()
810        self.assertTrue(
811            'Student account has been deactivated.' in self.browser.contents)
812        self.assertTrue(
813            'Base Data (account deactivated)' in self.browser.contents)
814        self.assertTrue(self.student.suspended)
815        self.browser.getLink("Activate").click()
816        self.assertTrue(
817            'Student account has been activated.' in self.browser.contents)
818        self.assertFalse(
819            'Base Data (account deactivated)' in self.browser.contents)
820        self.assertFalse(self.student.suspended)
821        # History messages have been added ...
822        self.browser.getLink("History").click()
823        # User is undisclosed
824        self.assertTrue(
825            'Student account deactivated<br />' in self.browser.contents)
826        self.assertTrue(
827            'Student account activated<br />' in self.browser.contents)
828        # ... and actions have been logged.
829        logfile = os.path.join(
830            self.app['datacenter'].storage, 'logs', 'students.log')
831        logcontent = open(logfile).read()
832        self.assertTrue('zope.mgr - waeup.uniben.students.browser.CustomStudentDeactivateView - '
833                        'B1000000 - account deactivated' in logcontent)
834        self.assertTrue('zope.mgr - waeup.uniben.students.browser.CustomStudentActivateView - '
835                        'B1000000 - account activated' in logcontent)
836
837    def test_manage_upload_fpm_file(self):
838        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
839        self.browser.open(self.manage_clearance_path)
840        image = open(SAMPLE_FPM, 'rb')
841        ctrl = self.browser.getControl(name='leftthumbprintupload')
842        file_ctrl = ctrl.mech_control
843        file_ctrl.add_file(image, filename='thumbprint.fpm')
844        self.browser.getControl(
845            name='upload_leftthumbprintupload').click()
846        self.assertTrue(
847            'File finger1.fpm uploaded.' in self.browser.contents)
848        self.assertTrue(
849            'http://localhost/app/students/B1000000/finger1.fpm'
850            in self.browser.contents)
851        self.browser.getControl(
852            name='delete_leftthumbprintupload').click()
853        self.assertTrue(
854            'finger1.fpm deleted'
855            in self.browser.contents)
856
857    def test_handle_clearance_by_co(self):
858        # Create clearance officer
859        self.app['users'].addUser('mrclear', 'mrclearsecret')
860        self.app['users']['mrclear'].email = 'mrclear@foo.ng'
861        self.app['users']['mrclear'].title = 'Carlo Pitter'
862        department = self.app['faculties']['fac1']['dep1']
863        prmlocal = IPrincipalRoleManager(department)
864        prmlocal.assignRoleToPrincipal('waeup.local.ClearanceOfficer', 'mrclear')
865        notify(LocalRoleSetEvent(
866            department, 'waeup.local.ClearanceOfficer', 'mrclear', granted=True))
867        IWorkflowState(self.student).setState('clearance requested')
868        # Login as clearance officer
869        self.browser.open(self.login_path)
870        self.browser.getControl(name="form.login").value = 'mrclear'
871        self.browser.getControl(name="form.password").value = 'mrclearsecret'
872        self.browser.getControl("Login").click()
873        self.assertMatches('...You logged in...', self.browser.contents)
874        # CO can view the student ...
875        self.browser.open(self.clearance_path)
876        self.assertEqual(self.browser.headers['Status'], '200 Ok')
877        self.assertEqual(self.browser.url, self.clearance_path)
878        # Clearance is disabled for this session for ug students ...
879        self.browser.open(self.clearance_path)
880        self.assertFalse('Clear student' in self.browser.contents)
881        self.browser.open(self.student_path + '/clear')
882        self.assertTrue('Clearance is disabled for this session'
883            in self.browser.contents)
884        # ... but not for
885        self.certificate.study_mode = 'pg_ft'
886        self.browser.open(self.clearance_path)
887        self.assertTrue('Clear student' in self.browser.contents)
888        self.browser.open(self.student_path + '/clear')
889        self.assertTrue('Student has been cleared' in self.browser.contents)
890
891    def test_transcripts(self):
892        studylevel = createObject(u'waeup.StudentStudyLevel')
893        studylevel.level = 100
894        studylevel.level_session = 2005
895        self.student['studycourse'].entry_mode = 'ug_ft'
896        self.student['studycourse'].addStudentStudyLevel(
897            self.certificate, studylevel)
898        studylevel2 = createObject(u'waeup.StudentStudyLevel')
899        studylevel2.level = 110
900        studylevel2.level_session = 2006
901        self.student['studycourse'].addStudentStudyLevel(
902            self.certificate, studylevel2)
903        # Add second course (COURSE has been added automatically)
904        courseticket = createObject('waeup.CourseTicket')
905        courseticket.code = 'ANYCODE'
906        courseticket.title = u'Any TITLE'
907        courseticket.credits = 13
908        courseticket.score = 66
909        courseticket.semester = 1
910        courseticket.dcode = u'ANYDCODE'
911        courseticket.fcode = u'ANYFCODE'
912        self.student['studycourse']['110']['COURSE2'] = courseticket
913        self.student['studycourse']['100']['COURSE1'].score = 55
914        self.assertEqual(self.student['studycourse']['100'].gpa_params_rectified[0], 3.0)
915        self.assertEqual(self.student['studycourse']['110'].gpa_params_rectified[0], 4.0)
916        # Get transcript data
917        td = self.student['studycourse'].getTranscriptData()
918        self.assertEqual(td[0][0]['level_key'], '100')
919        self.assertEqual(td[0][0]['sgpa'], 3.0)
920        self.assertEqual(td[0][0]['level'].level, 100)
921        self.assertEqual(td[0][0]['level'].level_session, 2005)
922        self.assertEqual(td[0][0]['tickets_1'][0].code, 'COURSE1')
923        self.assertEqual(td[0][1]['level_key'], '110')
924        self.assertEqual(td[0][1]['sgpa'], 4.0)
925        self.assertEqual(td[0][1]['level'].level, 110)
926        self.assertEqual(td[0][1]['level'].level_session, 2006)
927        self.assertEqual(td[0][1]['tickets_1'][0].code, 'ANYCODE')
928        self.assertEqual(td[1], 3.57)
929        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
930        self.browser.open(self.student_path + '/studycourse/transcript')
931        self.assertEqual(self.browser.headers['Status'], '200 Ok')
932        self.assertTrue('Transcript' in self.browser.contents)
933        # Officers can open the pdf transcript
934        self.browser.open(self.student_path + '/studycourse/transcript.pdf')
935        self.assertEqual(self.browser.headers['Status'], '200 Ok')
936        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
937        path = os.path.join(samples_dir(), 'transcript.pdf')
938        open(path, 'wb').write(self.browser.contents)
939        print "Sample PDF transcript.pdf written to %s" % path
940
941    def test_student_accommodation(self):
942        bed = Bed()
943        bed.bed_id = u'hall-1_A_101_C'
944        bed.bed_number = 3
945        bed.owner = NOT_OCCUPIED
946        bed.bed_type = u'regular_male_fi'
947        self.app['hostels']['hall-1'].addBed(bed)
948        self.browser.open(self.login_path)
949        self.browser.getControl(name="form.login").value = self.student_id
950        self.browser.getControl(name="form.password").value = 'spwd'
951        self.browser.getControl("Login").click()
952        # Students can add online booking fee payment tickets and open the
953        # callback view (see test_manage_payments).
954        self.browser.getLink("Payments").click()
955        self.browser.getLink("Add current session payment ticket").click()
956        self.browser.getControl(name="form.p_category").value = ['bed_allocation']
957        self.browser.getControl("Create ticket").click()
958        p_ticket = self.student['payments'].values()[0]
959        p_ticket.approveStudentPayment()
960        # The new HOS-0 pin has been created.
961        self.assertEqual(len(self.app['accesscodes']['HOS-0']),1)
962        pin = self.app['accesscodes']['HOS-0'].keys()[0]
963        ac = self.app['accesscodes']['HOS-0'][pin]
964        parts = pin.split('-')[1:]
965        sfeseries, sfenumber = parts
966        # Students can use HOS code and book a bed space with it ...
967        self.browser.open(self.acco_path)
968        # ... but not if booking period has expired ...
969        self.app['hostels'].enddate = datetime.now(pytz.utc)
970        self.browser.getControl("Book accommodation").click()
971        self.assertMatches('...Outside booking period: ...',
972                           self.browser.contents)
973        self.app['hostels'].enddate = datetime.now(pytz.utc) + timedelta(days=10)
974        # ... or student data are incomplete ...
975        self.student['studycourse'].current_level = None
976        self.browser.getControl("Book accommodation").click()
977        self.assertMatches('...Your data are incomplete...',
978            self.browser.contents)
979        self.student['studycourse'].current_level = 200
980        # ... or student is not the an allowed state ...
981        self.browser.getControl("Book accommodation").click()
982        self.assertMatches('...You are in the wrong...',
983                           self.browser.contents)
984        self.app['hostels'].accommodation_states = ['admitted', 'school fee paid']
985        IWorkflowState(self.student).setState('school fee paid')
986        # ... or student has not appropriate verdict (Uniben only!)
987        self.student['studycourse'].entry_session = 2000 # non-fresh
988        self.student['studycourse'].current_level = 500 # final-year
989        self.student['studycourse'].current_verdict = 'C'
990        self.browser.getControl("Book accommodation").click()
991        self.assertMatches('...Your are not eligible...',
992            self.browser.contents)
993        self.student['studycourse'].previous_verdict = 'A'
994        self.browser.getControl("Book accommodation").click()
995        self.assertMatches('...Activation Code:...',
996                           self.browser.contents)
997        # Student can't use faked ACs ...
998        self.browser.getControl(name="ac_series").value = u'nonsense'
999        self.browser.getControl(name="ac_number").value = sfenumber
1000        self.browser.getControl("Create bed ticket").click()
1001        self.assertMatches('...Activation code is invalid...',
1002                           self.browser.contents)
1003        # ... or ACs owned by somebody else.
1004        ac.owner = u'Anybody'
1005        self.browser.getControl(name="ac_series").value = sfeseries
1006        self.browser.getControl(name="ac_number").value = sfenumber
1007        self.browser.getControl("Create bed ticket").click()
1008        self.assertMatches('...You are not the owner of this access code...',
1009                           self.browser.contents)
1010        # The bed remains empty.
1011        bed = self.app['hostels']['hall-1']['hall-1_A_101_C']
1012        self.assertTrue(bed.owner == NOT_OCCUPIED)
1013        ac.owner = self.student_id
1014        self.browser.getControl(name="ac_series").value = sfeseries
1015        self.browser.getControl(name="ac_number").value = sfenumber
1016        self.browser.getControl("Create bed ticket").click()
1017        self.assertMatches('...Hall 1, Block/Unit A, Room 101, Bed C...',
1018                           self.browser.contents)
1019        # Bed has been allocated.
1020        self.assertTrue(bed.owner == self.student_id)
1021        # BedTicketAddPage is now blocked.
1022        self.browser.getControl("Book accommodation").click()
1023        self.assertMatches('...You already booked a bed space...',
1024            self.browser.contents)
1025        # The bed ticket displays the data correctly.
1026        self.browser.open(self.acco_path + '/2004')
1027        self.assertMatches('...Hall 1, Block/Unit A, Room 101, Bed C...',
1028                           self.browser.contents)
1029        self.assertMatches('...2004/2005...', self.browser.contents)
1030        self.assertMatches('...regular_male_fi...', self.browser.contents)
1031        self.assertMatches('...%s...' % pin, self.browser.contents)
1032        # Students can open the pdf slip.
1033        self.browser.open(self.browser.url + '/bed_allocation_slip.pdf')
1034        self.assertEqual(self.browser.headers['Status'], '200 Ok')
1035        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
1036        path = os.path.join(samples_dir(), 'bed_allocation_slip.pdf')
1037        open(path, 'wb').write(self.browser.contents)
1038        print "Sample PDF bed_allocation_slip.pdf written to %s" % path
1039        # Students can't relocate themselves.
1040        self.assertFalse('Relocate' in self.browser.contents)
1041        relocate_path = self.acco_path + '/2004/relocate'
1042        self.assertRaises(
1043            Unauthorized, self.browser.open, relocate_path)
1044        # Students can't see the Remove button and check boxes.
1045        self.browser.open(self.acco_path)
1046        self.assertFalse('Remove' in self.browser.contents)
1047        self.assertFalse('val_id' in self.browser.contents)
1048        # Students can pay maintenance fee now.
1049        self.browser.open(self.payments_path)
1050        self.browser.open(self.payments_path + '/addop')
1051        self.browser.getControl(name="form.p_category").value = ['hostel_maintenance']
1052        self.browser.getControl("Create ticket").click()
1053        self.assertMatches('...Payment ticket created...',
1054                           self.browser.contents)
1055        # Maintennace fee is taken from the hostel object.
1056        self.assertEqual(self.student['payments'].values()[1].amount_auth, 876.0)
1057        # If the hostel's maintenance fee isn't set, the fee is
1058        # taken from the session configuration object.
1059        self.app['hostels']['hall-1'].maint_fee = 0.0
1060        self.browser.open(self.payments_path + '/addop')
1061        self.browser.getControl(name="form.p_category").value = ['hostel_maintenance']
1062        self.browser.getControl("Create ticket").click()
1063        self.assertEqual(self.student['payments'].values()[2].amount_auth, 987.0)
1064        return
Note: See TracBrowser for help on using the repository browser.