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

Last change on this file since 15970 was 15966, checked in by Henrik Bettermann, 5 years ago

Add TrimmedDataExporter?.

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