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

Last change on this file since 11522 was 11004, checked in by Henrik Bettermann, 11 years ago

Add late registration payment category.

  • Property svn:keywords set to Id
File size: 20.1 KB
Line 
1## $Id: test_browser.py 11004 2014-01-29 16:08: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
21from StringIO import StringIO
22from hurry.workflow.interfaces import IWorkflowState
23from zope.component.hooks import setSite, clearSite
24from zope.component import getUtility, createObject
25from zope.interface import verify
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.interfaces import (
31    IExtFileStore, IFileStoreNameChooser)
32from waeup.kofa.students.interfaces import IStudentsUtils
33from waeup.aaue.testing import FunctionalLayer
34
35
36class StudentProcessorTest(FunctionalTestCase):
37    """Perform some batching tests.
38    """
39
40    layer = FunctionalLayer
41
42    def setUp(self):
43        super(StudentProcessorTest, self).setUp()
44        # Setup a sample site for each test
45        app = University()
46        self.dc_root = tempfile.mkdtemp()
47        app['datacenter'].setStoragePath(self.dc_root)
48
49        # Prepopulate the ZODB...
50        self.getRootFolder()['app'] = app
51        # we add the site immediately after creation to the
52        # ZODB. Catalogs and other local utilities are not setup
53        # before that step.
54        self.app = self.getRootFolder()['app']
55        # Set site here. Some of the following setup code might need
56        # to access grok.getSite() and should get our new app then
57        setSite(app)
58
59
60    def tearDown(self):
61        super(StudentProcessorTest, self).tearDown()
62        shutil.rmtree(self.workdir)
63        shutil.rmtree(self.dc_root)
64        clearSite()
65        return
66
67class OfficerUITests(StudentsFullSetup):
68    # Tests for Student class views and pages
69
70    layer = FunctionalLayer
71
72    def test_gpa_calculation(self):
73        studylevel = createObject(u'waeup.StudentStudyLevel')
74        studylevel.level = 100
75        studylevel.level_session = 2005
76        self.student['studycourse'].entry_mode = 'ug_ft'
77        self.student['studycourse'].addStudentStudyLevel(
78            self.certificate, studylevel)
79        # First course has been added automatically.
80        # Set score.
81        studylevel['COURSE1'].score = 55
82        # GPA is 3.0.
83        self.assertEqual(studylevel.gpa_params[0], 3.0)
84        courseticket = createObject('waeup.CourseTicket')
85        courseticket.code = 'ANYCODE'
86        courseticket.title = u'Any TITLE'
87        courseticket.credits = 13
88        courseticket.score = 66
89        courseticket.semester = 1
90        courseticket.dcode = u'ANYDCODE'
91        courseticket.fcode = u'ANYFCODE'
92        studylevel['COURSE2'] = courseticket
93        # total credits
94        self.assertEqual(self.student['studycourse']['100'].gpa_params[1], 23)
95        # weigheted credits = 3 * 10 + 4 * 13
96        self.assertEqual(self.student['studycourse']['100'].gpa_params[2], 82.0)
97        # sgpa = 82 / 23
98        self.assertEqual(self.student['studycourse']['100'].gpa_params[0], 3.565)
99        return
100
101class StudentUITests(StudentsFullSetup):
102    """Tests for customized student class views and pages
103    """
104
105    layer = FunctionalLayer
106
107    def setUp(self):
108        super(StudentUITests, self).setUp()
109
110        bedticket = BedTicket()
111        bedticket.booking_session = 2004
112        bedticket.bed_type = u'any bed type'
113        bedticket.bed = self.app['hostels']['hall-1']['hall-1_A_101_A']
114        bedticket.bed_coordinates = u'My bed coordinates'
115        self.student['accommodation'].addBedTicket(bedticket)
116
117    def test_manage_payments(self):
118        # Add missing configuration data
119        self.app['configuration']['2004'].gown_fee = 150.0
120        self.app['configuration']['2004'].transfer_fee = 90.0
121        self.app['configuration']['2004'].booking_fee = 150.0
122        self.app['configuration']['2004'].maint_fee = 180.0
123        self.app['configuration']['2004'].late_fee = 80.0
124
125        # Managers can add online payment tickets
126        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
127        self.browser.open(self.payments_path)
128        self.browser.getLink("Add current session payment ticket").click()
129        self.browser.getControl(name="form.p_category").value = ['schoolfee']
130        self.browser.getControl("Create ticket").click()
131        self.assertMatches('...Wrong state...',
132                           self.browser.contents)
133        IWorkflowState(self.student).setState('cleared')
134        self.browser.open(self.payments_path + '/addop')
135        self.browser.getControl("Create ticket").click()
136        self.assertMatches('...Amount could not be determined...',
137                           self.browser.contents)
138        self.app['configuration']['2004'].school_fee = 6666.0
139        self.browser.getControl(name="form.p_category").value = ['schoolfee']
140        self.browser.getControl("Create ticket").click()
141        self.assertMatches('...ticket created...',
142                           self.browser.contents)
143        ctrl = self.browser.getControl(name='val_id')
144        value = ctrl.options[0]
145        self.browser.getLink(value).click()
146        self.assertMatches('...Amount Authorized...',
147                           self.browser.contents)
148        # Managers can open payment slip
149        self.browser.getLink("Download payment slip").click()
150        self.assertEqual(self.browser.headers['Status'], '200 Ok')
151        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
152        # Set ticket paid
153        ticket = self.student['payments'].items()[0][1]
154        ticket.p_state = 'paid'
155        self.browser.open(self.payments_path + '/addop')
156        self.browser.getControl(name="form.p_category").value = ['schoolfee']
157        self.browser.getControl("Create ticket").click()
158        self.assertMatches('...This type of payment has already been made...',
159                           self.browser.contents)
160        self.browser.open(self.payments_path + '/addop')
161        # Also the other payments can be made
162        self.browser.getControl(name="form.p_category").value = ['gown']
163        self.browser.getControl("Create ticket").click()
164        self.assertMatches('...ticket created...',
165                           self.browser.contents)
166        self.browser.open(self.payments_path + '/addop')
167        self.browser.getControl(name="form.p_category").value = ['transfer']
168        self.browser.getControl("Create ticket").click()
169        self.assertMatches('...ticket created...',
170                           self.browser.contents)
171        self.browser.open(self.payments_path + '/addop')
172        self.browser.getControl(
173            name="form.p_category").value = ['bed_allocation']
174        self.browser.getControl("Create ticket").click()
175        self.assertMatches('...ticket created...',
176                           self.browser.contents)
177        self.browser.open(self.payments_path + '/addop')
178        self.browser.getControl(
179            name="form.p_category").value = ['hostel_maintenance']
180        self.browser.getControl("Create ticket").click()
181        self.assertMatches('...ticket created...',
182                           self.browser.contents)
183        self.browser.open(self.payments_path + '/addop')
184        self.browser.getControl(name="form.p_category").value = ['clearance']
185        self.browser.getControl("Create ticket").click()
186        self.assertMatches('...ticket created...',
187                           self.browser.contents)
188        self.browser.open(self.payments_path + '/addop')
189        self.browser.getControl(name="form.p_category").value = ['late_registration']
190        self.browser.getControl("Create ticket").click()
191        self.assertMatches('...ticket created...',
192                           self.browser.contents)
193
194
195    def deactivated_test_for_instalment_payments(self):
196        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
197        self.browser.open(self.payments_path)
198        self.browser.open(self.payments_path + '/addop')
199        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
200        self.browser.getControl("Create ticket").click()
201        self.assertMatches('...ticket created...',
202                           self.browser.contents)
203        # We can't add the 2nd instalment ticket because the
204        # first one has not yet been approved.
205        self.browser.open(self.payments_path + '/addop')
206        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
207        self.browser.getControl("Create ticket").click()
208        self.assertMatches('...1st school fee instalment has not yet been paid...',
209                           self.browser.contents)
210        # Ok, then we approve the first instalment ...
211        self.browser.open(self.payments_path)
212        ctrl = self.browser.getControl(name='val_id')
213        p_id = ctrl.options[0]
214        self.browser.open(self.payments_path + '/' + p_id + '/approve')
215        # ... add the second instalment ...
216        self.browser.open(self.payments_path + '/addop')
217        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
218        self.browser.getControl("Create ticket").click()
219        self.assertMatches('...ticket created...',
220                           self.browser.contents)
221        # ... approve the second instalment ...
222        ctrl = self.browser.getControl(name='val_id')
223        p_id = ctrl.options[1]
224        self.browser.open(self.payments_path + '/' + p_id + '/approve')
225        # ... and finally add the 1st instalment for the next session
226        # provided that student is returning.
227        IWorkflowState(self.student).setState('returning')
228        self.browser.open(self.payments_path + '/addop')
229        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
230        self.browser.getControl("Create ticket").click()
231        self.assertMatches('...Session configuration object is not...',
232                           self.browser.contents)
233        # Uups, we forgot to add a session configuration for next session
234        configuration = createObject('waeup.SessionConfiguration')
235        configuration.academic_session = 2005
236        self.app['configuration'].addSessionConfiguration(configuration)
237        self.app['configuration']['2005'].school_base = 7777.0
238        self.browser.open(self.payments_path + '/addop')
239        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
240        self.browser.getControl("Create ticket").click()
241        self.assertMatches('...ticket created...',
242                           self.browser.contents)
243        # If the session configuration doesn't exist an error message will
244        # be shown. No other requirement is being checked.
245        del self.app['configuration']['2004']
246        self.browser.open(self.payments_path)
247        self.browser.getLink("Add current session payment ticket").click()
248        self.browser.getControl("Create ticket").click()
249        self.assertMatches('...Session configuration object is not...',
250                           self.browser.contents)
251
252    def test_student_payments(self):
253        # Login
254        IWorkflowState(self.student).setState('returning')
255        self.browser.open(self.login_path)
256        self.browser.getControl(name="form.login").value = self.student_id
257        self.browser.getControl(name="form.password").value = 'spwd'
258        self.browser.getControl("Login").click()
259        self.browser.open(self.student_path + '/payments')
260        self.assertTrue(
261          'Add current session payment ticket' in self.browser.contents)
262        self.assertFalse(
263          'Add previous session payment ticket' in self.browser.contents)
264        return
265
266    def test_get_returning_data(self):
267        # Student is in level 100, session 2004 with verdict A
268        utils = getUtility(IStudentsUtils)
269        self.assertEqual(utils.getReturningData(self.student),(2005, 200))
270        self.student['studycourse'].current_verdict = 'C'
271        self.assertEqual(utils.getReturningData(self.student),(2005, 110))
272        self.student['studycourse'].current_verdict = 'NEOR'
273        self.assertEqual(utils.getReturningData(self.student),(2005, 100))
274        return
275
276    def test_set_payment_details(self):
277        self.app['configuration']['2004'].gown_fee = 150.0
278        self.app['configuration']['2004'].transfer_fee = 90.0
279        self.app['configuration']['2004'].booking_fee = 150.0
280        self.app['configuration']['2004'].maint_fee = 180.0
281        self.app['configuration']['2004'].clearance_fee = 1234.0
282        self.app['configuration']['2004'].school_fee = 6666.0
283        utils = getUtility(IStudentsUtils)
284
285        configuration = createObject('waeup.SessionConfiguration')
286        configuration.academic_session = 2005
287        self.app['configuration'].addSessionConfiguration(configuration)
288        self.app['configuration']['2005'].school_fee = 7777.0
289
290        error, payment = utils.setPaymentDetails('schoolfee',self.student)
291        self.assertEqual(payment, None)
292        self.assertEqual(error, u'Wrong state.')
293
294        IWorkflowState(self.student).setState('cleared')
295        error, payment = utils.setPaymentDetails('schoolfee',self.student)
296        self.assertEqual(payment.p_level, 100)
297        self.assertEqual(payment.p_session, 2004)
298        self.assertEqual(payment.amount_auth, 6666.0)
299        self.assertEqual(payment.p_item, u'CERT1')
300        self.assertEqual(error, None)
301
302        # Add penalty fee ...
303        # ... for cleared
304        self.app['configuration']['2004'].penalty_ug = 99.0
305        # ... for returning
306        self.app['configuration']['2005'].penalty_ug = 88.0
307        error, payment = utils.setPaymentDetails('schoolfee',self.student)
308        self.assertEqual(payment.amount_auth, 6765.0)
309        IWorkflowState(self.student).setState('returning')
310        error, payment = utils.setPaymentDetails('schoolfee',self.student)
311        self.assertEqual(payment.p_level, 200)
312        self.assertEqual(payment.p_session, 2005)
313        self.assertEqual(payment.amount_auth, 7865.0)
314        self.assertEqual(payment.p_item, u'CERT1')
315        self.assertEqual(error, None)
316
317        error, payment = utils.setPaymentDetails('clearance',self.student)
318        self.assertEqual(payment.p_level, 100)
319        self.assertEqual(payment.p_session, 2004)
320        self.assertEqual(payment.amount_auth, 1234.0)
321        self.assertEqual(payment.p_item, u'CERT1')
322        self.assertEqual(error, None)
323
324        error, payment = utils.setPaymentDetails('gown',self.student)
325        self.assertEqual(payment.p_level, 100)
326        self.assertEqual(payment.p_session, 2004)
327        self.assertEqual(payment.amount_auth, 150.0)
328        self.assertEqual(payment.p_item, u'')
329        self.assertEqual(error, None)
330
331        error, payment = utils.setPaymentDetails('hostel_maintenance',self.student)
332        self.assertEqual(payment.p_level, 100)
333        self.assertEqual(payment.p_session, 2004)
334        self.assertEqual(payment.amount_auth, 180.0)
335        self.assertEqual(payment.p_item, u'')
336        self.assertEqual(error, None)
337
338        error, payment = utils.setPaymentDetails('bed_allocation',self.student)
339        self.assertEqual(payment.p_level, 100)
340        self.assertEqual(payment.p_session, 2004)
341        self.assertEqual(payment.amount_auth, 150.0)
342        self.assertEqual(payment.p_item, u'')
343        self.assertEqual(error, None)
344
345        error, payment = utils.setPaymentDetails('transfer',self.student)
346        self.assertEqual(payment.p_level, 100)
347        self.assertEqual(payment.p_session, 2004)
348        self.assertEqual(payment.amount_auth, 90.0)
349        self.assertEqual(payment.p_item, u'')
350        self.assertEqual(error, None)
351
352        error, payment = utils.setPaymentDetails('schoolfee',self.student, 2004, 100)
353        self.assertEqual(error, u'Previous session payment not yet implemented.')
354        return
355
356    def deactivated_test_student_course_registration(self):
357
358        # Add more courses
359        self.course2 = createObject('waeup.Course')
360        self.course2.code = 'COURSE2'
361        self.course2.semester = 2
362        self.course2.credits = 10
363        self.course2.passmark = 40
364        self.app['faculties']['fac1']['dep1'].courses.addCourse(
365            self.course2)
366        self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCertCourse(
367            self.course2, level=100)
368        self.course3 = createObject('waeup.Course')
369        self.course3.code = 'COURSE3'
370        self.course3.semester = 3
371        self.course3.credits = 10
372        self.course3.passmark = 40
373        self.app['faculties']['fac1']['dep1'].courses.addCourse(
374            self.course3)
375        self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCertCourse(
376            self.course3, level=100)
377
378        # Login as student
379        self.browser.open(self.login_path)
380        IWorkflowState(self.student).setState('school fee paid')
381        self.browser.open(self.login_path)
382        self.browser.getControl(name="form.login").value = self.student_id
383        self.browser.getControl(name="form.password").value = 'spwd'
384        self.browser.getControl("Login").click()
385        # Students can add the current study level
386        self.browser.getLink("Study Course").click()
387        self.browser.getLink("Add course list").click()
388        self.assertMatches('...Add current level 100 (Year 1)...',
389                           self.browser.contents)
390        self.browser.getControl("Create course list now").click()
391        # Student has not paid second instalment, therefore a level
392        # with two course ticket was created (semester 1 and combined)
393        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 2)
394        self.browser.getLink("100").click()
395        self.browser.getLink("Edit course list").click()
396        self.browser.getControl("Add course ticket").click()
397        # Student can't add second semester course
398        self.assertTrue('<option value="COURSE1">' in self.browser.contents)
399        self.assertTrue('<option value="COURSE3">' in self.browser.contents)
400        self.assertFalse('<option value="COURSE2">' in self.browser.contents)
401
402        # Let's remove level and see what happens after 2nd instalment payment
403        del(self.student['studycourse']['100'])
404        payment2 = createObject('waeup.StudentOnlinePayment')
405        payment2.p_category = u'schoolfee_2'
406        payment2.p_session = self.student.current_session
407        self.student['payments']['anykey'] = payment2
408        self.browser.open(self.studycourse_path)
409        self.browser.getLink("Add course list").click()
410        self.browser.getControl("Create course list now").click()
411        # Still only 2 tickets have been created since payment ticket
412        # was not paid
413        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 2)
414        payment2.p_state = u'paid'
415        del(self.student['studycourse']['100'])
416        self.browser.open(self.studycourse_path)
417        self.browser.getLink("Add course list").click()
418        self.browser.getControl("Create course list now").click()
419        # Now 2nd semester course has been added
420        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 3)
421        # Student can add second semester course
422        self.browser.getLink("100").click()
423        self.browser.getLink("Edit course list").click()
424        self.browser.getControl("Add course ticket").click()
425        self.assertTrue('<option value="COURSE1">' in self.browser.contents)
426        self.assertTrue('<option value="COURSE2">' in self.browser.contents)
427        self.assertTrue('<option value="COURSE3">' in self.browser.contents)
428        return
429
430    def test_maxCredits(self):
431        dummy = object()
432        utils = getUtility(IStudentsUtils)
433        self.assertEqual(utils.maxCredits(dummy), 48)
434        return
Note: See TracBrowser for help on using the repository browser.