source: main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_export.py @ 12614

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

Add new payment state 'waived'. This state can only be set by import
and is only used for the payments overview exporter to
mark sessions with waived fees.

  • Property svn:keywords set to Id
File size: 47.1 KB
Line 
1## $Id: test_export.py 12568 2015-02-07 11:26:19Z 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##
18
19import os
20import grok
21import datetime
22from cStringIO import StringIO
23from zope.component import queryUtility, getUtility
24from zope.event import notify
25from zope.interface.verify import verifyObject, verifyClass
26from waeup.kofa.interfaces import (
27    ICSVExporter, IExtFileStore, IFileStoreNameChooser)
28from waeup.kofa.students.catalog import StudentsQuery
29from waeup.kofa.students.export import (
30    StudentExporter, StudentStudyCourseExporter, StudentStudyLevelExporter,
31    CourseTicketExporter, StudentPaymentsExporter, BedTicketsExporter,
32    StudentPaymentsOverviewExporter, StudentStudyLevelsOverviewExporter,
33    ComboCardDataExporter, DataForBursaryExporter,
34    get_students,)
35from waeup.kofa.students.accommodation import BedTicket
36from waeup.kofa.students.interfaces import ICSVStudentExporter
37from waeup.kofa.students.payments import StudentOnlinePayment
38from waeup.kofa.students.student import Student
39from waeup.kofa.students.studycourse import StudentStudyCourse
40from waeup.kofa.students.studylevel import StudentStudyLevel, CourseTicket
41from waeup.kofa.students.tests.test_batching import StudentImportExportSetup
42from waeup.kofa.testing import FunctionalLayer
43
44curr_year = datetime.datetime.now().year
45year_range = range(curr_year - 9, curr_year + 1)
46year_range_str = ','.join([str(i) for i in year_range])
47
48class ExportHelperTests(StudentImportExportSetup):
49    layer = FunctionalLayer
50    def setUp(self):
51        super(ExportHelperTests, self).setUp()
52        student = Student()
53        self.app['students'].addStudent(student)
54        student = self.setup_student(student)
55        notify(grok.ObjectModifiedEvent(student))
56        self.student = self.app['students'][student.student_id]
57        return
58
59    def test_get_students_plain(self):
60        # without a filter we get all students
61        result = get_students(self.app)
62        self.assertEqual(len(list(result)), 1)
63        return
64
65    def test_get_students_by_session(self):
66        # we can filter out students of a certain session
67        my_filter1 = StudentsQuery(current_session=2012)
68        result = get_students(self.app, stud_filter=my_filter1)
69        self.assertEqual(len(list(result)), 1)
70
71        my_filter2 = StudentsQuery(current_session=1964)
72        result = get_students(self.app, stud_filter=my_filter2)
73        self.assertEqual(len(list(result)), 0)
74        return
75
76    def test_get_students_by_level(self):
77        # we can filter out students of a certain level
78        my_filter1 = StudentsQuery(current_level=200)
79        result = get_students(self.app, stud_filter=my_filter1)
80        self.assertEqual(len(list(result)), 1)
81
82        my_filter2 = StudentsQuery(current_level=300)
83        result = get_students(self.app, stud_filter=my_filter2)
84        self.assertEqual(len(list(result)), 0)
85        return
86
87    def test_get_students_by_deptcode(self):
88        # we can filter out students of a certain dept.
89        my_filter1 = StudentsQuery(depcode='NA')
90        result = get_students(self.app, stud_filter=my_filter1)
91        self.assertEqual(len(list(result)), 1)
92
93        my_filter2 = StudentsQuery(depcode='NOTEXISTING')
94        result = get_students(self.app, stud_filter=my_filter2)
95        self.assertEqual(len(list(result)), 0)
96        return
97
98    def test_get_students_by_faccode(self):
99        # we can filter out students of a certain faculty.
100        my_filter1 = StudentsQuery(faccode='NA')
101        result = get_students(self.app, stud_filter=my_filter1)
102        self.assertEqual(len(list(result)), 1)
103
104        my_filter2 = StudentsQuery(faccode='NOTEXISTING')
105        result = get_students(self.app, stud_filter=my_filter2)
106        self.assertEqual(len(list(result)), 0)
107        return
108
109    def test_get_students_by_current_mode(self):
110        # we can filter out students in a certain mode.
111        my_filter1 = StudentsQuery(current_mode='ug_ft')
112        result = get_students(self.app, stud_filter=my_filter1)
113        self.assertEqual(len(list(result)), 1)
114
115        my_filter2 = StudentsQuery(current_mode='NOTEXISTING')
116        result = get_students(self.app, stud_filter=my_filter2)
117        self.assertEqual(len(list(result)), 0)
118        return
119
120
121class StudentExporterTest(StudentImportExportSetup):
122
123    layer = FunctionalLayer
124
125    std_csv_entry = (
126        'my adm code,0,my clr code,1981-02-04#,anna@sample.com,,'
127        'Anna,Tester,234,M.,NG,,"Studentroad 21\nLagos 123456\n",,'
128        '+234-123-12345#,123,f,A111111,0,,,,created'
129        )
130
131    def setUp(self):
132        super(StudentExporterTest, self).setUp()
133        self.setup_for_export()
134        return
135
136    def test_ifaces(self):
137        # make sure we fullfill interface contracts
138        obj = StudentExporter()
139        verifyObject(ICSVStudentExporter, obj)
140        verifyClass(ICSVStudentExporter, StudentExporter)
141        return
142
143    def test_get_as_utility(self):
144        # we can get an student exporter as utility
145        result = queryUtility(ICSVExporter, name="students")
146        self.assertTrue(result is not None)
147        return
148
149    def test_export(self):
150        # we can really export students
151        # set values we can expect in export file
152        self.setup_student(self.student)
153        exporter = StudentExporter()
154        exporter.export([self.student], self.outfile)
155        result = open(self.outfile, 'rb').read()
156        self.assertTrue(
157            'adm_code,clearance_locked,clr_code,date_of_birth,email,'
158            'employer,firstname,lastname,matric_number,middlename,'
159            'nationality,officer_comment,perm_address,personal_updated,'
160            'phone,reg_number,sex,student_id,suspended,suspended_comment,'
161            'transcript_comment,password,state,history,certcode,is_postgrad,'
162            'current_level,current_session\r\n'
163            'my adm code,0,my clr code,'
164            '1981-02-04#,anna@sample.com,,Anna,Tester,234,M.,NG,,'
165            '"Studentroad 21\nLagos 123456\n",,+234-123-12345#,123,f,'
166            'A111111,0,,,,created'
167            in result
168            )
169        return
170
171    def test_export_all(self):
172        # we can really export students
173        # set values we can expect in export file
174        self.setup_student(self.student)
175        exporter = StudentExporter()
176        exporter.export_all(self.app, self.outfile)
177        result = open(self.outfile, 'rb').read()
178        self.assertTrue(
179            'adm_code,clearance_locked,clr_code,date_of_birth,email,'
180            'employer,firstname,lastname,matric_number,middlename,'
181            'nationality,officer_comment,perm_address,personal_updated,'
182            'phone,reg_number,sex,student_id,suspended,suspended_comment,'
183            'transcript_comment,password,state,history,certcode,'
184            'is_postgrad,current_level,current_session\r\n'
185            'my adm code,0,my clr code,1981-02-04#,anna@sample.com,,'
186            'Anna,Tester,234,M.,NG,,"Studentroad 21\nLagos 123456\n"'
187            ',,+234-123-12345#,123,f,A111111,0,,,,created'
188            in result
189            )
190        return
191
192    def test_export_student(self):
193        # we can export a single student
194        self.setup_student(self.student)
195        exporter = StudentExporter()
196        exporter.export_student(self.student, self.outfile)
197        result = open(self.outfile, 'rb').read()
198        self.assertTrue(
199            'adm_code,clearance_locked,clr_code,date_of_birth,email,'
200            'employer,firstname,lastname,matric_number,middlename,'
201            'nationality,officer_comment,perm_address,personal_updated,'
202            'phone,reg_number,sex,student_id,suspended,suspended_comment,'
203            'transcript_comment,password,state,history,certcode,'
204            'is_postgrad,current_level,current_session\r\n'
205            'my adm code,0,my clr code,1981-02-04#,anna@sample.com,,'
206            'Anna,Tester,234,M.,NG,,"Studentroad 21\nLagos 123456\n"'
207            ',,+234-123-12345#,123,f,A111111,0,,,,created'
208            in result
209            )
210        return
211
212    def test_export_filtered(self):
213        # we can export a filtered set of students (filtered by session/level)
214        self.setup_student(self.student)
215        self.app['students'].addStudent(self.student)
216        notify(grok.ObjectModifiedEvent(self.student))
217        exporter = StudentExporter()
218
219        exporter.export_filtered(
220            self.app, self.outfile,
221            current_session=None, current_level=None)
222        result1 = open(self.outfile, 'rb').read()
223        exporter.export_filtered(
224            self.app, self.outfile,
225            current_session=2012, current_level=None)
226        result2 = open(self.outfile, 'rb').read()
227        # current_level and current_session can be both a string ...
228        exporter.export_filtered(
229            self.app, self.outfile,
230            current_session='2012', current_level=u'200')
231        result3 = open(self.outfile, 'rb').read()
232        exporter.export_filtered(
233            self.app, self.outfile,
234            current_session=2011, current_level=None)
235        result4 = open(self.outfile, 'rb').read()
236        # ... and an integer
237        exporter.export_filtered(
238            self.app, self.outfile,
239            current_session=None, current_level=100)
240        result5 = open(self.outfile, 'rb').read()
241        # Also students at probating levels are being exported ...
242        self.student['studycourse'].current_level = 210
243        notify(grok.ObjectModifiedEvent(self.student))
244        exporter.export_filtered(
245            self.app, self.outfile,
246            current_session=None, current_level=200)
247        result6 = open(self.outfile, 'rb').read()
248        # ... but not in the wrong level range.
249        self.student['studycourse'].current_level = 310
250        notify(grok.ObjectModifiedEvent(self.student))
251        exporter.export_filtered(
252            self.app, self.outfile,
253            current_session=None, current_level=200)
254        result7 = open(self.outfile, 'rb').read()
255        self.assertTrue(self.std_csv_entry in result1)
256        self.assertTrue(self.std_csv_entry in result2)
257        self.assertTrue(self.std_csv_entry in result3)
258        self.assertFalse(self.std_csv_entry in result4)
259        self.assertFalse(self.std_csv_entry in result5)
260        self.assertTrue(self.std_csv_entry in result6)
261        self.assertFalse(self.std_csv_entry in result7)
262        return
263
264    def test_export_selected(self):
265        # we can export a filtered set of students (filtered by session/level)
266        self.setup_student(self.student)
267        self.app['students'].addStudent(self.student)
268        notify(grok.ObjectModifiedEvent(self.student))
269        exporter = StudentExporter()
270        exporter.export_selected(
271            self.app, self.outfile, selected=['A111111'])
272        result1 = open(self.outfile, 'rb').read()
273        exporter.export_selected(
274            self.app, self.outfile, selected=[])
275        result2 = open(self.outfile, 'rb').read()
276        self.assertTrue(self.std_csv_entry in result1)
277        self.assertFalse(self.std_csv_entry in result2)
278        return
279
280    def test_export_filtered_by_dept(self):
281        # we can export a set of students filtered by department
282        self.setup_student(self.student)
283        self.app['students'].addStudent(self.student)
284        notify(grok.ObjectModifiedEvent(self.student))
285        exporter = StudentExporter()
286        # current_session can be both a string ...
287        exporter.export_filtered(
288            self.app, self.outfile,
289            current_session='2012', current_level=u'200', depcode='NA')
290        result1 = open(self.outfile, 'rb').read()
291        # ... and an integer
292        exporter.export_filtered(
293            self.app, self.outfile,
294            current_session=2012, current_level=200, depcode='NODEPT')
295        result2 = open(self.outfile, 'rb').read()
296        self.assertTrue(self.std_csv_entry in result1)
297        self.assertTrue(self.std_csv_entry not in result2)
298        return
299
300    def test_export_filtered_by_faculty(self):
301        # we can export a set of students filtered by faculty
302        self.setup_student(self.student)
303        self.app['students'].addStudent(self.student)
304        notify(grok.ObjectModifiedEvent(self.student))
305        exporter = StudentExporter()
306
307        exporter.export_filtered(
308            self.app, self.outfile,
309            current_session=2012, current_level='200', faccode='NA')
310        result1 = open(self.outfile, 'rb').read()
311        exporter.export_filtered(
312            self.app, self.outfile,
313            current_session=2012, current_level=200, faccode='NOFAC')
314        result2 = open(self.outfile, 'rb').read()
315        self.assertTrue(self.std_csv_entry in result1)
316        self.assertTrue(self.std_csv_entry not in result2)
317        return
318
319class StudentStudyCourseExporterTest(StudentImportExportSetup):
320
321    layer = FunctionalLayer
322
323    def setUp(self):
324        super(StudentStudyCourseExporterTest, self).setUp()
325        self.setup_for_export()
326        return
327
328    def test_ifaces(self):
329        # make sure we fullfill interface contracts
330        obj = StudentStudyCourseExporter()
331        verifyObject(ICSVStudentExporter, obj)
332        verifyClass(ICSVStudentExporter, StudentStudyCourseExporter)
333        return
334
335    def test_get_as_utility(self):
336        # we can get an student exporter as utility
337        result = queryUtility(ICSVExporter, name="studentstudycourses")
338        self.assertTrue(result is not None)
339        return
340
341    def test_export_empty(self):
342        # we can export a nearly empty study course
343        study_course = StudentStudyCourse()
344        exporter = StudentStudyCourseExporter()
345        exporter.export([study_course], self.outfile)
346        result = open(self.outfile, 'rb').read()
347        self.assertEqual(
348            result,
349            'certificate,current_level,current_session,current_verdict,'
350            'entry_mode,entry_session,previous_verdict,student_id\r\n'
351
352            ',,,0,,,0,\r\n'
353            )
354        return
355
356    def test_export(self):
357        # we can really export study courses.
358        # set values we can expect in export file
359        self.setup_student(self.student)
360        study_course = self.student.get('studycourse')
361        exporter = StudentStudyCourseExporter()
362        exporter.export([study_course], self.outfile)
363        result = open(self.outfile, 'rb').read()
364        self.assertEqual(
365            result,
366            'certificate,current_level,current_session,current_verdict,'
367            'entry_mode,entry_session,previous_verdict,student_id\r\n'
368
369            'CERT1,200,2012,0,ug_ft,2010,0,A111111\r\n'
370            )
371        return
372
373    def test_export_all(self):
374        # we can really export students
375        # set values we can expect in export file
376        self.setup_student(self.student)
377        exporter = StudentStudyCourseExporter()
378        exporter.export_all(self.app, self.outfile)
379        result = open(self.outfile, 'rb').read()
380        self.assertEqual(
381            result,
382            'certificate,current_level,current_session,current_verdict,'
383            'entry_mode,entry_session,previous_verdict,student_id\r\n'
384
385            'CERT1,200,2012,0,ug_ft,2010,0,A111111\r\n'
386            )
387        return
388
389    def test_export_student(self):
390        # we can export studycourse of a certain student
391        self.setup_student(self.student)
392        exporter = StudentStudyCourseExporter()
393        exporter.export_student(self.student, self.outfile)
394        result = open(self.outfile, 'rb').read()
395        self.assertEqual(
396            result,
397            'certificate,current_level,current_session,current_verdict,'
398            'entry_mode,entry_session,previous_verdict,student_id\r\n'
399
400            'CERT1,200,2012,0,ug_ft,2010,0,A111111\r\n'
401            )
402        return
403
404    def test_export_filtered(self):
405        # we can export studycourses of a filtered set of students
406        self.setup_student(self.student)
407        self.app['students'].addStudent(self.student)
408        notify(grok.ObjectModifiedEvent(self.student))
409
410        exporter = StudentStudyCourseExporter()
411        exporter.export_filtered(
412            self.student, self.outfile, current_session=2012)
413        result = open(self.outfile, 'rb').read()
414        self.assertEqual(
415            result,
416            'certificate,current_level,current_session,current_verdict,'
417            'entry_mode,entry_session,previous_verdict,student_id\r\n'
418
419            'CERT1,200,2012,0,ug_ft,2010,0,A111111\r\n'
420            )
421        return
422
423    def test_export_selected(self):
424        # we can export a filtered set of students (filtered by session/level)
425        self.setup_student(self.student)
426        self.app['students'].addStudent(self.student)
427        notify(grok.ObjectModifiedEvent(self.student))
428        exporter = StudentStudyCourseExporter()
429        exporter.export_selected(
430            self.app, self.outfile, selected=['A111111'])
431        result = open(self.outfile, 'rb').read()
432        self.assertEqual(
433            result,
434            'certificate,current_level,current_session,current_verdict,'
435            'entry_mode,entry_session,previous_verdict,student_id\r\n'
436
437            'CERT1,200,2012,0,ug_ft,2010,0,A111111\r\n'
438            )
439        return
440
441
442class StudentStudyLevelExporterTest(StudentImportExportSetup):
443
444    layer = FunctionalLayer
445
446    def setUp(self):
447        super(StudentStudyLevelExporterTest, self).setUp()
448        self.setup_for_export()
449        return
450
451    def test_ifaces(self):
452        # make sure we fullfill interface contracts
453        obj = StudentStudyLevelExporter()
454        verifyObject(ICSVStudentExporter, obj)
455        verifyClass(ICSVStudentExporter, StudentStudyLevelExporter)
456        return
457
458    def test_get_as_utility(self):
459        # we can get an student exporter as utility
460        result = queryUtility(ICSVExporter, name="studentstudylevels")
461        self.assertTrue(result is not None)
462        return
463
464    def test_export_empty(self):
465        # we can export a nearly empty study level
466        study_level = StudentStudyLevel()
467        exporter = StudentStudyLevelExporter()
468        exporter.export([study_level], self.outfile)
469        result = open(self.outfile, 'rb').read()
470        self.assertEqual(
471            result,
472            'gpa,level,level_session,level_verdict,total_credits,'
473            'validated_by,validation_date,'
474            'student_id,number_of_tickets,certcode\r\n'
475            '0.0,,,0,0,,,,0,\r\n'
476            )
477        return
478
479    def test_export(self):
480        # we can really export study levels.
481        # set values we can expect in export file
482        self.setup_student(self.student)
483        study_course = self.student.get('studycourse')
484        study_level = study_course[study_course.keys()[0]]
485        exporter = StudentStudyLevelExporter()
486        exporter.export([study_level], self.outfile)
487        result = open(self.outfile, 'rb').read()
488        self.assertEqual(
489            result,
490            'gpa,level,level_session,level_verdict,total_credits,'
491            'validated_by,validation_date,'
492            'student_id,number_of_tickets,certcode\r\n'
493            '0.0,100,2012,A,100,,,A111111,1,CERT1\r\n'
494            )
495        return
496
497    def test_export_all(self):
498        # we can really export study levels
499        # set values we can expect in export file
500        self.setup_student(self.student)
501        exporter = StudentStudyLevelExporter()
502        exporter.export_all(self.app, self.outfile)
503        result = open(self.outfile, 'rb').read()
504        self.assertEqual(
505            result,
506            'gpa,level,level_session,level_verdict,total_credits,'
507            'validated_by,validation_date,'
508            'student_id,number_of_tickets,certcode\r\n'
509            '0.0,100,2012,A,100,,,A111111,1,CERT1\r\n'
510            )
511        return
512
513    def test_export_student(self):
514        # we can really export study levels of a certain student
515        self.setup_student(self.student)
516        exporter = StudentStudyLevelExporter()
517        exporter.export_student(self.student, self.outfile)
518        result = open(self.outfile, 'rb').read()
519        self.assertEqual(
520            result,
521            'gpa,level,level_session,level_verdict,total_credits,'
522            'validated_by,validation_date,'
523            'student_id,number_of_tickets,certcode\r\n'
524            '0.0,100,2012,A,100,,,A111111,1,CERT1\r\n'
525            )
526        return
527
528    def test_export_filtered(self):
529        # we can export studylevels of a filtered set of students
530        self.setup_student(self.student)
531        self.app['students'].addStudent(self.student)
532        notify(grok.ObjectModifiedEvent(self.student))
533
534        exporter = StudentStudyLevelExporter()
535        exporter.export_filtered(
536            self.student, self.outfile)
537        result = open(self.outfile, 'rb').read()
538        self.assertEqual(
539            result,
540            'gpa,level,level_session,level_verdict,total_credits,'
541            'validated_by,validation_date,'
542            'student_id,number_of_tickets,certcode\r\n'
543            '0.0,100,2012,A,100,,,A111111,1,CERT1\r\n'
544            )
545        return
546
547    def test_export_selected(self):
548        # we can export studylevels of a filtered set of students
549        self.setup_student(self.student)
550        self.app['students'].addStudent(self.student)
551        notify(grok.ObjectModifiedEvent(self.student))
552
553        exporter = StudentStudyLevelExporter()
554        exporter.export_selected(
555            self.app, self.outfile, selected=['A111111'])
556        result = open(self.outfile, 'rb').read()
557        self.assertEqual(
558            result,
559            'gpa,level,level_session,level_verdict,total_credits,'
560            'validated_by,validation_date,'
561            'student_id,number_of_tickets,certcode\r\n'
562            '0.0,100,2012,A,100,,,A111111,1,CERT1\r\n'
563            )
564        return
565
566class CourseTicketExporterTest(StudentImportExportSetup):
567
568    layer = FunctionalLayer
569
570    def setUp(self):
571        super(CourseTicketExporterTest, self).setUp()
572        self.setup_for_export()
573        return
574
575    def test_ifaces(self):
576        # make sure we fullfill interface contracts
577        obj = CourseTicketExporter()
578        verifyObject(ICSVStudentExporter, obj)
579        verifyClass(ICSVStudentExporter, CourseTicketExporter)
580        return
581
582    def test_get_as_utility(self):
583        # we can get an student exporter as utility
584        result = queryUtility(ICSVExporter, name="coursetickets")
585        self.assertTrue(result is not None)
586        return
587
588    def test_export_empty(self):
589        # we can export a nearly empty course ticket
590        ticket = CourseTicket()
591        exporter = CourseTicketExporter()
592        exporter.export([ticket], self.outfile)
593        result = open(self.outfile, 'rb').read()
594        self.assertEqual(
595            result,
596            'automatic,carry_over,code,credits,dcode,fcode,level,level_session,'
597            'mandatory,passmark,score,semester,title,student_id,certcode,'
598            'display_fullname\r\n'
599            '0,0,,,,,,,0,,,,,,,\r\n'
600            )
601        return
602
603    def test_export(self):
604        # we can really export course tickets.
605        # set values we can expect in export file
606        self.setup_student(self.student)
607        study_course = self.student.get('studycourse')
608        study_level = study_course[study_course.keys()[0]]
609        ticket = study_level['CRS1']
610        exporter = CourseTicketExporter()
611        exporter.export([ticket], self.outfile)
612        result = open(self.outfile, 'rb').read()
613        self.assertEqual(
614            result,
615            'automatic,carry_over,code,credits,dcode,fcode,level,level_session,'
616            'mandatory,passmark,score,semester,title,student_id,certcode,'
617            'display_fullname\r\n'
618            '1,1,CRS1,100,DEP1,FAC1,100,2012,0,100,,2,Course 1,A111111,CERT1,'
619            'Anna M. Tester\r\n'
620            )
621        return
622
623    def test_export_all(self):
624        # we can really export all course tickets
625        # set values we can expect in export file
626        self.setup_student(self.student)
627        exporter = CourseTicketExporter()
628        exporter.export_all(self.app, self.outfile)
629        result = open(self.outfile, 'rb').read()
630        self.assertEqual(
631            result,
632            'automatic,carry_over,code,credits,dcode,fcode,level,level_session,'
633            'mandatory,passmark,score,semester,title,student_id,certcode,'
634            'display_fullname\r\n'
635            '1,1,CRS1,100,DEP1,FAC1,100,2012,0,100,,2,Course 1,A111111,CERT1,'
636            'Anna M. Tester\r\n'
637            )
638        return
639
640    def test_export_student(self):
641        # we can really export all course tickets of a certain student
642        self.setup_student(self.student)
643        exporter = CourseTicketExporter()
644        exporter.export_student(self.student, self.outfile)
645        result = open(self.outfile, 'rb').read()
646        self.assertEqual(
647            result,
648            'automatic,carry_over,code,credits,dcode,fcode,level,level_session,'
649            'mandatory,passmark,score,semester,title,student_id,certcode,'
650            'display_fullname\r\n'
651            '1,1,CRS1,100,DEP1,FAC1,100,2012,0,100,,2,Course 1,A111111,CERT1,'
652            'Anna M. Tester\r\n'
653            )
654        return
655
656    def test_export_filtered(self):
657        # we can export course tickets of a filtered set of students
658        self.setup_student(self.student)
659        self.app['students'].addStudent(self.student)
660        notify(grok.ObjectModifiedEvent(self.student))
661
662        exporter = CourseTicketExporter()
663        exporter.export_filtered(
664            self.student, self.outfile)
665        result = open(self.outfile, 'rb').read()
666        self.assertEqual(
667            result,
668            'automatic,carry_over,code,credits,dcode,fcode,level,level_session,'
669            'mandatory,passmark,score,semester,title,student_id,certcode,'
670            'display_fullname\r\n'
671            '1,1,CRS1,100,DEP1,FAC1,100,2012,0,100,,2,Course 1,A111111,CERT1,'
672            'Anna M. Tester\r\n'
673            )
674        # if the coursetickets catalog is used to filter students
675        # and (course) code is not None
676        # only course tickets which belong to this course are exported
677        exporter.export_filtered(
678            self.student, self.outfile, catalog='coursetickets', code='CRS1')
679        result = open(self.outfile, 'rb').read()
680        self.assertEqual(
681            result,
682            'automatic,carry_over,code,credits,dcode,fcode,level,level_session,'
683            'mandatory,passmark,score,semester,title,student_id,certcode,'
684            'display_fullname\r\n'
685            '1,1,CRS1,100,DEP1,FAC1,100,2012,0,100,,2,Course 1,A111111,CERT1,'
686            'Anna M. Tester\r\n'
687            )
688        exporter.export_filtered(
689            self.student, self.outfile, catalog='coursetickets', code='any code')
690        result = open(self.outfile, 'rb').read()
691        self.assertEqual(
692            result,
693            'automatic,carry_over,code,credits,dcode,fcode,level,level_session,'
694            'mandatory,passmark,score,semester,title,student_id,certcode,'
695            'display_fullname\r\n'
696            )
697        # Also tickets in probating levels are exported. Therefore
698        # we change the level attribute to fake a 110 level.
699        self.student['studycourse']['100'].level = 110
700        notify(grok.ObjectModifiedEvent(self.student['studycourse']['100']['CRS1']))
701        exporter.export_filtered(
702            self.student, self.outfile, catalog='coursetickets', code='CRS1', level='100')
703        result = open(self.outfile, 'rb').read()
704        self.assertEqual(
705            result,
706            'automatic,carry_over,code,credits,dcode,fcode,level,level_session,'
707            'mandatory,passmark,score,semester,title,student_id,certcode,'
708            'display_fullname\r\n'
709            '1,1,CRS1,100,DEP1,FAC1,110,2012,0,100,,2,Course 1,A111111,CERT1,'
710            'Anna M. Tester\r\n'
711            )
712        return
713
714class StudentPaymentsExporterTest(StudentImportExportSetup):
715
716    layer = FunctionalLayer
717
718    def setUp(self):
719        super(StudentPaymentsExporterTest, self).setUp()
720        self.setup_for_export()
721        return
722
723    def test_ifaces(self):
724        # make sure we fullfill interface contracts
725        obj = StudentPaymentsExporter()
726        verifyObject(ICSVStudentExporter, obj)
727        verifyClass(ICSVStudentExporter, StudentPaymentsExporter)
728        return
729
730    def test_get_as_utility(self):
731        # we can get a payments exporter as utility
732        result = queryUtility(ICSVExporter, name="studentpayments")
733        self.assertTrue(result is not None)
734        return
735
736    def test_export_empty(self):
737        # we can export a nearly empty payment
738        payment = StudentOnlinePayment()
739        payment.creation_date = datetime.datetime(2012, 4, 1, 13, 12, 1)
740        exporter = StudentPaymentsExporter()
741        exporter.export([payment], self.outfile)
742        result = open(self.outfile, 'rb').read()
743        self.assertEqual(
744            result,
745            'ac,amount_auth,creation_date,p_category,p_current,p_id,'
746            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
747            'r_code,r_desc,student_id,state,current_session\r\n'
748
749            ',0.0,2012-04-01 13:12:01#,,1,,,,,unpaid,,0.0,,,,,\r\n'
750            )
751        return
752
753    def test_export(self):
754        # we can really export student payments.
755        # set values we can expect in export file
756        self.setup_student(self.student)
757        payment = self.student['payments']['my-payment']
758        exporter = StudentPaymentsExporter()
759        exporter.export([payment], self.outfile)
760        result = open(self.outfile, 'rb').read()
761        self.assertEqual(
762            result,
763            'ac,amount_auth,creation_date,p_category,p_current,p_id,'
764            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
765            'r_code,r_desc,student_id,state,current_session\r\n'
766
767            '666,12.12,2012-04-01 13:12:01#,schoolfee,1,my-id,'
768            'p-item,100,2012,paid,2012-04-01 14:12:01#,12.12,'
769            'r-code,,A111111,created,2012\r\n'
770            )
771        return
772
773    def test_export_all(self):
774        # we can really export all payments
775        # set values we can expect in export file
776        self.setup_student(self.student)
777        exporter = StudentPaymentsExporter()
778        exporter.export_all(self.app, self.outfile)
779        result = open(self.outfile, 'rb').read()
780        self.assertEqual(
781            result,
782            'ac,amount_auth,creation_date,p_category,p_current,p_id,'
783            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
784            'r_code,r_desc,student_id,state,current_session\r\n'
785
786            '666,12.12,2012-04-01 13:12:01#,schoolfee,1,my-id,'
787            'p-item,100,2012,paid,2012-04-01 14:12:01#,12.12,'
788            'r-code,,A111111,created,2012\r\n'
789            )
790        return
791
792    def test_export_student(self):
793        # we can really export all payments of a certain student
794        # set values we can expect in export file
795        self.setup_student(self.student)
796        exporter = StudentPaymentsExporter()
797        exporter.export_student(self.student, self.outfile)
798        result = open(self.outfile, 'rb').read()
799        self.assertEqual(
800            result,
801            'ac,amount_auth,creation_date,p_category,p_current,p_id,'
802            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
803            'r_code,r_desc,student_id,state,current_session\r\n'
804
805            '666,12.12,2012-04-01 13:12:01#,schoolfee,1,my-id,'
806            'p-item,100,2012,paid,2012-04-01 14:12:01#,12.12,'
807            'r-code,,A111111,created,2012\r\n'
808            )
809        return
810
811    def test_export_filtered(self):
812        # we can export payments of a filtered set of students
813        self.setup_student(self.student)
814        self.app['students'].addStudent(self.student)
815        notify(grok.ObjectModifiedEvent(self.student))
816
817        exporter = StudentPaymentsExporter()
818        exporter.export_filtered(
819            self.student, self.outfile, current_level=200)
820        result = open(self.outfile, 'rb').read()
821        self.assertEqual(
822            result,
823            'ac,amount_auth,creation_date,p_category,p_current,p_id,'
824            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
825            'r_code,r_desc,student_id,state,current_session\r\n'
826
827            '666,12.12,2012-04-01 13:12:01#,schoolfee,1,my-id,'
828            'p-item,100,2012,paid,2012-04-01 14:12:01#,12.12,'
829            'r-code,,A111111,created,2012\r\n'
830            )
831        return
832
833    def test_export_filtered_by_date(self):
834        # payments_start and payments_end are being ignored
835        self.setup_student(self.student)
836        self.app['students'].addStudent(self.student)
837        notify(grok.ObjectModifiedEvent(self.student))
838        exporter = StudentPaymentsExporter()
839        # A key xxx does not exist
840        self.assertRaises(
841            KeyError, exporter.export_filtered, self.app, self.outfile,
842            current_session=None,
843            current_level=None, xxx='nonsense')
844        # payments_start and payments_end do exist but must match format '%Y-%m-%d'
845        self.assertRaises(
846            ValueError, exporter.export_filtered, self.app, self.outfile,
847            current_session=None, current_level=None,
848            payments_start='nonsense', payments_end='nonsense')
849        # If they match the format they are ignored by get_filtered and the
850        # exporter works properly
851        exporter.export_filtered(
852            self.app, self.outfile,
853            current_session=None, current_level=None,
854            payments_start='01/04/2012', payments_end='02/04/2012')
855        result = open(self.outfile, 'rb').read()
856        self.assertEqual(
857            result,
858            'ac,amount_auth,creation_date,p_category,p_current,p_id,'
859            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
860            'r_code,r_desc,student_id,state,current_session\r\n'
861
862            '666,12.12,2012-04-01 13:12:01#,schoolfee,1,my-id,'
863            'p-item,100,2012,paid,2012-04-01 14:12:01#,12.12,'
864            'r-code,,A111111,created,2012\r\n'
865            )
866        # no results if payment_date is outside the given period
867        exporter.export_filtered(
868            self.app, self.outfile,
869            current_session=None, current_level=None,
870            payments_start='31/03/2012', payments_end='01/04/2012')
871        result = open(self.outfile, 'rb').read()
872        self.assertEqual(
873            result,
874            'ac,amount_auth,creation_date,p_category,p_current,p_id,'
875            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
876            'r_code,r_desc,student_id,state,current_session\r\n'
877            )
878        exporter.export_filtered(
879            self.app, self.outfile,
880            current_session=None, current_level=None,
881            payments_start='02/04/2012', payments_end='03/04/2012')
882        result = open(self.outfile, 'rb').read()
883        self.assertEqual(
884            result,
885            'ac,amount_auth,creation_date,p_category,p_current,p_id,'
886            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
887            'r_code,r_desc,student_id,state,current_session\r\n'
888            )
889        # no results if payment_date is not set
890        self.payment.payment_date = None
891        exporter.export_filtered(
892            self.app, self.outfile,
893            current_session=None, current_level=None,
894            payments_start='01/04/2012', payments_end='02/04/2012')
895        result = open(self.outfile, 'rb').read()
896       
897        return
898
899class BursaryDataExporterTest(StudentImportExportSetup):
900
901    layer = FunctionalLayer
902
903    def setUp(self):
904        super(BursaryDataExporterTest, self).setUp()
905        self.setup_for_export()
906        return
907
908    def test_export_all(self):
909        # we can really export all payments
910        # set values we can expect in export file
911        self.setup_student(self.student)
912        exporter = DataForBursaryExporter()
913        exporter.export_all(self.app, self.outfile)
914        result = open(self.outfile, 'rb').read()
915        self.assertEqual(
916            result,
917            'ac,amount_auth,creation_date,p_category,p_current,p_id,p_item,'
918            'p_level,p_session,p_state,payment_date,r_amount_approved,r_code,'
919            'r_desc,student_id,matric_number,reg_number,firstname,middlename,lastname,'
920            'state,current_session,entry_session,entry_mode,faccode,depcode,certcode\r\n'
921
922            '666,12.12,2012-04-01 13:12:01#,schoolfee,1,my-id,p-item,100,2012,'
923            'paid,2012-04-01 14:12:01#,12.12,r-code,,A111111,234,123,'
924            'Anna,M.,Tester,created,2012,2010,ug_ft,NA,NA,CERT1\r\n'
925            )
926        return
927
928class BedTicketsExporterTest(StudentImportExportSetup):
929
930    layer = FunctionalLayer
931
932    def setUp(self):
933        super(BedTicketsExporterTest, self).setUp()
934        self.setup_for_export()
935        return
936
937    def test_ifaces(self):
938        # make sure we fullfill interface contracts
939        obj = BedTicketsExporter()
940        verifyObject(ICSVStudentExporter, obj)
941        verifyClass(ICSVStudentExporter, BedTicketsExporter)
942        return
943
944    def test_get_as_utility(self):
945        # we can get a bedtickets exporter as utility
946        result = queryUtility(ICSVExporter, name="bedtickets")
947        self.assertTrue(result is not None)
948        return
949
950    def test_export_empty(self):
951        # we can export a nearly empty bedticket
952        bedticket = BedTicket()
953        bed = self.app['hostels']['hall-1']['hall-1_A_101_A']
954        bedticket.bed = bed
955        exporter = BedTicketsExporter()
956        exporter.export([bedticket], self.outfile)
957        result = open(self.outfile, 'rb').read()
958        self.assertMatches(
959            result,
960            'bed,bed_coordinates,bed_type,booking_code,booking_date,'
961            'booking_session,student_id,actual_bed_type\r\n'
962            'hall-1_A_101_A,,,,<YYYY-MM-DD hh:mm:ss>.<6-DIGITS>#,,,regular_male_fr\r\n'
963            )
964        return
965
966    def test_export(self):
967        # we can really export student bedtickets.
968        # set values we can expect in export file
969        self.setup_student(self.student)
970        bedticket = self.student['accommodation']['2004']
971        exporter = BedTicketsExporter()
972        exporter.export([bedticket], self.outfile)
973        result = open(self.outfile, 'rb').read()
974        self.assertMatches(
975            result,
976            'bed,bed_coordinates,bed_type,booking_code,booking_date,'
977            'booking_session,student_id,actual_bed_type\r\n'
978            'hall-1_A_101_A,,any bed type,,<YYYY-MM-DD hh:mm:ss>.<6-DIGITS>#,2004,'
979            'A111111,regular_male_fr\r\n'
980            )
981        return
982
983    def test_export_all(self):
984        # we can really export all bedtickets
985        # set values we can expect in export file
986        self.setup_student(self.student)
987        exporter = BedTicketsExporter()
988        exporter.export_all(self.app, self.outfile)
989        result = open(self.outfile, 'rb').read()
990        self.assertMatches(
991            result,
992            'bed,bed_coordinates,bed_type,booking_code,booking_date,'
993            'booking_session,student_id,actual_bed_type\r\n'
994            'hall-1_A_101_A,,any bed type,,<YYYY-MM-DD hh:mm:ss>.<6-DIGITS>#,2004,'
995            'A111111,regular_male_fr\r\n'
996            )
997        return
998
999    def test_export_student(self):
1000        # we can really export all bedtickets of a certain student
1001        # set values we can expect in export file
1002        self.setup_student(self.student)
1003        exporter = BedTicketsExporter()
1004        exporter.export_student(self.student, self.outfile)
1005        result = open(self.outfile, 'rb').read()
1006        self.assertMatches(
1007            result,
1008            'bed,bed_coordinates,bed_type,booking_code,booking_date,'
1009            'booking_session,student_id,actual_bed_type\r\n'
1010            'hall-1_A_101_A,,any bed type,,<YYYY-MM-DD hh:mm:ss>.<6-DIGITS>#,2004,'
1011            'A111111,regular_male_fr\r\n'
1012            )
1013        return
1014
1015    def test_export_filtered(self):
1016        # we can export payments of a filtered set of students
1017        self.setup_student(self.student)
1018        self.app['students'].addStudent(self.student)
1019        notify(grok.ObjectModifiedEvent(self.student))
1020
1021        exporter = BedTicketsExporter()
1022        exporter.export_filtered(
1023            self.student, self.outfile, current_level=200)
1024        result = open(self.outfile, 'rb').read()
1025        self.assertMatches(
1026            result,
1027            'bed,bed_coordinates,bed_type,booking_code,booking_date,'
1028            'booking_session,student_id,actual_bed_type\r\n'
1029            'hall-1_A_101_A,,any bed type,,<YYYY-MM-DD hh:mm:ss>.<6-DIGITS>#,'
1030            '2004,A111111,regular_male_fr\r\n')
1031        return
1032
1033
1034class StudentPaymentsOverviewExporterTest(StudentImportExportSetup):
1035
1036    layer = FunctionalLayer
1037
1038    def setUp(self):
1039        super(StudentPaymentsOverviewExporterTest, self).setUp()
1040        self.setup_for_export()
1041        return
1042
1043    def test_ifaces(self):
1044        # make sure we fullfill interface contracts
1045        obj = StudentPaymentsOverviewExporter()
1046        verifyObject(ICSVStudentExporter, obj)
1047        verifyClass(ICSVStudentExporter, StudentPaymentsOverviewExporter)
1048        return
1049
1050    def test_get_as_utility(self):
1051        # we can get a payments exporter as utility
1052        result = queryUtility(ICSVExporter, name="paymentsoverview")
1053        self.assertTrue(result is not None)
1054        return
1055
1056    def test_export(self):
1057        self.setup_student(self.student)
1058        exporter = StudentPaymentsOverviewExporter()
1059        exporter.export([self.student], self.outfile)
1060        result = open(self.outfile, 'rb').read()
1061        self.assertTrue(
1062            'student_id,matric_number,display_fullname,state,certcode,'
1063            'faccode,depcode,is_postgrad,'
1064            'current_level,current_session,current_mode,'
1065            '%s\r\n'
1066            'A111111,234,Anna M. Tester,created,CERT1,NA,NA,0,200,2012,ug_ft,'
1067            % year_range_str in result
1068            )
1069        return
1070
1071    def test_export_all(self):
1072        # we can really export students
1073        # set values we can expect in export file
1074        self.setup_student(self.student)
1075        # We add successful payments.
1076        payment_2 = StudentOnlinePayment()
1077        payment_2.p_id = 'my-id'
1078        payment_2.p_session = curr_year - 5
1079        payment_2.amount_auth = 13.13
1080        payment_2.p_state = 'paid'
1081        payment_2.p_category = u'schoolfee'
1082        self.student['payments']['my-2ndpayment'] = payment_2
1083        # This one could be a balance payment.
1084        # The amount is being added.
1085        payment_3 = StudentOnlinePayment()
1086        payment_3.p_id = 'my-id_2'
1087        payment_3.p_session = curr_year - 5
1088        payment_3.amount_auth = 1.01
1089        payment_3.p_state = 'paid'
1090        payment_3.p_category = u'schoolfee'
1091        self.student['payments']['my-3rdpayment'] = payment_3
1092        # One session school fee has been waived
1093        payment_4 = StudentOnlinePayment()
1094        payment_4.p_id = 'my-id_2'
1095        payment_4.p_session = curr_year - 4
1096        payment_4.amount_auth = 1.01
1097        payment_4.p_state = 'waived'
1098        payment_4.p_category = u'schoolfee'
1099        self.student['payments']['my-4thpayment'] = payment_4
1100        exporter = StudentPaymentsOverviewExporter()
1101        exporter.export_all(self.app, self.outfile)
1102        result = open(self.outfile, 'rb').read()
1103        self.assertTrue(
1104            'student_id,matric_number,display_fullname,state,'
1105            'certcode,faccode,depcode,is_postgrad,'
1106            'current_level,current_session,current_mode,'
1107            '%s\r\nA111111,234,Anna M. Tester,created,CERT1,NA,NA,0,'
1108            '200,2012,ug_ft,,,,,14.14,waived,12.12,,,\r\n'
1109            % year_range_str in result
1110            )
1111        return
1112
1113class StudentStudyLevelsOverviewExporterTest(StudentImportExportSetup):
1114
1115    layer = FunctionalLayer
1116
1117    def setUp(self):
1118        super(StudentStudyLevelsOverviewExporterTest, self).setUp()
1119        self.setup_for_export()
1120        return
1121
1122    def test_ifaces(self):
1123        obj = StudentStudyLevelsOverviewExporter()
1124        verifyObject(ICSVStudentExporter, obj)
1125        verifyClass(ICSVStudentExporter, StudentStudyLevelsOverviewExporter)
1126        return
1127
1128    def test_get_as_utility(self):
1129        result = queryUtility(ICSVExporter, name="studylevelsoverview")
1130        self.assertTrue(result is not None)
1131        return
1132
1133    def test_export(self):
1134        self.setup_student(self.student)
1135        exporter = StudentStudyLevelsOverviewExporter()
1136        exporter.export([self.student], self.outfile)
1137        result = open(self.outfile, 'rb').read()
1138        self.assertEqual(
1139             'student_id,state,certcode,faccode,depcode,is_postgrad,'
1140             'entry_session,current_level,current_session,'
1141             '10,100,110,120,200,210,220,300,310,320,400,410,420,500,'
1142             '510,520,600,610,620,700,710,720,800,810,820,900,910,920,999\r\n'
1143             'A111111,created,CERT1,NA,NA,0,2010,200,2012,,2012'
1144             ',,,,,,,,,,,,,,,,,,,,,,,,,,,\r\n',
1145            result
1146            )
1147        return
1148
1149    def test_export_all(self):
1150        self.setup_student(self.student)
1151        exporter = StudentStudyLevelsOverviewExporter()
1152        exporter.export_all(self.app, self.outfile)
1153        result = open(self.outfile, 'rb').read()
1154        self.assertEqual(
1155            'student_id,state,certcode,faccode,depcode,is_postgrad,'
1156            'entry_session,current_level,current_session,'
1157            '10,100,110,120,200,210,220,300,310,320,400,410,420,500,'
1158            '510,520,600,610,620,700,710,720,800,810,820,900,910,920,999\r\n'
1159            'A111111,created,CERT1,NA,NA,0,2010,200,2012,,2012'
1160            ',,,,,,,,,,,,,,,,,,,,,,,,,,,\r\n',
1161            result
1162            )
1163        return
1164
1165class ComboCardExporterTest(StudentImportExportSetup):
1166
1167    layer = FunctionalLayer
1168
1169    def setUp(self):
1170        super(ComboCardExporterTest, self).setUp()
1171        self.setup_for_export()
1172        return
1173
1174    def create_passport_img(self, student):
1175        # create some passport file for `student`
1176        storage = getUtility(IExtFileStore)
1177        image_path = os.path.join(os.path.dirname(__file__), 'test_image.jpg')
1178        self.image_contents = open(image_path, 'rb').read()
1179        file_id = IFileStoreNameChooser(student).chooseName(
1180            attr='passport.jpg')
1181        storage.createFile(file_id, StringIO(self.image_contents))
1182
1183    def test_export_all(self):
1184        self.setup_student(self.student)
1185        self.create_passport_img(self.student)
1186        exporter = ComboCardDataExporter()
1187        exporter.export_all(self.app, self.outfile)
1188        result = open(self.outfile, 'rb').read()
1189        self.assertTrue(
1190            'display_fullname,student_id,matric_number,certificate,faculty,'
1191            'department,passport_path\r\nAnna M. Tester,A111111,234,'
1192            'Unnamed Certificate,Faculty of Unnamed Faculty (NA),'
1193            'Department of Unnamed Department (NA),'
1194            'students/00110/A111111/passport_A111111.jpg\r\n'
1195            in result
1196            )
1197        return
Note: See TracBrowser for help on using the repository browser.