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

Last change on this file since 14593 was 14585, checked in by Henrik Bettermann, 8 years ago

Replace maxCreditsExceeded by warnCreditsOOR.

  • Property svn:keywords set to Id
File size: 64.0 KB
Line 
1## $Id: test_browser.py 14585 2017-02-24 09:24:09Z 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 StringIO import StringIO
24from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState
25from zope.securitypolicy.interfaces import IPrincipalRoleManager
26from datetime import datetime, timedelta, date
27from mechanize import LinkNotFoundError
28from hurry.workflow.interfaces import IWorkflowState
29from zope.event import notify
30from zope.component.hooks import setSite, clearSite
31from zope.component import getUtility, createObject, queryUtility
32from zope.catalog.interfaces import ICatalog
33from waeup.kofa.app import University
34from waeup.kofa.interfaces import VALIDATED, PAID
35from waeup.kofa.students.tests.test_browser import StudentsFullSetup
36from waeup.kofa.students.accommodation import BedTicket
37from waeup.kofa.testing import FunctionalTestCase
38from waeup.kofa.authentication import LocalRoleSetEvent
39from waeup.kofa.browser.tests.test_pdf import samples_dir
40from waeup.kofa.applicants.container import ApplicantsContainer
41from waeup.aaue.testing import FunctionalLayer
42
43SAMPLE_IMAGE = os.path.join(os.path.dirname(__file__), 'test_image.jpg')
44
45
46UPLOAD_CSV_TEMPLATE = (
47    'matric_number,student_id,display_fullname,level,code,level_session,'
48    'score,ca\r\n'
49    '234,E1000000,Anna Tester,100,COURSE1,2004,%s,%s\r\n')
50
51class OfficerUITests(StudentsFullSetup):
52    # Tests for Student class views and pages
53
54    layer = FunctionalLayer
55
56    def login_as_lecturer(self):
57        self.app['users'].addUser('mrslecturer', 'mrslecturersecret')
58        self.app['users']['mrslecturer'].email = 'mrslecturer@foo.ng'
59        self.app['users']['mrslecturer'].title = u'Mercedes Benz'
60        # Add course ticket
61        studylevel = createObject(u'waeup.StudentStudyLevel')
62        studylevel.level = 100
63        studylevel.level_session = 2004
64        self.student['studycourse'].addStudentStudyLevel(
65            self.certificate, studylevel)
66        # Assign local Lecturer role for a certificate.
67        course = self.app['faculties']['fac1']['dep1'].courses['COURSE1']
68        prmlocal = IPrincipalRoleManager(course)
69        prmlocal.assignRoleToPrincipal('waeup.local.Lecturer', 'mrslecturer')
70        notify(LocalRoleSetEvent(
71            course, 'waeup.local.Lecturer', 'mrslecturer', granted=True))
72        # Login as lecturer.
73        self.browser.open(self.login_path)
74        self.browser.getControl(name="form.login").value = 'mrslecturer'
75        self.browser.getControl(
76            name="form.password").value = 'mrslecturersecret'
77        self.browser.getControl("Login").click()
78        # Store reused urls/paths
79        self.course_url = (
80            'http://localhost/app/faculties/fac1/dep1/courses/COURSE1')
81        self.edit_scores_url = '%s/edit_scores' % self.course_url
82        self.edit_prev_scores_url = '%s/edit_prev_scores' % self.course_url
83        # Set standard parameters
84        self.app['configuration'].current_academic_session = 2004
85        self.app['faculties']['fac1']['dep1'].score_editing_disabled = False
86        IWorkflowState(self.student).setState(VALIDATED)
87
88
89    def test_gpa_calculation(self):
90        studylevel = createObject(u'waeup.StudentStudyLevel')
91        studylevel.level = 100
92        studylevel.level_session = 2005
93        self.student['studycourse'].entry_mode = 'ug_ft'
94        self.student['studycourse'].addStudentStudyLevel(
95            self.certificate, studylevel)
96        # First course has been added automatically.
97        # Set score.
98        studylevel['COURSE1'].score = 35
99        studylevel['COURSE1'].ca = 20
100        # GPA is 3.0.
101        self.assertEqual(studylevel.gpa_params[0], 3.0)
102        courseticket = createObject('waeup.CourseTicket')
103        courseticket.code = 'ANYCODE'
104        courseticket.title = u'Any TITLE'
105        courseticket.credits = 13
106        courseticket.score = 44
107        courseticket.ca = 22
108        courseticket.semester = 1
109        courseticket.dcode = u'ANYDCODE'
110        courseticket.fcode = u'ANYFCODE'
111        studylevel['COURSE2'] = courseticket
112        # total credits
113        self.assertEqual(self.student['studycourse']['100'].gpa_params[1], 23)
114        # weigheted credits = 3 * 10 + 4 * 13
115        self.assertEqual(self.student['studycourse']['100'].gpa_params[2], 82.0)
116        # sgpa = 82 / 23
117        self.assertEqual(
118            self.student['studycourse']['100'].gpa_params[0], 3.5652173913043477)
119        # imported gpa values override calculated values
120        studylevel.imported_gpa = 4.3
121        studylevel.imported_cgpa = 5.4
122        self.assertEqual(self.student['studycourse']['100'].gpa_params[0], 4.3)
123        self.assertEqual(
124            self.student['studycourse']['100'].cumulative_params[0], 5.4)
125        self.assertEqual(self.student['studycourse']['100'].gpa, '4.30')
126        self.student['studycourse'].imported_cgpa = 6.6
127        self.assertEqual(
128            self.student['studycourse'].getTranscriptData()[1], 6.6)
129        return
130
131    def test_grade_weight(self):
132        studylevel = createObject(u'waeup.StudentStudyLevel')
133        studylevel.level = 100
134        studylevel.level_session = 2005
135        self.course.passmark = 40
136        self.student['studycourse'].entry_mode = 'ug_ft'
137        self.student['studycourse'].addStudentStudyLevel(
138            self.certificate, studylevel)
139        studylevel['COURSE1'].score = 42
140        studylevel['COURSE1'].ca = 0
141        courseticket = createObject('waeup.CourseTicket')
142        self.assertEqual(studylevel['COURSE1'].weight, 1)
143        self.assertEqual(studylevel['COURSE1'].grade, 'E')
144        self.assertEqual(studylevel['COURSE1'].weight, 1)
145        self.assertEqual(studylevel['COURSE1'].grade, 'E')
146        studylevel['COURSE1'].score = 45
147        self.assertEqual(studylevel['COURSE1'].weight, 2)
148        self.assertEqual(studylevel['COURSE1'].grade, 'D')
149        return
150
151    def test_manage_payments(self):
152        # Add missing configuration data
153        self.app['configuration']['2004'].gown_fee = 150.0
154        self.app['configuration']['2004'].transfer_fee = 90.0
155        self.app['configuration']['2004'].booking_fee = 150.0
156        self.app['configuration']['2004'].maint_fee = 180.0
157        self.app['configuration']['2004'].late_fee = 80.0
158
159        # Managers can add online payment tickets
160        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
161        self.browser.open(self.payments_path)
162        self.browser.getLink("Add current session payment ticket").click()
163        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
164        self.browser.getControl("Create ticket").click()
165        self.assertMatches('...Wrong state...',
166                           self.browser.contents)
167        IWorkflowState(self.student).setState('cleared')
168        self.browser.open(self.payments_path + '/addop')
169        self.app['configuration']['2004'].clearance_fee = 666.0
170        self.browser.getControl(name="form.p_category").value = ['clearance_incl']
171        self.browser.getControl("Create ticket").click()
172        ctrl = self.browser.getControl(name='val_id')
173        cpt_value = ctrl.options[0]
174        # School fee payment ticket can be added ...
175        self.student['studycourse'].certificate.school_fee_1 = 6666.0
176        self.student.nationality = u'NG'
177        self.browser.open(self.payments_path + '/addop')
178        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
179        self.browser.getControl("Create ticket").click()
180        self.assertMatches('...ticket created...',
181                           self.browser.contents)
182        # ... but not paid through the query_history page.
183        ctrl = self.browser.getControl(name='val_id')
184        sfpt_value = ctrl.options[1]
185        self.student['studycourse'].entry_session = 2013
186        self.browser.open(self.payments_path + '/' + sfpt_value)
187        self.browser.getLink("Query eTranzact History").click()
188        self.assertMatches('...alert-danger">Please pay acceptance fee first...',
189                           self.browser.contents)
190        # If clearance/acceptance fee is paid ...
191        self.student['payments'][cpt_value].approveStudentPayment()
192        self.browser.getLink("Query eTranzact History").click()
193        # ... query_history page is accessible.
194        self.assertMatches(
195            '...<h1 class="kofa-content-label">Requery eTranzact History</h1>...',
196            self.browser.contents)
197        # Managers can open school fee payment slip
198        self.browser.open(self.payments_path + '/' + sfpt_value)
199        self.browser.getLink("Download payment slip").click()
200        self.assertEqual(self.browser.headers['Status'], '200 Ok')
201        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
202        # If school fee ticket is paid, the student is automatically set to
203        # school fee paid...
204        ticket = self.student['payments'][sfpt_value].approveStudentPayment()
205        self.assertEqual(self.student.state, 'school fee paid')
206        # ... no further school fee ticket can be added.
207        self.browser.open(self.payments_path + '/addop')
208        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
209        self.browser.getControl("Create ticket").click()
210        self.assertMatches('...Wrong state...',
211                           self.browser.contents)
212        self.browser.open(self.payments_path + '/addop')
213        self.browser.getControl(name="form.p_category").value = ['late_registration']
214        self.browser.getControl("Create ticket").click()
215        self.assertMatches('...ticket created...',
216                           self.browser.contents)
217        return
218
219    def test_for_instalment_payments(self):
220
221        configuration_1 = createObject('waeup.SessionConfiguration')
222        configuration_1.academic_session = 2015
223        self.app['configuration'].addSessionConfiguration(configuration_1)
224        self.student['studycourse'].certificate.study_mode = 'ug_pt'
225        self.student['studycourse'].certificate.school_fee_1 = 6666.0
226        self.app['configuration']['2015'].union_fee = 1250.0
227        self.app['configuration']['2015'].welfare_fee = 750.0
228        self.student.nationality = u'NG'
229        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
230        self.browser.open(self.payments_path + '/addop')
231        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
232        self.browser.getControl("Create ticket").click()
233        self.assertTrue(
234            'Part-time students are not allowed' in self.browser.contents)
235        self.student['studycourse'].certificate.study_mode = 'ug_ft'
236        self.browser.open(self.payments_path + '/addop')
237        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
238        self.browser.getControl("Create ticket").click()
239        self.assertTrue('You are not allowed to pay by instalments.'
240            in self.browser.contents)
241        IWorkflowState(self.student).setState('cleared')
242        self.student['studycourse'].entry_session = 2015
243        self.student['studycourse'].current_session = 2015
244        self.browser.open(self.payments_path + '/addop')
245        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
246        self.browser.getControl("Create ticket").click()
247        self.assertTrue('ticket created' in self.browser.contents)
248        # We can't add the 2nd instalment ticket because the
249        # first one has not yet been approved.
250        #self.browser.open(self.payments_path + '/addop')
251        #self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
252        #self.browser.getControl("Create ticket").click()
253        #self.assertMatches('...1st school fee instalment has not yet been paid...',
254        #                   self.browser.contents)
255        # Ok, then we approve the first instalment ...
256        self.browser.open(self.payments_path)
257        ctrl = self.browser.getControl(name='val_id')
258        p_id = ctrl.options[0]
259        self.browser.open(self.payments_path + '/' + p_id + '/approve')
260        # ... add the second instalment ...
261        self.browser.open(self.payments_path + '/addop')
262        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
263        self.browser.getControl("Create ticket").click()
264        self.assertTrue('ticket created' in self.browser.contents)
265        # ... approve the second instalment ...
266        ctrl = self.browser.getControl(name='val_id')
267        p_id = ctrl.options[1]
268        self.browser.open(self.payments_path + '/' + p_id + '/approve')
269        self.assertEqual(self.student['payments'].values()[0].p_category, 'schoolfee_1')
270        self.assertEqual(self.student['payments'].values()[1].p_category, 'schoolfee_2')
271        # (6666-250)/2 + 1250 + 750 - 500 + 250
272        self.assertEqual(self.student['payments'].values()[0].amount_auth, 4958.0)
273        # (6666-250)/2 + 250
274        self.assertEqual(self.student['payments'].values()[1].amount_auth, 3458.0)
275        # The  two payments belong to the same session and level.
276        self.assertEqual(self.student['payments'].values()[0].p_session, 2015)
277        self.assertEqual(self.student['payments'].values()[0].p_level, 100)
278        self.assertEqual(self.student['payments'].values()[1].p_session, 2015)
279        self.assertEqual(self.student['payments'].values()[1].p_level, 100)
280
281        # Returning student
282        configuration_2 = createObject('waeup.SessionConfiguration')
283        configuration_2.academic_session = 2016
284        self.app['configuration'].addSessionConfiguration(configuration_2)
285        self.student['studycourse'].certificate.school_fee_2 = 5666.0
286        self.app['configuration']['2016'].union_fee = 1250.0
287        self.app['configuration']['2016'].welfare_fee = 750.0
288        self.student.father_name = u'Albert'
289        IWorkflowState(self.student).setState('returning')
290        self.browser.open(self.payments_path + '/addop')
291        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
292        self.browser.getControl("Create ticket").click()
293        self.browser.open(self.payments_path + '/addop')
294        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
295        self.browser.getControl("Create ticket").click()
296        # Student is still in the first  session.
297        self.assertTrue('This type of payment' in self.browser.contents)
298        self.browser.open(self.payments_path)
299        ctrl = self.browser.getControl(name='val_id')
300        p_id = ctrl.options[2]
301        self.browser.open(self.payments_path + '/' + p_id + '/approve')
302        self.browser.open(self.payments_path + '/addop')
303        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
304        self.browser.getControl("Create ticket").click()
305        self.assertTrue('ticket created' in self.browser.contents)
306        # (5666-250)/2 + 1250 + 750 - 500 + 250
307        self.assertEqual(self.student['payments'].values()[2].amount_auth, 4458.0)
308        # (5666-250)/2 + 250
309        self.assertEqual(self.student['payments'].values()[3].amount_auth, 2958.0)
310        # The last two payments belong to the same session and level.
311        self.assertEqual(self.student['payments'].values()[2].p_session, 2016)
312        self.assertEqual(self.student['payments'].values()[2].p_level, 200)
313        self.assertEqual(self.student['payments'].values()[3].p_session, 2016)
314        self.assertEqual(self.student['payments'].values()[3].p_level, 200)
315        return
316
317    def test_manage_payments_bypass_ac_creation(self):
318        self.student['studycourse'].certificate.school_fee_1 = 6666.0
319        self.student.nationality = u'NG'
320        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
321        self.browser.open(self.payments_path)
322        IWorkflowState(self.student).setState('cleared')
323        self.browser.getLink("Add current session payment ticket").click()
324        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
325        self.browser.getControl("Create ticket").click()
326        ctrl = self.browser.getControl(name='val_id')
327        value = ctrl.options[0]
328        self.browser.getLink(value).click()
329        payment_url = self.browser.url
330        logfile = os.path.join(
331            self.app['datacenter'].storage, 'logs', 'students.log')
332        # The ticket can be found in the payments_catalog
333        cat = queryUtility(ICatalog, name='payments_catalog')
334        results = list(cat.searchResults(p_state=('unpaid', 'unpaid')))
335        self.assertTrue(len(results), 1)
336        self.assertTrue(results[0] is self.student['payments'][value])
337        # Managers can approve the payment
338        self.browser.open(payment_url)
339        self.browser.getLink("Approve payment").click()
340        self.assertMatches('...Payment approved...',
341                          self.browser.contents)
342        # Approval is logged in students.log ...
343        logcontent = open(logfile).read()
344        self.assertTrue(
345            'zope.mgr - students.browser.OnlinePaymentApproveView '
346            '- E1000000 - schoolfee_incl payment approved'
347            in logcontent)
348        # ... and in payments.log
349        logfile = os.path.join(
350            self.app['datacenter'].storage, 'logs', 'payments.log')
351        logcontent = open(logfile).read()
352        self.assertTrue(
353            '"zope.mgr",E1000000,%s,schoolfee_incl,6666.0,AP,,,,,,\n' % value
354            in logcontent)
355        # Student is in state school fee paid, no activation
356        # code was necessary.
357        self.assertEqual(self.student.state, 'school fee paid')
358        self.assertEqual(len(self.app['accesscodes']['SFE-0']),0)
359        return
360
361    def test_scores_csv_upload_available(self):
362        # lecturers can upload a CSV file to set values.
363        self.login_as_lecturer()
364        # set value to change from
365        self.student['studycourse']['100']['COURSE1'].score = 55
366        self.browser.open(self.edit_scores_url)
367        upload_ctrl = self.browser.getControl(name='uploadfile:file')
368        upload_file = StringIO(UPLOAD_CSV_TEMPLATE % ('65','22'))
369        upload_ctrl.add_file(upload_file, 'text/csv', 'myscores.csv')
370        self.browser.getControl("Update editable scores from").click()
371        # value changed
372        self.assertEqual(
373            self.student['studycourse']['100']['COURSE1'].score, 65)
374        self.assertEqual(
375            self.student['studycourse']['100']['COURSE1'].ca, 22)
376
377    def test_scores_previous_session(self):
378        # lecturers can download a CSV file to set values.
379        self.login_as_lecturer()
380        self.student['studycourse']['100']['COURSE1'].score = 55
381        self.browser.open(self.edit_prev_scores_url)
382        self.assertTrue('No student found' in self.browser.contents)
383        self.student['studycourse']['100'].level_session = 2003
384        notify(grok.ObjectModifiedEvent(self.student['studycourse']['100']['COURSE1']))
385        self.browser.open(self.edit_prev_scores_url)
386        self.browser.getLink("Download csv file").click()
387        self.assertEqual(self.browser.headers['Status'], '200 Ok')
388        self.assertEqual(self.browser.headers['Content-Type'],
389                         'text/csv; charset=UTF-8')
390        self.assertEqual(self.browser.contents, 'matric_number,student_id,display_fullname,'
391            'level,code,level_session,ca,score\r\n234,E1000000,"TESTER, Anna",'
392            '100,COURSE1,2003,,55\r\n')
393        self.browser.open(self.edit_prev_scores_url)
394        upload_ctrl = self.browser.getControl(name='uploadfile:file')
395        upload_file = StringIO(UPLOAD_CSV_TEMPLATE % ('65','22'))
396        upload_ctrl.add_file(upload_file, 'text/csv', 'myscores.csv')
397        self.browser.getControl("Update editable scores from").click()
398        # value changed
399        self.assertEqual(
400            self.student['studycourse']['100']['COURSE1'].score, 65)
401        self.assertEqual(
402            self.student['studycourse']['100']['COURSE1'].ca, 22)
403
404    def test_lecturers_can_download_course_tickets(self):
405        # A course ticket slip can be downloaded
406        self.login_as_lecturer()
407        self.student['studycourse']['100']['COURSE1'].score = 55
408        self.student['studycourse']['100']['COURSE1'].ca = 11
409        pdf_url = '%s/coursetickets.pdf' % self.course_url
410        self.browser.open(pdf_url)
411        self.assertEqual(self.browser.headers['Status'], '200 Ok')
412        self.assertEqual(
413            self.browser.headers['Content-Type'], 'application/pdf')
414        path = os.path.join(samples_dir(), 'coursetickets.pdf')
415        open(path, 'wb').write(self.browser.contents)
416        print "Sample PDF coursetickets.pdf written to %s" % path
417
418    def test_transcripts(self):
419        studylevel = createObject(u'waeup.StudentStudyLevel')
420        studylevel.level = 100
421        studylevel.level_session = 2005
422        self.student['studycourse'].entry_mode = 'ug_ft'
423        self.student['studycourse'].addStudentStudyLevel(
424            self.certificate, studylevel)
425        studylevel2 = createObject(u'waeup.StudentStudyLevel')
426        studylevel2.level = 200
427        studylevel2.level_session = 2006
428        self.student['studycourse']['100']['COURSE1'].score = 33 # no carry-over!
429        self.student['studycourse']['100']['COURSE1'].ca = 22
430        self.student['studycourse'].addStudentStudyLevel(
431            self.certificate, studylevel2)
432        # Add second course (COURSE has been added automatically)
433        courseticket = createObject('waeup.CourseTicket')
434        courseticket.code = 'ANYCODE'
435        courseticket.title = u'Any TITLE'
436        courseticket.credits = 13
437        courseticket.score = 55
438        courseticket.ca = 11
439        courseticket.semester = 1
440        courseticket.dcode = u'ANYDCODE'
441        courseticket.fcode = u'ANYFCODE'
442        self.student['studycourse']['200']['COURSE2'] = courseticket
443        self.assertEqual(self.student['studycourse']['100'].gpa_params_rectified[0], 3.0)
444        self.assertEqual(self.student['studycourse']['200'].gpa_params_rectified[0], 4.0)
445        # Get transcript data
446        td = self.student['studycourse'].getTranscriptData()
447        self.assertEqual(td[0][0]['level_key'], '100')
448        self.assertEqual(td[0][0]['sgpa'], 3.0)
449        self.assertEqual(td[0][0]['level'].level, 100)
450        self.assertEqual(td[0][0]['level'].level_session, 2005)
451        self.assertEqual(td[0][0]['tickets_1'][0].code, 'COURSE1')
452        self.assertEqual(td[0][1]['level_key'], '200')
453        self.assertEqual(td[0][1]['sgpa'], 4.0)
454        self.assertEqual(td[0][1]['level'].level, 200)
455        self.assertEqual(td[0][1]['level'].level_session, 2006)
456        self.assertEqual(td[0][1]['tickets_1'][0].code, 'ANYCODE')
457        self.assertEqual(td[1], 3.5652173913043477)
458        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
459        self.browser.open(self.student_path + '/studycourse/transcript')
460        self.assertEqual(self.browser.headers['Status'], '200 Ok')
461        self.assertTrue('Transcript' in self.browser.contents)
462        # Officers can open the pdf transcript
463        self.browser.open(self.student_path + '/studycourse/transcript.pdf')
464        self.assertEqual(self.browser.headers['Status'], '200 Ok')
465        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
466        path = os.path.join(samples_dir(), 'transcript.pdf')
467        open(path, 'wb').write(self.browser.contents)
468        print "Sample PDF transcript.pdf written to %s" % path
469
470    def test_payment_disabled(self):
471        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
472        self.browser.open(self.payments_path)
473        IWorkflowState(self.student).setState('cleared')
474        self.browser.getLink("Add current session payment ticket").click()
475        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
476        self.browser.getControl("Create ticket").click()
477        self.assertMatches('...ticket created...', self.browser.contents)
478        self.app['configuration']['2004'].payment_disabled = ['sf_all']
479        self.browser.getLink("Add current session payment ticket").click()
480        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
481        self.browser.getControl("Create ticket").click()
482        self.assertMatches('...This category of payments has been disabled...',
483                           self.browser.contents)
484
485        self.app['configuration']['2004'].payment_disabled = ['sf_ug_pt']
486        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
487        self.browser.getControl("Create ticket").click()
488        self.assertMatches('...ticket created...', self.browser.contents)
489        self.certificate.study_mode = 'ug_pt'
490        self.browser.getLink("Add current session payment ticket").click()
491        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
492        self.browser.getControl("Create ticket").click()
493        self.assertMatches('...This category of payments has been disabled...',
494                           self.browser.contents)
495
496        self.app['configuration']['2004'].payment_disabled = ['sf_pg']
497        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
498        self.browser.getControl("Create ticket").click()
499        self.assertMatches('...ticket created...', self.browser.contents)
500        self.certificate.study_mode = 'special_pg_ft'
501        self.browser.getLink("Add current session payment ticket").click()
502        self.browser.getControl(name="form.p_category").value = ['schoolfee']
503        self.browser.getControl("Create ticket").click()
504        self.assertMatches('...This category of payments has been disabled...',
505                           self.browser.contents)
506        return
507
508class StudentUITests(StudentsFullSetup):
509    """Tests for customized student class views and pages
510    """
511
512    layer = FunctionalLayer
513
514    def setUp(self):
515        super(StudentUITests, self).setUp()
516
517        bedticket = BedTicket()
518        bedticket.booking_session = 2004
519        bedticket.bed_type = u'any bed type'
520        bedticket.bed = self.app['hostels']['hall-1']['hall-1_A_101_A']
521        bedticket.bed_coordinates = u'My bed coordinates'
522        self.student['accommodation'].addBedTicket(bedticket)
523
524    def test_maintenance_fee_payment(self):
525        self.certificate.study_mode = 'ug_ft'
526        self.student['studycourse'].entry_session = 2013
527        self.student.nationality = u'NG'
528        IWorkflowState(self.student).setState('cleared')
529        self.browser.open(self.login_path)
530        self.browser.getControl(name="form.login").value = self.student_id
531        self.browser.getControl(name="form.password").value = 'spwd'
532        self.browser.getControl("Login").click()
533        self.browser.open(self.student_path + '/payments')
534        self.browser.getLink("Add current session payment ticket").click()
535        self.browser.getControl(name="form.p_category").value = ['hostel_maintenance']
536        self.browser.getControl("Create ticket").click()
537        self.assertTrue('ticket created' in self.browser.contents)
538        value = self.student['payments'].keys()[0]
539        self.browser.getLink(value).click()
540        self.assertTrue('<span>My bed coordinates</span>' in self.browser.contents)
541        self.assertEqual(self.student['payments'][value].amount_auth, 876.0)
542        return
543
544    def test_student_schoolfee_payments(self):
545        configuration_1 = createObject('waeup.SessionConfiguration')
546        configuration_1.academic_session = 2016
547        self.app['configuration'].addSessionConfiguration(configuration_1)
548        self.certificate.study_mode = 'ug_ft'
549        self.student['studycourse'].entry_session = 2016
550        self.student['studycourse'].current_session = 2016
551        self.student['studycourse'].entry_mode = 'ug_ft'
552        self.student['studycourse'].certificate.school_fee_1 = 50250.0
553        self.app['configuration']['2016'].union_fee = 1250.0
554        self.app['configuration']['2016'].welfare_fee = 750.0
555        self.app['configuration']['2016'].id_card_fee = 350.0
556        self.student.nationality = u'NG'
557        # Login
558        IWorkflowState(self.student).setState('cleared')
559        self.browser.open(self.login_path)
560        self.browser.getControl(name="form.login").value = self.student_id
561        self.browser.getControl(name="form.password").value = 'spwd'
562        self.browser.getControl("Login").click()
563        # Test school fee payments
564        self.browser.open(self.student_path + '/payments')
565        self.browser.getLink("Add current session payment ticket").click()
566        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
567        self.browser.getControl("Create ticket").click()
568        self.assertTrue('ticket created' in self.browser.contents)
569        value = self.student['payments'].keys()[0]
570        self.browser.getLink(value).click()
571        self.assertTrue('Amount Authorized' in self.browser.contents)
572        # 50250 + 1000 + 500 + 100 = 51850
573        self.assertEqual(self.student['payments'][value].amount_auth, 51850.0)
574        self.browser.open(self.browser.url + '/payment_slip.pdf')
575        self.assertEqual(self.browser.headers['Status'], '200 Ok')
576        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
577        path = os.path.join(samples_dir(), 'payment_slip.pdf')
578        open(path, 'wb').write(self.browser.contents)
579        print "Sample PDF payment_slip.pdf written to %s" % path
580        # Another school fee payment cannot be added
581        self.student['payments'][value].approve()
582        self.browser.open(self.student_path + '/payments')
583        self.browser.getLink("Add current session payment ticket").click()
584        self.browser.getControl(name="form.p_category").value = ['schoolfee']
585        self.browser.getControl("Create ticket").click()
586        self.assertTrue(
587            'You must choose a payment which includes additional fees'
588            in self.browser.contents)
589        return
590
591    def test_late_registration(self):
592        self.app['configuration']['2004'].restitution_fee = 9999.0
593        delta = timedelta(days=10)
594        self.app['configuration'][
595            '2004'].coursereg_deadline = datetime.now(pytz.utc) - delta
596        IWorkflowState(self.student).setState('school fee paid')
597        # Current session is 2004. Here we test course registration for
598        # returning students.
599        self.student['studycourse'].entry_session = 2003
600        # Login
601        self.browser.open(self.login_path)
602        self.browser.getControl(name="form.login").value = self.student_id
603        self.browser.getControl(name="form.password").value = 'spwd'
604        self.browser.getControl("Login").click()
605        # Make restitution fee payment
606        self.browser.open(self.payments_path + '/addop')
607        self.browser.getControl(name="form.p_category").value = ['restitution']
608        self.browser.getControl("Create ticket").click()
609        self.student['payments'].values()[0].approveStudentPayment()
610        # Make late registration fee fee payment
611        self.browser.open(self.payments_path + '/addop')
612        self.browser.getControl(name="form.p_category").value = ['late_registration']
613        self.browser.getControl("Create ticket").click()
614        self.assertMatches('...ticket created...',
615                           self.browser.contents)
616        self.browser.getLink("Study Course").click()
617        self.browser.getLink("Add course list").click()
618        self.assertMatches('...Add current level 100 (Year 1)...',
619                           self.browser.contents)
620        self.browser.getControl("Create course list now").click()
621        self.student['studycourse']['100']['COURSE1'].score = 67
622        self.browser.getLink("100").click()
623        # Course results can't be seen
624        self.assertFalse('<td>67</td>' in self.browser.contents)
625        self.browser.getLink("Edit course list").click()
626        self.assertFalse('<td>67</td>' in self.browser.contents)
627        self.browser.getControl("Register course list").click()
628
629        ######################################################
630        # Temporarily disabled ug_ft course registration
631        self.assertTrue('Please check back later'
632            in self.browser.contents)
633        return
634        ######################################################
635
636
637        self.assertTrue('Course registration has ended. Please pay' in self.browser.contents)
638        self.student['payments'].values()[1].approve()
639        self.browser.getControl("Register course list").click()
640        self.assertTrue('Course list has been registered' in self.browser.contents)
641        self.assertEqual(self.student.state, 'courses registered')
642        # Reset student and check if fresh students are always allowed to
643        # register courses.
644        self.student['studycourse'].entry_session = 2004
645        del self.student['payments'][self.student['payments'].keys()[1]]
646        IWorkflowState(self.student).setState('school fee paid')
647        self.browser.open(self.studycourse_path + '/100/edit')
648        self.browser.getControl("Register course list").click()
649        self.assertTrue('Course list has been registered' in self.browser.contents)
650        return
651
652
653    def deactivated_test_student_course_registration(self):
654        # Add more courses
655        self.course2 = createObject('waeup.Course')
656        self.course2.code = 'COURSE2'
657        self.course2.semester = 2
658        self.course2.credits = 10
659        self.course2.passmark = 40
660        self.app['faculties']['fac1']['dep1'].courses.addCourse(
661            self.course2)
662        self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCertCourse(
663            self.course2, level=100)
664        self.course3 = createObject('waeup.Course')
665        self.course3.code = 'COURSE3'
666        self.course3.semester = 3
667        self.course3.credits = 10
668        self.course3.passmark = 40
669        self.app['faculties']['fac1']['dep1'].courses.addCourse(
670            self.course3)
671        self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCertCourse(
672            self.course3, level=100)
673
674        # Login as student
675        self.browser.open(self.login_path)
676        IWorkflowState(self.student).setState('school fee paid')
677        self.browser.open(self.login_path)
678        self.browser.getControl(name="form.login").value = self.student_id
679        self.browser.getControl(name="form.password").value = 'spwd'
680        self.browser.getControl("Login").click()
681        # Students can add the current study level
682        self.browser.getLink("Study Course").click()
683        self.browser.getLink("Add course list").click()
684        self.assertMatches('...Add current level 100 (Year 1)...',
685                           self.browser.contents)
686        self.browser.getControl("Create course list now").click()
687        # Student has not paid second instalment, therefore a level
688        # with two course ticket was created (semester 1 and combined)
689        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 2)
690        self.browser.getLink("100").click()
691        self.browser.getLink("Edit course list").click()
692        self.browser.getControl("Add course ticket").click()
693        # Student can't add second semester course
694        self.assertTrue('<option value="COURSE1">' in self.browser.contents)
695        self.assertTrue('<option value="COURSE3">' in self.browser.contents)
696        self.assertFalse('<option value="COURSE2">' in self.browser.contents)
697
698        # Let's remove level and see what happens after 2nd instalment payment
699        del(self.student['studycourse']['100'])
700        payment2 = createObject('waeup.StudentOnlinePayment')
701        payment2.p_category = u'schoolfee_2'
702        payment2.p_session = self.student.current_session
703        self.student['payments']['anykey'] = payment2
704        self.browser.open(self.studycourse_path)
705        self.browser.getLink("Add course list").click()
706        self.browser.getControl("Create course list now").click()
707        # Still only 2 tickets have been created since payment ticket
708        # was not paid
709        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 2)
710        payment2.p_state = u'paid'
711        del(self.student['studycourse']['100'])
712        self.browser.open(self.studycourse_path)
713        self.browser.getLink("Add course list").click()
714        self.browser.getControl("Create course list now").click()
715        # Now 2nd semester course has been added
716        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 3)
717        # Student can add second semester course
718        self.browser.getLink("100").click()
719        self.browser.getLink("Edit course list").click()
720        self.browser.getControl("Add course ticket").click()
721        self.assertTrue('<option value="COURSE1">' in self.browser.contents)
722        self.assertTrue('<option value="COURSE2">' in self.browser.contents)
723        self.assertTrue('<option value="COURSE3">' in self.browser.contents)
724        return
725
726    def test_set_matric_number(self):
727        #payment = createObject('waeup.StudentOnlinePayment')
728        #payment.p_category = u'concessional'
729        #payment.p_id = u'anyid'
730        #payment.p_state = u'paid'
731        #self.student['payments']['anykey'] = payment
732        # Login as student
733        self.browser.open(self.login_path)
734        IWorkflowState(self.student).setState('school fee paid')
735        self.browser.open(self.login_path)
736        self.browser.getControl(name="form.login").value = self.student_id
737        self.browser.getControl(name="form.password").value = 'spwd'
738        self.browser.getControl("Login").click()
739        self.assertRaises(
740            LinkNotFoundError,
741            self.browser.getLink, 'Get Matriculation Number')
742        self.student.matric_number = None
743        site = grok.getSite()
744        site['configuration'].next_matric_integer = 1
745        self.student['studycourse'].certificate.study_mode = 'ug_pt'
746        self.browser.open(self.student_path)
747        self.assertRaises(
748            LinkNotFoundError,
749            self.browser.getLink, 'Download matriculation number slip')
750        self.browser.getLink("Get Matriculation Number").click()
751        self.assertTrue('Matriculation number PTP/fac1/dep1/04/00001 assigned.'
752            in self.browser.contents)
753        self.assertEqual(self.student.matric_number, 'PTP/fac1/dep1/04/00001')
754        self.assertRaises(
755            LinkNotFoundError,
756            self.browser.getLink, 'Get Matriculation Number')
757        # Setting matric number is logged.
758        logfile = os.path.join(
759            self.app['datacenter'].storage, 'logs', 'students.log')
760        logcontent = open(logfile).read()
761        self.assertTrue('E1000000 - waeup.aaue.students.browser.StudentGetMatricNumberPage - '
762                        'E1000000 - PTP/fac1/dep1/04/00001 assigned' in logcontent)
763        # Matric Number Slip can be downloaded
764        self.browser.getLink("Download matriculation number slip").click()
765        self.assertEqual(self.browser.headers['Status'], '200 Ok')
766        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
767        path = os.path.join(samples_dir(), 'matric_number_slip.pdf')
768        open(path, 'wb').write(self.browser.contents)
769        print "Sample PDF matric_number_slip.pdf written to %s" % path
770        return
771
772    def test_personal_data_slip(self):
773        # Login as student
774        self.browser.open(self.login_path)
775        IWorkflowState(self.student).setState('school fee paid')
776        self.browser.open(self.login_path)
777        self.browser.getControl(name="form.login").value = self.student_id
778        self.browser.getControl(name="form.password").value = 'spwd'
779        self.browser.getControl("Login").click()
780        self.browser.getLink("Personal Data").click()
781        self.assertRaises(
782            LinkNotFoundError,
783            self.browser.getLink, 'Download personal data slip')
784        self.student.father_name = u'Rudolf'
785        self.browser.open(self.personal_path)
786        self.browser.getLink("Download personal data slip").click()
787        self.assertEqual(self.browser.headers['Status'], '200 Ok')
788        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
789        path = os.path.join(samples_dir(), 'personal_data_slip.pdf')
790        open(path, 'wb').write(self.browser.contents)
791        print "Sample PDF personal_data_slip.pdf written to %s" % path
792        return
793
794    def test_student_course_registration(self):
795        IWorkflowState(self.student).setState('school fee paid')
796        self.browser.open(self.login_path)
797        self.browser.getControl(name="form.login").value = self.student_id
798        self.browser.getControl(name="form.password").value = 'spwd'
799        self.browser.getControl("Login").click()
800        # Now students can add the current study level
801        self.browser.getLink("Study Course").click()
802        self.browser.getLink("Add course list").click()
803        self.assertMatches('...Add current level 100 (Year 1)...',
804                           self.browser.contents)
805        self.browser.getControl("Create course list now").click()
806        # Students can't open the customized pdf course registration slip
807        self.browser.open(
808            self.student_path + '/studycourse/100/course_registration_slip.pdf')
809        self.assertTrue('Forbidden' in self.browser.contents)
810        # They can open slips from the previous session ...
811        self.student['studycourse'].current_level = 200
812        self.browser.open(self.student_path + '/studycourse/100')
813        self.browser.getLink("Download course registration slip").click()
814        self.assertEqual(self.browser.headers['Status'], '200 Ok')
815        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
816        # or if they have registered their course list
817        self.student['studycourse'].current_level = 200
818        IWorkflowState(self.student).setState('courses registered')
819        self.browser.open(self.student_path + '/studycourse/100')
820        self.browser.getLink("Download course registration slip").click()
821        self.assertEqual(self.browser.headers['Status'], '200 Ok')
822        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
823        path = os.path.join(samples_dir(), 'ft_course_registration_slip.pdf')
824        open(path, 'wb').write(self.browser.contents)
825        print "Sample PDF ft_course_registration_slip.pdf written to %s" % path
826
827        self.certificate.study_mode = 'ug_pt'
828        self.browser.open(self.student_path + '/studycourse/100')
829        self.browser.getLink("Download course registration slip").click()
830        self.assertEqual(self.browser.headers['Status'], '200 Ok')
831        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
832        path = os.path.join(samples_dir(), 'pt_course_registration_slip.pdf')
833        open(path, 'wb').write(self.browser.contents)
834        print "Sample PDF pt_course_registration_slip.pdf written to %s" % path
835
836        self.certificate.study_mode = 'special_pg_ft'
837        self.student.matric_number = u'AAU/SPS/FLW/LAW/15/PHD/09504'
838        self.browser.open(self.student_path + '/studycourse/100')
839        self.browser.getLink("Download course registration slip").click()
840        self.assertEqual(self.browser.headers['Status'], '200 Ok')
841        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
842        path = os.path.join(samples_dir(), 'pg_course_registration_slip.pdf')
843        open(path, 'wb').write(self.browser.contents)
844        print "Sample PDF pg_course_registration_slip.pdf written to %s" % path
845
846        # Students cant' view scores, cas and grades.
847        self.browser.open(self.student_path + '/studycourse/100')
848        self.assertFalse('Score' in self.browser.contents)
849        self.assertFalse('CA' in self.browser.contents)
850        self.assertFalse('Grade' in self.browser.contents)
851        self.browser.getLink("COURSE1").click()
852        self.browser.open(self.student_path + '/studycourse/100')
853        self.assertFalse('Score' in self.browser.contents)
854        self.assertFalse('CA' in self.browser.contents)
855        self.assertFalse('Grade' in self.browser.contents)
856
857    def test_student_2nd_semester_course_registration(self):
858        IWorkflowState(self.student).setState('school fee paid')
859        self.student['studycourse'].entry_session = 2015
860        self.course.semester = 2
861        self.browser.open(self.login_path)
862        self.browser.getControl(name="form.login").value = self.student_id
863        self.browser.getControl(name="form.password").value = 'spwd'
864        self.browser.getControl("Login").click()
865        self.browser.getLink("Study Course").click()
866        self.browser.getLink("Add course list").click()
867        self.browser.getControl("Create course list now").click()
868        self.assertFalse('COURSE1' in self.browser.contents)
869        # 2nd semester tickets can't be added manually
870        self.browser.getLink("Edit course list").click()
871        self.browser.getLink("here").click()
872        self.browser.getControl(name="form.course").value = ['COURSE1']
873        self.browser.getControl("Add course ticket").click()
874        self.assertTrue(
875            'COURSE1 is a 2nd semester course which can only '
876            'be added if school fees have been fully paid.'
877            in self.browser.contents)
878        # 2nd instalment has to be paid first
879        self.certificate.school_fee_3 = 678.0
880        self.browser.open(self.payments_path + '/addop')
881        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
882        self.browser.getControl("Create ticket").click()
883        self.student['payments'].values()[0].approve()
884        self.browser.open(self.studycourse_path + '/100/ctadd')
885        self.browser.getControl(name="form.course").value = ['COURSE1']
886        self.browser.getControl("Add course ticket").click()
887        self.assertTrue('Successfully added COURSE1' in self.browser.contents)
888        return
889
890    def test_student_GST_registration(self):
891        configuration_1 = createObject('waeup.SessionConfiguration')
892        configuration_1.academic_session = 2016
893        configuration_1.gst_registration_1_fee = 3333.0
894        configuration_1.gst_text_book_1_fee = 4444.0
895        configuration_1.gst_text_book_0_fee = 2222.0
896        self.app['configuration'].addSessionConfiguration(configuration_1)
897        course = createObject('waeup.Course')
898        course.code = 'GST101'
899        course.semester = 1
900        course.credits = 10
901        course.passmark = 40
902        self.app['faculties']['fac1']['dep1'].courses.addCourse(
903            course)
904        self.app['faculties']['fac1']['dep1'].certificates[
905            'CERT1'].addCertCourse(course, level=100)
906        IWorkflowState(self.student).setState('school fee paid')
907        self.student['studycourse'].entry_session = 2016
908        self.student['studycourse'].current_session = 2016
909        self.course.semester = 2
910        self.browser.open(self.login_path)
911        self.browser.getControl(name="form.login").value = self.student_id
912        self.browser.getControl(name="form.password").value = 'spwd'
913        self.browser.getControl("Login").click()
914        self.browser.getLink("Study Course").click()
915        self.browser.getLink("Add course list").click()
916        self.browser.getControl("Create course list now").click()
917        self.assertFalse('GST101' in self.browser.contents)
918        # GST101 tickets can't be added manually
919        self.browser.getLink("Edit course list").click()
920        self.browser.getLink("here").click()
921        self.browser.getControl(name="form.course").value = ['GST101']
922        self.browser.getControl("Add course ticket").click()
923        self.assertTrue(
924            'GST101 can only be added if both registration fee and text'
925            in self.browser.contents)
926        # GST fees have to be paid first
927        self.browser.open(self.payments_path + '/addop')
928        self.browser.getControl(name="form.p_category").value = ['gst_registration_1']
929        self.browser.getControl("Create ticket").click()
930        self.student['payments'].values()[0].approve()
931        self.browser.open(self.studycourse_path + '/100/ctadd')
932        self.browser.getControl(name="form.course").value = ['GST101']
933        self.browser.getControl("Add course ticket").click()
934        self.assertTrue(
935            'GST101 can only be added if both registration fee and text'
936            in self.browser.contents)
937        self.browser.open(self.payments_path + '/addop')
938        self.browser.getControl(name="form.p_category").value = ['gst_text_book_0']
939        self.browser.getControl("Create ticket").click()
940        self.student['payments'].values()[1].approve()
941        self.browser.open(self.studycourse_path + '/100/ctadd')
942        self.browser.getControl(name="form.course").value = ['GST101']
943        self.browser.getControl("Add course ticket").click()
944        self.assertTrue('Successfully added GST101' in self.browser.contents)
945        return
946
947    def test_course_registration_forbidden(self):
948        IWorkflowState(self.student).setState('school fee paid')
949        self.student['studycourse'].entry_session = 2016
950        self.student['studycourse'].current_session = 2016
951        self.browser.open(self.login_path)
952        self.browser.getControl(name="form.login").value = self.student_id
953        self.browser.getControl(name="form.password").value = 'spwd'
954        self.browser.getControl("Login").click()
955        self.browser.getLink("Study Course").click()
956        self.browser.getLink("Add course list").click()
957        self.browser.getControl("Create course list now").click()
958        self.browser.getLink("Edit course list").click()
959        self.browser.getControl("Register course list").click()
960        #self.assertTrue('Please pay faculty and departmental dues first'
961        #    in self.browser.contents)
962        #configuration_1 = createObject('waeup.SessionConfiguration')
963        #configuration_1.academic_session = 2016
964        #configuration_1.fac_dep_fee = 9999.0
965        #self.app['configuration'].addSessionConfiguration(configuration_1)
966        #self.browser.open(self.payments_path + '/addop')
967        #self.browser.getControl(name="form.p_category").value = ['fac_dep']
968        #self.browser.getControl("Create ticket").click()
969        #self.student['payments'].values()[0].approveStudentPayment()
970        #self.browser.open(self.studycourse_path + '/100/edit')
971        #self.browser.getControl("Register course list").click()
972
973        ######################################################
974        # Temporarily disabled ug_ft course registration
975        self.assertTrue('Please check back later'
976            in self.browser.contents)
977        return
978        ######################################################
979
980        self.assertTrue('Course list has been registered'
981            in self.browser.contents)
982        return
983
984    def test_course_registration_forbidden_2(self):
985        IWorkflowState(self.student).setState('school fee paid')
986        self.student['studycourse'].entry_session = 2004
987        self.student['studycourse'].current_session = 2004
988        self.browser.open(self.login_path)
989        self.browser.getControl(name="form.login").value = self.student_id
990        self.browser.getControl(name="form.password").value = 'spwd'
991        self.browser.getControl("Login").click()
992        self.browser.getLink("Study Course").click()
993        self.browser.getLink("Add course list").click()
994        self.browser.getControl("Create course list now").click()
995        self.browser.getLink("Edit course list").click()
996        self.browser.getControl("Register course list").click()
997
998        ######################################################
999        # Temporarily disabled ug_ft course registration
1000        self.assertTrue('Please check back later'
1001            in self.browser.contents)
1002        return
1003        ######################################################
1004
1005        self.assertTrue('Please pay restitution fee first'
1006            in self.browser.contents)
1007        self.app['configuration']['2004'].restitution_fee = 9999.0
1008        self.browser.open(self.payments_path + '/addop')
1009        self.browser.getControl(name="form.p_category").value = ['restitution']
1010        self.browser.getControl("Create ticket").click()
1011        self.student['payments'].values()[0].approveStudentPayment()
1012        self.browser.open(self.studycourse_path + '/100/edit')
1013        self.browser.getControl("Register course list").click()
1014        self.assertTrue('Course list has been registered'
1015            in self.browser.contents)
1016        return
1017
1018    def test_student_clearance(self):
1019        # Student cant login if their password is not set
1020        IWorkflowInfo(self.student).fireTransition('admit')
1021        self.browser.open(self.login_path)
1022        self.browser.getControl(name="form.login").value = self.student_id
1023        self.browser.getControl(name="form.password").value = 'spwd'
1024        self.browser.getControl("Login").click()
1025        self.assertMatches(
1026            '...You logged in...', self.browser.contents)
1027        # Admitted student can upload a passport picture
1028        self.browser.open(self.student_path + '/change_portrait')
1029        ctrl = self.browser.getControl(name='passportuploadedit')
1030        file_obj = open(SAMPLE_IMAGE, 'rb')
1031        file_ctrl = ctrl.mech_control
1032        file_ctrl.add_file(file_obj, filename='my_photo.jpg')
1033        self.browser.getControl(
1034            name='upload_passportuploadedit').click()
1035        self.assertTrue(
1036            'src="http://localhost/app/students/E1000000/passport.jpg"'
1037            in self.browser.contents)
1038        # Student is redirected to the personal data form because
1039        # personal data form is not properly filled.
1040        self.browser.open(self.student_path + '/start_clearance')
1041        self.assertMatches('...Personal data form is not properly filled...',
1042                           self.browser.contents)
1043        self.assertEqual(self.browser.url, self.student_path + '/edit_personal')
1044        self.student.father_name = u'Rudolf'
1045        self.browser.open(self.student_path + '/start_clearance')
1046        self.assertMatches(
1047            '...<h1 class="kofa-content-label">Start clearance</h1>...',
1048            self.browser.contents)
1049
1050    def test_student_accommodation(self):
1051        del self.student['accommodation']['2004']
1052        self.student['studycourse'].certificate.study_mode = 'dp_ft'
1053        # All beds can be assigned
1054        bed1 = self.app['hostels']['hall-1']['hall-1_A_101_A']
1055        bed1.bed_type = u'regular_male_all'
1056        bed2 = self.app['hostels']['hall-1']['hall-1_A_101_B']
1057        bed2.bed_type = u'regular_female_all'
1058        notify(grok.ObjectModifiedEvent(bed1))
1059        notify(grok.ObjectModifiedEvent(bed2))
1060        # Login
1061        self.browser.open(self.login_path)
1062        self.browser.getControl(name="form.login").value = self.student_id
1063        self.browser.getControl(name="form.password").value = 'spwd'
1064        self.browser.getControl("Login").click()
1065        # Students can book accommodation without AC ...
1066        self.browser.open(self.acco_path)
1067        IWorkflowInfo(self.student).fireTransition('admit')
1068        self.browser.getControl("Book accommodation").click()
1069        self.assertTrue(
1070            'You are not eligible to book accommodation.'
1071            in self.browser.contents)
1072        self.student['studycourse'].certificate.study_mode = 'ug_ft'
1073        self.app['hostels'].accommodation_states = [PAID]
1074        self.browser.getControl("Book accommodation").click()
1075        self.assertTrue(
1076            'You are in the wrong registration state.'
1077            in self.browser.contents)
1078        IWorkflowState(self.student).setState(PAID)
1079        self.browser.getControl("Book accommodation").click()
1080        self.assertFalse('Activation Code:' in self.browser.contents)
1081        self.browser.getControl("Create bed ticket").click()
1082        # Bed is randomly selected but, since there is only
1083        # one bed for this student, we know that
1084        self.assertEqual(self.student['accommodation']['2004'].bed_coordinates,
1085            'Hall 1, Block A, Room 101, Bed A (regular_male_all)')
1086        # Only the hall name is displayed
1087        self.assertEqual(self.student[
1088            'accommodation']['2004'].display_coordinates,
1089            'Hall 1')
1090        self.assertFalse('Hall 1, Block A, Room 101, Bed A'
1091            in self.browser.contents)
1092        self.assertTrue('<td>Hall 1</td>'
1093            in self.browser.contents)
1094        return
1095
1096    def test_handle_courses_by_lecturer(self):
1097        self.app['users'].addUser('mrslecturer', 'mrslecturersecret')
1098        self.app['users']['mrslecturer'].email = 'mrslecturer@foo.ng'
1099        self.app['users']['mrslecturer'].title = u'Mercedes Benz'
1100        # Add course ticket
1101        studylevel = createObject(u'waeup.StudentStudyLevel')
1102        studylevel.level = 100
1103        studylevel.level_session = 2004
1104        self.student['studycourse'].addStudentStudyLevel(
1105            self.certificate, studylevel)
1106        # Assign local Lecturer role for a certificate.
1107        course = self.app['faculties']['fac1']['dep1'].courses['COURSE1']
1108        prmlocal = IPrincipalRoleManager(course)
1109        prmlocal.assignRoleToPrincipal('waeup.local.Lecturer', 'mrslecturer')
1110        notify(LocalRoleSetEvent(
1111            course, 'waeup.local.Lecturer', 'mrslecturer', granted=True))
1112        # Login as lecturer.
1113        self.browser.open(self.login_path)
1114        self.browser.getControl(name="form.login").value = 'mrslecturer'
1115        self.browser.getControl(name="form.password").value = 'mrslecturersecret'
1116        self.browser.getControl("Login").click()
1117        self.browser.getLink("My Courses").click()
1118        self.browser.getLink("COURSE1").click()
1119        # Course results can be batch edited via the edit_courses view.
1120        self.app['faculties']['fac1']['dep1'].score_editing_disabled = False
1121        self.app['configuration'].current_academic_session = 2004
1122        IWorkflowState(self.student).setState('courses validated')
1123        self.browser.open(
1124            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1/edit_scores")
1125        self.assertTrue(
1126            'input type="text" name="scores:list"'
1127            in self.browser.contents)
1128        self.browser.getControl(name="scores:list", index=0).value = '55'
1129        self.browser.getControl(name="cas:list", index=0).value = '22'
1130        self.browser.getControl("Update scores from").click()
1131        # New score and ca has been set.
1132        self.assertEqual(
1133            self.student['studycourse']['100']['COURSE1'].score, 55)
1134        self.assertEqual(
1135            self.student['studycourse']['100']['COURSE1'].ca, 22)
1136        # Score editing has been logged.
1137        logfile = os.path.join(
1138            self.app['datacenter'].storage, 'logs', 'students.log')
1139        logcontent = open(logfile).read()
1140        self.assertTrue('mrslecturer - waeup.aaue.students.browser.CustomEditScoresPage - '
1141                        'E1000000 100/COURSE1 score updated (55)' in logcontent)
1142        self.assertTrue('mrslecturer - waeup.aaue.students.browser.CustomEditScoresPage - '
1143                        'E1000000 100/COURSE1 ca updated (22)' in logcontent)
1144        # Non-integer scores won't be accepted.
1145        self.browser.open(
1146            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1/edit_scores")
1147        self.assertTrue('value="55" />' in self.browser.contents)
1148        self.browser.getControl(name="scores:list", index=0).value = 'abc'
1149        self.browser.getControl("Update scores").click()
1150        self.assertTrue('Error: Score(s) and CA(s) of TESTER, Anna have not be updated.'
1151            in self.browser.contents)
1152        # Scores can be removed.
1153        self.browser.open(
1154            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1/edit_scores")
1155        self.browser.getControl(name="scores:list", index=0).value = ''
1156        self.browser.getControl("Update scores").click()
1157        self.assertEqual(
1158            self.student['studycourse']['100']['COURSE1'].score, None)
1159        logcontent = open(logfile).read()
1160        self.assertTrue('mrslecturer - waeup.aaue.students.browser.CustomEditScoresPage - '
1161                        'E1000000 100/COURSE1 score updated (None)' in logcontent)
1162
1163
1164    def disabled_test_student_view_transcript(self):
1165        # Student cant login if their password is not set
1166        IWorkflowInfo(self.student).fireTransition('admit')
1167        self.browser.open(self.login_path)
1168        self.browser.getControl(name="form.login").value = self.student_id
1169        self.browser.getControl(name="form.password").value = 'spwd'
1170        self.browser.getControl("Login").click()
1171        self.assertMatches(
1172            '...You logged in...', self.browser.contents)
1173        # Students can view the transcript
1174        self.browser.open(self.studycourse_path)
1175        self.browser.getLink("Transcript").click()
1176        self.browser.getLink("Academic Transcript").click()
1177        self.assertEqual(self.browser.headers['Status'], '200 Ok')
1178        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
1179
1180    def test_alumni_request_pw(self):
1181        # Add an applicants container
1182        applicantscontainer = ApplicantsContainer()
1183        applicantscontainer.code = u'trans2017'
1184        applicantscontainer.prefix = 'trans'
1185        applicantscontainer.year = 2017
1186        applicantscontainer.title = u'This is the trans2017 container'
1187        applicantscontainer.application_category = 'no'
1188        applicantscontainer.mode = 'create'
1189        applicantscontainer.strict_deadline = True
1190        delta = timedelta(days=10)
1191        applicantscontainer.startdate = datetime.now(pytz.utc) - delta
1192        applicantscontainer.enddate = datetime.now(pytz.utc) + delta
1193        self.app['applicants']['trans2017'] = applicantscontainer
1194        self.applicantscontainer = self.app['applicants']['trans2017']
1195        # Student with wrong number can't be found.
1196        # Applicant is redirected to application section.
1197        self.browser.open('http://localhost/app/alumni_requestpw')
1198        self.browser.getControl(name="form.lastname").value = 'Tester'
1199        self.browser.getControl(name="form.number").value = 'anynumber'
1200        self.browser.getControl(name="form.email").value = 'xx@yy.zz'
1201        self.browser.getControl("Send login credentials").click()
1202        self.assertTrue('No student record found.'
1203            in self.browser.contents)
1204        self.assertEqual(self.browser.url,
1205            'http://localhost/app/applicants/trans2017/register')
1206
1207    def test_student_course_registration_outstanding(self):
1208        self.course = createObject('waeup.Course')
1209        self.course.code = 'COURSE2'
1210        self.course.semester = 1
1211        self.course.credits = 39
1212        self.course.passmark = 40
1213        self.app['faculties']['fac1']['dep1'].courses.addCourse(
1214            self.course)
1215        IWorkflowState(self.student).setState('school fee paid')
1216        self.browser.open(self.login_path)
1217        self.browser.getControl(name="form.login").value = self.student_id
1218        self.browser.getControl(name="form.password").value = 'spwd'
1219        self.browser.getControl("Login").click()
1220        self.browser.open(self.student_path + '/studycourse/add')
1221        self.browser.getControl("Create course list now").click()
1222        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 1)
1223        self.student['studycourse'].current_level = 200
1224        self.browser.getLink("Study Course").click()
1225        self.browser.getLink("Add course list").click()
1226        self.assertMatches('...Add current level 200 (Year 2)...',
1227                           self.browser.contents)
1228        self.browser.getControl("Create course list now").click()
1229        self.browser.getLink("200").click()
1230        self.browser.getLink("Edit course list").click()
1231        self.browser.getLink("here").click()
1232        self.browser.getControl(name="form.course").value = ['COURSE2']
1233        self.browser.getControl("Add course ticket").click()
1234        # Carryover COURSE1 in level 200 already has 10 credits
1235        self.assertMatches(
1236            '...Maximum credits exceeded...', self.browser.contents)
1237        # If COURSE1 is outstanding, its credits won't be considered
1238        self.student['studycourse']['200']['COURSE1'].outstanding = True
1239        self.browser.getControl("Add course ticket").click()
1240        self.assertMatches(
1241            '...Successfully added COURSE2...', self.browser.contents)
1242        return
Note: See TracBrowser for help on using the repository browser.