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

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

According to med's advice in ticket #1108: "Paying for the next session should only be done at the state returning"

  • Property svn:keywords set to Id
File size: 55.2 KB
Line 
1## $Id: test_browser.py 14857 2017-10-02 05:38:09Z 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
545        #error, payment = utils.setPaymentDetails('schoolfee',
546        #    self.student, None, None)
547        #self.assertTrue(
548        #    u'You have not yet paid your current/active session.' in error)
549        ## Ok, that means we have to add paid payment ticket first.
550        #payment = createObject('waeup.StudentOnlinePayment')
551        #payment.p_category = u'schoolfee'
552        #payment.p_session = self.student.current_session
553        #payment.p_item = u'My Certificate'
554        #payment.p_id = u'anyid'
555        #payment.p_state = u'paid'
556        #self.student['payments']['anykey'] = payment
557
558
559        error, payment = utils.setPaymentDetails('schoolfee',
560            self.student, None, None)
561        self.assertEqual(payment.p_level, 200)
562        self.assertEqual(payment.p_session, 2005)
563        self.assertEqual(payment.amount_auth, 20088.0)
564        self.assertEqual(payment.p_item, u'CERT1')
565        self.assertEqual(error, None)
566
567        # Staff members pay less.
568        self.student.is_staff = True
569        error, payment = utils.setPaymentDetails('schoolfee',
570            self.student, None, None)
571        self.assertEqual(payment.p_level, 200)
572        self.assertEqual(payment.p_session, 2005)
573        self.assertEqual(payment.amount_auth, 10088.0)
574        self.assertEqual(payment.p_item, u'CERT1')
575        self.assertEqual(error, None)
576
577        # Foreigners pay more.
578        IWorkflowState(self.student).setState('cleared')
579        self.student.is_staff = False
580        self.student.nationality = u'DE'
581        self.certificate.school_fee_3 = 60000.0
582        error, payment = utils.setPaymentDetails(
583            'schoolfee', self.student, None, None)
584        self.assertEqual(payment.p_level, 100)
585        self.assertEqual(payment.p_session, 2004)
586        self.assertEqual(payment.amount_auth, 60099.0)
587        self.assertEqual(payment.p_item, u'CERT1')
588        self.assertEqual(error, None)
589        IWorkflowState(self.student).setState('returning')
590        self.student.is_staff = False
591        self.certificate.school_fee_4 = 20000.0
592        error, payment = utils.setPaymentDetails(
593            'schoolfee', self.student, None, None)
594        self.assertEqual(payment.p_level, 200)
595        self.assertEqual(payment.p_session, 2005)
596        self.assertEqual(payment.amount_auth, 20088.0)
597        self.assertEqual(payment.p_item, u'CERT1')
598        self.assertEqual(error, None)
599
600        # In Uniben students can pay school fee in all states no matter
601        # if they are ug or pg students.
602        # diabled on 02/10/2017, see ticket 1108
603        #IWorkflowState(self.student).setState('school fee paid')
604        #self.student.is_staff = False
605        #self.student.nationality = u'NG'
606        #self.certificate.school_fee_2 = 10000.0
607        #error, payment = utils.setPaymentDetails(
608        #    'schoolfee', self.student, None, None)
609        #self.assertEqual(payment.p_level, None)
610        #self.assertEqual(payment.p_session, 2005)
611        #self.assertEqual(payment.amount_auth, 10088.0)
612        #self.assertEqual(payment.p_item, u'CERT1')
613        #self.assertEqual(error, None)
614        #IWorkflowState(self.student).setState('courses registered')
615        #self.certificate.study_mode = 'special_pg_pt'
616        #error, payment = utils.setPaymentDetails(
617        #    'schoolfee', self.student, None, None)
618        #self.assertEqual(payment.p_level, None)
619        #self.assertEqual(payment.p_session, 2005)
620        #self.assertEqual(payment.amount_auth, 10000.0)
621        #self.assertEqual(payment.p_item, u'CERT1')
622        #self.assertEqual(error, None)
623        #IWorkflowState(self.student).setState('courses validated')
624        #error, payment = utils.setPaymentDetails(
625        #    'schoolfee', self.student, None, None)
626        #self.assertEqual(payment.p_level, None)
627        #self.assertEqual(payment.p_session, 2005)
628        #self.assertEqual(payment.amount_auth, 10000.0)
629        #self.assertEqual(payment.p_item, u'CERT1')
630        #self.assertEqual(error, None)
631
632        error, payment = utils.setPaymentDetails('clearance',
633            self.student, None, None)
634        self.assertEqual(payment.p_level, 100)
635        self.assertEqual(payment.p_session, 2004)
636        self.assertEqual(payment.amount_auth, 45000.0)
637        self.assertEqual(payment.p_item, u'CERT1')
638        self.assertEqual(error, None)
639
640        error, payment = utils.setPaymentDetails('gown',
641            self.student, None, None)
642        self.assertEqual(payment.p_level, 100)
643        self.assertEqual(payment.p_session, 2004)
644        self.assertEqual(payment.amount_auth, 150.0)
645        self.assertEqual(payment.p_item, u'')
646        self.assertEqual(error, None)
647
648        bedticket = BedTicket()
649        bedticket.booking_session = 2004
650        bedticket.bed_type = u'any bed type'
651        bedticket.bed = self.app['hostels']['hall-1']['hall-1_A_101_A']
652        bedticket.bed_coordinates = u'My bed coordinates'
653        self.student['accommodation'].addBedTicket(bedticket)
654
655        error, payment = utils.setPaymentDetails('hostel_maintenance',
656            self.student, None, None)
657        self.assertEqual(payment.p_level, 100)
658        self.assertEqual(payment.p_session, 2004)
659        self.assertEqual(payment.amount_auth, 876.0)
660        self.assertEqual(payment.p_item, u'My bed coordinates')
661        self.assertEqual(error, None)
662
663        self.certificate.study_mode = 'ug_ft'
664        error, payment = utils.setPaymentDetails('bed_allocation',
665            self.student, None, None)
666        self.assertTrue(u'Amount could not be determined.' in error)
667        self.student['studycourse'].current_session = 2004
668        self.student['studycourse'].entry_session = 2004
669        self.student['studycourse'].current_level = 100
670        error, payment = utils.setPaymentDetails('bed_allocation',
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, 650.0) # plus 500 student union
675        self.assertEqual(payment.p_item, u'regular_male_fr')
676        self.assertEqual(error, None)
677
678        self.certificate.study_mode = 'pg_ft'
679        error, payment = utils.setPaymentDetails('bed_allocation',
680            self.student, None, None)
681        self.assertEqual(payment.p_level, 100)
682        self.assertEqual(payment.p_session, 2004)
683        self.assertEqual(payment.amount_auth, 150.0)
684        self.assertEqual(payment.p_item, u'pg_male_all')
685        self.assertEqual(error, None)
686
687        #error, payment = utils.setPaymentDetails('hostel_application',
688        #    self.student, None, None)
689        #self.assertEqual(payment.p_level, 100)
690        #self.assertEqual(payment.p_session, 2004)
691        #self.assertEqual(payment.amount_auth, 1000.0)
692        #self.assertEqual(payment.p_item, u'')
693        #self.assertEqual(error, None)
694
695        #payment.approve()
696        #self.student['payments'][payment.p_id] = payment
697
698        #error, payment = utils.setPaymentDetails('tempmaint_1',
699        #    self.student, None, None)
700        #self.assertEqual(payment.p_level, 100)
701        #self.assertEqual(payment.p_session, 2004)
702        #self.assertEqual(payment.amount_auth, 8150.0)
703        #self.assertEqual(payment.p_item, u'Hall 1-4 M/F Ekehuan')
704        #self.assertEqual(error, None)
705
706        #error, payment = utils.setPaymentDetails('tempmaint_2',
707        #    self.student, None, None)
708        #self.assertEqual(payment.p_level, 100)
709        #self.assertEqual(payment.p_session, 2004)
710        #self.assertEqual(payment.amount_auth, 12650.0)
711        #self.assertEqual(payment.p_item, u'Hall 5 M/F')
712        #self.assertEqual(error, None)
713
714        #error, payment = utils.setPaymentDetails('tempmaint_3',
715        #    self.student, None, None)
716        #self.assertEqual(payment.p_level, 100)
717        #self.assertEqual(payment.p_session, 2004)
718        #self.assertEqual(payment.amount_auth, 9650.0)
719        #self.assertEqual(payment.p_item, u'Clinical Hostel')
720        #self.assertEqual(error, None)
721
722        error, payment = utils.setPaymentDetails('transfer',
723            self.student, None, None)
724        self.assertEqual(payment.p_level, 100)
725        self.assertEqual(payment.p_session, 2004)
726        self.assertEqual(payment.amount_auth, 90.0)
727        self.assertEqual(payment.p_item, u'')
728        self.assertEqual(error, None)
729        return
730
731    def test_edit_level_by_co(self):
732        # Create clearance officer
733        self.app['users'].addUser('mrclear', 'mrclearsecret')
734        self.app['users']['mrclear'].email = 'mrclear@foo.ng'
735        self.app['users']['mrclear'].title = 'Carlo Pitter'
736        # Assign local ClearanceOfficer role
737        department = self.app['faculties']['fac1']['dep1']
738        prmlocal = IPrincipalRoleManager(department)
739        prmlocal.assignRoleToPrincipal('waeup.local.ClearanceOfficer', 'mrclear')
740        notify(LocalRoleSetEvent(
741            department, 'waeup.local.ClearanceOfficer', 'mrclear', granted=True))
742        IWorkflowState(self.student).setState('clearance started')
743        # Login as clearance officer
744        self.browser.open(self.login_path)
745        self.browser.getControl(name="form.login").value = 'mrclear'
746        self.browser.getControl(name="form.password").value = 'mrclearsecret'
747        self.browser.getControl("Login").click()
748        self.assertMatches('...You logged in...', self.browser.contents)
749        # Only in state clearance requested the CO does see the
750        # 'Edit level' button ...
751        self.browser.open(self.studycourse_path)
752        self.assertFalse('Edit level' in self.browser.contents)
753        # ... and can open the edit_level view
754        self.browser.open(self.studycourse_path + '/edit_level')
755        self.assertMatches('...is locked...', self.browser.contents)
756        self.assertEqual(self.browser.url, self.studycourse_path)
757        IWorkflowInfo(self.student).fireTransition('request_clearance')
758        self.browser.open(self.studycourse_path)
759        self.assertTrue('Edit level' in self.browser.contents)
760        self.browser.getLink("Edit level").click()
761        self.browser.getControl(name="form.current_level").value = ['200']
762        self.browser.getControl("Save").click()
763        self.assertMatches('...has been saved...', self.browser.contents)
764        self.assertEqual(self.student.current_level, 200)
765
766    def test_postgraduate_student_access(self):
767        self.certificate.study_mode = 'special_pg_pt'
768        self.certificate.start_level = 700
769        self.certificate.end_level = 800
770        self.student['studycourse'].current_level = 700
771        IWorkflowState(self.student).setState('school fee paid')
772        self.browser.open(self.login_path)
773        self.browser.getControl(name="form.login").value = self.student_id
774        self.browser.getControl(name="form.password").value = 'spwd'
775        self.browser.getControl("Login").click()
776        self.assertTrue(
777            'You logged in.' in self.browser.contents)
778        # Now students can add the current study level
779        self.browser.getLink("Study Course").click()
780        self.browser.getLink("Add course list").click()
781        self.assertMatches('...Add current level 700...',
782                           self.browser.contents)
783        self.browser.getControl("Create course list now").click()
784        # A level with no course ticket was created
785        self.assertEqual(self.student['studycourse']['700'].number_of_tickets, 0)
786        self.browser.getLink("700").click()
787        self.browser.getLink("Edit course list").click()
788        self.browser.getLink("here").click()
789        self.browser.getControl(name="form.course").value = ['COURSE1']
790        # Non-final year students can't add ticket with 51 credits
791        self.app['faculties']['fac1']['dep1'].courses['COURSE1'].credits = 51
792        self.browser.getControl("Add course ticket").click()
793        self.assertMatches('...Maximum credits exceeded...',
794                           self.browser.contents)
795        # Final year students can't add ticket with 52 credits ...
796        self.app['faculties']['fac1']['dep1'].courses['COURSE1'].credits = 52
797        self.student['studycourse'].certificate.end_level = 700
798        self.browser.getControl("Add course ticket").click()
799        self.assertMatches('...Maximum credits exceeded...',
800                           self.browser.contents)
801        # ... but with 51 credits
802        self.app['faculties']['fac1']['dep1'].courses['COURSE1'].credits = 51
803        self.browser.getControl("Add course ticket").click()
804        self.assertMatches('...Successfully added COURSE1...',
805                           self.browser.contents)
806        # Non-final year special postgraduate students can't register
807        # course lists if their total credits are 51 and thus exceed 50 ...
808        self.student['studycourse'].certificate.end_level = 800
809        self.browser.getControl("Register course list").click()
810        self.assertMatches('...Maximum credits exceeded...',
811            self.browser.contents)
812        # ... but final year students can
813        self.student['studycourse'].certificate.end_level = 700
814        self.browser.getControl("Register course list").click()
815        self.assertMatches('...Course list has been registered...',
816            self.browser.contents)
817        self.assertEqual(self.student.state, 'courses registered')
818        return
819
820    def test_login(self):
821        # If suspended_comment is set this message will be flashed instead
822        self.student.suspended_comment = u'Aetsch baetsch!'
823        self.student.suspended = True
824        self.browser.open(self.login_path)
825        self.browser.getControl(name="form.login").value = self.student_id
826        self.browser.getControl(name="form.password").value = 'spwd'
827        self.browser.getControl("Login").click()
828        # Uniben does not display suspended_comment
829        self.assertMatches(
830            '...<div class="alert alert-warning">Your account has been deactivated.</div>...',
831            self.browser.contents)
832        self.student.suspended = False
833
834    def test_activate_deactivate_buttons(self):
835        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
836        self.browser.open(self.student_path)
837        self.browser.getLink("Deactivate").click()
838        self.assertTrue(
839            'Student account has been deactivated.' in self.browser.contents)
840        self.assertTrue(
841            'Base Data (account deactivated)' in self.browser.contents)
842        self.assertTrue(self.student.suspended)
843        self.browser.getLink("Activate").click()
844        self.assertTrue(
845            'Student account has been activated.' in self.browser.contents)
846        self.assertFalse(
847            'Base Data (account deactivated)' in self.browser.contents)
848        self.assertFalse(self.student.suspended)
849        # History messages have been added ...
850        self.browser.getLink("History").click()
851        # User is undisclosed
852        self.assertTrue(
853            'Student account deactivated<br />' in self.browser.contents)
854        self.assertTrue(
855            'Student account activated<br />' in self.browser.contents)
856        # ... and actions have been logged.
857        logfile = os.path.join(
858            self.app['datacenter'].storage, 'logs', 'students.log')
859        logcontent = open(logfile).read()
860        self.assertTrue('zope.mgr - waeup.uniben.students.browser.CustomStudentDeactivateView - '
861                        'B1000000 - account deactivated' in logcontent)
862        self.assertTrue('zope.mgr - waeup.uniben.students.browser.CustomStudentActivateView - '
863                        'B1000000 - account activated' in logcontent)
864
865    def test_manage_upload_fpm_file(self):
866        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
867        self.browser.open(self.manage_clearance_path)
868        image = open(SAMPLE_FPM, 'rb')
869        ctrl = self.browser.getControl(name='leftthumbprintupload')
870        file_ctrl = ctrl.mech_control
871        file_ctrl.add_file(image, filename='thumbprint.fpm')
872        self.browser.getControl(
873            name='upload_leftthumbprintupload').click()
874        self.assertTrue(
875            'File finger1.fpm uploaded.' in self.browser.contents)
876        self.assertTrue(
877            'http://localhost/app/students/B1000000/finger1.fpm'
878            in self.browser.contents)
879        self.browser.getControl(
880            name='delete_leftthumbprintupload').click()
881        self.assertTrue(
882            'finger1.fpm deleted'
883            in self.browser.contents)
884
885    def test_handle_clearance_by_co(self):
886        # Create clearance officer
887        self.app['users'].addUser('mrclear', 'mrclearsecret')
888        self.app['users']['mrclear'].email = 'mrclear@foo.ng'
889        self.app['users']['mrclear'].title = 'Carlo Pitter'
890        department = self.app['faculties']['fac1']['dep1']
891        prmlocal = IPrincipalRoleManager(department)
892        prmlocal.assignRoleToPrincipal('waeup.local.ClearanceOfficer', 'mrclear')
893        notify(LocalRoleSetEvent(
894            department, 'waeup.local.ClearanceOfficer', 'mrclear', granted=True))
895        IWorkflowState(self.student).setState('clearance requested')
896        # Login as clearance officer
897        self.browser.open(self.login_path)
898        self.browser.getControl(name="form.login").value = 'mrclear'
899        self.browser.getControl(name="form.password").value = 'mrclearsecret'
900        self.browser.getControl("Login").click()
901        self.assertMatches('...You logged in...', self.browser.contents)
902        # CO can view the student ...
903        self.browser.open(self.clearance_path)
904        self.assertEqual(self.browser.headers['Status'], '200 Ok')
905        self.assertEqual(self.browser.url, self.clearance_path)
906        # Clearance is disabled for this session for ug students ...
907        self.browser.open(self.clearance_path)
908        self.assertFalse('Clear student' in self.browser.contents)
909        self.browser.open(self.student_path + '/clear')
910        self.assertTrue('Clearance is disabled for this session'
911            in self.browser.contents)
912        # ... but not for
913        self.certificate.study_mode = 'pg_ft'
914        self.browser.open(self.clearance_path)
915        self.assertTrue('Clear student' in self.browser.contents)
916        self.browser.open(self.student_path + '/clear')
917        self.assertTrue('Student has been cleared' in self.browser.contents)
918
919    def test_transcripts(self):
920        studylevel = createObject(u'waeup.StudentStudyLevel')
921        studylevel.level = 100
922        studylevel.level_session = 2005
923        self.student['studycourse'].entry_mode = 'ug_ft'
924        self.student['studycourse'].addStudentStudyLevel(
925            self.certificate, studylevel)
926        studylevel2 = createObject(u'waeup.StudentStudyLevel')
927        studylevel2.level = 110
928        studylevel2.level_session = 2006
929        self.student['studycourse'].addStudentStudyLevel(
930            self.certificate, studylevel2)
931        # Add second course (COURSE has been added automatically)
932        courseticket = createObject('waeup.CourseTicket')
933        courseticket.code = 'ANYCODE'
934        courseticket.title = u'Any TITLE'
935        courseticket.credits = 13
936        courseticket.score = 66
937        courseticket.semester = 1
938        courseticket.dcode = u'ANYDCODE'
939        courseticket.fcode = u'ANYFCODE'
940        self.student['studycourse']['110']['COURSE2'] = courseticket
941        self.student['studycourse']['100']['COURSE1'].score = 55
942        self.assertEqual(self.student['studycourse']['100'].gpa_params_rectified[0], 3.0)
943        self.assertEqual(self.student['studycourse']['110'].gpa_params_rectified[0], 4.0)
944        # Get transcript data
945        td = self.student['studycourse'].getTranscriptData()
946        self.assertEqual(td[0][0]['level_key'], '100')
947        self.assertEqual(td[0][0]['sgpa'], 3.0)
948        self.assertEqual(td[0][0]['level'].level, 100)
949        self.assertEqual(td[0][0]['level'].level_session, 2005)
950        self.assertEqual(td[0][0]['tickets_1'][0].code, 'COURSE1')
951        self.assertEqual(td[0][1]['level_key'], '110')
952        self.assertEqual(td[0][1]['sgpa'], 4.0)
953        self.assertEqual(td[0][1]['level'].level, 110)
954        self.assertEqual(td[0][1]['level'].level_session, 2006)
955        self.assertEqual(td[0][1]['tickets_1'][0].code, 'ANYCODE')
956        self.assertEqual(td[1], 3.5652173913043477)
957        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
958        self.browser.open(self.student_path + '/studycourse/transcript')
959        self.assertEqual(self.browser.headers['Status'], '200 Ok')
960        self.assertTrue('Transcript' in self.browser.contents)
961        # Officers can open the pdf transcript
962        self.browser.open(self.student_path + '/studycourse/transcript.pdf')
963        self.assertEqual(self.browser.headers['Status'], '200 Ok')
964        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
965        path = os.path.join(samples_dir(), 'transcript.pdf')
966        open(path, 'wb').write(self.browser.contents)
967        print "Sample PDF transcript.pdf written to %s" % path
968
969    def test_student_accommodation(self):
970        bed = Bed()
971        bed.bed_id = u'hall-1_A_101_C'
972        bed.bed_number = 3
973        bed.owner = NOT_OCCUPIED
974        bed.bed_type = u'regular_male_fi'
975        self.app['hostels']['hall-1'].addBed(bed)
976        self.browser.open(self.login_path)
977        self.browser.getControl(name="form.login").value = self.student_id
978        self.browser.getControl(name="form.password").value = 'spwd'
979        self.browser.getControl("Login").click()
980        # Students can add online booking fee payment tickets and open the
981        # callback view (see test_manage_payments).
982        self.browser.getLink("Payments").click()
983        self.browser.getLink("Add current session payment ticket").click()
984        self.browser.getControl(name="form.p_category").value = ['bed_allocation']
985        self.browser.getControl("Create ticket").click()
986        p_ticket = self.student['payments'].values()[0]
987        p_ticket.approveStudentPayment()
988        # The new HOS-0 pin has been created.
989        self.assertEqual(len(self.app['accesscodes']['HOS-0']),1)
990        pin = self.app['accesscodes']['HOS-0'].keys()[0]
991        ac = self.app['accesscodes']['HOS-0'][pin]
992        parts = pin.split('-')[1:]
993        sfeseries, sfenumber = parts
994        # Students can use HOS code and book a bed space with it ...
995        self.browser.open(self.acco_path)
996        # ... but not if booking period has expired ...
997        self.app['hostels'].enddate = datetime.now(pytz.utc)
998        self.browser.getControl("Book accommodation").click()
999        self.assertMatches('...Outside booking period: ...',
1000                           self.browser.contents)
1001        self.app['hostels'].enddate = datetime.now(pytz.utc) + timedelta(days=10)
1002        # ... or student data are incomplete ...
1003        self.student['studycourse'].current_level = None
1004        self.browser.getControl("Book accommodation").click()
1005        self.assertMatches('...Your data are incomplete...',
1006            self.browser.contents)
1007        self.student['studycourse'].current_level = 200
1008        # ... or student is not the an allowed state ...
1009        self.browser.getControl("Book accommodation").click()
1010        self.assertMatches('...You are in the wrong...',
1011                           self.browser.contents)
1012        self.app['hostels'].accommodation_states = ['admitted', 'school fee paid']
1013        IWorkflowState(self.student).setState('school fee paid')
1014        # ... or student has not appropriate verdict (Uniben only!)
1015        self.student['studycourse'].entry_session = 2000 # non-fresh
1016        self.student['studycourse'].current_level = 500 # final-year
1017        self.student['studycourse'].current_verdict = 'C'
1018        self.browser.getControl("Book accommodation").click()
1019        self.assertMatches('...Your are not eligible...',
1020            self.browser.contents)
1021        self.student['studycourse'].previous_verdict = 'A'
1022        self.browser.getControl("Book accommodation").click()
1023        self.assertMatches('...Activation Code:...',
1024                           self.browser.contents)
1025        # Student can't use faked ACs ...
1026        self.browser.getControl(name="ac_series").value = u'nonsense'
1027        self.browser.getControl(name="ac_number").value = sfenumber
1028        self.browser.getControl("Create bed ticket").click()
1029        self.assertMatches('...Activation code is invalid...',
1030                           self.browser.contents)
1031        # ... or ACs owned by somebody else.
1032        ac.owner = u'Anybody'
1033        self.browser.getControl(name="ac_series").value = sfeseries
1034        self.browser.getControl(name="ac_number").value = sfenumber
1035        self.browser.getControl("Create bed ticket").click()
1036        self.assertMatches('...You are not the owner of this access code...',
1037                           self.browser.contents)
1038        # The bed remains empty.
1039        bed = self.app['hostels']['hall-1']['hall-1_A_101_C']
1040        self.assertTrue(bed.owner == NOT_OCCUPIED)
1041        ac.owner = self.student_id
1042        self.browser.getControl(name="ac_series").value = sfeseries
1043        self.browser.getControl(name="ac_number").value = sfenumber
1044        self.browser.getControl("Create bed ticket").click()
1045        self.assertMatches('...Hall 1, Block/Unit A, Room 101, Bed C...',
1046                           self.browser.contents)
1047        # Bed has been allocated.
1048        self.assertTrue(bed.owner == self.student_id)
1049        # BedTicketAddPage is now blocked.
1050        self.browser.getControl("Book accommodation").click()
1051        self.assertMatches('...You already booked a bed space...',
1052            self.browser.contents)
1053        # The bed ticket displays the data correctly.
1054        self.browser.open(self.acco_path + '/2004')
1055        self.assertMatches('...Hall 1, Block/Unit A, Room 101, Bed C...',
1056                           self.browser.contents)
1057        self.assertMatches('...2004/2005...', self.browser.contents)
1058        self.assertMatches('...regular_male_fi...', self.browser.contents)
1059        self.assertMatches('...%s...' % pin, self.browser.contents)
1060        # Students can open the pdf slip.
1061        self.browser.open(self.browser.url + '/bed_allocation_slip.pdf')
1062        self.assertEqual(self.browser.headers['Status'], '200 Ok')
1063        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
1064        path = os.path.join(samples_dir(), 'bed_allocation_slip.pdf')
1065        open(path, 'wb').write(self.browser.contents)
1066        print "Sample PDF bed_allocation_slip.pdf written to %s" % path
1067        # Students can't relocate themselves.
1068        self.assertFalse('Relocate' in self.browser.contents)
1069        relocate_path = self.acco_path + '/2004/relocate'
1070        self.assertRaises(
1071            Unauthorized, self.browser.open, relocate_path)
1072        # Students can't see the Remove button and check boxes.
1073        self.browser.open(self.acco_path)
1074        self.assertFalse('Remove' in self.browser.contents)
1075        self.assertFalse('val_id' in self.browser.contents)
1076        # Students can pay maintenance fee now.
1077        self.browser.open(self.payments_path)
1078        self.browser.open(self.payments_path + '/addop')
1079        self.browser.getControl(name="form.p_category").value = ['hostel_maintenance']
1080        self.browser.getControl("Create ticket").click()
1081        self.assertMatches('...Payment ticket created...',
1082                           self.browser.contents)
1083        # Maintennace fee is taken from the hostel object.
1084        self.assertEqual(self.student['payments'].values()[1].amount_auth, 876.0)
1085        # If the hostel's maintenance fee isn't set, the fee is
1086        # taken from the session configuration object.
1087        self.app['hostels']['hall-1'].maint_fee = 0.0
1088        self.browser.open(self.payments_path + '/addop')
1089        self.browser.getControl(name="form.p_category").value = ['hostel_maintenance']
1090        self.browser.getControl("Create ticket").click()
1091        self.assertEqual(self.student['payments'].values()[2].amount_auth, 987.0)
1092        return
Note: See TracBrowser for help on using the repository browser.