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

Last change on this file since 10009 was 9902, checked in by Henrik Bettermann, 12 years ago

Adjust to changes made in base package (r9895).

  • Property svn:keywords set to Id
File size: 35.5 KB
Line 
1## $Id: test_browser.py 9902 2013-01-18 10:10:32Z 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
21from StringIO import StringIO
22from hurry.workflow.interfaces import IWorkflowState, IWorkflowInfo
23from zope.securitypolicy.interfaces import IPrincipalRoleManager
24from zope.component.hooks import setSite, clearSite
25from zope.component import getUtility, createObject
26from zope.interface import verify
27from zope.event import notify
28from waeup.kofa.authentication import LocalRoleSetEvent
29from waeup.kofa.app import University
30from waeup.kofa.students.tests.test_browser import StudentsFullSetup
31from waeup.kofa.students.accommodation import BedTicket
32from waeup.kofa.testing import FunctionalTestCase
33from waeup.kofa.interfaces import (
34    IExtFileStore, IFileStoreNameChooser)
35from waeup.kofa.students.interfaces import IStudentsUtils
36from waeup.uniben.testing import FunctionalLayer
37
38
39class StudentProcessorTest(FunctionalTestCase):
40    """Perform some batching tests.
41    """
42
43    layer = FunctionalLayer
44
45    def setUp(self):
46        super(StudentProcessorTest, self).setUp()
47        # Setup a sample site for each test
48        app = University()
49        self.dc_root = tempfile.mkdtemp()
50        app['datacenter'].setStoragePath(self.dc_root)
51
52        # Prepopulate the ZODB...
53        self.getRootFolder()['app'] = app
54        # we add the site immediately after creation to the
55        # ZODB. Catalogs and other local utilities are not setup
56        # before that step.
57        self.app = self.getRootFolder()['app']
58        # Set site here. Some of the following setup code might need
59        # to access grok.getSite() and should get our new app then
60        setSite(app)
61
62
63    def tearDown(self):
64        super(StudentProcessorTest, self).tearDown()
65        shutil.rmtree(self.workdir)
66        shutil.rmtree(self.dc_root)
67        clearSite()
68        return
69
70class StudentUITests(StudentsFullSetup):
71    """Tests for customized student class views and pages
72    """
73
74    layer = FunctionalLayer
75
76    def setUp(self):
77        super(StudentUITests, self).setUp()
78
79        bedticket = BedTicket()
80        bedticket.booking_session = 2004
81        bedticket.bed_type = u'any bed type'
82        bedticket.bed = self.app['hostels']['hall-1']['hall-1_A_101_A']
83        bedticket.bed_coordinates = u'My bed coordinates'
84        self.student['accommodation'].addBedTicket(bedticket)
85
86    def test_next_session_allowed(self):
87        # Let's see if next_session_allowed works as expected
88        # A, ug_ft, 100
89        IWorkflowState(self.student).setState('returning')
90        self.assertTrue(self.student['studycourse'].next_session_allowed)
91        # Uniben special PG programmes have the same workflow
92        # as UG students
93        self.certificate.study_mode = 'special_pg_pt'
94        self.assertTrue(self.student['studycourse'].next_session_allowed)
95        IWorkflowState(self.student).setState('school fee paid')
96        self.assertFalse(self.student['studycourse'].next_session_allowed)
97        # Now we convert the certificate into a 'regular
98        # postgraduate certificate ...
99        self.certificate.study_mode = 'pg_ft'
100        # ... and voila next session registration is allowed
101        self.assertTrue(self.student['studycourse'].next_session_allowed)
102
103    def test_manage_access(self):
104        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
105        # The student created in the base package is a ug student
106        self.browser.open(self.manage_clearance_path)
107        self.assertMatches('...First Sitting Record...',
108                           self.browser.contents)
109        # There is no pg field in the clearance form
110        self.assertFalse('Second Higher Education Record'
111            in self.browser.contents)
112        # Now we change the study mode ...
113        self.certificate.study_mode = 'pg_ft'
114        self.browser.open(self.clearance_path)
115        # ... and additional pg clearance fields appear
116        self.assertMatches('...Second Higher Education Record...',
117                           self.browser.contents)
118        # But also fields from the ug form are displayed
119        self.assertMatches('...First Sitting Record...',
120                           self.browser.contents)
121        # The same holds for Uniben's special pg students
122        self.certificate.study_mode = 'special_pg_ft'
123        self.browser.open(self.clearance_path)
124        self.assertMatches('...Second Higher Education Record...',
125                           self.browser.contents)
126        self.assertMatches('...First Sitting Record...',
127                           self.browser.contents)
128        self.browser.open(self.student_path + '/clearance_slip.pdf')
129        self.assertEqual(self.browser.headers['Status'], '200 Ok')
130        self.assertEqual(self.browser.headers['Content-Type'],
131                         'application/pdf')
132
133    def test_student_access(self):
134        # Students can edit clearance data
135        IWorkflowState(self.student).setState('clearance started')
136        self.student.clearance_locked = False
137        self.student.nationality = u'NG'
138        file_store = getUtility(IExtFileStore)
139        self.browser.open(self.login_path)
140        self.browser.getControl(name="form.login").value = self.student_id
141        self.browser.getControl(name="form.password").value = 'spwd'
142        self.browser.getControl("Login").click()
143        self.browser.open(self.edit_clearance_path)
144
145        # Clearance can only be requested if all required documents
146        # have been uploaded.
147        self.browser.getControl("Save and request clearance").click()
148        self.assertTrue('No birth certificate uploaded'
149            in self.browser.contents)
150        birth_certificate = 'My birth certificate'
151        file_id = IFileStoreNameChooser(self.student).chooseName(
152            attr="birth_certificate.jpg")
153        file_store.createFile(file_id, StringIO(birth_certificate))
154        self.browser.open(self.edit_clearance_path)
155        self.browser.getControl("Save and request clearance").click()
156
157        self.assertTrue('No guarantor/referee letter uploaded'
158            in self.browser.contents)
159        ref_let = 'My ref let'
160        file_id = IFileStoreNameChooser(self.student).chooseName(
161            attr="ref_let.jpg")
162        file_store.createFile(file_id, StringIO(ref_let))
163        self.browser.open(self.edit_clearance_path)
164        self.browser.getControl("Save and request clearance").click()
165
166        self.assertTrue('No acceptance letter uploaded'
167            in self.browser.contents)
168        acc_let = 'My acc let'
169        file_id = IFileStoreNameChooser(self.student).chooseName(
170            attr="acc_let.jpg")
171        file_store.createFile(file_id, StringIO(acc_let))
172        self.browser.open(self.edit_clearance_path)
173        self.browser.getControl("Save and request clearance").click()
174
175        self.assertTrue('No first sitting result uploaded'
176            in self.browser.contents)
177        fst_sit_scan = 'My first sitting result'
178        file_id = IFileStoreNameChooser(self.student).chooseName(
179            attr="fst_sit_scan.jpg")
180        file_store.createFile(file_id, StringIO(fst_sit_scan))
181        self.browser.open(self.edit_clearance_path)
182        self.browser.getControl("Save and request clearance").click()
183
184        #self.assertTrue('No second sitting result uploaded'
185        #    in self.browser.contents)
186        #scd_sit_scan = 'My second sitting result'
187        #file_id = IFileStoreNameChooser(self.student).chooseName(
188        #    attr="scd_sit_scan.jpg")
189        #file_store.createFile(file_id, StringIO(scd_sit_scan))
190        #self.browser.open(self.edit_clearance_path)
191        #self.browser.getControl("Save and request clearance").click()
192
193        self.assertTrue('No affidavit of non-membership of secret cults uploaded'
194            in self.browser.contents)
195        secr_cults = 'My non-membership scan'
196        file_id = IFileStoreNameChooser(self.student).chooseName(
197            attr="secr_cults.jpg")
198        file_store.createFile(file_id, StringIO(secr_cults))
199        self.browser.open(self.edit_clearance_path)
200        self.browser.getControl("Save and request clearance").click()
201
202        self.assertTrue('Clearance has been requested'
203            in self.browser.contents)
204
205    def test_manage_payments(self):
206        # Add missing configuration data
207        self.app['configuration']['2004'].gown_fee = 150.0
208        self.app['configuration']['2004'].transfer_fee = 90.0
209        #self.app['configuration']['2004'].clearance_fee = 120.0
210        self.app['configuration']['2004'].booking_fee = 150.0
211        self.app['configuration']['2004'].maint_fee = 180.0
212
213        # Managers can add online payment tickets
214        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
215        self.browser.open(self.payments_path)
216        self.browser.getLink("Add current session payment ticket").click()
217        self.browser.getControl("Create ticket").click()
218        self.assertMatches('...Amount could not be determined...',
219                           self.browser.contents)
220        IWorkflowState(self.student).setState('cleared')
221        self.student.nationality = u'NG'
222        self.browser.open(self.payments_path + '/addop')
223        self.browser.getControl(name="form.p_category").value = ['schoolfee']
224        self.browser.getControl("Create ticket").click()
225        self.assertMatches('...ticket created...',
226                           self.browser.contents)
227        ctrl = self.browser.getControl(name='val_id')
228        value = ctrl.options[0]
229        self.browser.getLink(value).click()
230        self.assertMatches('...Amount Authorized...',
231                           self.browser.contents)
232        # Managers can open payment slip
233        self.browser.getLink("Download payment slip").click()
234        self.assertEqual(self.browser.headers['Status'], '200 Ok')
235        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
236        # Set ticket paid
237        ticket = self.student['payments'].items()[0][1]
238        ticket.p_state = 'paid'
239        self.browser.open(self.payments_path + '/addop')
240        self.browser.getControl(name="form.p_category").value = ['schoolfee']
241        self.browser.getControl("Create ticket").click()
242        self.assertMatches('...This type of payment has already been made...',
243                           self.browser.contents)
244        # Remove all payments so that we can add a school fee payment again
245        keys = [i for i in self.student['payments'].keys()]
246        for payment in keys:
247            del self.student['payments'][payment]
248        self.browser.open(self.payments_path + '/addop')
249        self.browser.getControl(name="form.p_category").value = ['schoolfee']
250        self.browser.getControl("Create ticket").click()
251        self.assertMatches('...ticket created...',
252                           self.browser.contents)
253        schoolfee_ticket = self.student['payments'].values()[0]
254        self.browser.open(self.payments_path + '/addop')
255        self.browser.getControl(name="form.p_category").value = ['gown']
256        self.browser.getControl("Create ticket").click()
257        self.assertMatches('...ticket created...',
258                           self.browser.contents)
259        self.browser.open(self.payments_path + '/addop')
260        self.browser.getControl(
261            name="form.p_category").value = ['tempmaint_1']
262        self.browser.getControl("Create ticket").click()
263        self.assertMatches('...ticket created...',
264                           self.browser.contents)
265        self.browser.open(self.payments_path + '/addop')
266        self.browser.getControl(
267            name="form.p_category").value = ['tempmaint_2']
268        self.browser.getControl("Create ticket").click()
269        self.assertMatches('...ticket created...',
270                           self.browser.contents)
271        self.browser.open(self.payments_path + '/addop')
272        self.browser.getControl(
273            name="form.p_category").value = ['tempmaint_3']
274        self.browser.getControl("Create ticket").click()
275        self.assertMatches('...ticket created...',
276                           self.browser.contents)
277        self.browser.open(self.payments_path + '/addop')
278        self.browser.getControl(name="form.p_category").value = ['clearance']
279        self.browser.getControl("Create ticket").click()
280        self.assertMatches('...ticket created...',
281                           self.browser.contents)
282        self.browser.open(self.payments_path + '/addop')
283        self.browser.getControl(name="form.p_category").value = ['schoolfee']
284        self.browser.getControl("Create ticket").click()
285        self.assertMatches('...ticket created...',
286                           self.browser.contents)
287        # In state returning we can add a new school fee ticket since
288        # p_session and p_level is different
289        IWorkflowState(self.student).setState('returning')
290        self.browser.open(self.payments_path + '/addop')
291        self.browser.getControl(name="form.p_category").value = ['schoolfee']
292        self.browser.getControl("Create ticket").click()
293        # Uups, we forgot to add a session configuration for next session
294        self.assertMatches('...Session configuration object is not...',
295                           self.browser.contents)
296        configuration = createObject('waeup.SessionConfiguration')
297        configuration.academic_session = 2005
298        self.app['configuration'].addSessionConfiguration(configuration)
299        self.browser.open(self.payments_path + '/addop')
300        self.browser.getControl(name="form.p_category").value = ['schoolfee']
301        self.browser.getControl("Create ticket").click()
302
303
304        #self.assertMatches('...You have not yet paid your current/active session...',
305        #                   self.browser.contents)
306        ## Ok, let's pay the first schoolfee ticket.
307        #schoolfee_ticket.approve()
308        #self.browser.open(self.payments_path + '/addop')
309        #self.browser.getControl(name="form.p_category").value = ['schoolfee']
310        #self.browser.getControl("Create ticket").click()
311
312
313        self.assertMatches('...ticket created...',
314                           self.browser.contents)
315        # In state admitted school fee can't be determined
316        IWorkflowState(self.student).setState('admitted')
317        self.browser.open(self.payments_path + '/addop')
318        self.browser.getControl(name="form.p_category").value = ['schoolfee']
319        self.browser.getControl("Create ticket").click()
320        self.assertMatches('...Amount could not be determined...',
321                           self.browser.contents)
322
323        # If the session configuration doesn't exist an error message will
324        # be shown. No other requirement is being checked.
325        del self.app['configuration']['2004']
326        self.browser.open(self.payments_path)
327        self.browser.getLink("Add current session payment ticket").click()
328        self.browser.getControl("Create ticket").click()
329        self.assertMatches('...Session configuration object is not...',
330                           self.browser.contents)
331
332    def test_student_course_registration(self):
333        # Uniben students see grade instead of score on all level pages
334        # and on course ticket page.
335        IWorkflowState(self.student).setState('school fee paid')
336        self.browser.open(self.login_path)
337        self.browser.getControl(name="form.login").value = self.student_id
338        self.browser.getControl(name="form.password").value = 'spwd'
339        self.browser.getControl("Login").click()
340        # Now students can add the current study level
341        self.browser.getLink("Study Course").click()
342        self.browser.getLink("Add course list").click()
343        self.assertMatches('...Add current level 100 (Year 1)...',
344                           self.browser.contents)
345        self.browser.getControl("Create course list now").click()
346        # A level with one course ticket was created
347        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 1)
348        self.student['studycourse']['100']['COURSE1'].score = 55
349        self.browser.getLink("100").click()
350        # GPA has been properly calculated and is shown on the page
351        self.assertTrue('3.0' in self.browser.contents)
352        self.assertEqual(self.student['studycourse']['100'].gpa, 3.0)
353        # Score is not shown but grade
354        self.assertTrue('<th>Grade</th>' in self.browser.contents)
355        self.assertFalse('<th>Score</th>' in self.browser.contents)
356        self.browser.getLink("Edit course list").click()
357        self.assertTrue('<th>Grade</th>' in self.browser.contents)
358        self.assertFalse('<th>Score</th>' in self.browser.contents)
359        self.browser.getLink("COURSE1").click()
360        self.assertFalse('Score' in self.browser.contents)
361        # Students can open the customized pdf course registration slip
362        self.browser.open(self.student_path + '/studycourse/100')
363        self.browser.getLink("Download course registration slip").click()
364        self.assertEqual(self.browser.headers['Status'], '200 Ok')
365        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
366        # Students can open the special Uniben pdf course result slip
367        self.browser.open(self.student_path + '/studycourse/100')
368        self.browser.getLink("Download course result slip").click()
369        self.assertEqual(self.browser.headers['Status'], '200 Ok')
370        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
371        # Even if course is mandatory, students can remove the course
372        self.student['studycourse']['100']['COURSE1'].mandatory = True
373        self.browser.open(self.student_path + '/studycourse/100')
374        self.browser.getLink("Edit course list").click()
375        ctrl = self.browser.getControl(name='val_id')
376        ctrl.getControl(value='COURSE1').selected = True
377        self.browser.getControl("Remove selected", index=0).click()
378        self.assertTrue('Successfully removed' in self.browser.contents)
379
380    def test_get_returning_data(self):
381        # Student is in level 100, session 2004 with verdict A
382        utils = getUtility(IStudentsUtils)
383        self.assertEqual(utils.getReturningData(self.student),(2005, 200))
384        self.student['studycourse'].current_verdict = 'C'
385        self.assertEqual(utils.getReturningData(self.student),(2005, 110))
386        self.student['studycourse'].current_verdict = 'D'
387        self.assertEqual(utils.getReturningData(self.student),(2005, 100))
388        return
389
390    def test_set_returning_data(self):
391        # Student is in level 100, session 2004 with verdict A
392        utils = getUtility(IStudentsUtils)
393
394        utils.setReturningData(self.student)
395        self.assertEqual(self.student['studycourse'].current_session, 2005)
396        self.assertEqual(self.student['studycourse'].current_level, 200)
397
398        self.student['studycourse'].current_session = 2004
399        self.student['studycourse'].current_level = 100
400        self.student['studycourse'].current_verdict = 'C'
401        utils.setReturningData(self.student)
402        self.assertEqual(self.student['studycourse'].current_session, 2005)
403        self.assertEqual(self.student['studycourse'].current_level, 110)
404
405        self.student['studycourse'].current_session = 2004
406        self.student['studycourse'].current_level = 100
407        self.student['studycourse'].current_verdict = 'D'
408        utils.setReturningData(self.student)
409        self.assertEqual(self.student['studycourse'].current_session, 2005)
410        self.assertEqual(self.student['studycourse'].current_level, 100)
411        return
412
413    def test_set_payment_details(self):
414        self.app['configuration']['2004'].gown_fee = 150.0
415        self.app['configuration']['2004'].transfer_fee = 90.0
416        self.app['configuration']['2004'].booking_fee = 150.0
417        self.app['configuration']['2004'].maint_fee = 180.0
418
419        configuration = createObject('waeup.SessionConfiguration')
420        configuration.academic_session = 2000
421        self.app['configuration'].addSessionConfiguration(configuration)
422        configuration2 = createObject('waeup.SessionConfiguration')
423        configuration2.academic_session = 2002
424        self.app['configuration'].addSessionConfiguration(configuration2)
425        configuration3 = createObject('waeup.SessionConfiguration')
426        configuration3.academic_session = 2003
427        self.app['configuration'].addSessionConfiguration(configuration3)
428        configuration4 = createObject('waeup.SessionConfiguration')
429        configuration4.academic_session = 2005
430        self.app['configuration'].addSessionConfiguration(configuration4)
431        utils = getUtility(IStudentsUtils)
432        self.student['studycourse'].entry_session = 2002
433        self.student.nationality = u'NG'
434
435        error, payment = utils.setPaymentDetails('schoolfee',
436            self.student, None, None)
437        self.assertEqual(payment, None)
438        # Student is in state 'created' and can thus not pay.
439        self.assertTrue(u'Amount could not be determined.' in error)
440
441        # Previous session must be valid.
442        error, payment = utils.setPaymentDetails('schoolfee',
443            self.student, 2000, 300)
444        self.assertEqual(payment, None)
445        self.assertTrue(u'The previous session must not fall below' in error)
446        error, payment = utils.setPaymentDetails('schoolfee',
447            self.student, 2005, 300)
448        self.assertEqual(payment, None)
449        self.assertTrue(u'This is not a previous session' in error)
450
451        # Previous session schoolfee payment; fresh and returning
452        # are distinguished by their entry_level
453        error, payment = utils.setPaymentDetails('schoolfee',
454            self.student, 2002, 300)
455        self.assertEqual(payment.amount_auth, 40000.0)
456        self.assertEqual(payment.p_session, 2002)
457        self.assertEqual(payment.p_level, 300)
458        self.assertFalse(payment.p_current)
459        error, payment = utils.setPaymentDetails('schoolfee',
460            self.student, 2003, 300)
461        self.assertEqual(payment.amount_auth, 20000.0)
462        self.assertEqual(payment.p_session, 2003)
463        self.assertEqual(payment.p_level, 300)
464        self.assertFalse(payment.p_current)
465
466        # Current schoolfee payment; fresh and returning
467        # are distinguished by their state
468        IWorkflowState(self.student).setState('cleared')
469        error, payment = utils.setPaymentDetails('schoolfee',
470            self.student, None, None)
471        self.assertEqual(payment.p_level, 100)
472        self.assertEqual(payment.p_session, 2004)
473        self.assertEqual(payment.amount_auth, 40000.0)
474        self.assertEqual(payment.p_item, u'CERT1')
475        self.assertEqual(error, None)
476        self.assertTrue(payment.p_current)
477
478        # Add penalty fee ...
479        # ... for cleared
480        self.app['configuration']['2004'].penalty_ug = 99.0
481        # ... for returning
482        self.app['configuration']['2005'].penalty_ug = 88.0
483        error, payment = utils.setPaymentDetails('schoolfee',
484            self.student, None, None)
485        self.assertEqual(payment.amount_auth, 40099.0)
486
487        IWorkflowState(self.student).setState('returning')
488
489
490        #error, payment = utils.setPaymentDetails('schoolfee',
491        #    self.student, None, None)
492        #self.assertTrue(
493        #    u'You have not yet paid your current/active session.' in error)
494        ## Ok, that means we have to add paid payment ticket first.
495        #payment = createObject('waeup.StudentOnlinePayment')
496        #payment.p_category = u'schoolfee'
497        #payment.p_session = self.student.current_session
498        #payment.p_item = u'My Certificate'
499        #payment.p_id = u'anyid'
500        #payment.p_state = u'paid'
501        #self.student['payments']['anykey'] = payment
502
503
504        error, payment = utils.setPaymentDetails('schoolfee',
505            self.student, None, None)
506        self.assertEqual(payment.p_level, 200)
507        self.assertEqual(payment.p_session, 2005)
508        self.assertEqual(payment.amount_auth, 20088.0)
509        self.assertEqual(payment.p_item, u'CERT1')
510        self.assertEqual(error, None)
511
512        # Staff members pay less.
513        self.student.is_staff = True
514        error, payment = utils.setPaymentDetails('schoolfee',
515            self.student, None, None)
516        self.assertEqual(payment.p_level, 200)
517        self.assertEqual(payment.p_session, 2005)
518        self.assertEqual(payment.amount_auth, 10088.0)
519        self.assertEqual(payment.p_item, u'CERT1')
520        self.assertEqual(error, None)
521
522        # Foreigners pay more.
523        IWorkflowState(self.student).setState('cleared')
524        self.student.is_staff = False
525        self.student.nationality = u'DE'
526        self.certificate.school_fee_3 = 60000.0
527        error, payment = utils.setPaymentDetails(
528            'schoolfee', self.student, None, None)
529        self.assertEqual(payment.p_level, 100)
530        self.assertEqual(payment.p_session, 2004)
531        self.assertEqual(payment.amount_auth, 60099.0)
532        self.assertEqual(payment.p_item, u'CERT1')
533        self.assertEqual(error, None)
534        IWorkflowState(self.student).setState('returning')
535        self.student.is_staff = False
536        self.certificate.school_fee_4 = 20000.0
537        error, payment = utils.setPaymentDetails(
538            'schoolfee', self.student, None, None)
539        self.assertEqual(payment.p_level, 200)
540        self.assertEqual(payment.p_session, 2005)
541        self.assertEqual(payment.amount_auth, 20088.0)
542        self.assertEqual(payment.p_item, u'CERT1')
543        self.assertEqual(error, None)
544
545        # In Uniben students can pay school fee in all states no matter
546        # if they are ug or pg students.
547        IWorkflowState(self.student).setState('school fee paid')
548        self.student.is_staff = False
549        self.student.nationality = u'NG'
550        self.certificate.school_fee_2 = 10000.0
551        error, payment = utils.setPaymentDetails(
552            'schoolfee', self.student, None, None)
553        self.assertEqual(payment.p_level, None)
554        self.assertEqual(payment.p_session, 2005)
555        self.assertEqual(payment.amount_auth, 10088.0)
556        self.assertEqual(payment.p_item, u'CERT1')
557        self.assertEqual(error, None)
558        IWorkflowState(self.student).setState('courses registered')
559        self.certificate.study_mode = 'special_pg_pt'
560        error, payment = utils.setPaymentDetails(
561            'schoolfee', self.student, None, None)
562        self.assertEqual(payment.p_level, None)
563        self.assertEqual(payment.p_session, 2005)
564        self.assertEqual(payment.amount_auth, 10000.0)
565        self.assertEqual(payment.p_item, u'CERT1')
566        self.assertEqual(error, None)
567        IWorkflowState(self.student).setState('courses validated')
568        error, payment = utils.setPaymentDetails(
569            'schoolfee', self.student, None, None)
570        self.assertEqual(payment.p_level, None)
571        self.assertEqual(payment.p_session, 2005)
572        self.assertEqual(payment.amount_auth, 10000.0)
573        self.assertEqual(payment.p_item, u'CERT1')
574        self.assertEqual(error, None)
575
576        error, payment = utils.setPaymentDetails('clearance',
577            self.student, None, None)
578        self.assertEqual(payment.p_level, 100)
579        self.assertEqual(payment.p_session, 2004)
580        self.assertEqual(payment.amount_auth, 45000.0)
581        self.assertEqual(payment.p_item, u'CERT1')
582        self.assertEqual(error, None)
583
584        error, payment = utils.setPaymentDetails('gown',
585            self.student, None, None)
586        self.assertEqual(payment.p_level, 100)
587        self.assertEqual(payment.p_session, 2004)
588        self.assertEqual(payment.amount_auth, 150.0)
589        self.assertEqual(payment.p_item, u'')
590        self.assertEqual(error, None)
591
592        error, payment = utils.setPaymentDetails('hostel_maintenance',
593            self.student, None, None)
594        self.assertEqual(payment.p_level, 100)
595        self.assertEqual(payment.p_session, 2004)
596        self.assertEqual(payment.amount_auth, 180.0)
597        self.assertEqual(payment.p_item, u'')
598        self.assertEqual(error, None)
599
600        error, payment = utils.setPaymentDetails('bed_allocation',
601            self.student, None, None)
602        self.assertEqual(payment.p_level, 100)
603        self.assertEqual(payment.p_session, 2004)
604        self.assertEqual(payment.amount_auth, 150.0)
605        self.assertEqual(payment.p_item, u'')
606        self.assertEqual(error, None)
607
608        error, payment = utils.setPaymentDetails('tempmaint_1',
609            self.student, None, None)
610        self.assertEqual(payment.p_level, 100)
611        self.assertEqual(payment.p_session, 2004)
612        self.assertEqual(payment.amount_auth, 8150.0)
613        self.assertEqual(payment.p_item, u'Hall 1-4 M/F Ekehuan')
614        self.assertEqual(error, None)
615
616        error, payment = utils.setPaymentDetails('tempmaint_2',
617            self.student, None, None)
618        self.assertEqual(payment.p_level, 100)
619        self.assertEqual(payment.p_session, 2004)
620        self.assertEqual(payment.amount_auth, 12650.0)
621        self.assertEqual(payment.p_item, u'Hall 5 M/F')
622        self.assertEqual(error, None)
623
624        error, payment = utils.setPaymentDetails('tempmaint_3',
625            self.student, None, None)
626        self.assertEqual(payment.p_level, 100)
627        self.assertEqual(payment.p_session, 2004)
628        self.assertEqual(payment.amount_auth, 9650.0)
629        self.assertEqual(payment.p_item, u'Clinical Hostel')
630        self.assertEqual(error, None)
631
632        error, payment = utils.setPaymentDetails('transfer',
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, 90.0)
637        self.assertEqual(payment.p_item, u'')
638        self.assertEqual(error, None)
639        return
640
641    def test_edit_level_by_co(self):
642        # Create clearance officer
643        self.app['users'].addUser('mrclear', 'mrclearsecret')
644        self.app['users']['mrclear'].email = 'mrclear@foo.ng'
645        self.app['users']['mrclear'].title = 'Carlo Pitter'
646        # Assign local ClearanceOfficer role
647        department = self.app['faculties']['fac1']['dep1']
648        prmlocal = IPrincipalRoleManager(department)
649        prmlocal.assignRoleToPrincipal('waeup.local.ClearanceOfficer', 'mrclear')
650        notify(LocalRoleSetEvent(
651            department, 'waeup.local.ClearanceOfficer', 'mrclear', granted=True))
652        IWorkflowState(self.student).setState('clearance started')
653        # Login as clearance officer
654        self.browser.open(self.login_path)
655        self.browser.getControl(name="form.login").value = 'mrclear'
656        self.browser.getControl(name="form.password").value = 'mrclearsecret'
657        self.browser.getControl("Login").click()
658        self.assertMatches('...You logged in...', self.browser.contents)
659        # Only in state clearance requested the CO does see the
660        # 'Edit level' button ...
661        self.browser.open(self.studycourse_path)
662        self.assertFalse('Edit level' in self.browser.contents)
663        # ... and can open the edit_level view
664        self.browser.open(self.studycourse_path + '/edit_level')
665        self.assertMatches('...is locked...', self.browser.contents)
666        self.assertEqual(self.browser.url, self.studycourse_path)
667        IWorkflowInfo(self.student).fireTransition('request_clearance')
668        self.browser.open(self.studycourse_path)
669        self.assertTrue('Edit level' in self.browser.contents)
670        self.browser.getLink("Edit level").click()
671        self.browser.getControl(name="form.current_level").value = ['200']
672        self.browser.getControl("Save").click()
673        self.assertMatches('...has been saved...', self.browser.contents)
674        self.assertEqual(self.student.current_level, 200)
675
676    def test_postgraduate_student_access(self):
677        self.certificate.study_mode = 'special_pg_pt'
678        self.certificate.start_level = 700
679        self.certificate.end_level = 800
680        self.student['studycourse'].current_level = 700
681        IWorkflowState(self.student).setState('school fee paid')
682        self.browser.open(self.login_path)
683        self.browser.getControl(name="form.login").value = self.student_id
684        self.browser.getControl(name="form.password").value = 'spwd'
685        self.browser.getControl("Login").click()
686        self.assertTrue(
687            'You logged in.' in self.browser.contents)
688        # Now students can add the current study level
689        self.browser.getLink("Study Course").click()
690        self.browser.getLink("Add course list").click()
691        self.assertMatches('...Add current level 700...',
692                           self.browser.contents)
693        self.browser.getControl("Create course list now").click()
694        # A level with no course ticket was created
695        self.assertEqual(self.student['studycourse']['700'].number_of_tickets, 0)
696        self.browser.getLink("700").click()
697        self.browser.getLink("Edit course list").click()
698        self.browser.getLink("here").click()
699        self.browser.getControl(name="form.course").value = ['COURSE1']
700        # Non-final year students can't add ticket with 51 credits
701        self.app['faculties']['fac1']['dep1'].courses['COURSE1'].credits = 51
702        self.browser.getControl("Add course ticket").click()
703        self.assertMatches('...Total credits exceed 50...',
704                           self.browser.contents)
705        # Final year students can't add ticket with 52 credits ...
706        self.app['faculties']['fac1']['dep1'].courses['COURSE1'].credits = 52
707        self.student['studycourse'].certificate.end_level = 700
708        self.browser.getControl("Add course ticket").click()
709        self.assertMatches('...Total credits exceed 51...',
710                           self.browser.contents)
711        # ... but with 51 credits
712        self.app['faculties']['fac1']['dep1'].courses['COURSE1'].credits = 51
713        self.browser.getControl("Add course ticket").click()
714        self.assertMatches('...Successfully added COURSE1...',
715                           self.browser.contents)
716        # Non-final year special postgraduate students can't register
717        # course lists if their total credits are 51 and thus exceed 50 ...
718        self.student['studycourse'].certificate.end_level = 800
719        self.browser.getControl("Register course list").click()
720        self.assertMatches('...Maximum credits of 50 exceeded...',
721            self.browser.contents)
722        # ... but final year students can
723        self.student['studycourse'].certificate.end_level = 700
724        self.browser.getControl("Register course list").click()
725        self.assertMatches('...Course list has been registered...',
726            self.browser.contents)
727        self.assertEqual(self.student.state, 'courses registered')
728        return
729
730    def test_login(self):
731        # If suspended_comment is set this message will be flashed instead
732        self.student.suspended_comment = u'Aetsch baetsch!'
733        self.student.suspended = True
734        self.browser.open(self.login_path)
735        self.browser.getControl(name="form.login").value = self.student_id
736        self.browser.getControl(name="form.password").value = 'spwd'
737        self.browser.getControl("Login").click()
738        # Uniben does not display suspended_comment
739        self.assertMatches(
740            '...<div class="alert-message warning">Your account has been deactivated.</div>...',
741            self.browser.contents)
742        self.student.suspended = False
Note: See TracBrowser for help on using the repository browser.