Changeset 14288
- Timestamp:
- 18 Nov 2016, 07:19:25 (8 years ago)
- Location:
- main/waeup.aaue/trunk/src/waeup/aaue
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
main/waeup.aaue/trunk/src/waeup/aaue/browser/viewlets.py
r13357 r14288 18 18 19 19 import grok 20 from waeup.kofa.interfaces import IKofaObject 21 from waeup.kofa.browser.viewlets import PrimaryNavTab 20 from waeup.kofa.interfaces import IKofaObject, academic_sessions_vocab 21 from waeup.kofa.browser.viewlets import ( 22 PrimaryNavTab, ManageActionButton, UpdateScoresActionButton) 22 23 from waeup.aaue.interfaces import MessageFactory as _ 23 24 … … 41 42 return self.view.application_url('applicants') + '/checkstatus' 42 43 return 44 45 46 class UpdatePreviousSessionScoresActionButton(UpdateScoresActionButton): 47 """ 'Update scores' button in course. 48 """ 49 grok.name('updateprevscores') 50 target = 'edit_prev_scores' 51 52 @property 53 def target_url(self): 54 ca = grok.getSite()[ 55 'configuration'].current_academic_session 56 if not ca: 57 return '' 58 return self.view.url(self.view.context, self.target) 59 60 @property 61 def text(self): 62 ca = grok.getSite()[ 63 'configuration'].current_academic_session 64 st = academic_sessions_vocab.getTerm(ca-1).title 65 return _('Update session ${a} scores', mapping = {'a':st}) 66 -
main/waeup.aaue/trunk/src/waeup/aaue/students/browser.py
r14267 r14288 28 28 from waeup.kofa.browser.layout import UtilityView 29 29 from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget 30 from waeup.kofa.interfaces import IKofaUtils, academic_sessions_vocab 30 from waeup.kofa.interfaces import ( 31 IKofaUtils, academic_sessions_vocab, ICSVExporter) 31 32 from waeup.kofa.students.interfaces import IStudentsUtils, IStudent 32 33 from waeup.kofa.students.workflow import PAID, REGISTERED, RETURNING … … 49 50 ExportPDFScoresSlip, 50 51 StudyCourseTranscriptPage, 52 DownloadScoresView, 51 53 ) 52 54 from kofacustom.nigeria.students.browser import ( … … 668 670 return result 669 671 670 def update(self, *args, **kw): 671 form = self.request.form 672 def _update_scores(self, form): 672 673 ob_class = self.__implemented__.__name__.replace('waeup.kofa.', '') 673 self.current_academic_session = grok.getSite()[ 674 'configuration'].current_academic_session 675 if self.context.__parent__.__parent__.score_editing_disabled: 676 self.flash(_('Score editing disabled.'), type="warning") 677 self.redirect(self.url(self.context)) 678 return 679 if not self.current_academic_session: 680 self.flash(_('Current academic session not set.'), type="warning") 681 self.redirect(self.url(self.context)) 682 return 683 self.session_title = academic_sessions_vocab.getTerm( 684 self.current_academic_session).title 685 self.tickets = self._searchCatalog(self.current_academic_session) 686 self.editable_tickets = [ 687 ticket for ticket in self.tickets if ticket.editable_by_lecturer] 688 if not self.tickets: 689 self.flash(_('No student found.'), type="warning") 690 self.redirect(self.url(self.context)) 691 return 692 if not 'UPDATE_TABLE' in form and not 'UPDATE_FILE' in form: 693 return 694 695 if not self.editable_tickets: 696 return 674 error = '' 697 675 if 'UPDATE_FILE' in form: 698 676 if form['uploadfile']: … … 703 681 _('Uploaded file contains illegal data. Ignored'), 704 682 type="danger") 705 return 683 return False 706 684 else: 707 685 self.flash( 708 686 _('No file provided.'), type="danger") 709 return 687 return False 710 688 else: 711 689 formvals = dict(zip(form['sids'], zip(form['scores'], form['cas']))) 712 error = ''713 # In AAUE only editable tickets are shown, see also customized714 # pagetemplate715 690 for ticket in self.editable_tickets: 716 691 ticket_error = False … … 754 729 self.flash(_('Error: Score(s) and CA(s) of %s have not be updated. ' 755 730 % error.strip(', ')), type="danger") 731 return True 732 733 class EditPreviousSessionScoresPage(CustomEditScoresPage): 734 735 grok.name('edit_prev_scores') 736 737 def update(self, *args, **kw): 738 form = self.request.form 739 self.current_academic_session = grok.getSite()[ 740 'configuration'].current_academic_session 741 if self.context.__parent__.__parent__.score_editing_disabled: 742 self.flash(_('Score editing disabled.'), type="warning") 743 self.redirect(self.url(self.context)) 756 744 return 757 self.flash(_('You successfully updated course results.')) 745 if not self.current_academic_session: 746 self.flash(_('Current academic session not set.'), type="warning") 747 self.redirect(self.url(self.context)) 748 return 749 previous_session = self.current_academic_session - 1 750 self.session_title = academic_sessions_vocab.getTerm( 751 previous_session).title 752 self.tickets = self._searchCatalog(previous_session) 753 if not self.tickets: 754 self.flash(_('No student found.'), type="warning") 755 self.redirect(self.url(self.context)) 756 return 757 self.editable_tickets = [ 758 ticket for ticket in self.tickets if ticket.editable_by_lecturer] 759 if not 'UPDATE_TABLE' in form and not 'UPDATE_FILE' in form: 760 return 761 if not self.editable_tickets: 762 return 763 success = self._update_scores(form) 764 if success: 765 self.flash(_('You successfully updated course results.')) 758 766 return 759 767 … … 783 791 _('Grade'), 784 792 ],] 793 sorted_tickets = sorted(editable_tickets, 794 key=lambda ticket: ticket.student.certcode + 795 ticket.student.display_fullname + str(ticket.level)) 796 no = 1 785 797 tickets = [] 786 no = 1787 798 # In AAUE only editable tickets can be printed 788 for ticket in editable_tickets:799 for ticket in sorted_tickets: 789 800 if None in (ticket.score, ticket.ca): 790 801 total = 'n/a' … … 808 819 tickets.append(row) 809 820 no += 1 810 return header + sorted(tickets, 811 key=lambda value: value[5] + value[3] + str(value[6])) 821 return header + tickets 822 823 class DownloadPreviousSessionScoresView(DownloadScoresView): 824 """View that exports scores. 825 """ 826 grok.name('download_prev_scores') 827 828 def update(self): 829 self.current_academic_session = grok.getSite()[ 830 'configuration'].current_academic_session 831 if self.context.__parent__.__parent__.score_editing_disabled: 832 self.flash(_('Score editing disabled.'), type="warning") 833 self.redirect(self.url(self.context)) 834 return 835 if not self.current_academic_session: 836 self.flash(_('Current academic session not set.'), type="warning") 837 self.redirect(self.url(self.context)) 838 return 839 site = grok.getSite() 840 exporter = getUtility(ICSVExporter, name='lecturer') 841 self.csv = exporter.export_filtered(site, filepath=None, 842 catalog='coursetickets', 843 session=self.current_academic_session-1, 844 level=None, 845 code=self.context.code) 846 return -
main/waeup.aaue/trunk/src/waeup/aaue/students/browser_templates/editscorespage.pt
r14149 r14288 4 4 (press 'Help' for further information) or by 5 5 changing score or CA values in the table below. Only scores and CAs 6 of students in state 'courses validated' andcurrent session6 of students in current session 7 7 <span i18n:name="current_academic_session" 8 8 tal:replace="view/session_title"></span> … … 61 61 <strong>Note:</strong> 62 62 Only course results of students which are in 63 state 'courses validated' and in current academic session 63 academic session 64 <span i18n:name="current_academic_session" 65 tal:replace="view/session_title"></span> 64 66 can be modified. Additional data will just be ignored. 65 67 </div> -
main/waeup.aaue/trunk/src/waeup/aaue/students/studylevel.py
r14266 r14288 312 312 return self.score + self.ca 313 313 314 @property 315 def editable_by_lecturer(self): 316 """True if lecturer is allowed to edit the ticket. 317 """ 318 return True 319 314 320 CustomCourseTicket = attrs_to_fields(CustomCourseTicket) 315 321 -
main/waeup.aaue/trunk/src/waeup/aaue/students/tests/test_browser.py
r14266 r14288 79 79 'http://localhost/app/faculties/fac1/dep1/courses/COURSE1') 80 80 self.edit_scores_url = '%s/edit_scores' % self.course_url 81 self.edit_prev_scores_url = '%s/edit_prev_scores' % self.course_url 81 82 # Set standard parameters 82 83 self.app['configuration'].current_academic_session = 2004 … … 363 364 self.student['studycourse']['100']['COURSE1'].score = 55 364 365 self.browser.open(self.edit_scores_url) 366 upload_ctrl = self.browser.getControl(name='uploadfile:file') 367 upload_file = StringIO(UPLOAD_CSV_TEMPLATE % ('65','22')) 368 upload_ctrl.add_file(upload_file, 'text/csv', 'myscores.csv') 369 self.browser.getControl("Update editable scores from").click() 370 # value changed 371 self.assertEqual( 372 self.student['studycourse']['100']['COURSE1'].score, 65) 373 self.assertEqual( 374 self.student['studycourse']['100']['COURSE1'].ca, 22) 375 376 def test_scores_previous_session(self): 377 # lecturers can download a CSV file to set values. 378 self.login_as_lecturer() 379 self.student['studycourse']['100']['COURSE1'].score = 55 380 self.browser.open(self.edit_prev_scores_url) 381 self.assertTrue('No student found' in self.browser.contents) 382 self.student['studycourse']['100'].level_session = 2003 383 notify(grok.ObjectModifiedEvent(self.student['studycourse']['100']['COURSE1'])) 384 self.browser.open(self.edit_prev_scores_url) 385 self.browser.getLink("Download csv file").click() 386 self.assertEqual(self.browser.headers['Status'], '200 Ok') 387 self.assertEqual(self.browser.headers['Content-Type'], 388 'text/csv; charset=UTF-8') 389 self.assertEqual(self.browser.contents, 'matric_number,student_id,' 390 'level,code,level_session,ca,score\r\n234,E1000000,' 391 '100,COURSE1,2003,,55\r\n') 392 self.browser.open(self.edit_prev_scores_url) 365 393 upload_ctrl = self.browser.getControl(name='uploadfile:file') 366 394 upload_file = StringIO(UPLOAD_CSV_TEMPLATE % ('65','22')) -
main/waeup.aaue/trunk/src/waeup/aaue/students/viewlets.py
r14207 r14288 27 27 StudentPassportActionButton, 28 28 StudyCourseTranscriptActionButton, 29 TranscriptSlipActionButton) 29 TranscriptSlipActionButton, 30 DownloadCSVFileActionButton, 31 DownloadTicketOverviewActionButton) 30 32 from waeup.kofa.students.browser import StudyLevelDisplayFormPage 31 33 … … 129 131 grok.require('waeup.viewStudent') 130 132 grok.name('transcript_slip') 133 134 class CustomDownloadCSVFileActionButton(DownloadCSVFileActionButton): 135 """ 'Download csv file' button for courses. 136 """ 137 138 @property 139 def target_url(self): 140 if self.view.__name__ == 'edit_prev_scores': 141 return self.view.url(self.view.context, 'download_prev_scores') 142 return self.view.url(self.view.context, 'download_scores') 143 144 class CustomDownloadTicketOverviewActionButton( 145 DownloadTicketOverviewActionButton): 146 """ 'Download ticket overview' button for courses. 147 """ 148 149 @property 150 def target_url(self): 151 if self.view.__name__ == 'edit_prev_scores': 152 return '' 153 return self.view.url(self.view.context, 'coursetickets.pdf')
Note: See TracChangeset for help on using the changeset viewer.