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

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

To guarantee that cleared students pay both acceptance fee and school fees,
the eTranzact History can only be queried for school fee payments if
acceptance/clearance fee has been successfully queried/paid beforehand.

  • Property svn:keywords set to Id
File size: 17.4 KB
Line 
1## $Id: test_browser.py 11627 2014-05-07 18:21:58Z 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 grok
22from mechanize import LinkNotFoundError
23from hurry.workflow.interfaces import IWorkflowState
24from zope.component.hooks import setSite, clearSite
25from zope.component import getUtility, createObject
26from waeup.kofa.app import University
27from waeup.kofa.students.tests.test_browser import StudentsFullSetup
28from waeup.kofa.students.accommodation import BedTicket
29from waeup.kofa.testing import FunctionalTestCase
30from waeup.kofa.browser.tests.test_pdf import samples_dir
31from waeup.aaue.testing import FunctionalLayer
32
33
34class StudentProcessorTest(FunctionalTestCase):
35    """Perform some batching tests.
36    """
37
38    layer = FunctionalLayer
39
40    def setUp(self):
41        super(StudentProcessorTest, self).setUp()
42        # Setup a sample site for each test
43        app = University()
44        self.dc_root = tempfile.mkdtemp()
45        app['datacenter'].setStoragePath(self.dc_root)
46
47        # Prepopulate the ZODB...
48        self.getRootFolder()['app'] = app
49        # we add the site immediately after creation to the
50        # ZODB. Catalogs and other local utilities are not setup
51        # before that step.
52        self.app = self.getRootFolder()['app']
53        # Set site here. Some of the following setup code might need
54        # to access grok.getSite() and should get our new app then
55        setSite(app)
56
57
58    def tearDown(self):
59        super(StudentProcessorTest, self).tearDown()
60        shutil.rmtree(self.workdir)
61        shutil.rmtree(self.dc_root)
62        clearSite()
63        return
64
65class OfficerUITests(StudentsFullSetup):
66    # Tests for Student class views and pages
67
68    layer = FunctionalLayer
69
70    def test_gpa_calculation(self):
71        studylevel = createObject(u'waeup.StudentStudyLevel')
72        studylevel.level = 100
73        studylevel.level_session = 2005
74        self.student['studycourse'].entry_mode = 'ug_ft'
75        self.student['studycourse'].addStudentStudyLevel(
76            self.certificate, studylevel)
77        # First course has been added automatically.
78        # Set score.
79        studylevel['COURSE1'].score = 55
80        # GPA is 3.0.
81        self.assertEqual(studylevel.gpa_params[0], 3.0)
82        courseticket = createObject('waeup.CourseTicket')
83        courseticket.code = 'ANYCODE'
84        courseticket.title = u'Any TITLE'
85        courseticket.credits = 13
86        courseticket.score = 66
87        courseticket.semester = 1
88        courseticket.dcode = u'ANYDCODE'
89        courseticket.fcode = u'ANYFCODE'
90        studylevel['COURSE2'] = courseticket
91        # total credits
92        self.assertEqual(self.student['studycourse']['100'].gpa_params[1], 23)
93        # weigheted credits = 3 * 10 + 4 * 13
94        self.assertEqual(self.student['studycourse']['100'].gpa_params[2], 82.0)
95        # sgpa = 82 / 23
96        self.assertEqual(self.student['studycourse']['100'].gpa_params[0], 3.565)
97        return
98
99class StudentUITests(StudentsFullSetup):
100    """Tests for customized student class views and pages
101    """
102
103    layer = FunctionalLayer
104
105    def setUp(self):
106        super(StudentUITests, self).setUp()
107
108        bedticket = BedTicket()
109        bedticket.booking_session = 2004
110        bedticket.bed_type = u'any bed type'
111        bedticket.bed = self.app['hostels']['hall-1']['hall-1_A_101_A']
112        bedticket.bed_coordinates = u'My bed coordinates'
113        self.student['accommodation'].addBedTicket(bedticket)
114
115    def test_manage_payments(self):
116        # Add missing configuration data
117        self.app['configuration']['2004'].gown_fee = 150.0
118        self.app['configuration']['2004'].transfer_fee = 90.0
119        self.app['configuration']['2004'].booking_fee = 150.0
120        self.app['configuration']['2004'].maint_fee = 180.0
121        self.app['configuration']['2004'].late_fee = 80.0
122
123        # Managers can add online payment tickets
124        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
125        self.browser.open(self.payments_path)
126        self.browser.getLink("Add current session payment ticket").click()
127        self.browser.getControl(name="form.p_category").value = ['schoolfee']
128        self.browser.getControl("Create ticket").click()
129        self.assertMatches('...Wrong state...',
130                           self.browser.contents)
131        IWorkflowState(self.student).setState('cleared')
132        self.browser.open(self.payments_path + '/addop')
133        self.browser.getControl("Create ticket").click()
134        self.assertMatches('...Amount could not be determined...',
135                           self.browser.contents)
136        self.app['configuration']['2004'].school_fee_1 = 6666.0
137        #self.browser.getControl(name="form.p_category").value = ['schoolfee']
138        # Accepotance fee must be paid first
139        #self.browser.getControl("Create ticket").click()
140        #self.assertMatches('...Please pay acceptance fee first...',
141        #                   self.browser.contents)
142        self.app['configuration']['2004'].clearance_fee = 666.0
143        self.browser.getControl(name="form.p_category").value = ['clearance']
144        self.browser.getControl("Create ticket").click()
145        ctrl = self.browser.getControl(name='val_id')
146        cpt_value = ctrl.options[0]
147        # School fee payment ticket can be added ...
148        self.browser.open(self.payments_path + '/addop')
149        self.browser.getControl(name="form.p_category").value = ['schoolfee']
150        self.browser.getControl("Create ticket").click()
151        self.assertMatches('...ticket created...',
152                           self.browser.contents)
153        # ... but not paid through the query_history page.
154        ctrl = self.browser.getControl(name='val_id')
155        sfpt_value = ctrl.options[1]
156        self.browser.open(self.payments_path + '/' + sfpt_value)
157        self.browser.getLink("Query eTranzact History").click()
158        self.assertMatches('...alert-danger">Please pay acceptance fee first...',
159                           self.browser.contents)
160        # If clearance/acceptance fee is paid ...
161        self.student['payments'][cpt_value].approveStudentPayment()
162        self.browser.getLink("Query eTranzact History").click()
163        # ... query_history page is accessible.
164        self.assertMatches(
165            '...<h1 class="kofa-content-label">Requery eTranzact History</h1>...',
166            self.browser.contents)
167        # Managers can open school fee payment slip
168        self.browser.open(self.payments_path + '/' + sfpt_value)
169        self.browser.getLink("Download payment slip").click()
170        self.assertEqual(self.browser.headers['Status'], '200 Ok')
171        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
172        # If school fee ticket is paid ...
173        ticket = self.student['payments'][sfpt_value].approveStudentPayment()
174        # ... no further school fee ticket can be added.
175        self.browser.open(self.payments_path + '/addop')
176        self.browser.getControl(name="form.p_category").value = ['schoolfee']
177        self.browser.getControl("Create ticket").click()
178        self.assertMatches('...This type of payment has already been made...',
179                           self.browser.contents)
180
181    def deactivated_test_for_instalment_payments(self):
182        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
183        self.browser.open(self.payments_path)
184        self.browser.open(self.payments_path + '/addop')
185        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
186        self.browser.getControl("Create ticket").click()
187        self.assertMatches('...ticket created...',
188                           self.browser.contents)
189        # We can't add the 2nd instalment ticket because the
190        # first one has not yet been approved.
191        self.browser.open(self.payments_path + '/addop')
192        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
193        self.browser.getControl("Create ticket").click()
194        self.assertMatches('...1st school fee instalment has not yet been paid...',
195                           self.browser.contents)
196        # Ok, then we approve the first instalment ...
197        self.browser.open(self.payments_path)
198        ctrl = self.browser.getControl(name='val_id')
199        p_id = ctrl.options[0]
200        self.browser.open(self.payments_path + '/' + p_id + '/approve')
201        # ... add the second instalment ...
202        self.browser.open(self.payments_path + '/addop')
203        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
204        self.browser.getControl("Create ticket").click()
205        self.assertMatches('...ticket created...',
206                           self.browser.contents)
207        # ... approve the second instalment ...
208        ctrl = self.browser.getControl(name='val_id')
209        p_id = ctrl.options[1]
210        self.browser.open(self.payments_path + '/' + p_id + '/approve')
211        # ... and finally add the 1st instalment for the next session
212        # provided that student is returning.
213        IWorkflowState(self.student).setState('returning')
214        self.browser.open(self.payments_path + '/addop')
215        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
216        self.browser.getControl("Create ticket").click()
217        self.assertMatches('...Session configuration object is not...',
218                           self.browser.contents)
219        # Uups, we forgot to add a session configuration for next session
220        configuration = createObject('waeup.SessionConfiguration')
221        configuration.academic_session = 2005
222        self.app['configuration'].addSessionConfiguration(configuration)
223        self.app['configuration']['2005'].school_base = 7777.0
224        self.browser.open(self.payments_path + '/addop')
225        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
226        self.browser.getControl("Create ticket").click()
227        self.assertMatches('...ticket created...',
228                           self.browser.contents)
229        # If the session configuration doesn't exist an error message will
230        # be shown. No other requirement is being checked.
231        del self.app['configuration']['2004']
232        self.browser.open(self.payments_path)
233        self.browser.getLink("Add current session payment ticket").click()
234        self.browser.getControl("Create ticket").click()
235        self.assertMatches('...Session configuration object is not...',
236                           self.browser.contents)
237
238    def test_student_payments(self):
239        # Login
240        IWorkflowState(self.student).setState('returning')
241        self.browser.open(self.login_path)
242        self.browser.getControl(name="form.login").value = self.student_id
243        self.browser.getControl(name="form.password").value = 'spwd'
244        self.browser.getControl("Login").click()
245        self.browser.open(self.student_path + '/payments')
246        self.assertTrue(
247          'Add current session payment ticket' in self.browser.contents)
248        self.assertFalse(
249          'Add previous session payment ticket' in self.browser.contents)
250        return
251
252    def deactivated_test_student_course_registration(self):
253
254        # Add more courses
255        self.course2 = createObject('waeup.Course')
256        self.course2.code = 'COURSE2'
257        self.course2.semester = 2
258        self.course2.credits = 10
259        self.course2.passmark = 40
260        self.app['faculties']['fac1']['dep1'].courses.addCourse(
261            self.course2)
262        self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCertCourse(
263            self.course2, level=100)
264        self.course3 = createObject('waeup.Course')
265        self.course3.code = 'COURSE3'
266        self.course3.semester = 3
267        self.course3.credits = 10
268        self.course3.passmark = 40
269        self.app['faculties']['fac1']['dep1'].courses.addCourse(
270            self.course3)
271        self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCertCourse(
272            self.course3, level=100)
273
274        # Login as student
275        self.browser.open(self.login_path)
276        IWorkflowState(self.student).setState('school fee paid')
277        self.browser.open(self.login_path)
278        self.browser.getControl(name="form.login").value = self.student_id
279        self.browser.getControl(name="form.password").value = 'spwd'
280        self.browser.getControl("Login").click()
281        # Students can add the current study level
282        self.browser.getLink("Study Course").click()
283        self.browser.getLink("Add course list").click()
284        self.assertMatches('...Add current level 100 (Year 1)...',
285                           self.browser.contents)
286        self.browser.getControl("Create course list now").click()
287        # Student has not paid second instalment, therefore a level
288        # with two course ticket was created (semester 1 and combined)
289        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 2)
290        self.browser.getLink("100").click()
291        self.browser.getLink("Edit course list").click()
292        self.browser.getControl("Add course ticket").click()
293        # Student can't add second semester course
294        self.assertTrue('<option value="COURSE1">' in self.browser.contents)
295        self.assertTrue('<option value="COURSE3">' in self.browser.contents)
296        self.assertFalse('<option value="COURSE2">' in self.browser.contents)
297
298        # Let's remove level and see what happens after 2nd instalment payment
299        del(self.student['studycourse']['100'])
300        payment2 = createObject('waeup.StudentOnlinePayment')
301        payment2.p_category = u'schoolfee_2'
302        payment2.p_session = self.student.current_session
303        self.student['payments']['anykey'] = payment2
304        self.browser.open(self.studycourse_path)
305        self.browser.getLink("Add course list").click()
306        self.browser.getControl("Create course list now").click()
307        # Still only 2 tickets have been created since payment ticket
308        # was not paid
309        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 2)
310        payment2.p_state = u'paid'
311        del(self.student['studycourse']['100'])
312        self.browser.open(self.studycourse_path)
313        self.browser.getLink("Add course list").click()
314        self.browser.getControl("Create course list now").click()
315        # Now 2nd semester course has been added
316        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 3)
317        # Student can add second semester course
318        self.browser.getLink("100").click()
319        self.browser.getLink("Edit course list").click()
320        self.browser.getControl("Add course ticket").click()
321        self.assertTrue('<option value="COURSE1">' in self.browser.contents)
322        self.assertTrue('<option value="COURSE2">' in self.browser.contents)
323        self.assertTrue('<option value="COURSE3">' in self.browser.contents)
324        return
325
326    def test_set_matric_number(self):
327        # Login as student
328        self.browser.open(self.login_path)
329        IWorkflowState(self.student).setState('school fee paid')
330        self.browser.open(self.login_path)
331        self.browser.getControl(name="form.login").value = self.student_id
332        self.browser.getControl(name="form.password").value = 'spwd'
333        self.browser.getControl("Login").click()
334        self.assertRaises(
335            LinkNotFoundError,
336            self.browser.getLink, 'Get Matriculation Number')
337        self.student.matric_number = None
338        site = grok.getSite()
339        site['configuration'].next_matric_integer = 1
340        self.student['studycourse'].certificate.study_mode = 'ug_pt'
341        self.browser.open(self.student_path)
342        self.assertRaises(
343            LinkNotFoundError,
344            self.browser.getLink, 'Download matriculation number slip')
345        self.browser.getLink("Get Matriculation Number").click()
346        self.assertTrue('Matriculation number PTP/fac1/dep1/04/00001 assigned.'
347            in self.browser.contents)
348        self.assertEqual(self.student.matric_number, 'PTP/fac1/dep1/04/00001')
349        self.assertRaises(
350            LinkNotFoundError,
351            self.browser.getLink, 'Get Matriculation Number')
352        # Setting matric number is logged.
353        logfile = os.path.join(
354            self.app['datacenter'].storage, 'logs', 'students.log')
355        logcontent = open(logfile).read()
356        self.assertTrue('E1000000 - waeup.aaue.students.browser.StudentGetMatricNumberPage - '
357                        'E1000000 - PTP/fac1/dep1/04/00001 assigned' in logcontent)
358        # Matric Number Slip can be downloaded
359        self.browser.getLink("Download matriculation number slip").click()
360        self.assertEqual(self.browser.headers['Status'], '200 Ok')
361        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
362        path = os.path.join(samples_dir(), 'transcript.pdf')
363        open(path, 'wb').write(self.browser.contents)
364        print "Sample PDF matric_number_slip.pdf written to %s" % path
365        return
366
Note: See TracBrowser for help on using the repository browser.