source: main/waeup.uniben/trunk/src/waeup/uniben/students/tests/test_browser.py @ 8715

Last change on this file since 8715 was 8676, checked in by Henrik Bettermann, 12 years ago

Add ug and pg penalty fees.

  • Property svn:keywords set to Id
File size: 17.4 KB
Line 
1## $Id: test_browser.py 8676 2012-06-11 11:11:11Z 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 hurry.workflow.interfaces import IWorkflowState
22from zope.component.hooks import setSite, clearSite
23from zope.component import getUtility, createObject
24from zope.interface import verify
25from waeup.kofa.app import University
26from waeup.kofa.students.tests.test_browser import StudentsFullSetup
27from waeup.kofa.testing import FunctionalTestCase
28from waeup.kofa.students.batching import StudentProcessor
29from waeup.kofa.students.interfaces import IStudentsUtils
30from waeup.uniben.students.batching import CustomStudentProcessor
31from waeup.uniben.testing import FunctionalLayer
32from waeup.uniben.students.interfaces import (
33    ICustomStudentStudyCourse, ICustomStudent,
34    ICustomStudentStudyLevel, ICustomCourseTicket)
35
36
37STUDENT_SAMPLE_DATA = open(
38    os.path.join(os.path.dirname(__file__), 'sample_student_data.csv'),
39    'rb').read()
40
41STUDENT_HEADER_FIELDS = STUDENT_SAMPLE_DATA.split(
42    '\n')[0].split(',')
43
44class StudentProcessorTest(FunctionalTestCase):
45    """Perform some batching tests.
46    """
47
48    layer = FunctionalLayer
49
50    def setUp(self):
51        super(StudentProcessorTest, self).setUp()
52        # Setup a sample site for each test
53        app = University()
54        self.dc_root = tempfile.mkdtemp()
55        app['datacenter'].setStoragePath(self.dc_root)
56
57        # Prepopulate the ZODB...
58        self.getRootFolder()['app'] = app
59        # we add the site immediately after creation to the
60        # ZODB. Catalogs and other local utilities are not setup
61        # before that step.
62        self.app = self.getRootFolder()['app']
63        # Set site here. Some of the following setup code might need
64        # to access grok.getSite() and should get our new app then
65        setSite(app)
66
67        self.processor_base = StudentProcessor()
68        self.processor = CustomStudentProcessor()
69        self.workdir = tempfile.mkdtemp()
70        self.csv_file = os.path.join(self.workdir, 'sample_student_data.csv')
71        open(self.csv_file, 'wb').write(STUDENT_SAMPLE_DATA)
72
73    def tearDown(self):
74        super(StudentProcessorTest, self).tearDown()
75        shutil.rmtree(self.workdir)
76        shutil.rmtree(self.dc_root)
77        clearSite()
78        return
79
80    def test_import(self):
81        # We have an empty column 'date_of_birth' in  the import file.
82        # The original processor will fail because 'date_of_birth' is required
83        # in the base package.
84        num, num_warns, fin_file, fail_file = self.processor_base.doImport(
85            self.csv_file, STUDENT_HEADER_FIELDS)
86        self.assertEqual(num_warns,3)
87        assert len(self.app['students'].keys()) == 0
88        # The customized processor does not complain since 'date_of_birth' is
89        # not required in the custom package.
90        num, num_warns, fin_file, fail_file = self.processor.doImport(
91            self.csv_file, STUDENT_HEADER_FIELDS)
92        #print open(fail_file).read()
93        self.assertEqual(num_warns,0)
94        assert len(self.app['students'].keys()) == 3
95        shutil.rmtree(os.path.dirname(fin_file))
96
97
98class StudentUITests(StudentsFullSetup):
99    """Tests for customized student class views and pages
100    """
101
102    layer = FunctionalLayer
103
104    def test_classes(self):
105        # Let's see if objects created in the customized
106        # portal really implement the customized interfaces
107        verify.verifyObject(ICustomStudent, self.student)
108        verify.verifyObject(
109            ICustomStudentStudyCourse, self.student['studycourse'])
110        studylevel = createObject(u'waeup.StudentStudyLevel')
111        verify.verifyObject(ICustomStudentStudyLevel, studylevel)
112        ticket = createObject(u'waeup.CourseTicket')
113        verify.verifyObject(ICustomCourseTicket, ticket)
114        IWorkflowState(self.student).setState('returning')
115        # Let's see if next_session_allowed works as expected
116        # A, ug_ft, 100
117        self.assertTrue(self.student['studycourse'].next_session_allowed)
118        # O, ug_ft, 100
119        self.student['studycourse'].current_verdict = 'O'
120        self.assertTrue(self.student['studycourse'].next_session_allowed)
121        # O, ug_ft, 200
122        self.student['studycourse'].current_level = 200
123        self.assertFalse(self.student['studycourse'].next_session_allowed)
124        # O, de_ft, 200
125        self.student['studycourse'].certificate.study_mode = 'de_ft'
126        self.assertTrue(self.student['studycourse'].next_session_allowed)
127        # O, ph_ft, 300
128        self.student['studycourse'].certificate.study_mode = 'ph_ft'
129        self.student['studycourse'].current_level = 300
130        self.assertTrue(self.student['studycourse'].next_session_allowed)
131        # O, ph_ft, 400
132        self.student['studycourse'].current_level = 400
133        self.assertFalse(self.student['studycourse'].next_session_allowed)
134
135        # Now we convert the certificate into a postgraduate certificate
136        IWorkflowState(self.student).setState('school fee paid')
137        self.certificate.study_mode = 'pg_ft'
138        # ... and voila next session registration is allowed
139        self.assertTrue(self.student['studycourse'].next_session_allowed)
140
141    def test_manage_access(self):
142        # Managers can access the pages of students
143        # and can perform actions
144        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
145        # The student created in the base package is an ug student
146        self.browser.open(self.student_path)
147        self.browser.getLink("Clearance Data").click()
148        self.assertEqual(self.browser.headers['Status'], '200 Ok')
149        self.assertEqual(self.browser.url, self.clearance_path)
150        self.browser.getLink("Manage").click()
151        self.assertEqual(self.browser.headers['Status'], '200 Ok')
152        self.assertEqual(self.browser.url, self.manage_clearance_path)
153        self.browser.getControl(name="form.date_of_birth").value = '09/10/1961'
154        self.browser.getControl("Save").click()
155        self.assertMatches('...Form has been saved...',
156                           self.browser.contents)
157        self.assertMatches('...First Sitting Record...',
158                           self.browser.contents)
159        # Managers can open clearance slip of ug students
160        self.browser.open(self.student_path + '/clearance.pdf')
161        self.assertEqual(self.browser.headers['Status'], '200 Ok')
162        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
163        # There is no pg field in the clearance form
164        self.assertFalse('Second Higher Education Record'
165            in self.browser.contents)
166        # Now we change the study mode ...
167        self.certificate.study_mode = 'pg_ft'
168        self.browser.open(self.clearance_path)
169        # ... and additional pg clearance fields appear
170        self.assertMatches('...Second Higher Education Record...',
171                           self.browser.contents)
172        # But also fields from the ug form are displayed
173        self.assertMatches('...First Sitting Record...',
174                           self.browser.contents)
175        # Managers can open clearance slip of pg students
176        self.browser.open(self.student_path + '/clearance.pdf')
177        self.assertEqual(self.browser.headers['Status'], '200 Ok')
178        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
179
180    def test_manage_payments(self):
181        # Add missing configuration data
182        self.app['configuration']['2004'].gown_fee = 150.0
183        self.app['configuration']['2004'].transfer_fee = 90.0
184        #self.app['configuration']['2004'].clearance_fee = 120.0
185        self.app['configuration']['2004'].booking_fee = 150.0
186        self.app['configuration']['2004'].maint_fee = 180.0
187
188        # Managers can add online payment tickets
189        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
190        self.browser.open(self.payments_path)
191        self.browser.getControl("Add online payment ticket").click()
192        self.browser.getControl("Create ticket").click()
193        self.assertMatches('...Amount could not be determined...',
194                           self.browser.contents)
195        IWorkflowState(self.student).setState('cleared')
196        self.browser.open(self.payments_path + '/addop')
197        self.browser.getControl("Create ticket").click()
198        self.assertMatches('...ticket created...',
199                           self.browser.contents)
200        ctrl = self.browser.getControl(name='val_id')
201        value = ctrl.options[0]
202        self.browser.getLink(value).click()
203        self.assertMatches('...Amount Authorized...',
204                           self.browser.contents)
205        # Managers can open payment slip
206        self.browser.getLink("Download payment slip").click()
207        self.assertEqual(self.browser.headers['Status'], '200 Ok')
208        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
209        # Set ticket paid
210        ticket = self.student['payments'].items()[0][1]
211        ticket.p_state = 'paid'
212        self.browser.open(self.payments_path + '/addop')
213        self.browser.getControl("Create ticket").click()
214        self.assertMatches('...This type of payment has already been made...',
215                           self.browser.contents)
216        # Remove all payments so that we can add a school fee payment again
217        keys = [i for i in self.student['payments'].keys()]
218        for payment in keys:
219            del self.student['payments'][payment]
220        self.browser.open(self.payments_path + '/addop')
221        self.browser.getControl("Create ticket").click()
222        self.assertMatches('...ticket created...',
223                           self.browser.contents)
224        self.browser.open(self.payments_path + '/addop')
225        self.browser.getControl(name="form.p_category").value = ['gown']
226        self.browser.getControl("Create ticket").click()
227        self.assertMatches('...ticket created...',
228                           self.browser.contents)
229        self.browser.open(self.payments_path + '/addop')
230        self.browser.getControl(name="form.p_category").value = ['transfer']
231        self.browser.getControl("Create ticket").click()
232        self.assertMatches('...ticket created...',
233                           self.browser.contents)
234        self.browser.open(self.payments_path + '/addop')
235        self.browser.getControl(
236            name="form.p_category").value = ['bed_allocation']
237        self.browser.getControl("Create ticket").click()
238        self.assertMatches('...ticket created...',
239                           self.browser.contents)
240        self.browser.open(self.payments_path + '/addop')
241        self.browser.getControl(
242            name="form.p_category").value = ['hostel_maintenance']
243        self.browser.getControl("Create ticket").click()
244        self.assertMatches('...ticket created...',
245                           self.browser.contents)
246        self.browser.open(self.payments_path + '/addop')
247        self.browser.getControl(name="form.p_category").value = ['clearance']
248        self.browser.getControl("Create ticket").click()
249        self.assertMatches('...ticket created...',
250                           self.browser.contents)
251        self.browser.open(self.payments_path + '/addop')
252        self.browser.getControl(name="form.p_category").value = ['schoolfee']
253        self.browser.getControl("Create ticket").click()
254        self.assertMatches('...ticket created...',
255                           self.browser.contents)
256        # In state returning we can add a new school fee ticket since
257        # p_session and p_level is different
258        IWorkflowState(self.student).setState('returning')
259        self.browser.open(self.payments_path + '/addop')
260        self.browser.getControl(name="form.p_category").value = ['schoolfee']
261        self.browser.getControl("Create ticket").click()
262        self.assertMatches('...ticket created...',
263                           self.browser.contents)
264        # In state admitted school fee can't be determined
265        IWorkflowState(self.student).setState('admitted')
266        self.browser.open(self.payments_path + '/addop')
267        self.browser.getControl(name="form.p_category").value = ['schoolfee']
268        self.browser.getControl("Create ticket").click()
269        self.assertMatches('...Amount could not be determined...',
270                           self.browser.contents)
271
272        # If the session configuration doesn't exist an error message will
273        # be shown. No other requirement is being checked.
274        del self.app['configuration']['2004']
275        self.browser.open(self.payments_path)
276        self.browser.getControl("Add online payment ticket").click()
277        self.browser.getControl("Create ticket").click()
278        self.assertMatches('...Session configuration object is not...',
279                           self.browser.contents)
280
281    def test_student_access(self):
282        # Students can edit clearance data
283        IWorkflowState(self.student).setState('cleared')
284        self.student.clearance_locked = False
285        self.browser.open(self.login_path)
286        self.browser.getControl(name="form.login").value = self.student_id
287        self.browser.getControl(name="form.password").value = 'spwd'
288        self.browser.getControl("Login").click()
289        # Student can view and edit clearance data
290        self.browser.getLink("Clearance Data").click()
291        self.browser.getLink("Edit").click()
292        self.assertTrue('Save' in self.browser.contents)
293
294    def test_get_returning_data(self):
295        # Student is in level 100, session 2004 with verdict A
296        utils = getUtility(IStudentsUtils)
297        self.assertEqual(utils.getReturningData(self.student),(2005, 200))
298        self.student['studycourse'].current_verdict = 'C'
299        self.assertEqual(utils.getReturningData(self.student),(2005, 110))
300        self.student['studycourse'].current_verdict = 'D'
301        self.assertEqual(utils.getReturningData(self.student),(2005, 100))
302        return
303
304    def test_set_payment_details(self):
305        self.app['configuration']['2004'].gown_fee = 150.0
306        self.app['configuration']['2004'].transfer_fee = 90.0
307        self.app['configuration']['2004'].booking_fee = 150.0
308        self.app['configuration']['2004'].maint_fee = 180.0
309        utils = getUtility(IStudentsUtils)
310
311        error, payment = utils.setPaymentDetails('schoolfee',self.student)
312        self.assertEqual(payment, None)
313        self.assertEqual(error, u'Amount could not be determined.')
314
315        IWorkflowState(self.student).setState('cleared')
316        error, payment = utils.setPaymentDetails('schoolfee',self.student)
317        self.assertEqual(payment.p_level, 100)
318        self.assertEqual(payment.p_session, 2004)
319        self.assertEqual(payment.amount_auth, 40000.0)
320        self.assertEqual(payment.p_item, u'CERT1')
321        self.assertEqual(error, None)
322
323        # Add penalty fee.
324        self.app['configuration']['2004'].penalty_ug = 99.0
325        error, payment = utils.setPaymentDetails('schoolfee',self.student)
326        self.assertEqual(payment.amount_auth, 40099.0)
327
328        IWorkflowState(self.student).setState('returning')
329        error, payment = utils.setPaymentDetails('schoolfee',self.student)
330        self.assertEqual(payment.p_level, 200)
331        self.assertEqual(payment.p_session, 2005)
332        self.assertEqual(payment.amount_auth, 20099.0)
333        self.assertEqual(payment.p_item, u'CERT1')
334        self.assertEqual(error, None)
335
336        error, payment = utils.setPaymentDetails('clearance',self.student)
337        self.assertEqual(payment.p_level, 100)
338        self.assertEqual(payment.p_session, 2004)
339        self.assertEqual(payment.amount_auth, 34250.0)
340        self.assertEqual(payment.p_item, u'CERT1')
341        self.assertEqual(error, None)
342
343        error, payment = utils.setPaymentDetails('gown',self.student)
344        self.assertEqual(payment.p_level, 100)
345        self.assertEqual(payment.p_session, 2004)
346        self.assertEqual(payment.amount_auth, 150.0)
347        self.assertEqual(payment.p_item, u'')
348        self.assertEqual(error, None)
349
350        error, payment = utils.setPaymentDetails('hostel_maintenance',self.student)
351        self.assertEqual(payment.p_level, 100)
352        self.assertEqual(payment.p_session, 2004)
353        self.assertEqual(payment.amount_auth, 180.0)
354        self.assertEqual(payment.p_item, u'')
355        self.assertEqual(error, None)
356
357        error, payment = utils.setPaymentDetails('bed_allocation',self.student)
358        self.assertEqual(payment.p_level, 100)
359        self.assertEqual(payment.p_session, 2004)
360        self.assertEqual(payment.amount_auth, 150.0)
361        self.assertEqual(payment.p_item, u'')
362        self.assertEqual(error, None)
363
364        error, payment = utils.setPaymentDetails('transfer',self.student)
365        self.assertEqual(payment.p_level, 100)
366        self.assertEqual(payment.p_session, 2004)
367        self.assertEqual(payment.amount_auth, 90.0)
368        self.assertEqual(payment.p_item, u'')
369        self.assertEqual(error, None)
370        return
Note: See TracBrowser for help on using the repository browser.