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

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

Add new application category and type (ticket #966).

Implement hostel application fee payment (ticket #959). Uniben is still waiting for an agrrement with Interwsicth.

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