source: main/waeup.aaue/trunk/src/waeup/aaue/students/tests/test_browser.py @ 13800

Last change on this file since 13800 was 13786, checked in by Henrik Bettermann, 9 years ago

School fee payments must not be paid twice.

  • Property svn:keywords set to Id
File size: 36.5 KB
Line 
1## $Id: test_browser.py 13786 2016-03-22 06:20:49Z henrik $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18import os
19import shutil
20import tempfile
21import pytz
22import grok
23from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState
24from zope.securitypolicy.interfaces import IPrincipalRoleManager
25from datetime import datetime, timedelta, date
26from mechanize import LinkNotFoundError
27from hurry.workflow.interfaces import IWorkflowState
28from zope.event import notify
29from zope.component.hooks import setSite, clearSite
30from zope.component import getUtility, createObject, queryUtility
31from zope.catalog.interfaces import ICatalog
32from waeup.kofa.app import University
33from waeup.kofa.students.tests.test_browser import StudentsFullSetup
34from waeup.kofa.students.accommodation import BedTicket
35from waeup.kofa.testing import FunctionalTestCase
36from waeup.kofa.authentication import LocalRoleSetEvent
37from waeup.kofa.browser.tests.test_pdf import samples_dir
38from waeup.aaue.testing import FunctionalLayer
39
40SAMPLE_IMAGE = os.path.join(os.path.dirname(__file__), 'test_image.jpg')
41
42
43class StudentProcessorTest(FunctionalTestCase):
44    """Perform some batching tests.
45    """
46
47    layer = FunctionalLayer
48
49    def setUp(self):
50        super(StudentProcessorTest, self).setUp()
51        # Setup a sample site for each test
52        app = University()
53        self.dc_root = tempfile.mkdtemp()
54        app['datacenter'].setStoragePath(self.dc_root)
55
56        # Prepopulate the ZODB...
57        self.getRootFolder()['app'] = app
58        # we add the site immediately after creation to the
59        # ZODB. Catalogs and other local utilities are not setup
60        # before that step.
61        self.app = self.getRootFolder()['app']
62        # Set site here. Some of the following setup code might need
63        # to access grok.getSite() and should get our new app then
64        setSite(app)
65
66
67    def tearDown(self):
68        super(StudentProcessorTest, self).tearDown()
69        shutil.rmtree(self.workdir)
70        shutil.rmtree(self.dc_root)
71        clearSite()
72        return
73
74class OfficerUITests(StudentsFullSetup):
75    # Tests for Student class views and pages
76
77    layer = FunctionalLayer
78
79    def test_gpa_calculation(self):
80        studylevel = createObject(u'waeup.StudentStudyLevel')
81        studylevel.level = 100
82        studylevel.level_session = 2005
83        self.student['studycourse'].entry_mode = 'ug_ft'
84        self.student['studycourse'].addStudentStudyLevel(
85            self.certificate, studylevel)
86        # First course has been added automatically.
87        # Set score.
88        studylevel['COURSE1'].score = 55
89        # GPA is 3.0.
90        self.assertEqual(studylevel.gpa_params[0], 3.0)
91        courseticket = createObject('waeup.CourseTicket')
92        courseticket.code = 'ANYCODE'
93        courseticket.title = u'Any TITLE'
94        courseticket.credits = 13
95        courseticket.score = 66
96        courseticket.semester = 1
97        courseticket.dcode = u'ANYDCODE'
98        courseticket.fcode = u'ANYFCODE'
99        studylevel['COURSE2'] = courseticket
100        # total credits
101        self.assertEqual(self.student['studycourse']['100'].gpa_params[1], 23)
102        # weigheted credits = 3 * 10 + 4 * 13
103        self.assertEqual(self.student['studycourse']['100'].gpa_params[2], 82.0)
104        # sgpa = 82 / 23
105        self.assertEqual(self.student['studycourse']['100'].gpa_params[0], 3.565)
106        return
107
108    def test_manage_payments(self):
109        # Add missing configuration data
110        self.app['configuration']['2004'].gown_fee = 150.0
111        self.app['configuration']['2004'].transfer_fee = 90.0
112        self.app['configuration']['2004'].booking_fee = 150.0
113        self.app['configuration']['2004'].maint_fee = 180.0
114        self.app['configuration']['2004'].late_fee = 80.0
115
116        # Managers can add online payment tickets
117        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
118        self.browser.open(self.payments_path)
119        self.browser.getLink("Add current session payment ticket").click()
120        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
121        self.browser.getControl("Create ticket").click()
122        self.assertMatches('...Wrong state...',
123                           self.browser.contents)
124        IWorkflowState(self.student).setState('cleared')
125        self.browser.open(self.payments_path + '/addop')
126        self.browser.getControl("Create ticket").click()
127        self.assertMatches('...Amount could not be determined...',
128                           self.browser.contents)
129        #self.browser.getControl(name="form.p_category").value = ['schoolfee']
130        # Accepotance fee must be paid first
131        #self.browser.getControl("Create ticket").click()
132        #self.assertMatches('...Please pay acceptance fee first...',
133        #                   self.browser.contents)
134        self.app['configuration']['2004'].clearance_fee = 666.0
135        self.browser.getControl(name="form.p_category").value = ['clearance_incl']
136        self.browser.getControl("Create ticket").click()
137        ctrl = self.browser.getControl(name='val_id')
138        cpt_value = ctrl.options[0]
139        # School fee payment ticket can be added ...
140        self.student['studycourse'].certificate.school_fee_1 = 6666.0
141        self.student.nationality = u'NG'
142        self.browser.open(self.payments_path + '/addop')
143        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
144        self.browser.getControl("Create ticket").click()
145        self.assertMatches('...ticket created...',
146                           self.browser.contents)
147        # ... but not paid through the query_history page.
148        ctrl = self.browser.getControl(name='val_id')
149        sfpt_value = ctrl.options[1]
150        self.student['studycourse'].entry_session = 2013
151        self.browser.open(self.payments_path + '/' + sfpt_value)
152        self.browser.getLink("Query eTranzact History").click()
153        self.assertMatches('...alert-danger">Please pay acceptance fee first...',
154                           self.browser.contents)
155        # If clearance/acceptance fee is paid ...
156        self.student['payments'][cpt_value].approveStudentPayment()
157        self.browser.getLink("Query eTranzact History").click()
158        # ... query_history page is accessible.
159        self.assertMatches(
160            '...<h1 class="kofa-content-label">Requery eTranzact History</h1>...',
161            self.browser.contents)
162        # Managers can open school fee payment slip
163        self.browser.open(self.payments_path + '/' + sfpt_value)
164        self.browser.getLink("Download payment slip").click()
165        self.assertEqual(self.browser.headers['Status'], '200 Ok')
166        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
167        # If school fee ticket is paid, the student is automatically set to
168        # school fee paid...
169        ticket = self.student['payments'][sfpt_value].approveStudentPayment()
170        self.assertEqual(self.student.state, 'school fee paid')
171        # ... no further school fee ticket can be added.
172        self.browser.open(self.payments_path + '/addop')
173        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
174        self.browser.getControl("Create ticket").click()
175        self.assertMatches('...Wrong state...',
176                           self.browser.contents)
177        self.browser.open(self.payments_path + '/addop')
178        self.browser.getControl(name="form.p_category").value = ['late_registration']
179        self.browser.getControl("Create ticket").click()
180        self.assertMatches('...ticket created...',
181                           self.browser.contents)
182        return
183
184    def test_for_instalment_payments(self):
185        self.student['studycourse'].certificate.study_mode = 'ug_pt'
186        self.student['studycourse'].certificate.school_fee_1 = 6666.0
187        self.app['configuration']['2004'].union_fee = 1250.0
188        self.app['configuration']['2004'].welfare_fee = 750.0
189        self.student.nationality = u'NG'
190        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
191        self.browser.open(self.payments_path + '/addop')
192        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
193        self.browser.getControl("Create ticket").click()
194        self.assertTrue(
195            'Part-time students are not allowed' in self.browser.contents)
196        self.student['studycourse'].certificate.study_mode = 'ug_ft'
197        self.browser.open(self.payments_path + '/addop')
198        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
199        self.browser.getControl("Create ticket").click()
200        self.assertTrue(
201            'Wrong state. Only students in state \'cleared\' are allowed to pay by instalments'
202            in self.browser.contents)
203        IWorkflowState(self.student).setState('cleared')
204        self.browser.open(self.payments_path + '/addop')
205        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
206        self.browser.getControl("Create ticket").click()
207        self.assertTrue('ticket created' in self.browser.contents)
208        # We can't add the 2nd instalment ticket because the
209        # first one has not yet been approved.
210        #self.browser.open(self.payments_path + '/addop')
211        #self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
212        #self.browser.getControl("Create ticket").click()
213        #self.assertMatches('...1st school fee instalment has not yet been paid...',
214        #                   self.browser.contents)
215        # Ok, then we approve the first instalment ...
216        self.browser.open(self.payments_path)
217        ctrl = self.browser.getControl(name='val_id')
218        p_id = ctrl.options[0]
219        self.browser.open(self.payments_path + '/' + p_id + '/approve')
220        # ... add the second instalment ...
221        self.browser.open(self.payments_path + '/addop')
222        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
223        self.browser.getControl("Create ticket").click()
224        self.assertTrue('ticket created' in self.browser.contents)
225        # ... approve the second instalment ...
226        ctrl = self.browser.getControl(name='val_id')
227        p_id = ctrl.options[1]
228        self.browser.open(self.payments_path + '/' + p_id + '/approve')
229        self.assertEqual(self.student['payments'].values()[0].p_category, 'schoolfee_1')
230        self.assertEqual(self.student['payments'].values()[1].p_category, 'schoolfee_2')
231        # (6666-250)/2 + 1250 + 750 - 500 + 250
232        self.assertEqual(self.student['payments'].values()[0].amount_auth, 4958.0)
233        # (6666-250)/2 + 250
234        self.assertEqual(self.student['payments'].values()[1].amount_auth, 3458.0)
235        return
236
237    def test_manage_payments_bypass_ac_creation(self):
238        self.student['studycourse'].certificate.school_fee_1 = 6666.0
239        self.student.nationality = u'NG'
240        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
241        self.browser.open(self.payments_path)
242        IWorkflowState(self.student).setState('cleared')
243        self.browser.getLink("Add current session payment ticket").click()
244        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
245        self.browser.getControl("Create ticket").click()
246        ctrl = self.browser.getControl(name='val_id')
247        value = ctrl.options[0]
248        self.browser.getLink(value).click()
249        payment_url = self.browser.url
250        logfile = os.path.join(
251            self.app['datacenter'].storage, 'logs', 'students.log')
252        # The ticket can be found in the payments_catalog
253        cat = queryUtility(ICatalog, name='payments_catalog')
254        results = list(cat.searchResults(p_state=('unpaid', 'unpaid')))
255        self.assertTrue(len(results), 1)
256        self.assertTrue(results[0] is self.student['payments'][value])
257        # Managers can approve the payment
258        self.browser.open(payment_url)
259        self.browser.getLink("Approve payment").click()
260        self.assertMatches('...Payment approved...',
261                          self.browser.contents)
262        # Approval is logged in students.log ...
263        logcontent = open(logfile).read()
264        self.assertTrue(
265            'zope.mgr - students.browser.OnlinePaymentApproveView '
266            '- E1000000 - schoolfee_incl payment approved'
267            in logcontent)
268        # ... and in payments.log
269        logfile = os.path.join(
270            self.app['datacenter'].storage, 'logs', 'payments.log')
271        logcontent = open(logfile).read()
272        self.assertTrue(
273            '"zope.mgr",E1000000,%s,schoolfee_incl,6666.0,AP,,,,,,\n' % value
274            in logcontent)
275        # Student is in state school fee paid, no activation
276        # code was necessary.
277        self.assertEqual(self.student.state, 'school fee paid')
278        self.assertEqual(len(self.app['accesscodes']['SFE-0']),0)
279        return
280
281class StudentUITests(StudentsFullSetup):
282    """Tests for customized student class views and pages
283    """
284
285    layer = FunctionalLayer
286
287    def setUp(self):
288        super(StudentUITests, self).setUp()
289
290        bedticket = BedTicket()
291        bedticket.booking_session = 2004
292        bedticket.bed_type = u'any bed type'
293        bedticket.bed = self.app['hostels']['hall-1']['hall-1_A_101_A']
294        bedticket.bed_coordinates = u'My bed coordinates'
295        self.student['accommodation'].addBedTicket(bedticket)
296
297    def test_student_payments(self):
298        self.certificate.study_mode = 'ug_ft'
299        self.student['studycourse'].entry_session = 2013
300        self.student['studycourse'].certificate.school_fee_1 = 50250.0
301        self.app['configuration']['2004'].union_fee = 1250.0
302        self.app['configuration']['2004'].welfare_fee = 750.0
303        self.student.nationality = u'NG'
304        # Login
305        IWorkflowState(self.student).setState('cleared')
306        self.browser.open(self.login_path)
307        self.browser.getControl(name="form.login").value = self.student_id
308        self.browser.getControl(name="form.password").value = 'spwd'
309        self.browser.getControl("Login").click()
310        # Test school fee payments
311        self.browser.open(self.student_path + '/payments')
312        self.browser.getLink("Add current session payment ticket").click()
313        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
314        self.browser.getControl("Create ticket").click()
315        self.assertTrue('ticket created' in self.browser.contents)
316        value = self.student['payments'].keys()[0]
317        self.browser.getLink(value).click()
318        self.assertTrue('Amount Authorized' in self.browser.contents)
319        self.assertEqual(self.student['payments'][value].amount_auth, 51750.0)
320        self.browser.open(self.browser.url + '/payment_slip.pdf')
321        self.assertEqual(self.browser.headers['Status'], '200 Ok')
322        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
323        path = os.path.join(samples_dir(), 'payment_slip.pdf')
324        open(path, 'wb').write(self.browser.contents)
325        print "Sample PDF payment_slip.pdf written to %s" % path
326        # Another school fee payment cannot be added
327        self.student['payments'][value].approve()
328        self.browser.open(self.student_path + '/payments')
329        self.browser.getLink("Add current session payment ticket").click()
330        self.browser.getControl(name="form.p_category").value = ['schoolfee']
331        self.browser.getControl("Create ticket").click()
332        self.assertTrue(
333            'Another school fee payment for this session has already been made'
334            in self.browser.contents)
335        # Test hostel maintenance payments
336        self.browser.open(self.student_path + '/payments')
337        self.browser.getLink("Add current session payment ticket").click()
338        self.browser.getControl(name="form.p_category").value = ['hostel_maintenance']
339        self.browser.getControl("Create ticket").click()
340        self.assertTrue('ticket created' in self.browser.contents)
341        value = self.student['payments'].keys()[1]
342        self.browser.getLink(value).click()
343        self.assertTrue('<span>My bed coordinates</span>' in self.browser.contents)
344        self.assertEqual(self.student['payments'][value].amount_auth, 876.0)
345        return
346
347    def test_late_registration(self):
348        # Login
349        delta = timedelta(days=10)
350        self.app['configuration'][
351            '2004'].coursereg_deadline = datetime.now(pytz.utc) - delta
352        IWorkflowState(self.student).setState('school fee paid')
353        # Current session is 2004. Here we test course registration for
354        # returning students.
355        self.student['studycourse'].entry_session = 2003
356        self.browser.open(self.login_path)
357        self.browser.getControl(name="form.login").value = self.student_id
358        self.browser.getControl(name="form.password").value = 'spwd'
359        self.browser.getControl("Login").click()
360        self.browser.open(self.payments_path)
361        self.browser.open(self.payments_path + '/addop')
362        self.browser.getControl(name="form.p_category").value = ['late_registration']
363        self.browser.getControl("Create ticket").click()
364        self.assertMatches('...ticket created...',
365                           self.browser.contents)
366        self.browser.getLink("Study Course").click()
367        self.browser.getLink("Add course list").click()
368        self.assertMatches('...Add current level 100 (Year 1)...',
369                           self.browser.contents)
370        self.browser.getControl("Create course list now").click()
371        self.browser.getLink("100").click()
372        self.browser.getLink("Edit course list").click()
373        self.browser.getControl("Register course list").click()
374        self.assertTrue('Course registration has ended. Please pay' in self.browser.contents)
375        self.student['payments'].values()[0].approve()
376        self.browser.getControl("Register course list").click()
377        self.assertTrue('Course list has been registered' in self.browser.contents)
378        self.assertEqual(self.student.state, 'courses registered')
379        # Reset student and check if fresh students are always allowed to
380        # register courses.
381        self.student['studycourse'].entry_session = 2004
382        del self.student['payments'][self.student['payments'].keys()[0]]
383        IWorkflowState(self.student).setState('school fee paid')
384        self.browser.open(self.studycourse_path + '/100/edit')
385        self.browser.getControl("Register course list").click()
386        self.assertTrue('Course list has been registered' in self.browser.contents)
387        return
388
389
390    def deactivated_test_student_course_registration(self):
391        # Add more courses
392        self.course2 = createObject('waeup.Course')
393        self.course2.code = 'COURSE2'
394        self.course2.semester = 2
395        self.course2.credits = 10
396        self.course2.passmark = 40
397        self.app['faculties']['fac1']['dep1'].courses.addCourse(
398            self.course2)
399        self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCertCourse(
400            self.course2, level=100)
401        self.course3 = createObject('waeup.Course')
402        self.course3.code = 'COURSE3'
403        self.course3.semester = 3
404        self.course3.credits = 10
405        self.course3.passmark = 40
406        self.app['faculties']['fac1']['dep1'].courses.addCourse(
407            self.course3)
408        self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCertCourse(
409            self.course3, level=100)
410
411        # Login as student
412        self.browser.open(self.login_path)
413        IWorkflowState(self.student).setState('school fee paid')
414        self.browser.open(self.login_path)
415        self.browser.getControl(name="form.login").value = self.student_id
416        self.browser.getControl(name="form.password").value = 'spwd'
417        self.browser.getControl("Login").click()
418        # Students can add the current study level
419        self.browser.getLink("Study Course").click()
420        self.browser.getLink("Add course list").click()
421        self.assertMatches('...Add current level 100 (Year 1)...',
422                           self.browser.contents)
423        self.browser.getControl("Create course list now").click()
424        # Student has not paid second instalment, therefore a level
425        # with two course ticket was created (semester 1 and combined)
426        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 2)
427        self.browser.getLink("100").click()
428        self.browser.getLink("Edit course list").click()
429        self.browser.getControl("Add course ticket").click()
430        # Student can't add second semester course
431        self.assertTrue('<option value="COURSE1">' in self.browser.contents)
432        self.assertTrue('<option value="COURSE3">' in self.browser.contents)
433        self.assertFalse('<option value="COURSE2">' in self.browser.contents)
434
435        # Let's remove level and see what happens after 2nd instalment payment
436        del(self.student['studycourse']['100'])
437        payment2 = createObject('waeup.StudentOnlinePayment')
438        payment2.p_category = u'schoolfee_2'
439        payment2.p_session = self.student.current_session
440        self.student['payments']['anykey'] = payment2
441        self.browser.open(self.studycourse_path)
442        self.browser.getLink("Add course list").click()
443        self.browser.getControl("Create course list now").click()
444        # Still only 2 tickets have been created since payment ticket
445        # was not paid
446        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 2)
447        payment2.p_state = u'paid'
448        del(self.student['studycourse']['100'])
449        self.browser.open(self.studycourse_path)
450        self.browser.getLink("Add course list").click()
451        self.browser.getControl("Create course list now").click()
452        # Now 2nd semester course has been added
453        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 3)
454        # Student can add second semester course
455        self.browser.getLink("100").click()
456        self.browser.getLink("Edit course list").click()
457        self.browser.getControl("Add course ticket").click()
458        self.assertTrue('<option value="COURSE1">' in self.browser.contents)
459        self.assertTrue('<option value="COURSE2">' in self.browser.contents)
460        self.assertTrue('<option value="COURSE3">' in self.browser.contents)
461        return
462
463    def test_set_matric_number(self):
464        #payment = createObject('waeup.StudentOnlinePayment')
465        #payment.p_category = u'concessional'
466        #payment.p_id = u'anyid'
467        #payment.p_state = u'paid'
468        #self.student['payments']['anykey'] = payment
469        # Login as student
470        self.browser.open(self.login_path)
471        IWorkflowState(self.student).setState('school fee paid')
472        self.browser.open(self.login_path)
473        self.browser.getControl(name="form.login").value = self.student_id
474        self.browser.getControl(name="form.password").value = 'spwd'
475        self.browser.getControl("Login").click()
476        self.assertRaises(
477            LinkNotFoundError,
478            self.browser.getLink, 'Get Matriculation Number')
479        self.student.matric_number = None
480        site = grok.getSite()
481        site['configuration'].next_matric_integer = 1
482        self.student['studycourse'].certificate.study_mode = 'ug_pt'
483        self.browser.open(self.student_path)
484        self.assertRaises(
485            LinkNotFoundError,
486            self.browser.getLink, 'Download matriculation number slip')
487        self.browser.getLink("Get Matriculation Number").click()
488        self.assertTrue('Matriculation number PTP/fac1/dep1/04/00001 assigned.'
489            in self.browser.contents)
490        self.assertEqual(self.student.matric_number, 'PTP/fac1/dep1/04/00001')
491        self.assertRaises(
492            LinkNotFoundError,
493            self.browser.getLink, 'Get Matriculation Number')
494        # Setting matric number is logged.
495        logfile = os.path.join(
496            self.app['datacenter'].storage, 'logs', 'students.log')
497        logcontent = open(logfile).read()
498        self.assertTrue('E1000000 - waeup.aaue.students.browser.StudentGetMatricNumberPage - '
499                        'E1000000 - PTP/fac1/dep1/04/00001 assigned' in logcontent)
500        # Matric Number Slip can be downloaded
501        self.browser.getLink("Download matriculation number slip").click()
502        self.assertEqual(self.browser.headers['Status'], '200 Ok')
503        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
504        path = os.path.join(samples_dir(), 'matric_number_slip.pdf')
505        open(path, 'wb').write(self.browser.contents)
506        print "Sample PDF matric_number_slip.pdf written to %s" % path
507        return
508
509    def test_personal_data_slip(self):
510        # Login as student
511        self.browser.open(self.login_path)
512        IWorkflowState(self.student).setState('school fee paid')
513        self.browser.open(self.login_path)
514        self.browser.getControl(name="form.login").value = self.student_id
515        self.browser.getControl(name="form.password").value = 'spwd'
516        self.browser.getControl("Login").click()
517        self.browser.getLink("Personal Data").click()
518        self.assertRaises(
519            LinkNotFoundError,
520            self.browser.getLink, 'Download personal data slip')
521        self.student.father_name = u'Rudolf'
522        self.browser.open(self.personal_path)
523        self.browser.getLink("Download personal data slip").click()
524        self.assertEqual(self.browser.headers['Status'], '200 Ok')
525        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
526        path = os.path.join(samples_dir(), 'personal_data_slip.pdf')
527        open(path, 'wb').write(self.browser.contents)
528        print "Sample PDF personal_data_slip.pdf written to %s" % path
529        return
530
531    def test_student_course_registration(self):
532        IWorkflowState(self.student).setState('school fee paid')
533        self.browser.open(self.login_path)
534        self.browser.getControl(name="form.login").value = self.student_id
535        self.browser.getControl(name="form.password").value = 'spwd'
536        self.browser.getControl("Login").click()
537        # Now students can add the current study level
538        self.browser.getLink("Study Course").click()
539        self.browser.getLink("Add course list").click()
540        self.assertMatches('...Add current level 100 (Year 1)...',
541                           self.browser.contents)
542        self.browser.getControl("Create course list now").click()
543        # Students can't open the customized pdf course registration slip
544        self.browser.open(
545            self.student_path + '/studycourse/100/course_registration_slip.pdf')
546        self.assertTrue('Forbidden' in self.browser.contents)
547        # They can open slips from the previous session ...
548        self.student['studycourse'].current_level = 200
549        self.browser.open(self.student_path + '/studycourse/100')
550        self.browser.getLink("Download course registration slip").click()
551        self.assertEqual(self.browser.headers['Status'], '200 Ok')
552        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
553        # or if they have registered their course list
554        self.student['studycourse'].current_level = 200
555        IWorkflowState(self.student).setState('courses registered')
556        self.browser.open(self.student_path + '/studycourse/100')
557        self.browser.getLink("Download course registration slip").click()
558        self.assertEqual(self.browser.headers['Status'], '200 Ok')
559        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
560        path = os.path.join(samples_dir(), 'ft_course_registration_slip.pdf')
561        open(path, 'wb').write(self.browser.contents)
562        print "Sample PDF ft_course_registration_slip.pdf written to %s" % path
563
564        self.certificate.study_mode = 'ug_pt'
565        self.browser.open(self.student_path + '/studycourse/100')
566        self.browser.getLink("Download course registration slip").click()
567        self.assertEqual(self.browser.headers['Status'], '200 Ok')
568        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
569        path = os.path.join(samples_dir(), 'pt_course_registration_slip.pdf')
570        open(path, 'wb').write(self.browser.contents)
571        print "Sample PDF pt_course_registration_slip.pdf written to %s" % path
572
573        self.certificate.study_mode = 'special_pg_ft'
574        self.student.matric_number = u'AAU/SPS/FLW/LAW/15/PHD/09504'
575        self.browser.open(self.student_path + '/studycourse/100')
576        self.browser.getLink("Download course registration slip").click()
577        self.assertEqual(self.browser.headers['Status'], '200 Ok')
578        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
579        path = os.path.join(samples_dir(), 'pg_course_registration_slip.pdf')
580        open(path, 'wb').write(self.browser.contents)
581        print "Sample PDF pg_course_registration_slip.pdf written to %s" % path
582
583    def test_student_clearance(self):
584        # Student cant login if their password is not set
585        IWorkflowInfo(self.student).fireTransition('admit')
586        self.browser.open(self.login_path)
587        self.browser.getControl(name="form.login").value = self.student_id
588        self.browser.getControl(name="form.password").value = 'spwd'
589        self.browser.getControl("Login").click()
590        self.assertMatches(
591            '...You logged in...', self.browser.contents)
592        # Admitted student can upload a passport picture
593        self.browser.open(self.student_path + '/change_portrait')
594        ctrl = self.browser.getControl(name='passportuploadedit')
595        file_obj = open(SAMPLE_IMAGE, 'rb')
596        file_ctrl = ctrl.mech_control
597        file_ctrl.add_file(file_obj, filename='my_photo.jpg')
598        self.browser.getControl(
599            name='upload_passportuploadedit').click()
600        self.assertTrue(
601            'src="http://localhost/app/students/E1000000/passport.jpg"'
602            in self.browser.contents)
603        # Student is redirected to the personal data form because
604        # personal data form is not properly filled.
605        self.browser.open(self.student_path + '/start_clearance')
606        self.assertMatches('...Personal data form is not properly filled...',
607                           self.browser.contents)
608        self.assertEqual(self.browser.url, self.student_path + '/edit_personal')
609        self.student.father_name = u'Rudolf'
610        self.browser.open(self.student_path + '/start_clearance')
611        self.assertMatches(
612            '...<h1 class="kofa-content-label">Start clearance</h1>...',
613            self.browser.contents)
614
615    def test_student_accommodation(self):
616        del self.student['accommodation']['2004']
617        self.student['studycourse'].certificate.study_mode = 'dp_ft'
618        # All beds can be assigned
619        bed1 = self.app['hostels']['hall-1']['hall-1_A_101_A']
620        bed1.bed_type = u'regular_male_all'
621        bed2 = self.app['hostels']['hall-1']['hall-1_A_101_B']
622        bed2.bed_type = u'regular_female_all'
623        notify(grok.ObjectModifiedEvent(bed1))
624        notify(grok.ObjectModifiedEvent(bed2))
625        # Login
626        self.browser.open(self.login_path)
627        self.browser.getControl(name="form.login").value = self.student_id
628        self.browser.getControl(name="form.password").value = 'spwd'
629        self.browser.getControl("Login").click()
630        # Students can book accommodation without AC ...
631        self.browser.open(self.acco_path)
632        IWorkflowInfo(self.student).fireTransition('admit')
633        self.browser.getControl("Book accommodation").click()
634        self.assertTrue(
635            'You are not eligible to book accommodation.'
636            in self.browser.contents)
637        self.student['studycourse'].certificate.study_mode = 'ug_ft'
638        self.browser.getControl("Book accommodation").click()
639        self.assertFalse('Activation Code:' in self.browser.contents)
640        self.browser.getControl("Create bed ticket").click()
641        # Bed is randomly selected but, since there is only
642        # one bed for this student, we know that
643        self.assertEqual(self.student['accommodation']['2004'].bed_coordinates,
644            'Hall 1, Block A, Room 101, Bed A (regular_male_all)')
645        # Only the hall name is displayed
646        self.assertEqual(self.student[
647            'accommodation']['2004'].display_coordinates,
648            'Hall 1')
649        self.assertFalse('Hall 1, Block A, Room 101, Bed A'
650            in self.browser.contents)
651        self.assertTrue('<td>Hall 1</td>'
652            in self.browser.contents)
653        return
654
655    def test_handle_courses_by_lecturer(self):
656        self.app['users'].addUser('mrslecturer', 'mrslecturersecret')
657        self.app['users']['mrslecturer'].email = 'mrslecturer@foo.ng'
658        self.app['users']['mrslecturer'].title = u'Mercedes Benz'
659        # Add course ticket
660        studylevel = createObject(u'waeup.StudentStudyLevel')
661        studylevel.level = 100
662        studylevel.level_session = 2004
663        self.student['studycourse'].addStudentStudyLevel(
664            self.certificate, studylevel)
665        # Assign local Lecturer role for a certificate.
666        course = self.app['faculties']['fac1']['dep1'].courses['COURSE1']
667        prmlocal = IPrincipalRoleManager(course)
668        prmlocal.assignRoleToPrincipal('waeup.local.Lecturer', 'mrslecturer')
669        notify(LocalRoleSetEvent(
670            course, 'waeup.local.Lecturer', 'mrslecturer', granted=True))
671        # Login as lecturer.
672        self.browser.open(self.login_path)
673        self.browser.getControl(name="form.login").value = 'mrslecturer'
674        self.browser.getControl(name="form.password").value = 'mrslecturersecret'
675        self.browser.getControl("Login").click()
676        self.browser.getLink("My Roles").click()
677        self.browser.getLink(
678            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1").click()
679        # Course results can be batch edited via the edit_courses view.
680        self.app['faculties']['fac1']['dep1'].score_editing_disabled = False
681        self.app['configuration'].current_academic_session = 2004
682        IWorkflowState(self.student).setState('courses validated')
683        self.browser.open(
684            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1/edit_scores")
685        self.assertTrue(
686            'input type="text" name="scores"'
687            in self.browser.contents)
688        self.browser.getControl(name="scores", index=0).value = '55'
689        self.browser.getControl(name="cas", index=0).value = '66'
690        self.browser.getControl("Update scores").click()
691        # New score and ca has been set.
692        self.assertEqual(
693            self.student['studycourse']['100']['COURSE1'].score, 55)
694        self.assertEqual(
695            self.student['studycourse']['100']['COURSE1'].ca, 66)
696        # Score editing has been logged.
697        logfile = os.path.join(
698            self.app['datacenter'].storage, 'logs', 'students.log')
699        logcontent = open(logfile).read()
700        self.assertTrue('mrslecturer - waeup.aaue.students.browser.CustomEditScoresPage - '
701                        'E1000000 100/COURSE1 score updated (55)' in logcontent)
702        self.assertTrue('mrslecturer - waeup.aaue.students.browser.CustomEditScoresPage - '
703                        'E1000000 100/COURSE1 ca updated (66)' in logcontent)
704        # Non-integer scores won't be accepted.
705        self.browser.open(
706            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1/edit_scores")
707        self.assertTrue('value="55" />' in self.browser.contents)
708        self.browser.getControl(name="scores", index=0).value = 'abc'
709        self.browser.getControl("Update scores").click()
710        self.assertTrue('Error: Score(s) and CA(s) of Anna Tester have not be updated.'
711            in self.browser.contents)
712        # Scores can be removed.
713        self.browser.open(
714            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1/edit_scores")
715        self.browser.getControl(name="scores", index=0).value = ''
716        self.browser.getControl("Update scores").click()
717        self.assertEqual(
718            self.student['studycourse']['100']['COURSE1'].score, None)
719        logcontent = open(logfile).read()
720        self.assertTrue('mrslecturer - waeup.aaue.students.browser.CustomEditScoresPage - '
721                        'E1000000 100/COURSE1 score updated (None)' in logcontent)
Note: See TracBrowser for help on using the repository browser.