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

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