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

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

Implement ExportExaminationScheduleSlip?.

  • Property svn:keywords set to Id
File size: 65.0 KB
Line 
1## $Id: test_browser.py 14661 2017-03-30 07:51:15Z 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        self.assertTrue('Course registration has ended. Please pay' in self.browser.contents)
637        self.student['payments'].values()[1].approve()
638        self.browser.getControl("Register course list").click()
639        self.assertTrue('Course list has been registered' in self.browser.contents)
640        self.assertEqual(self.student.state, 'courses registered')
641        # Reset student and check if fresh students are always allowed to
642        # register courses.
643        self.student['studycourse'].entry_session = 2004
644        del self.student['payments'][self.student['payments'].keys()[1]]
645        IWorkflowState(self.student).setState('school fee paid')
646        self.browser.open(self.studycourse_path + '/100/edit')
647        self.browser.getControl("Register course list").click()
648        self.assertTrue('Course list has been registered' in self.browser.contents)
649        return
650
651
652    def deactivated_test_student_course_registration(self):
653        # Add more courses
654        self.course2 = createObject('waeup.Course')
655        self.course2.code = 'COURSE2'
656        self.course2.semester = 2
657        self.course2.credits = 10
658        self.course2.passmark = 40
659        self.app['faculties']['fac1']['dep1'].courses.addCourse(
660            self.course2)
661        self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCertCourse(
662            self.course2, level=100)
663        self.course3 = createObject('waeup.Course')
664        self.course3.code = 'COURSE3'
665        self.course3.semester = 3
666        self.course3.credits = 10
667        self.course3.passmark = 40
668        self.app['faculties']['fac1']['dep1'].courses.addCourse(
669            self.course3)
670        self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCertCourse(
671            self.course3, level=100)
672
673        # Login as student
674        self.browser.open(self.login_path)
675        IWorkflowState(self.student).setState('school fee paid')
676        self.browser.open(self.login_path)
677        self.browser.getControl(name="form.login").value = self.student_id
678        self.browser.getControl(name="form.password").value = 'spwd'
679        self.browser.getControl("Login").click()
680        # Students can add the current study level
681        self.browser.getLink("Study Course").click()
682        self.browser.getLink("Add course list").click()
683        self.assertMatches('...Add current level 100 (Year 1)...',
684                           self.browser.contents)
685        self.browser.getControl("Create course list now").click()
686        # Student has not paid second instalment, therefore a level
687        # with two course ticket was created (semester 1 and combined)
688        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 2)
689        self.browser.getLink("100").click()
690        self.browser.getLink("Edit course list").click()
691        self.browser.getControl("Add course ticket").click()
692        # Student can't add second semester course
693        self.assertTrue('<option value="COURSE1">' in self.browser.contents)
694        self.assertTrue('<option value="COURSE3">' in self.browser.contents)
695        self.assertFalse('<option value="COURSE2">' in self.browser.contents)
696
697        # Let's remove level and see what happens after 2nd instalment payment
698        del(self.student['studycourse']['100'])
699        payment2 = createObject('waeup.StudentOnlinePayment')
700        payment2.p_category = u'schoolfee_2'
701        payment2.p_session = self.student.current_session
702        self.student['payments']['anykey'] = payment2
703        self.browser.open(self.studycourse_path)
704        self.browser.getLink("Add course list").click()
705        self.browser.getControl("Create course list now").click()
706        # Still only 2 tickets have been created since payment ticket
707        # was not paid
708        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 2)
709        payment2.p_state = u'paid'
710        del(self.student['studycourse']['100'])
711        self.browser.open(self.studycourse_path)
712        self.browser.getLink("Add course list").click()
713        self.browser.getControl("Create course list now").click()
714        # Now 2nd semester course has been added
715        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 3)
716        # Student can add second semester course
717        self.browser.getLink("100").click()
718        self.browser.getLink("Edit course list").click()
719        self.browser.getControl("Add course ticket").click()
720        self.assertTrue('<option value="COURSE1">' in self.browser.contents)
721        self.assertTrue('<option value="COURSE2">' in self.browser.contents)
722        self.assertTrue('<option value="COURSE3">' in self.browser.contents)
723        return
724
725    def test_set_matric_number(self):
726        #payment = createObject('waeup.StudentOnlinePayment')
727        #payment.p_category = u'concessional'
728        #payment.p_id = u'anyid'
729        #payment.p_state = u'paid'
730        #self.student['payments']['anykey'] = payment
731        # Login as student
732        self.browser.open(self.login_path)
733        IWorkflowState(self.student).setState('school fee paid')
734        self.browser.open(self.login_path)
735        self.browser.getControl(name="form.login").value = self.student_id
736        self.browser.getControl(name="form.password").value = 'spwd'
737        self.browser.getControl("Login").click()
738        self.assertRaises(
739            LinkNotFoundError,
740            self.browser.getLink, 'Get Matriculation Number')
741        self.student.matric_number = None
742        site = grok.getSite()
743        site['configuration'].next_matric_integer = 1
744        self.student['studycourse'].certificate.study_mode = 'ug_pt'
745        self.browser.open(self.student_path)
746        self.assertRaises(
747            LinkNotFoundError,
748            self.browser.getLink, 'Download matriculation number slip')
749        self.browser.getLink("Get Matriculation Number").click()
750        self.assertTrue('Matriculation number PTP/fac1/dep1/04/00001 assigned.'
751            in self.browser.contents)
752        self.assertEqual(self.student.matric_number, 'PTP/fac1/dep1/04/00001')
753        self.assertRaises(
754            LinkNotFoundError,
755            self.browser.getLink, 'Get Matriculation Number')
756        # Setting matric number is logged.
757        logfile = os.path.join(
758            self.app['datacenter'].storage, 'logs', 'students.log')
759        logcontent = open(logfile).read()
760        self.assertTrue('E1000000 - waeup.aaue.students.browser.StudentGetMatricNumberPage - '
761                        'E1000000 - PTP/fac1/dep1/04/00001 assigned' in logcontent)
762        # Matric Number Slip can be downloaded
763        self.browser.getLink("Download matriculation number slip").click()
764        self.assertEqual(self.browser.headers['Status'], '200 Ok')
765        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
766        path = os.path.join(samples_dir(), 'matric_number_slip.pdf')
767        open(path, 'wb').write(self.browser.contents)
768        print "Sample PDF matric_number_slip.pdf written to %s" % path
769        return
770
771    def test_personal_data_slip(self):
772        # Login as student
773        self.browser.open(self.login_path)
774        IWorkflowState(self.student).setState('school fee paid')
775        self.browser.open(self.login_path)
776        self.browser.getControl(name="form.login").value = self.student_id
777        self.browser.getControl(name="form.password").value = 'spwd'
778        self.browser.getControl("Login").click()
779        self.browser.getLink("Personal Data").click()
780        self.assertRaises(
781            LinkNotFoundError,
782            self.browser.getLink, 'Download personal data slip')
783        self.student.father_name = u'Rudolf'
784        self.browser.open(self.personal_path)
785        self.browser.getLink("Download personal data slip").click()
786        self.assertEqual(self.browser.headers['Status'], '200 Ok')
787        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
788        path = os.path.join(samples_dir(), 'personal_data_slip.pdf')
789        open(path, 'wb').write(self.browser.contents)
790        print "Sample PDF personal_data_slip.pdf written to %s" % path
791        return
792
793    def test_student_course_registration(self):
794        IWorkflowState(self.student).setState('school fee paid')
795        self.browser.open(self.login_path)
796        self.browser.getControl(name="form.login").value = self.student_id
797        self.browser.getControl(name="form.password").value = 'spwd'
798        self.browser.getControl("Login").click()
799        # Now students can add the current study level
800        self.browser.getLink("Study Course").click()
801        self.browser.getLink("Add course list").click()
802        self.assertMatches('...Add current level 100 (Year 1)...',
803                           self.browser.contents)
804        self.browser.getControl("Create course list now").click()
805        # Students can't open the customized pdf course registration slip
806        self.browser.open(
807            self.student_path + '/studycourse/100/course_registration_slip.pdf')
808        self.assertTrue('Forbidden' in self.browser.contents)
809        # They can open slips from the previous session ...
810        self.student['studycourse'].current_level = 200
811        self.browser.open(self.student_path + '/studycourse/100')
812        self.browser.getLink("Download course registration slip").click()
813        self.assertEqual(self.browser.headers['Status'], '200 Ok')
814        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
815        # or if they have registered their course list
816        self.student['studycourse'].current_level = 200
817        IWorkflowState(self.student).setState('courses registered')
818        self.browser.open(self.student_path + '/studycourse/100')
819        self.browser.getLink("Download course registration slip").click()
820        self.assertEqual(self.browser.headers['Status'], '200 Ok')
821        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
822        path = os.path.join(samples_dir(), 'ft_course_registration_slip.pdf')
823        open(path, 'wb').write(self.browser.contents)
824        print "Sample PDF ft_course_registration_slip.pdf written to %s" % path
825
826        self.certificate.study_mode = 'ug_pt'
827        self.browser.open(self.student_path + '/studycourse/100')
828        self.browser.getLink("Download course registration slip").click()
829        self.assertEqual(self.browser.headers['Status'], '200 Ok')
830        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
831        path = os.path.join(samples_dir(), 'pt_course_registration_slip.pdf')
832        open(path, 'wb').write(self.browser.contents)
833        print "Sample PDF pt_course_registration_slip.pdf written to %s" % path
834
835        self.certificate.study_mode = 'special_pg_ft'
836        self.student.matric_number = u'AAU/SPS/FLW/LAW/15/PHD/09504'
837        self.browser.open(self.student_path + '/studycourse/100')
838        self.browser.getLink("Download course registration slip").click()
839        self.assertEqual(self.browser.headers['Status'], '200 Ok')
840        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
841        path = os.path.join(samples_dir(), 'pg_course_registration_slip.pdf')
842        open(path, 'wb').write(self.browser.contents)
843        print "Sample PDF pg_course_registration_slip.pdf written to %s" % path
844
845        # Students cant' view scores, cas and grades.
846        self.browser.open(self.student_path + '/studycourse/100')
847        self.assertFalse('Score' in self.browser.contents)
848        self.assertFalse('CA' in self.browser.contents)
849        self.assertFalse('Grade' in self.browser.contents)
850        self.browser.getLink("COURSE1").click()
851        self.browser.open(self.student_path + '/studycourse/100')
852        self.assertFalse('Score' in self.browser.contents)
853        self.assertFalse('CA' in self.browser.contents)
854        self.assertFalse('Grade' in self.browser.contents)
855
856    def test_student_2nd_semester_course_registration(self):
857        IWorkflowState(self.student).setState('school fee paid')
858        self.student['studycourse'].entry_session = 2015
859        self.course.semester = 2
860        self.browser.open(self.login_path)
861        self.browser.getControl(name="form.login").value = self.student_id
862        self.browser.getControl(name="form.password").value = 'spwd'
863        self.browser.getControl("Login").click()
864        self.browser.getLink("Study Course").click()
865        self.browser.getLink("Add course list").click()
866        self.browser.getControl("Create course list now").click()
867        self.assertFalse('COURSE1' in self.browser.contents)
868        # 2nd semester tickets can't be added manually
869        self.browser.getLink("Edit course list").click()
870        self.browser.getLink("here").click()
871        self.browser.getControl(name="form.course").value = ['COURSE1']
872        self.browser.getControl("Add course ticket").click()
873        self.assertTrue(
874            'COURSE1 is a 2nd semester course which can only '
875            'be added if school fees have been fully paid.'
876            in self.browser.contents)
877        # 2nd instalment has to be paid first
878        self.certificate.school_fee_3 = 678.0
879        self.browser.open(self.payments_path + '/addop')
880        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
881        self.browser.getControl("Create ticket").click()
882        self.student['payments'].values()[0].approve()
883        self.browser.open(self.studycourse_path + '/100/ctadd')
884        self.browser.getControl(name="form.course").value = ['COURSE1']
885        self.browser.getControl("Add course ticket").click()
886        self.assertTrue('Successfully added COURSE1' in self.browser.contents)
887        return
888
889    def test_student_GST_registration(self):
890        configuration_1 = createObject('waeup.SessionConfiguration')
891        configuration_1.academic_session = 2016
892        configuration_1.gst_registration_1_fee = 3333.0
893        configuration_1.gst_text_book_1_fee = 4444.0
894        configuration_1.gst_text_book_0_fee = 2222.0
895        self.app['configuration'].addSessionConfiguration(configuration_1)
896        course = createObject('waeup.Course')
897        course.code = 'GST101'
898        course.semester = 1
899        course.credits = 10
900        course.passmark = 40
901        self.app['faculties']['fac1']['dep1'].courses.addCourse(
902            course)
903        self.app['faculties']['fac1']['dep1'].certificates[
904            'CERT1'].addCertCourse(course, level=100)
905        IWorkflowState(self.student).setState('school fee paid')
906        self.student['studycourse'].entry_session = 2016
907        self.student['studycourse'].current_session = 2016
908        self.course.semester = 2
909        self.browser.open(self.login_path)
910        self.browser.getControl(name="form.login").value = self.student_id
911        self.browser.getControl(name="form.password").value = 'spwd'
912        self.browser.getControl("Login").click()
913        self.browser.getLink("Study Course").click()
914        self.browser.getLink("Add course list").click()
915        self.browser.getControl("Create course list now").click()
916        self.assertFalse('GST101' in self.browser.contents)
917        # GST101 tickets can't be added manually
918        self.browser.getLink("Edit course list").click()
919        self.browser.getLink("here").click()
920        self.browser.getControl(name="form.course").value = ['GST101']
921        self.browser.getControl("Add course ticket").click()
922        self.assertTrue(
923            'GST101 can only be added if both registration fee and text'
924            in self.browser.contents)
925        # GST fees have to be paid first
926        self.browser.open(self.payments_path + '/addop')
927        self.browser.getControl(name="form.p_category").value = ['gst_registration_1']
928        self.browser.getControl("Create ticket").click()
929        self.student['payments'].values()[0].approve()
930        self.browser.open(self.studycourse_path + '/100/ctadd')
931        self.browser.getControl(name="form.course").value = ['GST101']
932        self.browser.getControl("Add course ticket").click()
933        self.assertTrue(
934            'GST101 can only be added if both registration fee and text'
935            in self.browser.contents)
936        self.browser.open(self.payments_path + '/addop')
937        self.browser.getControl(name="form.p_category").value = ['gst_text_book_0']
938        self.browser.getControl("Create ticket").click()
939        self.student['payments'].values()[1].approve()
940        self.browser.open(self.studycourse_path + '/100/ctadd')
941        self.browser.getControl(name="form.course").value = ['GST101']
942        self.browser.getControl("Add course ticket").click()
943        self.assertTrue('Successfully added GST101' in self.browser.contents)
944        return
945
946    def test_course_registration_forbidden(self):
947        IWorkflowState(self.student).setState('school fee paid')
948        self.student['studycourse'].entry_session = 2016
949        self.student['studycourse'].current_session = 2016
950        self.browser.open(self.login_path)
951        self.browser.getControl(name="form.login").value = self.student_id
952        self.browser.getControl(name="form.password").value = 'spwd'
953        self.browser.getControl("Login").click()
954        self.browser.getLink("Study Course").click()
955        self.browser.getLink("Add course list").click()
956        self.browser.getControl("Create course list now").click()
957        self.browser.getLink("Edit course list").click()
958        self.browser.getControl("Register course list").click()
959        #self.assertTrue('Please pay faculty and departmental dues first'
960        #    in self.browser.contents)
961        #configuration_1 = createObject('waeup.SessionConfiguration')
962        #configuration_1.academic_session = 2016
963        #configuration_1.fac_dep_fee = 9999.0
964        #self.app['configuration'].addSessionConfiguration(configuration_1)
965        #self.browser.open(self.payments_path + '/addop')
966        #self.browser.getControl(name="form.p_category").value = ['fac_dep']
967        #self.browser.getControl("Create ticket").click()
968        #self.student['payments'].values()[0].approveStudentPayment()
969        #self.browser.open(self.studycourse_path + '/100/edit')
970        #self.browser.getControl("Register course list").click()
971
972        ######################################################
973        # Temporarily disabled ug_ft course registration
974        #self.assertTrue('Please check back later'
975        #    in self.browser.contents)
976        #return
977        ######################################################
978
979        self.assertTrue('Course list has been registered'
980            in self.browser.contents)
981        return
982
983    def test_course_registration_forbidden_2(self):
984        IWorkflowState(self.student).setState('school fee paid')
985        self.student['studycourse'].entry_session = 2004
986        self.student['studycourse'].current_session = 2004
987        self.browser.open(self.login_path)
988        self.browser.getControl(name="form.login").value = self.student_id
989        self.browser.getControl(name="form.password").value = 'spwd'
990        self.browser.getControl("Login").click()
991        self.browser.getLink("Study Course").click()
992        self.browser.getLink("Add course list").click()
993        self.browser.getControl("Create course list now").click()
994        self.browser.getLink("Edit course list").click()
995        self.browser.getControl("Register course list").click()
996
997        ######################################################
998        # Temporarily disabled ug_ft course registration
999        #self.assertTrue('Please check back later'
1000        #    in self.browser.contents)
1001        #return
1002        ######################################################
1003
1004        self.assertTrue('Please pay restitution fee first'
1005            in self.browser.contents)
1006        self.app['configuration']['2004'].restitution_fee = 9999.0
1007        self.browser.open(self.payments_path + '/addop')
1008        self.browser.getControl(name="form.p_category").value = ['restitution']
1009        self.browser.getControl("Create ticket").click()
1010        self.student['payments'].values()[0].approveStudentPayment()
1011        self.browser.open(self.studycourse_path + '/100/edit')
1012        self.browser.getControl("Register course list").click()
1013        self.assertTrue('Course list has been registered'
1014            in self.browser.contents)
1015        return
1016
1017    def test_student_clearance(self):
1018        # Student cant login if their password is not set
1019        IWorkflowInfo(self.student).fireTransition('admit')
1020        self.browser.open(self.login_path)
1021        self.browser.getControl(name="form.login").value = self.student_id
1022        self.browser.getControl(name="form.password").value = 'spwd'
1023        self.browser.getControl("Login").click()
1024        self.assertMatches(
1025            '...You logged in...', self.browser.contents)
1026        # Admitted student can upload a passport picture
1027        self.browser.open(self.student_path + '/change_portrait')
1028        ctrl = self.browser.getControl(name='passportuploadedit')
1029        file_obj = open(SAMPLE_IMAGE, 'rb')
1030        file_ctrl = ctrl.mech_control
1031        file_ctrl.add_file(file_obj, filename='my_photo.jpg')
1032        self.browser.getControl(
1033            name='upload_passportuploadedit').click()
1034        self.assertTrue(
1035            'src="http://localhost/app/students/E1000000/passport.jpg"'
1036            in self.browser.contents)
1037        # Student is redirected to the personal data form because
1038        # personal data form is not properly filled.
1039        self.browser.open(self.student_path + '/start_clearance')
1040        self.assertMatches('...Personal data form is not properly filled...',
1041                           self.browser.contents)
1042        self.assertEqual(self.browser.url, self.student_path + '/edit_personal')
1043        self.student.father_name = u'Rudolf'
1044        self.browser.open(self.student_path + '/start_clearance')
1045        self.assertMatches(
1046            '...<h1 class="kofa-content-label">Start clearance</h1>...',
1047            self.browser.contents)
1048
1049    def test_student_accommodation(self):
1050        del self.student['accommodation']['2004']
1051        self.student['studycourse'].certificate.study_mode = 'dp_ft'
1052        # All beds can be assigned
1053        bed1 = self.app['hostels']['hall-1']['hall-1_A_101_A']
1054        bed1.bed_type = u'regular_male_all'
1055        bed2 = self.app['hostels']['hall-1']['hall-1_A_101_B']
1056        bed2.bed_type = u'regular_female_all'
1057        notify(grok.ObjectModifiedEvent(bed1))
1058        notify(grok.ObjectModifiedEvent(bed2))
1059        # Login
1060        self.browser.open(self.login_path)
1061        self.browser.getControl(name="form.login").value = self.student_id
1062        self.browser.getControl(name="form.password").value = 'spwd'
1063        self.browser.getControl("Login").click()
1064        # Students can book accommodation without AC ...
1065        self.browser.open(self.acco_path)
1066        IWorkflowInfo(self.student).fireTransition('admit')
1067        self.browser.getControl("Book accommodation").click()
1068        self.assertTrue(
1069            'You are not eligible to book accommodation.'
1070            in self.browser.contents)
1071        self.student['studycourse'].certificate.study_mode = 'ug_ft'
1072        self.app['hostels'].accommodation_states = [PAID]
1073        self.browser.getControl("Book accommodation").click()
1074        self.assertTrue(
1075            'You are in the wrong registration state.'
1076            in self.browser.contents)
1077        IWorkflowState(self.student).setState(PAID)
1078        self.browser.getControl("Book accommodation").click()
1079        self.assertFalse('Activation Code:' in self.browser.contents)
1080        self.browser.getControl("Create bed ticket").click()
1081        # Bed is randomly selected but, since there is only
1082        # one bed for this student, we know that
1083        self.assertEqual(self.student['accommodation']['2004'].bed_coordinates,
1084            'Hall 1, Block A, Room 101, Bed A (regular_male_all)')
1085        # Only the hall name is displayed
1086        self.assertEqual(self.student[
1087            'accommodation']['2004'].display_coordinates,
1088            'Hall 1')
1089        self.assertFalse('Hall 1, Block A, Room 101, Bed A'
1090            in self.browser.contents)
1091        self.assertTrue('<td>Hall 1</td>'
1092            in self.browser.contents)
1093        return
1094
1095    def test_handle_courses_by_lecturer(self):
1096        self.app['users'].addUser('mrslecturer', 'mrslecturersecret')
1097        self.app['users']['mrslecturer'].email = 'mrslecturer@foo.ng'
1098        self.app['users']['mrslecturer'].title = u'Mercedes Benz'
1099        # Add course ticket
1100        studylevel = createObject(u'waeup.StudentStudyLevel')
1101        studylevel.level = 100
1102        studylevel.level_session = 2004
1103        self.student['studycourse'].addStudentStudyLevel(
1104            self.certificate, studylevel)
1105        # Assign local Lecturer role for a certificate.
1106        course = self.app['faculties']['fac1']['dep1'].courses['COURSE1']
1107        prmlocal = IPrincipalRoleManager(course)
1108        prmlocal.assignRoleToPrincipal('waeup.local.Lecturer', 'mrslecturer')
1109        notify(LocalRoleSetEvent(
1110            course, 'waeup.local.Lecturer', 'mrslecturer', granted=True))
1111        # Login as lecturer.
1112        self.browser.open(self.login_path)
1113        self.browser.getControl(name="form.login").value = 'mrslecturer'
1114        self.browser.getControl(name="form.password").value = 'mrslecturersecret'
1115        self.browser.getControl("Login").click()
1116        self.browser.getLink("My Courses").click()
1117        self.browser.getLink("COURSE1").click()
1118        # Course results can be batch edited via the edit_courses view.
1119        self.app['faculties']['fac1']['dep1'].score_editing_disabled = False
1120        self.app['configuration'].current_academic_session = 2004
1121        IWorkflowState(self.student).setState('courses validated')
1122        self.browser.open(
1123            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1/edit_scores")
1124        self.assertTrue(
1125            'input type="text" name="scores:list"'
1126            in self.browser.contents)
1127        self.browser.getControl(name="scores:list", index=0).value = '55'
1128        self.browser.getControl(name="cas:list", index=0).value = '22'
1129        self.browser.getControl("Update scores from").click()
1130        # New score and ca has been set.
1131        self.assertEqual(
1132            self.student['studycourse']['100']['COURSE1'].score, 55)
1133        self.assertEqual(
1134            self.student['studycourse']['100']['COURSE1'].ca, 22)
1135        # Score editing has been logged.
1136        logfile = os.path.join(
1137            self.app['datacenter'].storage, 'logs', 'students.log')
1138        logcontent = open(logfile).read()
1139        self.assertTrue('mrslecturer - waeup.aaue.students.browser.CustomEditScoresPage - '
1140                        'E1000000 100/COURSE1 score updated (55)' in logcontent)
1141        self.assertTrue('mrslecturer - waeup.aaue.students.browser.CustomEditScoresPage - '
1142                        'E1000000 100/COURSE1 ca updated (22)' in logcontent)
1143        # Non-integer scores won't be accepted.
1144        self.browser.open(
1145            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1/edit_scores")
1146        self.assertTrue('value="55" />' in self.browser.contents)
1147        self.browser.getControl(name="scores:list", index=0).value = 'abc'
1148        self.browser.getControl("Update scores").click()
1149        self.assertTrue('Error: Score(s) and CA(s) of TESTER, Anna have not be updated.'
1150            in self.browser.contents)
1151        # Scores can be removed.
1152        self.browser.open(
1153            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1/edit_scores")
1154        self.browser.getControl(name="scores:list", index=0).value = ''
1155        self.browser.getControl("Update scores").click()
1156        self.assertEqual(
1157            self.student['studycourse']['100']['COURSE1'].score, None)
1158        logcontent = open(logfile).read()
1159        self.assertTrue('mrslecturer - waeup.aaue.students.browser.CustomEditScoresPage - '
1160                        'E1000000 100/COURSE1 score updated (None)' in logcontent)
1161
1162
1163    def disabled_test_student_view_transcript(self):
1164        # Student cant login if their password is not set
1165        IWorkflowInfo(self.student).fireTransition('admit')
1166        self.browser.open(self.login_path)
1167        self.browser.getControl(name="form.login").value = self.student_id
1168        self.browser.getControl(name="form.password").value = 'spwd'
1169        self.browser.getControl("Login").click()
1170        self.assertMatches(
1171            '...You logged in...', self.browser.contents)
1172        # Students can view the transcript
1173        self.browser.open(self.studycourse_path)
1174        self.browser.getLink("Transcript").click()
1175        self.browser.getLink("Academic Transcript").click()
1176        self.assertEqual(self.browser.headers['Status'], '200 Ok')
1177        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
1178
1179    def test_alumni_request_pw(self):
1180        # Add an applicants container
1181        applicantscontainer = ApplicantsContainer()
1182        applicantscontainer.code = u'trans2017'
1183        applicantscontainer.prefix = 'trans'
1184        applicantscontainer.year = 2017
1185        applicantscontainer.title = u'This is the trans2017 container'
1186        applicantscontainer.application_category = 'no'
1187        applicantscontainer.mode = 'create'
1188        applicantscontainer.strict_deadline = True
1189        delta = timedelta(days=10)
1190        applicantscontainer.startdate = datetime.now(pytz.utc) - delta
1191        applicantscontainer.enddate = datetime.now(pytz.utc) + delta
1192        self.app['applicants']['trans2017'] = applicantscontainer
1193        self.applicantscontainer = self.app['applicants']['trans2017']
1194        # Student with wrong number can't be found.
1195        # Applicant is redirected to application section.
1196        self.browser.open('http://localhost/app/alumni_requestpw')
1197        self.browser.getControl(name="form.lastname").value = 'Tester'
1198        self.browser.getControl(name="form.number").value = 'anynumber'
1199        self.browser.getControl(name="form.email").value = 'xx@yy.zz'
1200        self.browser.getControl("Send login credentials").click()
1201        self.assertTrue('No student record found.'
1202            in self.browser.contents)
1203        self.assertEqual(self.browser.url,
1204            'http://localhost/app/applicants/trans2017/register')
1205
1206    def test_student_course_registration_outstanding(self):
1207        self.course = createObject('waeup.Course')
1208        self.course.code = 'COURSE2'
1209        self.course.semester = 1
1210        self.course.credits = 39
1211        self.course.passmark = 40
1212        self.app['faculties']['fac1']['dep1'].courses.addCourse(
1213            self.course)
1214        IWorkflowState(self.student).setState('school fee paid')
1215        self.browser.open(self.login_path)
1216        self.browser.getControl(name="form.login").value = self.student_id
1217        self.browser.getControl(name="form.password").value = 'spwd'
1218        self.browser.getControl("Login").click()
1219        self.browser.open(self.student_path + '/studycourse/add')
1220        self.browser.getControl("Create course list now").click()
1221        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 1)
1222        self.student['studycourse'].current_level = 200
1223        self.browser.getLink("Study Course").click()
1224        self.browser.getLink("Add course list").click()
1225        self.assertMatches('...Add current level 200 (Year 2)...',
1226                           self.browser.contents)
1227        self.browser.getControl("Create course list now").click()
1228        self.browser.getLink("200").click()
1229        self.browser.getLink("Edit course list").click()
1230        self.browser.getLink("here").click()
1231        self.browser.getControl(name="form.course").value = ['COURSE2']
1232        self.browser.getControl("Add course ticket").click()
1233        # Carryover COURSE1 in level 200 already has 10 credits
1234        self.assertMatches(
1235            '...Maximum credits exceeded...', self.browser.contents)
1236        # If COURSE1 is outstanding, its credits won't be considered
1237        self.student['studycourse']['200']['COURSE1'].outstanding = True
1238        self.browser.getControl("Add course ticket").click()
1239        self.assertMatches(
1240            '...Successfully added COURSE2...', self.browser.contents)
1241        return
1242
1243    def test_examination_schedule_slip(self):
1244        self.student.flash_notice = u'My Examination Date'
1245        self.browser.open(self.login_path)
1246        self.browser.getControl(name="form.login").value = self.student_id
1247        self.browser.getControl(name="form.password").value = 'spwd'
1248        self.browser.getControl("Login").click()
1249        self.browser.getLink("Download examination schedule slip").click()
1250        self.assertEqual(self.browser.headers['Status'], '200 Ok')
1251        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
1252        path = os.path.join(samples_dir(), 'examination_schedule_slip.pdf')
1253        open(path, 'wb').write(self.browser.contents)
1254        print "Sample PDF examination_schedule_slip.pdf written to %s" % path
1255        # If flash_notive does not contain exam' the button does not show up.
1256        self.student.flash_notice = u'anything'
1257        self.browser.open(self.student_path)
1258        self.assertFalse('examination schedule slip' in self.browser.contents)
Note: See TracBrowser for help on using the repository browser.