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

Last change on this file since 14896 was 14893, checked in by Henrik Bettermann, 7 years ago

Use custom_float_1 for old returning student discount.

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