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

Last change on this file since 16282 was 16186, checked in by Henrik Bettermann, 4 years ago

reg_number is no longer a required field in IApplicantBaseData.

Add entry_session to student data exporters.

  • Property svn:keywords set to Id
File size: 66.2 KB
Line 
1## $Id: test_export.py 16186 2020-08-04 07:49:51Z 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.university.course import Course
30from waeup.kofa.university.certificate import CertificateCourse
31from waeup.kofa.students.export import (
32    StudentExporter, StudentStudyCourseExporter, StudentStudyLevelExporter,
33    CourseTicketExporter, StudentPaymentExporter, BedTicketExporter,
34    SchoolFeePaymentsOverviewExporter, StudyLevelsOverviewExporter,
35    ComboCardDataExporter, DataForBursaryExporter,
36    UnpaidPaymentsExporter, SessionPaymentsOverviewExporter,
37    OutstandingCoursesExporter,
38    AccommodationPaymentsExporter,
39    TranscriptDataExporter,
40    TrimmedDataExporter,
41    StudentTrimmedPaymentExporter,
42    get_students,)
43from waeup.kofa.students.accommodation import BedTicket
44from waeup.kofa.students.interfaces import ICSVStudentExporter
45from waeup.kofa.students.payments import StudentOnlinePayment
46from waeup.kofa.students.student import Student
47from waeup.kofa.students.studycourse import StudentStudyCourse
48from waeup.kofa.students.studylevel import StudentStudyLevel, CourseTicket
49from waeup.kofa.students.tests.test_batching import StudentImportExportSetup
50from waeup.kofa.testing import FunctionalLayer
51
52curr_year = datetime.datetime.now().year
53year_range = range(curr_year - 11, curr_year + 1)
54year_range_str = ','.join([str(i) for i in year_range])
55
56class ExportHelperTests(StudentImportExportSetup):
57    layer = FunctionalLayer
58    def setUp(self):
59        super(ExportHelperTests, self).setUp()
60        student = Student()
61        self.app['students'].addStudent(student)
62        student = self.setup_student(student)
63        notify(grok.ObjectModifiedEvent(student))
64        self.student = self.app['students'][student.student_id]
65        return
66
67    def test_get_students_plain(self):
68        # without a filter we get all students
69        result = get_students(self.app)
70        self.assertEqual(len(list(result)), 1)
71        return
72
73    def test_get_students_by_session(self):
74        # we can filter out students of a certain session
75        my_filter1 = StudentsQuery(current_session=2012)
76        result = get_students(self.app, stud_filter=my_filter1)
77        self.assertEqual(len(list(result)), 1)
78
79        my_filter2 = StudentsQuery(current_session=1964)
80        result = get_students(self.app, stud_filter=my_filter2)
81        self.assertEqual(len(list(result)), 0)
82        return
83
84    def test_get_students_by_level(self):
85        # we can filter out students of a certain level
86        my_filter1 = StudentsQuery(current_level=200)
87        result = get_students(self.app, stud_filter=my_filter1)
88        self.assertEqual(len(list(result)), 1)
89
90        my_filter2 = StudentsQuery(current_level=300)
91        result = get_students(self.app, stud_filter=my_filter2)
92        self.assertEqual(len(list(result)), 0)
93        return
94
95    def test_get_students_by_deptcode(self):
96        # we can filter out students of a certain dept.
97        my_filter1 = StudentsQuery(depcode='NA')
98        result = get_students(self.app, stud_filter=my_filter1)
99        self.assertEqual(len(list(result)), 1)
100
101        my_filter2 = StudentsQuery(depcode='NOTEXISTING')
102        result = get_students(self.app, stud_filter=my_filter2)
103        self.assertEqual(len(list(result)), 0)
104        return
105
106    def test_get_students_by_faccode(self):
107        # we can filter out students of a certain faculty.
108        my_filter1 = StudentsQuery(faccode='NA')
109        result = get_students(self.app, stud_filter=my_filter1)
110        self.assertEqual(len(list(result)), 1)
111
112        my_filter2 = StudentsQuery(faccode='NOTEXISTING')
113        result = get_students(self.app, stud_filter=my_filter2)
114        self.assertEqual(len(list(result)), 0)
115        return
116
117    def test_get_students_by_current_mode(self):
118        # we can filter out students in a certain mode.
119        my_filter1 = StudentsQuery(current_mode='ug_ft')
120        result = get_students(self.app, stud_filter=my_filter1)
121        self.assertEqual(len(list(result)), 1)
122
123        my_filter2 = StudentsQuery(current_mode='NOTEXISTING')
124        result = get_students(self.app, stud_filter=my_filter2)
125        self.assertEqual(len(list(result)), 0)
126        return
127
128
129class StudentExporterTest(StudentImportExportSetup):
130
131    layer = FunctionalLayer
132
133    std_csv_entry = (
134        'my adm code,my clr code,1981-02-04#,anna@sample.com,,'
135        'Anna,,Tester,234,M.,NG,,,"Studentroad 21\nLagos 123456\n",,'
136        '+234-123-12345#,123,f,A111111,0,,,created'
137        )
138
139    def setUp(self):
140        super(StudentExporterTest, self).setUp()
141        self.setup_for_export()
142        return
143
144    def test_ifaces(self):
145        # make sure we fullfill interface contracts
146        obj = StudentExporter()
147        verifyObject(ICSVStudentExporter, obj)
148        verifyClass(ICSVStudentExporter, StudentExporter)
149        return
150
151    def test_get_as_utility(self):
152        # we can get an student exporter as utility
153        result = queryUtility(ICSVExporter, name="students")
154        self.assertTrue(result is not None)
155        return
156
157    def test_export(self):
158        # we can really export students
159        # set values we can expect in export file
160        self.setup_student(self.student)
161        exporter = StudentExporter()
162        exporter.export([self.student], self.outfile)
163        result = open(self.outfile, 'rb').read()
164        self.assertTrue(
165            'adm_code,clr_code,date_of_birth,email,'
166            'employer,firstname,flash_notice,lastname,matric_number,middlename,'
167            'nationality,officer_comment,parents_email,'
168            'perm_address,personal_updated,'
169            'phone,reg_number,sex,student_id,suspended,suspended_comment,'
170            'password,state,history,certcode,is_postgrad,'
171            'current_level,current_session,entry_session\r\n'
172            'my adm code,my clr code,'
173            '1981-02-04#,anna@sample.com,,Anna,,Tester,234,M.,NG,,,'
174            '"Studentroad 21\nLagos 123456\n",,+234-123-12345#,123,f,'
175            'A111111,0,,,created'
176            in result
177            )
178        return
179
180    def test_export_all(self):
181        # we can really export students
182        # set values we can expect in export file
183        self.setup_student(self.student)
184        exporter = StudentExporter()
185        exporter.export_all(self.app, self.outfile)
186        result = open(self.outfile, 'rb').read()
187        self.assertTrue(
188            'adm_code,clr_code,date_of_birth,email,'
189            'employer,firstname,flash_notice,lastname,matric_number,middlename,'
190            'nationality,officer_comment,parents_email,'
191            'perm_address,personal_updated,'
192            'phone,reg_number,sex,student_id,suspended,suspended_comment,'
193            'password,state,history,certcode,is_postgrad,'
194            'current_level,current_session,entry_session\r\n'
195            'my adm code,my clr code,1981-02-04#,anna@sample.com,,'
196            'Anna,,Tester,234,M.,NG,,,"Studentroad 21\nLagos 123456\n"'
197            ',,+234-123-12345#,123,f,A111111,0,,,created'
198            in result
199            )
200        return
201
202    def test_export_student(self):
203        # we can export a single student
204        self.setup_student(self.student)
205        exporter = StudentExporter()
206        exporter.export_student(self.student, self.outfile)
207        result = open(self.outfile, 'rb').read()
208        self.assertTrue(
209            'adm_code,clr_code,date_of_birth,email,'
210            'employer,firstname,flash_notice,lastname,matric_number,middlename,'
211            'nationality,officer_comment,parents_email,'
212            'perm_address,personal_updated,'
213            'phone,reg_number,sex,student_id,suspended,suspended_comment,'
214            'password,state,history,certcode,is_postgrad,'
215            'current_level,current_session,entry_session\r\n'
216            'my adm code,my clr code,1981-02-04#,anna@sample.com,,'
217            'Anna,,Tester,234,M.,NG,,,"Studentroad 21\nLagos 123456\n"'
218            ',,+234-123-12345#,123,f,A111111,0,,,created'
219            in result
220            )
221        return
222
223    def test_export_filtered(self):
224        # we can export a filtered set of students (filtered by session/level)
225        self.setup_student(self.student)
226        self.app['students'].addStudent(self.student)
227        notify(grok.ObjectModifiedEvent(self.student))
228        exporter = StudentExporter()
229
230        exporter.export_filtered(
231            self.app, self.outfile,
232            current_session=None, current_level=None)
233        result1 = open(self.outfile, 'rb').read()
234        exporter.export_filtered(
235            self.app, self.outfile,
236            current_session=2012, current_level=None)
237        result2 = open(self.outfile, 'rb').read()
238        # current_level and current_session can be both a string ...
239        exporter.export_filtered(
240            self.app, self.outfile,
241            current_session='2012', current_level=u'200')
242        result3 = open(self.outfile, 'rb').read()
243        exporter.export_filtered(
244            self.app, self.outfile,
245            current_session=2011, current_level=None)
246        result4 = open(self.outfile, 'rb').read()
247        # ... and an integer
248        exporter.export_filtered(
249            self.app, self.outfile,
250            current_session=None, current_level=100)
251        result5 = open(self.outfile, 'rb').read()
252        # Also students at probating levels are being exported ...
253        self.student['studycourse'].current_level = 210
254        notify(grok.ObjectModifiedEvent(self.student))
255        exporter.export_filtered(
256            self.app, self.outfile,
257            current_session=None, current_level=200)
258        result6 = open(self.outfile, 'rb').read()
259        # ... but not in the wrong level range.
260        self.student['studycourse'].current_level = 310
261        notify(grok.ObjectModifiedEvent(self.student))
262        exporter.export_filtered(
263            self.app, self.outfile,
264            current_session=None, current_level=200)
265        result7 = open(self.outfile, 'rb').read()
266        self.assertTrue(self.std_csv_entry in result1)
267        self.assertTrue(self.std_csv_entry in result2)
268        self.assertTrue(self.std_csv_entry in result3)
269        self.assertFalse(self.std_csv_entry in result4)
270        self.assertFalse(self.std_csv_entry in result5)
271        self.assertTrue(self.std_csv_entry in result6)
272        self.assertFalse(self.std_csv_entry in result7)
273        return
274
275    def test_export_selected(self):
276        # we can export a filtered set of students (filtered by session/level)
277        self.setup_student(self.student)
278        self.app['students'].addStudent(self.student)
279        notify(grok.ObjectModifiedEvent(self.student))
280        exporter = StudentExporter()
281        exporter.export_selected(
282            self.app, self.outfile, selected=['A111111'])
283        result1 = open(self.outfile, 'rb').read()
284        exporter.export_selected(
285            self.app, self.outfile, selected=[])
286        result2 = open(self.outfile, 'rb').read()
287        self.assertTrue(self.std_csv_entry in result1)
288        self.assertFalse(self.std_csv_entry in result2)
289        return
290
291    def test_export_filtered_by_dept(self):
292        # we can export a set of students filtered by department
293        self.setup_student(self.student)
294        self.app['students'].addStudent(self.student)
295        notify(grok.ObjectModifiedEvent(self.student))
296        exporter = StudentExporter()
297        # current_session can be both a string ...
298        exporter.export_filtered(
299            self.app, self.outfile,
300            current_session='2012', current_level=u'200', depcode='NA')
301        result1 = open(self.outfile, 'rb').read()
302        # ... and an integer
303        exporter.export_filtered(
304            self.app, self.outfile,
305            current_session=2012, current_level=200, depcode='NODEPT')
306        result2 = open(self.outfile, 'rb').read()
307        self.assertTrue(self.std_csv_entry in result1)
308        self.assertTrue(self.std_csv_entry not in result2)
309        return
310
311    def test_export_filtered_by_faculty(self):
312        # we can export a set of students filtered by faculty
313        self.setup_student(self.student)
314        self.app['students'].addStudent(self.student)
315        notify(grok.ObjectModifiedEvent(self.student))
316        exporter = StudentExporter()
317
318        exporter.export_filtered(
319            self.app, self.outfile,
320            current_session=2012, current_level='200', faccode='NA')
321        result1 = open(self.outfile, 'rb').read()
322        exporter.export_filtered(
323            self.app, self.outfile,
324            current_session=2012, current_level=200, faccode='NOFAC')
325        result2 = open(self.outfile, 'rb').read()
326        self.assertTrue(self.std_csv_entry in result1)
327        self.assertTrue(self.std_csv_entry not in result2)
328        return
329
330
331
332class StudentTrimmedDataExporterTest(StudentImportExportSetup):
333
334    layer = FunctionalLayer
335
336    std_csv_entry = (
337        'my adm code,my clr code,1981-02-04#,anna@sample.com,,'
338        'Anna,,Tester,234,M.,NG,,,"Studentroad 21\nLagos 123456\n",,'
339        '+234-123-12345#,123,f,A111111,0,,,created'
340        )
341
342    def setUp(self):
343        super(StudentTrimmedDataExporterTest, self).setUp()
344        self.setup_for_export()
345        return
346
347    def test_ifaces(self):
348        # make sure we fullfill interface contracts
349        obj = TrimmedDataExporter()
350        verifyObject(ICSVStudentExporter, obj)
351        verifyClass(ICSVStudentExporter, TrimmedDataExporter)
352        return
353
354    def test_get_as_utility(self):
355        # we can get an student exporter as utility
356        result = queryUtility(ICSVExporter, name="trimmed")
357        self.assertTrue(result is not None)
358        return
359
360    def test_export_all(self):
361        # we can really export students
362        # set values we can expect in export file
363        self.setup_student(self.student)
364        exporter = TrimmedDataExporter()
365        exporter.export_all(self.app, self.outfile)
366        result = open(self.outfile, 'rb').read()
367        self.assertTrue(
368            'student_id,matric_number,reg_number,firstname,middlename,'
369            'lastname,sex,email,phone,nationality,date_of_birth,state,'
370            'current_mode,certcode,faccode,depcode,current_level,'
371            'current_session,current_verdict,entry_session\r\n'
372            'A111111,234,123,Anna,M.,Tester,f,anna@sample.com,+234-123-12345#,'
373            'NG,1981-02-04#,created,ug_ft,CERT1,NA,NA,200,2012,0,2010'
374            in result
375            )
376        return
377
378class StudentStudyCourseExporterTest(StudentImportExportSetup):
379
380    layer = FunctionalLayer
381
382    def setUp(self):
383        super(StudentStudyCourseExporterTest, self).setUp()
384        self.setup_for_export()
385        return
386
387    def test_ifaces(self):
388        # make sure we fullfill interface contracts
389        obj = StudentStudyCourseExporter()
390        verifyObject(ICSVStudentExporter, obj)
391        verifyClass(ICSVStudentExporter, StudentStudyCourseExporter)
392        return
393
394    def test_get_as_utility(self):
395        # we can get an student exporter as utility
396        result = queryUtility(ICSVExporter, name="studentstudycourses")
397        self.assertTrue(result is not None)
398        return
399
400    def test_export_empty(self):
401        # we can export a nearly empty study course
402        study_course = StudentStudyCourse()
403        exporter = StudentStudyCourseExporter()
404        exporter.export([study_course], self.outfile)
405        result = open(self.outfile, 'rb').read()
406        self.assertEqual(
407            result,
408            'certificate,current_level,current_session,current_verdict,'
409            'entry_mode,entry_session,previous_verdict,student_id\r\n'
410
411            ',,,0,,,0,\r\n'
412            )
413        return
414
415    def test_export(self):
416        # we can really export study courses.
417        # set values we can expect in export file
418        self.setup_student(self.student)
419        study_course = self.student.get('studycourse')
420        exporter = StudentStudyCourseExporter()
421        exporter.export([study_course], self.outfile)
422        result = open(self.outfile, 'rb').read()
423        self.assertEqual(
424            result,
425            'certificate,current_level,current_session,current_verdict,'
426            'entry_mode,entry_session,previous_verdict,student_id\r\n'
427
428            'CERT1,200,2012,0,ug_ft,2010,0,A111111\r\n'
429            )
430        return
431
432    def test_export_all(self):
433        # we can really export students
434        # set values we can expect in export file
435        self.setup_student(self.student)
436        exporter = StudentStudyCourseExporter()
437        exporter.export_all(self.app, self.outfile)
438        result = open(self.outfile, 'rb').read()
439        self.assertEqual(
440            result,
441            'certificate,current_level,current_session,current_verdict,'
442            'entry_mode,entry_session,previous_verdict,student_id\r\n'
443
444            'CERT1,200,2012,0,ug_ft,2010,0,A111111\r\n'
445            )
446        return
447
448    def test_export_student(self):
449        # we can export studycourse of a certain student
450        self.setup_student(self.student)
451        exporter = StudentStudyCourseExporter()
452        exporter.export_student(self.student, self.outfile)
453        result = open(self.outfile, 'rb').read()
454        self.assertEqual(
455            result,
456            'certificate,current_level,current_session,current_verdict,'
457            'entry_mode,entry_session,previous_verdict,student_id\r\n'
458
459            'CERT1,200,2012,0,ug_ft,2010,0,A111111\r\n'
460            )
461        return
462
463    def test_export_filtered(self):
464        # we can export studycourses of a filtered set of students
465        self.setup_student(self.student)
466        self.app['students'].addStudent(self.student)
467        notify(grok.ObjectModifiedEvent(self.student))
468
469        exporter = StudentStudyCourseExporter()
470        exporter.export_filtered(
471            self.student, self.outfile, current_session=2012)
472        result = open(self.outfile, 'rb').read()
473        self.assertEqual(
474            result,
475            'certificate,current_level,current_session,current_verdict,'
476            'entry_mode,entry_session,previous_verdict,student_id\r\n'
477
478            'CERT1,200,2012,0,ug_ft,2010,0,A111111\r\n'
479            )
480        return
481
482    def test_export_selected_student_id(self):
483        # we can export a filtered set of students (filtered by session/level)
484        self.setup_student(self.student)
485        self.app['students'].addStudent(self.student)
486        notify(grok.ObjectModifiedEvent(self.student))
487        exporter = StudentStudyCourseExporter()
488        exporter.export_selected(
489            self.app, self.outfile, selected=['A111111'])
490        result = open(self.outfile, 'rb').read()
491        self.assertEqual(
492            result,
493            'certificate,current_level,current_session,current_verdict,'
494            'entry_mode,entry_session,previous_verdict,student_id\r\n'
495
496            'CERT1,200,2012,0,ug_ft,2010,0,A111111\r\n'
497            )
498        return
499
500    def test_export_selected_matric_number(self):
501        # we can export a filtered set of students (filtered by session/level)
502        self.setup_student(self.student)
503        self.app['students'].addStudent(self.student)
504        notify(grok.ObjectModifiedEvent(self.student))
505        exporter = StudentStudyCourseExporter()
506        exporter.export_selected(
507            self.app, self.outfile, selected=['234'])
508        result = open(self.outfile, 'rb').read()
509        self.assertEqual(
510            result,
511            'certificate,current_level,current_session,current_verdict,'
512            'entry_mode,entry_session,previous_verdict,student_id\r\n'
513
514            'CERT1,200,2012,0,ug_ft,2010,0,A111111\r\n'
515            )
516        return
517
518
519class StudentStudyLevelExporterTest(StudentImportExportSetup):
520
521    layer = FunctionalLayer
522
523    def setUp(self):
524        super(StudentStudyLevelExporterTest, self).setUp()
525        self.setup_for_export()
526        return
527
528    def test_ifaces(self):
529        # make sure we fullfill interface contracts
530        obj = StudentStudyLevelExporter()
531        verifyObject(ICSVStudentExporter, obj)
532        verifyClass(ICSVStudentExporter, StudentStudyLevelExporter)
533        return
534
535    def test_get_as_utility(self):
536        # we can get an student exporter as utility
537        result = queryUtility(ICSVExporter, name="studentstudylevels")
538        self.assertTrue(result is not None)
539        return
540
541    def test_export_empty(self):
542        # we can export a nearly empty study level
543        study_level = StudentStudyLevel()
544        exporter = StudentStudyLevelExporter()
545        exporter.export([study_level], self.outfile)
546        result = open(self.outfile, 'rb').read()
547        self.assertEqual(
548            result,
549            'gpa,level,level_session,level_verdict,total_credits,'
550            'transcript_remark,validated_by,validation_date,'
551            'student_id,number_of_tickets,certcode\r\n'
552            '0.00,,,0,0,,,,,0,\r\n'
553            )
554        return
555
556    def test_export(self):
557        # we can really export study levels.
558        # set values we can expect in export file
559        self.setup_student(self.student)
560        study_course = self.student.get('studycourse')
561        study_level = study_course[study_course.keys()[0]]
562        exporter = StudentStudyLevelExporter()
563        exporter.export([study_level], self.outfile)
564        result = open(self.outfile, 'rb').read()
565        self.assertEqual(
566            result,
567            'gpa,level,level_session,level_verdict,total_credits,'
568            'transcript_remark,validated_by,validation_date,'
569            'student_id,number_of_tickets,certcode\r\n'
570            '0.00,100,2012,A,100,,,,A111111,1,CERT1\r\n'
571            )
572        return
573
574    def test_export_all(self):
575        # we can really export study levels
576        # set values we can expect in export file
577        self.setup_student(self.student)
578        exporter = StudentStudyLevelExporter()
579        exporter.export_all(self.app, self.outfile)
580        result = open(self.outfile, 'rb').read()
581        self.assertEqual(
582            result,
583            'gpa,level,level_session,level_verdict,total_credits,'
584            'transcript_remark,validated_by,validation_date,'
585            'student_id,number_of_tickets,certcode\r\n'
586            '0.00,100,2012,A,100,,,,A111111,1,CERT1\r\n'
587            )
588        return
589
590    def test_export_student(self):
591        # we can really export study levels of a certain student
592        self.setup_student(self.student)
593        exporter = StudentStudyLevelExporter()
594        exporter.export_student(self.student, self.outfile)
595        result = open(self.outfile, 'rb').read()
596        self.assertEqual(
597            result,
598            'gpa,level,level_session,level_verdict,total_credits,'
599            'transcript_remark,validated_by,validation_date,'
600            'student_id,number_of_tickets,certcode\r\n'
601            '0.00,100,2012,A,100,,,,A111111,1,CERT1\r\n'
602            )
603        return
604
605    def test_export_filtered(self):
606        # we can export studylevels of a filtered set of students
607        self.setup_student(self.student)
608        self.app['students'].addStudent(self.student)
609        notify(grok.ObjectModifiedEvent(self.student))
610
611        exporter = StudentStudyLevelExporter()
612        exporter.export_filtered(
613            self.student, self.outfile)
614        result = open(self.outfile, 'rb').read()
615        self.assertEqual(
616            result,
617            'gpa,level,level_session,level_verdict,total_credits,'
618            'transcript_remark,validated_by,validation_date,'
619            'student_id,number_of_tickets,certcode\r\n'
620            '0.00,100,2012,A,100,,,,A111111,1,CERT1\r\n'
621            )
622        return
623
624    def test_export_selected(self):
625        # we can export studylevels of a filtered set of students
626        self.setup_student(self.student)
627        self.app['students'].addStudent(self.student)
628        notify(grok.ObjectModifiedEvent(self.student))
629
630        exporter = StudentStudyLevelExporter()
631        exporter.export_selected(
632            self.app, self.outfile, selected=['A111111'])
633        result = open(self.outfile, 'rb').read()
634        self.assertEqual(
635            result,
636            'gpa,level,level_session,level_verdict,total_credits,'
637            'transcript_remark,validated_by,validation_date,'
638            'student_id,number_of_tickets,certcode\r\n'
639            '0.00,100,2012,A,100,,,,A111111,1,CERT1\r\n'
640            )
641        return
642
643class CourseTicketExporterTest(StudentImportExportSetup):
644
645    layer = FunctionalLayer
646
647    def setUp(self):
648        super(CourseTicketExporterTest, self).setUp()
649        self.setup_for_export()
650        return
651
652    def test_ifaces(self):
653        # make sure we fullfill interface contracts
654        obj = CourseTicketExporter()
655        verifyObject(ICSVStudentExporter, obj)
656        verifyClass(ICSVStudentExporter, CourseTicketExporter)
657        return
658
659    def test_get_as_utility(self):
660        # we can get an student exporter as utility
661        result = queryUtility(ICSVExporter, name="coursetickets")
662        self.assertTrue(result is not None)
663        return
664
665    def test_export_empty(self):
666        # we can export a nearly empty course ticket
667        ticket = CourseTicket()
668        exporter = CourseTicketExporter()
669        exporter.export([ticket], self.outfile)
670        result = open(self.outfile, 'rb').read()
671        self.assertEqual(
672            result,
673            'automatic,carry_over,code,course_category,credits,dcode,fcode,level,level_session,'
674            'mandatory,outstanding,passmark,score,semester,ticket_session,title,student_id,certcode,'
675            'display_fullname\r\n'
676            '0,0,,,,,,,,0,0,,,,,,,,\r\n'
677            )
678        return
679
680    def test_export(self):
681        # we can really export course tickets.
682        # set values we can expect in export file
683        self.setup_student(self.student)
684        study_course = self.student.get('studycourse')
685        study_level = study_course[study_course.keys()[0]]
686        ticket = study_level['CRS1']
687        exporter = CourseTicketExporter()
688        exporter.export([ticket], self.outfile)
689        result = open(self.outfile, 'rb').read()
690        self.assertEqual(
691            result,
692            'automatic,carry_over,code,course_category,credits,dcode,fcode,level,level_session,'
693            'mandatory,outstanding,passmark,score,semester,ticket_session,title,student_id,certcode,'
694            'display_fullname\r\n'
695            '1,1,CRS1,,100,DEP1,FAC1,100,2012,0,0,100,,2,,Course 1,A111111,CERT1,'
696            'Anna M. Tester\r\n'
697            )
698        return
699
700    def test_export_all(self):
701        # we can really export all course tickets
702        # set values we can expect in export file
703        self.setup_student(self.student)
704        exporter = CourseTicketExporter()
705        exporter.export_all(self.app, self.outfile)
706        result = open(self.outfile, 'rb').read()
707        self.assertEqual(
708            result,
709            'automatic,carry_over,code,course_category,credits,dcode,fcode,level,level_session,'
710            'mandatory,outstanding,passmark,score,semester,ticket_session,title,student_id,certcode,'
711            'display_fullname\r\n'
712            '1,1,CRS1,,100,DEP1,FAC1,100,2012,0,0,100,,2,,Course 1,A111111,CERT1,'
713            'Anna M. Tester\r\n'
714            )
715        return
716
717    def test_export_student(self):
718        # we can really export all course tickets of a certain student
719        self.setup_student(self.student)
720        exporter = CourseTicketExporter()
721        exporter.export_student(self.student, self.outfile)
722        result = open(self.outfile, 'rb').read()
723        self.assertEqual(
724            result,
725            'automatic,carry_over,code,course_category,credits,dcode,fcode,level,level_session,'
726            'mandatory,outstanding,passmark,score,semester,ticket_session,title,student_id,certcode,'
727            'display_fullname\r\n'
728            '1,1,CRS1,,100,DEP1,FAC1,100,2012,0,0,100,,2,,Course 1,A111111,CERT1,'
729            'Anna M. Tester\r\n'
730            )
731        return
732
733    def test_export_filtered(self):
734        # we can export course tickets of a filtered set of students
735        self.setup_student(self.student)
736        self.app['students'].addStudent(self.student)
737        notify(grok.ObjectModifiedEvent(self.student))
738
739        exporter = CourseTicketExporter()
740        exporter.export_filtered(self.student, self.outfile)
741        result = open(self.outfile, 'rb').read()
742        self.assertEqual(
743            result,
744            'automatic,carry_over,code,course_category,credits,dcode,fcode,level,level_session,'
745            'mandatory,outstanding,passmark,score,semester,ticket_session,title,student_id,certcode,'
746            'display_fullname\r\n'
747            '1,1,CRS1,,100,DEP1,FAC1,100,2012,0,0,100,,2,,Course 1,A111111,CERT1,'
748            'Anna M. Tester\r\n'
749            )
750        # We can set the course tickets level, semester and level_session
751        # without code (used in the datacenter)
752        notify(grok.ObjectModifiedEvent(self.student['studycourse']['100']['CRS1']))
753        exporter.export_filtered(self.student, self.outfile, ct_level='100',
754            ct_session='2012', ct_semester='2')
755        result = open(self.outfile, 'rb').read()
756        self.assertEqual(
757            result,
758            'automatic,carry_over,code,course_category,credits,dcode,fcode,level,level_session,'
759            'mandatory,outstanding,passmark,score,semester,ticket_session,title,student_id,certcode,'
760            'display_fullname\r\n'
761            '1,1,CRS1,,100,DEP1,FAC1,100,2012,0,0,100,,2,,Course 1,A111111,CERT1,'
762            'Anna M. Tester\r\n'
763            )
764        # 'all' does select all
765        notify(grok.ObjectModifiedEvent(self.student['studycourse']['100']['CRS1']))
766        exporter.export_filtered(self.student, self.outfile, ct_level='all',
767            ct_session='2012', ct_semester='all')
768        result = open(self.outfile, 'rb').read()
769        self.assertEqual(
770            result,
771            'automatic,carry_over,code,course_category,credits,dcode,fcode,level,level_session,'
772            'mandatory,outstanding,passmark,score,semester,ticket_session,title,student_id,certcode,'
773            'display_fullname\r\n'
774            '1,1,CRS1,,100,DEP1,FAC1,100,2012,0,0,100,,2,,Course 1,A111111,CERT1,'
775            'Anna M. Tester\r\n'
776            )
777        # Level 200 tickets do not exist.
778        notify(grok.ObjectModifiedEvent(self.student['studycourse']['100']['CRS1']))
779        exporter.export_filtered(self.student, self.outfile, ct_level='200')
780        result = open(self.outfile, 'rb').read()
781        self.assertEqual(
782            result,
783            'automatic,carry_over,code,course_category,credits,dcode,fcode,level,level_session,'
784            'mandatory,outstanding,passmark,score,semester,ticket_session,title,student_id,certcode,'
785            'display_fullname\r\n'
786                        )
787        # Session 2013 tickets do not exist.
788        notify(grok.ObjectModifiedEvent(self.student['studycourse']['100']['CRS1']))
789        exporter.export_filtered(self.student, self.outfile,
790            ct_level='all', ct_session='2013')
791        result = open(self.outfile, 'rb').read()
792        self.assertEqual(
793            result,
794            'automatic,carry_over,code,course_category,credits,dcode,fcode,level,level_session,'
795            'mandatory,outstanding,passmark,score,semester,ticket_session,title,student_id,certcode,'
796            'display_fullname\r\n'
797            )
798        # 1st semester tickets do not exist.
799        notify(grok.ObjectModifiedEvent(self.student['studycourse']['100']['CRS1']))
800        exporter.export_filtered(self.student, self.outfile,
801            ct_level='all', ct_session='all', ct_semester='1')
802        result = open(self.outfile, 'rb').read()
803        self.assertEqual(
804            result,
805            'automatic,carry_over,code,course_category,credits,dcode,fcode,level,level_session,'
806            'mandatory,outstanding,passmark,score,semester,ticket_session,title,student_id,certcode,'
807            'display_fullname\r\n'
808            )
809        # If the coursetickets catalog is used to filter students
810        # and (course) code is not None
811        # only course tickets which belong to this course are exported
812        exporter.export_filtered(
813            self.student, self.outfile, catalog='coursetickets', code='CRS1')
814        result = open(self.outfile, 'rb').read()
815        self.assertEqual(
816            result,
817            'automatic,carry_over,code,course_category,credits,dcode,fcode,level,level_session,'
818            'mandatory,outstanding,passmark,score,semester,ticket_session,title,student_id,certcode,'
819            'display_fullname\r\n'
820            '1,1,CRS1,,100,DEP1,FAC1,100,2012,0,0,100,,2,,Course 1,A111111,CERT1,'
821            'Anna M. Tester\r\n'
822            )
823        exporter.export_filtered(
824            self.student, self.outfile, catalog='coursetickets', code='any code')
825        result = open(self.outfile, 'rb').read()
826        self.assertEqual(
827            result,
828            'automatic,carry_over,code,course_category,credits,dcode,fcode,level,level_session,'
829            'mandatory,outstanding,passmark,score,semester,ticket_session,title,student_id,certcode,'
830            'display_fullname\r\n'
831            )
832        # Also tickets in probating levels are exported. Therefore
833        # we change the level attribute to fake a 110 level.
834        self.student['studycourse']['100'].level = 110
835        notify(grok.ObjectModifiedEvent(self.student['studycourse']['100']['CRS1']))
836        exporter.export_filtered(
837            self.student, self.outfile, catalog='coursetickets', code='CRS1', level='100')
838        result = open(self.outfile, 'rb').read()
839        self.assertEqual(
840            result,
841            'automatic,carry_over,code,course_category,credits,dcode,fcode,level,level_session,'
842            'mandatory,outstanding,passmark,score,semester,ticket_session,title,student_id,certcode,'
843            'display_fullname\r\n'
844            '1,1,CRS1,,100,DEP1,FAC1,110,2012,0,0,100,,2,,Course 1,A111111,CERT1,'
845            'Anna M. Tester\r\n'
846            )
847        return
848
849class OutstandingCoursesExporterTest(StudentImportExportSetup):
850
851    layer = FunctionalLayer
852
853    def setUp(self):
854        super(OutstandingCoursesExporterTest, self).setUp()
855        self.setup_for_export()
856        return
857
858    def test_ifaces(self):
859        # make sure we fullfill interface contracts
860        obj = OutstandingCoursesExporter()
861        verifyObject(ICSVStudentExporter, obj)
862        verifyClass(ICSVStudentExporter, OutstandingCoursesExporter)
863        return
864
865    def test_get_as_utility(self):
866        # we can get an student exporter as utility
867        result = queryUtility(ICSVExporter, name="outstandingcourses")
868        self.assertTrue(result is not None)
869        return
870
871    def test_export_all(self):
872        course1 = Course(u'Cheese Basics', 'C1')
873        course2 = Course(u'Advanced Cheese Making', 'C2')
874        course3 = Course(u'Selling Cheese', 'C3')
875        self.app['faculties']['fac1']['dep1'].courses.addCourse(course1)
876        self.app['faculties']['fac1']['dep1'].courses.addCourse(course2)
877        self.app['faculties']['fac1']['dep1'].courses.addCourse(course3)
878        self.certificate.addCertCourse(course1, 100, True)
879        self.certificate.addCertCourse(course2, 400, False)
880        self.certificate.addCertCourse(course3, 100, False)
881        self.setup_student(self.student)
882        self.student['studycourse']['100']['C3'].score = 25
883        exporter = OutstandingCoursesExporter()
884        exporter.export_all(self.app, self.outfile)
885        result = open(self.outfile, 'rb').read()
886        # The only student has registered C1, C3 and CRS1
887        # She missed C2, has failed C3 and  did not
888        # take C1 and CRS1
889        self.assertEqual(
890            result,
891            'student_id,matric_number,certcode,display_fullname,missed,failed,nottaken\r\n'
892            'A111111,234,CERT1,Anna M. Tester,C2_400 ,C3 ,C1 CRS1 \r\n'
893            )
894        return
895
896class StudentPaymentExporterTest(StudentImportExportSetup):
897
898    layer = FunctionalLayer
899
900    def setUp(self):
901        super(StudentPaymentExporterTest, self).setUp()
902        self.setup_for_export()
903        return
904
905    def test_ifaces(self):
906        # make sure we fullfill interface contracts
907        obj = StudentPaymentExporter()
908        verifyObject(ICSVStudentExporter, obj)
909        verifyClass(ICSVStudentExporter, StudentPaymentExporter)
910        return
911
912    def test_get_as_utility(self):
913        # we can get a payments exporter as utility
914        result = queryUtility(ICSVExporter, name="studentpayments")
915        self.assertTrue(result is not None)
916        return
917
918    def test_export_empty(self):
919        # we can export a nearly empty payment
920        payment = StudentOnlinePayment()
921        payment.creation_date = datetime.datetime(2012, 4, 1, 13, 12, 1)
922        exporter = StudentPaymentExporter()
923        exporter.export([payment], self.outfile)
924        result = open(self.outfile, 'rb').read()
925        self.assertEqual(
926            result,
927            'ac,amount_auth,creation_date,p_category,p_combi,p_current,p_id,'
928            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
929            'r_code,r_desc,student_id,state,current_session\r\n'
930
931            ',0.0,2012-04-01 13:12:01#,,[],1,,,,,unpaid,,0.0,,,,,\r\n'
932            )
933        return
934
935    def test_export(self):
936        # we can really export student payments.
937        # set values we can expect in export file
938        self.setup_student(self.student)
939        payment = self.student['payments']['my-payment']
940        exporter = StudentPaymentExporter()
941        exporter.export([payment], self.outfile)
942        result = open(self.outfile, 'rb').read()
943        self.assertEqual(
944            result,
945            'ac,amount_auth,creation_date,p_category,p_combi,p_current,p_id,'
946            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
947            'r_code,r_desc,student_id,state,current_session\r\n'
948
949            '666,12.12,%s-04-01 13:12:01#,schoolfee,[],1,my-id,'
950            'p-item,100,%s,paid,%s-04-01 14:12:01#,12.12,'
951            'r-code,,A111111,created,2012\r\n'
952            % (curr_year-6, curr_year-6, curr_year-6)
953            )
954        return
955
956    def test_export_all(self):
957        # we can really export all payments
958        # set values we can expect in export file
959        self.setup_student(self.student)
960        exporter = StudentPaymentExporter()
961        exporter.export_all(self.app, self.outfile)
962        result = open(self.outfile, 'rb').read()
963        self.assertEqual(
964            result,
965            'ac,amount_auth,creation_date,p_category,p_combi,p_current,p_id,'
966            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
967            'r_code,r_desc,student_id,state,current_session\r\n'
968
969            '666,12.12,%s-04-01 13:12:01#,schoolfee,[],1,my-id,'
970            'p-item,100,%s,paid,%s-04-01 14:12:01#,12.12,'
971            'r-code,,A111111,created,2012\r\n'
972            % (curr_year-6, curr_year-6, curr_year-6)
973            )
974        return
975
976    def test_export_student(self):
977        # we can really export all payments of a certain student
978        # set values we can expect in export file
979        self.setup_student(self.student)
980        exporter = StudentPaymentExporter()
981        exporter.export_student(self.student, self.outfile)
982        result = open(self.outfile, 'rb').read()
983        self.assertEqual(
984            result,
985            'ac,amount_auth,creation_date,p_category,p_combi,p_current,p_id,'
986            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
987            'r_code,r_desc,student_id,state,current_session\r\n'
988
989            '666,12.12,%s-04-01 13:12:01#,schoolfee,[],1,my-id,'
990            'p-item,100,%s,paid,%s-04-01 14:12:01#,12.12,'
991            'r-code,,A111111,created,2012\r\n'
992            % (curr_year-6, curr_year-6, curr_year-6)
993            )
994        return
995
996    def test_export_filtered(self):
997        # we can export payments of a filtered set of students
998        self.setup_student(self.student)
999        self.app['students'].addStudent(self.student)
1000        notify(grok.ObjectModifiedEvent(self.student))
1001
1002        exporter = StudentPaymentExporter()
1003        exporter.export_filtered(
1004            self.student, self.outfile, current_level=200)
1005        result = open(self.outfile, 'rb').read()
1006        self.assertEqual(
1007            result,
1008            'ac,amount_auth,creation_date,p_category,p_combi,p_current,p_id,'
1009            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
1010            'r_code,r_desc,student_id,state,current_session\r\n'
1011
1012            '666,12.12,%s-04-01 13:12:01#,schoolfee,[],1,my-id,'
1013            'p-item,100,%s,paid,%s-04-01 14:12:01#,12.12,'
1014            'r-code,,A111111,created,2012\r\n'
1015            % (curr_year-6, curr_year-6, curr_year-6)
1016            )
1017        return
1018
1019    def test_export_filtered_by_date(self):
1020        # payments_start and payments_end are being ignored
1021        self.setup_student(self.student)
1022        self.app['students'].addStudent(self.student)
1023        notify(grok.ObjectModifiedEvent(self.student))
1024        exporter = StudentPaymentExporter()
1025        # A key xxx does not exist
1026        self.assertRaises(
1027            KeyError, exporter.export_filtered, self.app, self.outfile,
1028            current_session=None,
1029            current_level=None, xxx='nonsense')
1030        # payments_start and payments_end do exist but must match format '%Y-%m-%d'
1031        self.assertRaises(
1032            ValueError, exporter.export_filtered, self.app, self.outfile,
1033            current_session=None, current_level=None,
1034            payments_start='nonsense', payments_end='nonsense')
1035        # If they match the format they are ignored by get_filtered and the
1036        # exporter works properly.
1037        # Attention: End day is included!
1038        exporter.export_filtered(
1039            self.app, self.outfile,
1040            current_session=None, current_level=None,
1041            payments_start='01/04/%s' % (curr_year-6),
1042            payments_end='01/04/%s' % (curr_year-6))
1043        result = open(self.outfile, 'rb').read()
1044        self.assertEqual(
1045            result,
1046            'ac,amount_auth,creation_date,p_category,p_combi,p_current,p_id,'
1047            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
1048            'r_code,r_desc,student_id,state,current_session\r\n'
1049
1050            '666,12.12,%s-04-01 13:12:01#,schoolfee,[],1,my-id,'
1051            'p-item,100,%s,paid,%s-04-01 14:12:01#,12.12,'
1052            'r-code,,A111111,created,2012\r\n'
1053            % (curr_year-6, curr_year-6, curr_year-6)
1054            )
1055        # Payment date is 2012-04-01, 14:12:01.
1056        # No results if payment_date is outside the given period.
1057        exporter.export_filtered(
1058            self.app, self.outfile,
1059            current_session=None, current_level=None,
1060            payments_start='30/03/2012', payments_end='31/03/2012')
1061        result = open(self.outfile, 'rb').read()
1062        self.assertEqual(
1063            result,
1064            'ac,amount_auth,creation_date,p_category,p_combi,p_current,p_id,'
1065            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
1066            'r_code,r_desc,student_id,state,current_session\r\n'
1067            )
1068        exporter.export_filtered(
1069            self.app, self.outfile,
1070            current_session=None, current_level=None,
1071            payments_start='02/04/2012', payments_end='03/04/2012')
1072        result = open(self.outfile, 'rb').read()
1073        self.assertEqual(
1074            result,
1075            'ac,amount_auth,creation_date,p_category,p_combi,p_current,p_id,'
1076            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
1077            'r_code,r_desc,student_id,state,current_session\r\n'
1078            )
1079        # No results if payment_date is not set
1080        self.payment.payment_date = None
1081        exporter.export_filtered(
1082            self.app, self.outfile,
1083            current_session=None, current_level=None,
1084            payments_start='31/03/2012', payments_end='02/04/2012')
1085        result = open(self.outfile, 'rb').read()
1086        self.assertEqual(
1087            result,
1088            'ac,amount_auth,creation_date,p_category,p_combi,p_current,p_id,'
1089            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
1090            'r_code,r_desc,student_id,state,current_session\r\n'
1091            )
1092        return
1093
1094class StudentTrimmedPaymentExporterTest(StudentImportExportSetup):
1095
1096    layer = FunctionalLayer
1097
1098    def setUp(self):
1099        super(StudentTrimmedPaymentExporterTest, self).setUp()
1100        self.setup_for_export()
1101        return
1102
1103    def test_ifaces(self):
1104        # make sure we fullfill interface contracts
1105        obj = StudentTrimmedPaymentExporter()
1106        verifyObject(ICSVStudentExporter, obj)
1107        verifyClass(ICSVStudentExporter, StudentTrimmedPaymentExporter)
1108        return
1109
1110    def test_get_as_utility(self):
1111        # we can get a payments exporter as utility
1112        result = queryUtility(ICSVExporter, name="trimmedpayments")
1113        self.assertTrue(result is not None)
1114        return
1115
1116    def test_export_all(self):
1117        # we can really export all payments
1118        # set values we can expect in export file
1119        self.setup_student(self.student)
1120        exporter = StudentTrimmedPaymentExporter()
1121        exporter.export_all(self.app, self.outfile)
1122        result = open(self.outfile, 'rb').read()
1123        self.assertEqual(
1124            result,
1125            'amount_auth,creation_date,p_category,p_combi,p_current,'
1126            'p_id,p_item,p_level,p_session,p_state,payment_date,'
1127            'r_amount_approved,r_code,r_desc,student_id,faccode,'
1128            'depcode,state,current_session\r\n'
1129
1130            '12.12,%s-04-01 13:12:01#,schoolfee,[],1,my-id,p-item,'
1131            '100,%s,paid,%s-04-01 14:12:01#,12.12,r-code,,'
1132            'A111111,NA,NA,created,2012\r\n'
1133            % (curr_year-6, curr_year-6, curr_year-6)
1134            )
1135        return
1136
1137
1138class UnpaidPaymentsExporterTest(StudentImportExportSetup):
1139
1140    layer = FunctionalLayer
1141
1142    def setUp(self):
1143        super(UnpaidPaymentsExporterTest, self).setUp()
1144        self.setup_for_export()
1145        return
1146
1147    def test_export_all(self):
1148        # we can really export all payments
1149        # set values we can expect in export file
1150        self.setup_student(self.student)
1151        exporter = UnpaidPaymentsExporter()
1152        exporter.export_all(self.app, self.outfile)
1153        result = open(self.outfile, 'rb').read()
1154        # No unpaid ticket exists
1155        self.assertEqual(
1156            result,
1157            'ac,amount_auth,creation_date,p_category,p_combi,p_current,p_id,'
1158            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
1159            'r_code,r_desc,student_id,state,current_session\r\n'
1160            )
1161        # Make ticket unpaid
1162        self.payment.p_state = 'unpaid'
1163        exporter.export_all(self.app, self.outfile)
1164        result = open(self.outfile, 'rb').read()
1165        self.assertEqual(
1166            result,
1167            'ac,amount_auth,creation_date,p_category,p_combi,p_current,p_id,'
1168            'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,'
1169            'r_code,r_desc,student_id,state,current_session\r\n'
1170
1171            '666,12.12,%s-04-01 13:12:01#,schoolfee,[],1,my-id,'
1172            'p-item,100,%s,unpaid,%s-04-01 14:12:01#,12.12,'
1173            'r-code,,A111111,created,2012\r\n'
1174            % (curr_year-6, curr_year-6, curr_year-6)
1175            )
1176        return
1177
1178class BursaryDataExporterTest(StudentImportExportSetup):
1179
1180    layer = FunctionalLayer
1181
1182    def setUp(self):
1183        super(BursaryDataExporterTest, self).setUp()
1184        self.setup_for_export()
1185        return
1186
1187    def test_export_all(self):
1188        # we can really export all payments
1189        # set values we can expect in export file
1190        self.setup_student(self.student)
1191        exporter = DataForBursaryExporter()
1192        exporter.export_all(self.app, self.outfile)
1193        result = open(self.outfile, 'rb').read()
1194        self.assertEqual(
1195            result,
1196            'ac,amount_auth,creation_date,p_category,p_combi,p_current,p_id,p_item,'
1197            'p_level,p_session,p_state,payment_date,r_amount_approved,r_code,'
1198            'r_desc,student_id,matric_number,reg_number,firstname,middlename,lastname,'
1199            'state,current_session,entry_session,entry_mode,faccode,depcode,certcode\r\n'
1200
1201            '666,12.12,%s-04-01 13:12:01#,schoolfee,[],1,my-id,p-item,100,%s,'
1202            'paid,%s-04-01 14:12:01#,12.12,r-code,,A111111,234,123,'
1203            'Anna,M.,Tester,created,2012,2010,ug_ft,NA,NA,CERT1\r\n'
1204            % (curr_year-6, curr_year-6, curr_year-6)
1205            )
1206        return
1207
1208class AccommodationPaymentsExporterTest(StudentImportExportSetup):
1209
1210    layer = FunctionalLayer
1211
1212    def setUp(self):
1213        super(AccommodationPaymentsExporterTest, self).setUp()
1214        self.setup_for_export()
1215        return
1216
1217    def test_export_all(self):
1218        self.setup_student(self.student)
1219        # add accommodation payments
1220        payment = StudentOnlinePayment()
1221        payment.creation_date = datetime.datetime(curr_year-6, 4, 1, 13, 12, 1)
1222        payment.p_id = 'id1'
1223        payment.p_category = u'bed_allocation'
1224        payment.p_state = 'paid'
1225        payment.ac = u'abc'
1226        payment.p_item = u'xyz'
1227        payment.p_level = 100
1228        payment.p_session = curr_year - 6
1229        payment.payment_date = datetime.datetime(curr_year-6, 4, 1, 14, 12, 1)
1230        payment.amount_auth = 12.12
1231        payment.r_amount_approved = 12.12
1232        payment.r_code = u'cde'
1233        payment2 = StudentOnlinePayment()
1234        payment2.creation_date = datetime.datetime(curr_year-6, 4, 1, 13, 12, 1)
1235        payment2.p_id = 'id2'
1236        payment2.p_category = u'hostel_maintenance'
1237        payment2.p_state = 'paid'
1238        payment2.ac = u'abc'
1239        payment2.p_item = u'xyz'
1240        payment2.p_level = 100
1241        payment2.p_session = curr_year - 6
1242        payment2.payment_date = datetime.datetime(curr_year-6, 4, 1, 14, 12, 1)
1243        payment2.amount_auth = 12.12
1244        payment2.r_amount_approved = 12.12
1245        payment2.r_code = u'cde'
1246        # XXX: there is no addPayment method to give predictable names
1247        self.payment = self.student['payments']['id1'] = payment
1248        self.payment = self.student['payments']['id2'] = payment2
1249        exporter = AccommodationPaymentsExporter()
1250        exporter.export_all(self.app, self.outfile)
1251        result = open(self.outfile, 'rb').read()
1252        # only accommodation payments are exported
1253        self.assertEqual(
1254            result,
1255            'ac,amount_auth,creation_date,p_category,p_combi,p_current,p_id,p_item,'
1256            'p_level,p_session,p_state,payment_date,r_amount_approved,r_code,'
1257            'r_desc,student_id,matric_number,reg_number,firstname,middlename,lastname,'
1258            'state,current_session,entry_session,entry_mode,faccode,depcode,certcode\r\n'
1259            'abc,12.12,%s-04-01 13:12:01#,bed_allocation,[],1,id1,xyz,100,%s,'
1260            'paid,%s-04-01 14:12:01#,12.12,cde,,A111111,234,123,'
1261            'Anna,M.,Tester,created,2012,2010,ug_ft,NA,NA,CERT1\r\n'
1262            'abc,12.12,%s-04-01 13:12:01#,hostel_maintenance,[],1,id2,xyz,100,%s,'
1263            'paid,%s-04-01 14:12:01#,12.12,cde,,A111111,234,123,'
1264            'Anna,M.,Tester,created,2012,2010,ug_ft,NA,NA,CERT1\r\n'
1265            % (curr_year-6, curr_year-6, curr_year-6,
1266               curr_year-6, curr_year-6, curr_year-6)
1267            )
1268        return
1269
1270class BedTicketExporterTest(StudentImportExportSetup):
1271
1272    layer = FunctionalLayer
1273
1274    def setUp(self):
1275        super(BedTicketExporterTest, self).setUp()
1276        self.setup_for_export()
1277        return
1278
1279    def test_ifaces(self):
1280        # make sure we fullfill interface contracts
1281        obj = BedTicketExporter()
1282        verifyObject(ICSVStudentExporter, obj)
1283        verifyClass(ICSVStudentExporter, BedTicketExporter)
1284        return
1285
1286    def test_get_as_utility(self):
1287        # we can get a bedtickets exporter as utility
1288        result = queryUtility(ICSVExporter, name="bedtickets")
1289        self.assertTrue(result is not None)
1290        return
1291
1292    def test_export_empty(self):
1293        # we can export a nearly empty bedticket
1294        bedticket = BedTicket()
1295        bed = self.app['hostels']['hall-1']['hall-1_A_101_A']
1296        bedticket.bed = bed
1297        exporter = BedTicketExporter()
1298        exporter.export([bedticket], self.outfile)
1299        result = open(self.outfile, 'rb').read()
1300        self.assertMatches(
1301            result,
1302            'bed,bed_coordinates,bed_type,booking_code,booking_date,'
1303            'booking_session,student_id,actual_bed_type\r\n'
1304            'hall-1_A_101_A,,,,<YYYY-MM-DD hh:mm:ss>.<6-DIGITS>#,,,regular_male_fr\r\n'
1305            )
1306        return
1307
1308    def test_export(self):
1309        # we can really export student bedtickets.
1310        # set values we can expect in export file
1311        self.setup_student(self.student)
1312        bedticket = self.student['accommodation']['2004']
1313        exporter = BedTicketExporter()
1314        exporter.export([bedticket], self.outfile)
1315        result = open(self.outfile, 'rb').read()
1316        self.assertMatches(
1317            result,
1318            'bed,bed_coordinates,bed_type,booking_code,booking_date,'
1319            'booking_session,student_id,actual_bed_type\r\n'
1320            'hall-1_A_101_A,,any bed type,,<YYYY-MM-DD hh:mm:ss>.<6-DIGITS>#,2004,'
1321            'A111111,regular_male_fr\r\n'
1322            )
1323        return
1324
1325    def test_export_all(self):
1326        # we can really export all bedtickets
1327        # set values we can expect in export file
1328        self.setup_student(self.student)
1329        exporter = BedTicketExporter()
1330        exporter.export_all(self.app, self.outfile)
1331        result = open(self.outfile, 'rb').read()
1332        self.assertMatches(
1333            result,
1334            'bed,bed_coordinates,bed_type,booking_code,booking_date,'
1335            'booking_session,student_id,actual_bed_type\r\n'
1336            'hall-1_A_101_A,,any bed type,,<YYYY-MM-DD hh:mm:ss>.<6-DIGITS>#,2004,'
1337            'A111111,regular_male_fr\r\n'
1338            )
1339        return
1340
1341    def test_export_student(self):
1342        # we can really export all bedtickets of a certain student
1343        # set values we can expect in export file
1344        self.setup_student(self.student)
1345        exporter = BedTicketExporter()
1346        exporter.export_student(self.student, self.outfile)
1347        result = open(self.outfile, 'rb').read()
1348        self.assertMatches(
1349            result,
1350            'bed,bed_coordinates,bed_type,booking_code,booking_date,'
1351            'booking_session,student_id,actual_bed_type\r\n'
1352            'hall-1_A_101_A,,any bed type,,<YYYY-MM-DD hh:mm:ss>.<6-DIGITS>#,2004,'
1353            'A111111,regular_male_fr\r\n'
1354            )
1355        return
1356
1357    def test_export_filtered(self):
1358        # we can export payments of a filtered set of students
1359        self.setup_student(self.student)
1360        self.app['students'].addStudent(self.student)
1361        notify(grok.ObjectModifiedEvent(self.student))
1362
1363        exporter = BedTicketExporter()
1364        exporter.export_filtered(
1365            self.student, self.outfile, current_level=200)
1366        result = open(self.outfile, 'rb').read()
1367        self.assertMatches(
1368            result,
1369            'bed,bed_coordinates,bed_type,booking_code,booking_date,'
1370            'booking_session,student_id,actual_bed_type\r\n'
1371            'hall-1_A_101_A,,any bed type,,<YYYY-MM-DD hh:mm:ss>.<6-DIGITS>#,'
1372            '2004,A111111,regular_male_fr\r\n')
1373        return
1374
1375
1376class SchoolFeePaymentsOverviewExporterTest(StudentImportExportSetup):
1377
1378    layer = FunctionalLayer
1379
1380    def setUp(self):
1381        super(SchoolFeePaymentsOverviewExporterTest, self).setUp()
1382        self.setup_for_export()
1383        return
1384
1385    def test_ifaces(self):
1386        # make sure we fullfill interface contracts
1387        obj = SchoolFeePaymentsOverviewExporter()
1388        verifyObject(ICSVStudentExporter, obj)
1389        verifyClass(ICSVStudentExporter, SchoolFeePaymentsOverviewExporter)
1390        return
1391
1392    def test_get_as_utility(self):
1393        # we can get a payments exporter as utility
1394        result = queryUtility(ICSVExporter, name="sfpaymentsoverview")
1395        self.assertTrue(result is not None)
1396        return
1397
1398    def test_export(self):
1399        self.setup_student(self.student)
1400        exporter = SchoolFeePaymentsOverviewExporter()
1401        exporter.export([self.student], self.outfile)
1402        result = open(self.outfile, 'rb').read()
1403        self.assertTrue(
1404            'student_id,matric_number,display_fullname,state,certcode,'
1405            'faccode,depcode,is_postgrad,'
1406            'current_level,current_session,current_mode,entry_session,'
1407            'reg_number,%s\r\n'
1408            'A111111,234,Anna M. Tester,created,CERT1,NA,NA,0,'
1409            '200,2012,ug_ft,2010,'
1410            % year_range_str in result
1411            )
1412        return
1413
1414    def test_export_all(self):
1415        # we can really export students
1416        # set values we can expect in export file
1417        self.setup_student(self.student)
1418        # We add successful payments.
1419        payment_2 = StudentOnlinePayment()
1420        payment_2.p_id = 'my-id'
1421        payment_2.p_session = curr_year - 5
1422        payment_2.amount_auth = 13.13
1423        payment_2.p_state = 'paid'
1424        payment_2.p_category = u'schoolfee'
1425        self.student['payments']['my-2ndpayment'] = payment_2
1426        # This one could be a balance payment.
1427        # The amount is being added.
1428        payment_3 = StudentOnlinePayment()
1429        payment_3.p_id = 'my-id_2'
1430        payment_3.p_session = curr_year - 5
1431        payment_3.amount_auth = 1.01
1432        payment_3.p_state = 'paid'
1433        payment_3.p_category = u'schoolfee'
1434        self.student['payments']['my-3rdpayment'] = payment_3
1435        # One session school fee has been waived
1436        payment_4 = StudentOnlinePayment()
1437        payment_4.p_id = 'my-id_2'
1438        payment_4.p_session = curr_year - 4
1439        payment_4.amount_auth = 1.01
1440        payment_4.p_state = 'waived'
1441        payment_4.p_category = u'schoolfee'
1442        self.student['payments']['my-4thpayment'] = payment_4
1443        exporter = SchoolFeePaymentsOverviewExporter()
1444        exporter.export_all(self.app, self.outfile)
1445        result = open(self.outfile, 'rb').read()
1446        self.assertTrue(
1447            'student_id,matric_number,display_fullname,state,'
1448            'certcode,faccode,depcode,is_postgrad,'
1449            'current_level,current_session,current_mode,entry_session,'
1450            'reg_number,%s\r\nA111111,234,Anna M. Tester,created,CERT1,NA,NA,0,'
1451            '200,2012,ug_ft,2010,123,,,,,,12.12,14.14,waived,,,,\r\n'
1452            % year_range_str in result
1453            )
1454        return
1455
1456class SessionPaymentsOverviewExporterTest(StudentImportExportSetup):
1457
1458    layer = FunctionalLayer
1459
1460    def setUp(self):
1461        super(SessionPaymentsOverviewExporterTest, self).setUp()
1462        self.setup_for_export()
1463        paycats = ('schoolfee', 'clearance', 'gown', 'transcript')
1464        paycatyears = ''
1465        grok.getSite()['configuration'].current_academic_session = curr_year - 4
1466        year_range = range(curr_year-6, curr_year-3)
1467        year_range_tuple = tuple([str(year)[2:] for year in year_range])
1468        for cat in paycats:
1469            for year in year_range_tuple:
1470                paycatyears += '%s,'%(cat+str(year))
1471        self.paycatyears = paycatyears.strip(',')
1472        return
1473
1474    def test_ifaces(self):
1475        # make sure we fullfill interface contracts
1476        obj = SessionPaymentsOverviewExporter()
1477        verifyObject(ICSVStudentExporter, obj)
1478        verifyClass(ICSVStudentExporter, SessionPaymentsOverviewExporter)
1479        return
1480
1481    def test_get_as_utility(self):
1482        # we can get a payments exporter as utility
1483        result = queryUtility(ICSVExporter, name="sessionpaymentsoverview")
1484        self.assertTrue(result is not None)
1485        return
1486
1487    def test_export(self):
1488        self.setup_student(self.student)
1489        exporter = SessionPaymentsOverviewExporter()
1490        exporter.export([self.student], self.outfile)
1491        result = open(self.outfile, 'rb').read()
1492        self.assertTrue(
1493            'student_id,matric_number,display_fullname,state,certcode,'
1494            'faccode,depcode,is_postgrad,current_level,current_session,'
1495            'current_mode,entry_session,reg_number,%s\r\n'
1496            'A111111,234,Anna M. Tester,created,CERT1,NA,NA,0,200,'
1497            '2012,ug_ft,2010,123,'
1498            '12.12,,,,,,,,,,,\r\n' %self.paycatyears in result
1499            )
1500        return
1501
1502    def test_export_all(self):
1503        self.setup_student(self.student)
1504        # We add successful payments.
1505        payment_2 = StudentOnlinePayment()
1506        payment_2.p_id = 'my-id'
1507        payment_2.p_session = curr_year - 5
1508        payment_2.amount_auth = 13.13
1509        payment_2.p_state = 'paid'
1510        payment_2.p_category = u'schoolfee'
1511        self.student['payments']['my-2ndpayment'] = payment_2
1512        # This one could be a balance payment.
1513        # The amount is being added.
1514        payment_3 = StudentOnlinePayment()
1515        payment_3.p_id = 'my-id_2'
1516        payment_3.p_session = curr_year - 5
1517        payment_3.amount_auth = 1.01
1518        payment_3.p_state = 'paid'
1519        payment_3.p_category = u'schoolfee'
1520        self.student['payments']['my-3rdpayment'] = payment_3
1521        # One session school fee has been waived
1522        payment_4 = StudentOnlinePayment()
1523        payment_4.p_id = 'my-id_2'
1524        payment_4.p_session = curr_year - 4
1525        payment_4.amount_auth = 1.01
1526        payment_4.p_state = 'waived'
1527        payment_4.p_category = u'schoolfee'
1528        self.student['payments']['my-4thpayment'] = payment_4
1529        exporter = SessionPaymentsOverviewExporter()
1530        exporter.export_all(self.app, self.outfile)
1531        result = open(self.outfile, 'rb').read()
1532        self.assertTrue(
1533            'student_id,matric_number,display_fullname,state,certcode,faccode,'
1534            'depcode,is_postgrad,current_level,current_session,'
1535            'current_mode,entry_session,reg_number,%s\r\n'
1536            'A111111,234,Anna M. Tester,created,CERT1,NA,NA,0,200,2012,ug_ft,'
1537            '2010,123,'
1538            '12.12,14.14,1.01,,,,,,,,,\r\n'
1539            %self.paycatyears in result
1540            )
1541        return
1542
1543class StudyLevelsOverviewExporterTest(StudentImportExportSetup):
1544
1545    layer = FunctionalLayer
1546
1547    def setUp(self):
1548        super(StudyLevelsOverviewExporterTest, self).setUp()
1549        self.setup_for_export()
1550        return
1551
1552    def test_ifaces(self):
1553        obj = StudyLevelsOverviewExporter()
1554        verifyObject(ICSVStudentExporter, obj)
1555        verifyClass(ICSVStudentExporter, StudyLevelsOverviewExporter)
1556        return
1557
1558    def test_get_as_utility(self):
1559        result = queryUtility(ICSVExporter, name="studylevelsoverview")
1560        self.assertTrue(result is not None)
1561        return
1562
1563    def test_export(self):
1564        self.setup_student(self.student)
1565        exporter = StudyLevelsOverviewExporter()
1566        exporter.export([self.student], self.outfile)
1567        result = open(self.outfile, 'rb').read()
1568        self.assertEqual(
1569             'student_id,state,certcode,faccode,depcode,is_postgrad,'
1570             'entry_session,current_level,current_session,'
1571             '0,10,100,110,120,200,210,220,300,310,320,400,410,420,500,'
1572             '510,520,600,610,620,700,710,720,800,810,820,900,910,920,999\r\n'
1573             'A111111,created,CERT1,NA,NA,0,2010,200,2012,,,2012'
1574             ',,,,,,,,,,,,,,,,,,,,,,,,,,,\r\n',
1575            result
1576            )
1577        return
1578
1579    def test_export_all(self):
1580        self.setup_student(self.student)
1581        exporter = StudyLevelsOverviewExporter()
1582        exporter.export_all(self.app, self.outfile)
1583        result = open(self.outfile, 'rb').read()
1584        self.assertEqual(
1585            'student_id,state,certcode,faccode,depcode,is_postgrad,'
1586            'entry_session,current_level,current_session,'
1587            '0,10,100,110,120,200,210,220,300,310,320,400,410,420,500,'
1588            '510,520,600,610,620,700,710,720,800,810,820,900,910,920,999\r\n'
1589            'A111111,created,CERT1,NA,NA,0,2010,200,2012,,,2012'
1590            ',,,,,,,,,,,,,,,,,,,,,,,,,,,\r\n',
1591            result
1592            )
1593        return
1594
1595class ComboCardExporterTest(StudentImportExportSetup):
1596
1597    layer = FunctionalLayer
1598
1599    def setUp(self):
1600        super(ComboCardExporterTest, self).setUp()
1601        self.setup_for_export()
1602        return
1603
1604    def create_passport_img(self, student):
1605        # create some passport file for `student`
1606        storage = getUtility(IExtFileStore)
1607        image_path = os.path.join(os.path.dirname(__file__), 'test_image.jpg')
1608        self.image_contents = open(image_path, 'rb').read()
1609        file_id = IFileStoreNameChooser(student).chooseName(
1610            attr='passport.jpg')
1611        storage.createFile(file_id, StringIO(self.image_contents))
1612
1613    def test_export_all(self):
1614        self.setup_student(self.student)
1615        self.create_passport_img(self.student)
1616        exporter = ComboCardDataExporter()
1617        exporter.export_all(self.app, self.outfile)
1618        result = open(self.outfile, 'rb').read()
1619        self.assertTrue(
1620            'display_fullname,student_id,matric_number,certificate,faculty,'
1621            'department,passport_path\r\nAnna M. Tester,A111111,234,'
1622            'Unnamed Certificate,Faculty of Unnamed Faculty (NA),'
1623            'Department of Unnamed Department (NA),'
1624            'students/00110/A111111/passport_A111111.jpg\r\n'
1625            in result
1626            )
1627        return
1628
1629class TranscriptDataExporterTest(StudentImportExportSetup):
1630
1631    layer = FunctionalLayer
1632
1633    def setUp(self):
1634        super(TranscriptDataExporterTest, self).setUp()
1635        self.setup_for_export()
1636        return
1637
1638    def test_export_all(self):
1639        self.setup_student(self.student)
1640        exporter = TranscriptDataExporter()
1641        exporter.export_all(self.app, self.outfile)
1642        result = open(self.outfile, 'rb').read()
1643        self.assertTrue(
1644            'student_id,state,certcode,faccode,depcode,entry_session,'
1645            'current_level,current_session,transcript_data\r\n'
1646            'A111111,created,CERT1,NA,NA,2010,200,2012,'
1647            'Level 100; 1st: ; 2nd: CRS1; 3rd: ; sgpa: 0.0\r\n'
1648            in result
1649            )
1650        return
Note: See TracBrowser for help on using the repository browser.