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

Last change on this file since 15369 was 15352, checked in by Henrik Bettermann, 6 years ago

Add ExportJHLIdCard page.

Make email field required on CustomStudentBaseEditFormPage?.

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