source: main/waeup.uniben/branches/0.1/src/waeup/uniben/students/tests/test_browser.py

Last change on this file was 11069, checked in by Henrik Bettermann, 11 years ago

Do not show public user name in history when activating or deactivating students.

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