Changeset 9797 for main/waeup.kofa/trunk/src/waeup/kofa/students
- Timestamp:
- 13 Dec 2012, 15:39:31 (12 years ago)
- Location:
- main/waeup.kofa/trunk/src/waeup/kofa/students
- Files:
-
- 2 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py
r9795 r9797 36 36 KofaPage, KofaEditFormPage, KofaAddFormPage, KofaDisplayFormPage, 37 37 KofaForm, NullValidator) 38 from waeup.kofa.browser.breadcrumbs import Breadcrumb 38 39 from waeup.kofa.browser.pages import ContactAdminForm 39 from waeup.kofa.browser. breadcrumbs import Breadcrumb40 from waeup.kofa.browser.resources import datepicker, datatable, tabs, warning 40 from waeup.kofa.browser.resources import ( 41 datepicker, datatable, tabs, warning, toggleall) 41 42 from waeup.kofa.browser.layout import jsaction, action, UtilityView 42 43 from waeup.kofa.browser.interfaces import ICaptchaManager 44 from waeup.kofa.hostels.hostel import NOT_OCCUPIED 43 45 from waeup.kofa.interfaces import ( 44 46 IKofaObject, IUserAccount, IExtFileStore, IPasswordValidator, IContactForm, 45 IKofaUtils, IUniversity, IObjectHistory, academic_sessions) 47 IKofaUtils, IUniversity, IObjectHistory, academic_sessions, ICSVExporter, 48 academic_sessions_vocab, IJobManager) 46 49 from waeup.kofa.interfaces import MessageFactory as _ 47 50 from waeup.kofa.widgets.datewidget import ( 48 51 FriendlyDateWidget, FriendlyDateDisplayWidget, 49 52 FriendlyDatetimeDisplayWidget) 53 from waeup.kofa.mandates.mandate import PasswordMandate 54 from waeup.kofa.university.department import ( 55 VirtualDepartmentExportJobContainer,) 56 from waeup.kofa.university.vocabularies import course_levels 57 from waeup.kofa.utils.helpers import get_current_principal, to_timezone 50 58 from waeup.kofa.widgets.restwidget import ReSTDisplayWidget 51 59 from waeup.kofa.students.interfaces import ( … … 59 67 IBedTicket, IStudentsUtils, IStudentRequestPW 60 68 ) 61 from waeup.kofa.students.catalog import search 69 from waeup.kofa.students.catalog import search, StudentsQuery 70 from waeup.kofa.students.studylevel import StudentStudyLevel, CourseTicket 71 from waeup.kofa.students.vocabularies import StudyLevelSource 62 72 from waeup.kofa.students.workflow import (CREATED, ADMITTED, PAID, 63 73 CLEARANCE, REQUESTED, RETURNING, CLEARED, REGISTERED, VALIDATED, 64 74 FORBIDDEN_POSTGRAD_TRANS) 65 from waeup.kofa.students.studylevel import StudentStudyLevel, CourseTicket 66 from waeup.kofa.students.vocabularies import StudyLevelSource 67 from waeup.kofa.browser.resources import toggleall 68 from waeup.kofa.hostels.hostel import NOT_OCCUPIED 69 from waeup.kofa.utils.helpers import get_current_principal, to_timezone 70 from waeup.kofa.mandates.mandate import PasswordMandate 75 71 76 72 77 grok.context(IKofaObject) # Make IKofaObject the default context … … 2496 2501 self.student_id = student_id 2497 2502 return 2503 2504 class DepartmentExportJobContainerOverview(KofaPage): 2505 """Page that filters and lists students. 2506 """ 2507 grok.context(VirtualDepartmentExportJobContainer) 2508 grok.require('waeup.showStudents') 2509 grok.name('index.html') 2510 grok.template('exportjobsindex') 2511 label = _('Department Exports') 2512 pnav = 1 2513 2514 def doll_up(self): 2515 job_entries = self.context.get_running_export_jobs( 2516 self.request.principal.id) 2517 job_manager = getUtility(IJobManager) 2518 entries = [] 2519 for job_id, exporter_name, user_id in job_entries: 2520 job = job_manager.get(job_id) 2521 descr = 'Export (%r, %r)' % (job.args[1:], job.kwargs) 2522 status = job.status 2523 start_time = '%s' % job.begin_after 2524 download_url = self.url(self.context, 'download', 2525 data=dict(job_id=job_id)) 2526 new_entry = dict( 2527 job=job_id, descr=descr, status=status, start_time=start_time, 2528 download_url=download_url) 2529 entries.append(new_entry) 2530 self.entries = entries 2531 pass 2532 2533 def update(self, CREATE=None, DISCARD=None, job_id=None): 2534 if CREATE: 2535 self.redirect(self.url('jobconfig')) 2536 return 2537 if DISCARD and job_id: 2538 print "DISCARD: ", job_id 2539 entry = self.context.entry_from_job_id(job_id) 2540 self.context.delete_export_entry(entry) 2541 self.flash('Discarded export %s' % job_id) 2542 self.doll_up() 2543 return 2544 2545 class DepartmentExportJobContainerJobConfig(KofaPage): 2546 """Page that configures a students export job. 2547 """ 2548 grok.context(VirtualDepartmentExportJobContainer) 2549 grok.require('waeup.showStudents') 2550 grok.name('jobconfig') 2551 grok.template('exportjobsjobconfig') 2552 label = _('Create New Export Job') 2553 pnav = 1 2554 2555 def _set_session_values(self): 2556 vocab_terms = academic_sessions_vocab.by_value.values() 2557 self.sessions = sorted( 2558 [(x.title, x.token) for x in vocab_terms], reverse=True) 2559 self.sessions += [('All Sessions', 'all')] 2560 return 2561 2562 def _set_level_values(self): 2563 vocab_terms = course_levels.by_value.values() 2564 self.levels = sorted( 2565 [(x.title, x.token) for x in vocab_terms]) 2566 self.levels += [('All Levels', 'all')] 2567 return 2568 2569 def update(self, START=None, session=None, level=None): 2570 self._set_session_values() 2571 self._set_level_values() 2572 if START is None: 2573 return 2574 if session == 'all': 2575 session=None 2576 if level == 'all': 2577 level = None 2578 code = self.context.__parent__.code 2579 self.context.start_export_job('students', self.request.principal.id, 2580 current_session=session, 2581 current_level=level, 2582 depcode=code) 2583 self.flash('Export started for students from %s ' 2584 '(session=%s, level=%s)' % ( 2585 code, session, level)) 2586 self.redirect(self.url(self.context)) 2587 return 2588 2589 class DepartmentExportJobContainerDownload(grok.View): 2590 """Page that configures a students export job. 2591 """ 2592 grok.context(VirtualDepartmentExportJobContainer) 2593 grok.require('waeup.showStudents') 2594 grok.name('download') 2595 2596 def update(self, job_id=None): 2597 self.job_id=job_id 2598 return 2599 2600 def render(self): 2601 job = getUtility(IJobManager).get(self.job_id) 2602 self.response.setHeader( 2603 'Content-Type', 'text/csv; charset=UTF-8') 2604 self.response.setHeader( 2605 'Content-Disposition:', 'attachment; filename="%s' % ( 2606 'students.csv',)) 2607 return open(job.result, 'rb') 2608 return -
main/waeup.kofa/trunk/src/waeup/kofa/students/export.py
r9787 r9797 34 34 'coursetickets', 'studentpayments') 35 35 36 def ident(x): 37 return x 38 #for item in x: 39 # yield item 40 36 41 def get_students(site, stud_filter=StudentsQuery()): 37 42 """Get all students registered in catalog in `site`. … … 90 95 grok.provides(ICSVStudentExporter) 91 96 97 def filter_func(self, x): 98 return get_students(x) 99 100 def get_filtered(self, site, current_session=None, 101 current_level=None, faccode=None, depcode=None, ): 102 query = StudentsQuery( 103 current_session=current_session, 104 current_level=current_level, 105 faccode=faccode, depcode=depcode) 106 return query.query() 107 92 108 def export(self, values, filepath=None): 93 109 """Export `values`, an iterable, as CSV file. … … 100 116 return self.close_outfile(filepath, outfile) 101 117 102 def export_ filtered(self, site, session, level, faccode=None,103 depcode=None, filepath=None):104 """Export all students denoted by the given parameters. 105 """106 filter_inst = StudentsQuery(107 current_session=session, current_level=level,108 faccode=faccode, depcode=depcode) 109 result_set = get_students(site, stud_filter=filter_inst)110 return self.export( result_set, filepath=filepath)118 def export_all(self, site, filepath=None): 119 """Export students into filepath as CSV data. 120 121 If `filepath` is ``None``, a raw string with CSV data is returned. 122 """ 123 return self.export(self.filter_func(site), filepath) 124 125 def export_student(self, student, filepath=None): 126 return self.export(self.filter_func([student]), filepath=filepath) 111 127 112 128 … … 146 162 return self.export([student], filepath=filepath) 147 163 148 149 164 class StudentStudyCourseExporter(grok.GlobalUtility, StudentExporterBase): 150 165 """Exporter for StudentStudyCourses. … … 157 172 #: The title under which this exporter will be displayed 158 173 title = _(u'Student Study Courses') 174 175 def filter_func(self, x): 176 return get_studycourses(x) 159 177 160 178 def mangle_value(self, value, name, context=None): … … 183 201 return self.export(get_studycourses([student]), filepath) 184 202 203 def export_filtered(self, site, filepath=None, **kw): 204 """Export items denoted by `args` and `kw`. 205 206 If `filepath` is ``None``, a raw string with CSV data should 207 be returned. 208 """ 209 data = self.get_filtered(site, **kw) 210 return self.export(get_studycourses(data), filepath=filepath) 211 185 212 186 213 class StudentStudyLevelExporter(grok.GlobalUtility, StudentExporterBase): … … 216 243 def export_student(self, student, filepath=None): 217 244 return self.export(get_levels([student]), filepath) 245 246 def export_filtered(self, site, filepath=None, **kw): 247 """Export items denoted by `args` and `kw`. 248 249 If `filepath` is ``None``, a raw string with CSV data should 250 be returned. 251 """ 252 data = self.get_filtered(site, **kw) 253 return self.export(get_levels(data), filepath=filepath) 218 254 219 255 class CourseTicketExporter(grok.GlobalUtility, StudentExporterBase): … … 252 288 return self.export(get_tickets([student]), filepath) 253 289 290 def export_filtered(self, site, filepath=None, **kw): 291 """Export items denoted by `args` and `kw`. 292 293 If `filepath` is ``None``, a raw string with CSV data should 294 be returned. 295 """ 296 data = self.get_filtered(site, **kw) 297 return self.export(get_tickets(data), filepath=filepath) 298 254 299 255 300 class PaymentsExporter(grok.GlobalUtility, StudentExporterBase): … … 287 332 def export_student(self, student, filepath=None): 288 333 return self.export(get_payments([student]), filepath) 334 335 def export_filtered(self, site, filepath=None, **kw): 336 """Export items denoted by `args` and `kw`. 337 338 If `filepath` is ``None``, a raw string with CSV data should 339 be returned. 340 """ 341 data = self.get_filtered(site, **kw) 342 return self.export(get_payments(data), filepath=filepath) 289 343 290 344 class BedTicketsExporter(grok.GlobalUtility, StudentExporterBase): … … 326 380 def export_student(self, student, filepath=None): 327 381 return self.export(get_bedtickets([student]), filepath) 382 383 def export_filtered(self, site, filepath=None, **kw): 384 """Export items denoted by `args` and `kw`. 385 386 If `filepath` is ``None``, a raw string with CSV data should 387 be returned. 388 """ 389 data = self.get_filtered(site, **kw) 390 return self.export(get_bedtickets(data), filepath=filepath) 328 391 329 392 class StudentPaymentsOverviewExporter(StudentsExporter): -
main/waeup.kofa/trunk/src/waeup/kofa/students/interfaces.py
r9761 r9797 748 748 data from a given student object. 749 749 """ 750 def get_filtered(site, current_session=None, current_level=None, 751 faculty_code=None, department_code=None): 752 """Get a filtered set of students. 753 """ 750 754 751 755 def export_student(student, filepath=None): … … 753 757 """ 754 758 755 def export_filtered(site, session, level, faculty_code=None, 756 department_code=None, filepath=None): 759 def export_filtered(site, filepath=None, **kw): 757 760 """Export filtered set of students. 758 761 """ -
main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_export.py
r9788 r9797 183 183 exporter = StudentsExporter() 184 184 185 exporter.export_filtered(self.app, None, None, filepath=self.outfile) 185 exporter.export_filtered( 186 self.app, self.outfile, 187 current_session=None, current_level=None) 186 188 result1 = open(self.outfile, 'rb').read() 187 exporter.export_filtered(self.app, 2012, None, filepath=self.outfile) 189 exporter.export_filtered( 190 self.app, self.outfile, 191 current_session=2012, current_level=None) 188 192 result2 = open(self.outfile, 'rb').read() 189 exporter.export_filtered(self.app, None, 200, filepath=self.outfile) 193 exporter.export_filtered( 194 self.app, self.outfile, 195 current_session=None, current_level=200) 190 196 result3 = open(self.outfile, 'rb').read() 191 exporter.export_filtered(self.app, 2011, None, filepath=self.outfile) 197 exporter.export_filtered( 198 self.app, self.outfile, 199 current_session=2011, current_level=None) 192 200 result4 = open(self.outfile, 'rb').read() 193 exporter.export_filtered(self.app, None, 100, filepath=self.outfile) 201 exporter.export_filtered( 202 self.app, self.outfile, 203 current_session=None, current_level=100) 194 204 result5 = open(self.outfile, 'rb').read() 195 205 self.assertTrue(self.std_csv_entry in result1) … … 207 217 exporter = StudentsExporter() 208 218 209 exporter.export_filtered(self.app, 2012, 200, depcode='NA', 210 filepath=self.outfile) 219 exporter.export_filtered( 220 self.app, self.outfile, 221 current_session=2012, current_level=200, depcode='NA') 211 222 result1 = open(self.outfile, 'rb').read() 212 exporter.export_filtered(self.app, 2012, 200, depcode='NODEPT', 213 filepath=self.outfile) 223 exporter.export_filtered( 224 self.app, self.outfile, 225 current_session=2012, current_level=200, depcode='NODEPT') 214 226 result2 = open(self.outfile, 'rb').read() 215 227 self.assertTrue(self.std_csv_entry in result1) … … 225 237 226 238 exporter.export_filtered( 227 self.app, 2012, 200, faccode='NA', filepath=self.outfile) 239 self.app, self.outfile, 240 current_session=2012, current_level=200, faccode='NA') 228 241 result1 = open(self.outfile, 'rb').read() 229 exporter.export_filtered(self.app, 2012, 200, faccode='NOFAC', 230 filepath=self.outfile) 242 exporter.export_filtered( 243 self.app, self.outfile, 244 current_session=2012, current_level=200, faccode='NOFAC') 231 245 result2 = open(self.outfile, 'rb').read() 232 246 self.assertTrue(self.std_csv_entry in result1) … … 234 248 return 235 249 236 237 250 class StudentStudyCourseExporterTest(StudentImportExportSetup): 238 251 … … 247 260 # make sure we fullfill interface contracts 248 261 obj = StudentStudyCourseExporter() 249 verifyObject(ICSV Exporter, obj)250 verifyClass(ICSV Exporter, StudentStudyCourseExporter)262 verifyObject(ICSVStudentExporter, obj) 263 verifyClass(ICSVStudentExporter, StudentStudyCourseExporter) 251 264 return 252 265 … … 320 333 return 321 334 335 def test_export_filtered(self): 336 # we can export studycourses of a filtered set of students 337 self.setup_student(self.student) 338 self.app['students'].addStudent(self.student) 339 notify(grok.ObjectModifiedEvent(self.student)) 340 341 exporter = StudentStudyCourseExporter() 342 exporter.export_filtered( 343 self.student, self.outfile, current_session=2012) 344 result = open(self.outfile, 'rb').read() 345 self.assertEqual( 346 result, 347 'certificate,current_level,current_session,current_verdict,' 348 'entry_mode,entry_session,previous_verdict,student_id\r\n' 349 350 'CERT1,200,2012,0,ug_ft,2010,0,A111111\r\n' 351 ) 352 return 353 354 355 322 356 class StudentStudyLevelExporterTest(StudentImportExportSetup): 323 357 … … 332 366 # make sure we fullfill interface contracts 333 367 obj = StudentStudyLevelExporter() 334 verifyObject(ICSV Exporter, obj)335 verifyClass(ICSV Exporter, StudentStudyLevelExporter)368 verifyObject(ICSVStudentExporter, obj) 369 verifyClass(ICSVStudentExporter, StudentStudyLevelExporter) 336 370 return 337 371 … … 406 440 return 407 441 442 def test_export_filtered(self): 443 # we can export studylevels of a filtered set of students 444 self.setup_student(self.student) 445 self.app['students'].addStudent(self.student) 446 notify(grok.ObjectModifiedEvent(self.student)) 447 448 exporter = StudentStudyLevelExporter() 449 exporter.export_filtered( 450 self.student, self.outfile, current_level=200) 451 result = open(self.outfile, 'rb').read() 452 self.assertEqual( 453 result, 454 'gpa,level,level_session,level_verdict,total_credits,' 455 'validated_by,validation_date,' 456 'student_id,number_of_tickets,certcode\r\n' 457 '0.0,100,2012,A,100,,,A111111,1,CERT1\r\n' 458 ) 459 return 460 408 461 class CourseTicketExporterTest(StudentImportExportSetup): 409 462 … … 418 471 # make sure we fullfill interface contracts 419 472 obj = CourseTicketExporter() 420 verifyObject(ICSV Exporter, obj)421 verifyClass(ICSV Exporter, CourseTicketExporter)473 verifyObject(ICSVStudentExporter, obj) 474 verifyClass(ICSVStudentExporter, CourseTicketExporter) 422 475 return 423 476 … … 489 542 return 490 543 544 def test_export_filtered(self): 545 # we can export studylevels of a filtered set of students 546 self.setup_student(self.student) 547 self.app['students'].addStudent(self.student) 548 notify(grok.ObjectModifiedEvent(self.student)) 549 550 exporter = CourseTicketExporter() 551 exporter.export_filtered( 552 self.student, self.outfile, current_level=200) 553 result = open(self.outfile, 'rb').read() 554 self.assertEqual( 555 result, 556 'automatic,carry_over,code,credits,dcode,fcode,level,mandatory,' 557 'passmark,score,semester,title,student_id,certcode\r\n' 558 '1,1,CRS1,100,DEP1,FAC1,100,0,100,,2,Course 1,A111111,CERT1\r\n' 559 ) 560 return 561 491 562 class PaymentsExporterTest(StudentImportExportSetup): 492 563 … … 501 572 # make sure we fullfill interface contracts 502 573 obj = PaymentsExporter() 503 verifyObject(ICSV Exporter, obj)504 verifyClass(ICSV Exporter, PaymentsExporter)574 verifyObject(ICSVStudentExporter, obj) 575 verifyClass(ICSVStudentExporter, PaymentsExporter) 505 576 return 506 577 … … 586 657 return 587 658 659 def test_export_filtered(self): 660 # we can export payments of a filtered set of students 661 self.setup_student(self.student) 662 self.app['students'].addStudent(self.student) 663 notify(grok.ObjectModifiedEvent(self.student)) 664 665 exporter = PaymentsExporter() 666 exporter.export_filtered( 667 self.student, self.outfile, current_level=200) 668 result = open(self.outfile, 'rb').read() 669 self.assertEqual( 670 result, 671 'ac,amount_auth,creation_date,p_category,p_current,p_id,' 672 'p_item,p_level,p_session,p_state,payment_date,r_amount_approved,' 673 'r_code,r_desc,student_id,student_state,current_session\r\n' 674 675 '666,0.0,2012-04-01 13:12:01,schoolfee,1,my-id,' 676 'p-item,100,2012,unpaid,2012-04-01 14:12:01,12.12,' 677 'r-code,,A111111,created,2012\r\n' 678 ) 679 return 680 588 681 class BedTicketsExporterTest(StudentImportExportSetup): 589 682 … … 598 691 # make sure we fullfill interface contracts 599 692 obj = BedTicketsExporter() 600 verifyObject(ICSV Exporter, obj)601 verifyClass(ICSV Exporter, BedTicketsExporter)693 verifyObject(ICSVStudentExporter, obj) 694 verifyClass(ICSVStudentExporter, BedTicketsExporter) 602 695 return 603 696 … … 673 766 return 674 767 768 def test_export_filtered(self): 769 # we can export payments of a filtered set of students 770 self.setup_student(self.student) 771 self.app['students'].addStudent(self.student) 772 notify(grok.ObjectModifiedEvent(self.student)) 773 774 exporter = BedTicketsExporter() 775 exporter.export_filtered( 776 self.student, self.outfile, current_level=200) 777 result = open(self.outfile, 'rb').read() 778 self.assertMatches( 779 result, 780 'bed,bed_coordinates,bed_type,booking_code,booking_date,' 781 'booking_session,student_id,actual_bed_type\r\n' 782 'hall-1_A_101_A,,any bed type,,<YYYY-MM-DD hh:mm:ss>.<6-DIGITS>,' 783 '2004,A111111,regular_male_fr\r\n') 784 return 785 786 675 787 class StudentPaymentsOverviewExporterTest(StudentImportExportSetup): 676 788 … … 685 797 # make sure we fullfill interface contracts 686 798 obj = StudentPaymentsOverviewExporter() 687 verifyObject(ICSV Exporter, obj)688 verifyClass(ICSV Exporter, StudentPaymentsOverviewExporter)799 verifyObject(ICSVStudentExporter, obj) 800 verifyClass(ICSVStudentExporter, StudentPaymentsOverviewExporter) 689 801 return 690 802 … … 744 856 def test_ifaces(self): 745 857 obj = StudentStudyLevelsOverviewExporter() 746 verifyObject(ICSV Exporter, obj)747 verifyClass(ICSV Exporter, StudentStudyLevelsOverviewExporter)858 verifyObject(ICSVStudentExporter, obj) 859 verifyClass(ICSVStudentExporter, StudentStudyLevelsOverviewExporter) 748 860 return 749 861
Note: See TracChangeset for help on using the changeset viewer.