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

Last change on this file since 11865 was 11773, checked in by Henrik Bettermann, 10 years ago

Customize clearance_disabled_message.

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