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

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

AAUE matric number construction scheme applied by customization of _constructMatricNumber.

Two more study modes added.

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