- Timestamp:
- 14 Jun 2016, 01:38:12 (8 years ago)
- Location:
- main/waeup.kofa/trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
main/waeup.kofa/trunk
- Property svn:mergeinfo changed
/main/waeup.kofa/branches/uli-scores-upload merged: 13913-13934
- Property svn:mergeinfo changed
-
main/waeup.kofa/trunk/src/waeup/kofa
- Property svn:mergeinfo changed
/main/waeup.kofa/branches/uli-scores-upload/src/waeup/kofa merged: 13913-13934
- Property svn:mergeinfo changed
-
main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py
r13908 r13935 18 18 """UI components for students and related components. 19 19 """ 20 import sys20 import csv 21 21 import grok 22 22 import pytz 23 import sys 24 from cStringIO import StringIO 25 from datetime import datetime 26 from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState 23 27 from urllib import urlencode 24 from datetime import datetime25 from zope.event import notify26 from zope.i18n import translate27 28 from zope.catalog.interfaces import ICatalog 28 29 from zope.component import queryUtility, getUtility, createObject 30 from zope.event import notify 31 from zope.formlib.textwidgets import BytesDisplayWidget 32 from zope.i18n import translate 29 33 from zope.schema.interfaces import ConstraintNotSatisfied, RequiredMissing 30 from zope.formlib.textwidgets import BytesDisplayWidget31 34 from zope.security import checkPermission 32 from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState 33 from waeup.kofa.accesscodes import ( 34 invalidate_accesscode, get_access_code) 35 from waeup.kofa.accesscodes import invalidate_accesscode, get_access_code 35 36 from waeup.kofa.accesscodes.workflow import USED 37 from waeup.kofa.browser.breadcrumbs import Breadcrumb 38 from waeup.kofa.browser.interfaces import ICaptchaManager 36 39 from waeup.kofa.browser.layout import ( 37 40 KofaPage, KofaEditFormPage, KofaAddFormPage, KofaDisplayFormPage, 38 41 NullValidator, jsaction, action, UtilityView) 39 from waeup.kofa.browser.breadcrumbs import Breadcrumb40 42 from waeup.kofa.browser.pages import ( 41 43 ContactAdminFormPage, ExportCSVView, doll_up, exports_not_allowed, 42 44 LocalRoleAssignmentUtilityView) 43 from waeup.kofa.browser.interfaces import ICaptchaManager44 45 from waeup.kofa.hostels.hostel import NOT_OCCUPIED 45 46 from waeup.kofa.interfaces import ( 46 47 IKofaObject, IUserAccount, IExtFileStore, IPasswordValidator, IContactForm, 47 IKofaUtils, I University, IObjectHistory, academic_sessions, ICSVExporter,48 academic_sessions_vocab, I JobManager, IDataCenter, DOCLINK)48 IKofaUtils, IObjectHistory, academic_sessions, ICSVExporter, 49 academic_sessions_vocab, IDataCenter, DOCLINK) 49 50 from waeup.kofa.interfaces import MessageFactory as _ 50 from waeup.kofa.widgets.datewidget import (51 FriendlyDateWidget, FriendlyDateDisplayWidget,52 FriendlyDatetimeDisplayWidget)53 51 from waeup.kofa.mandates.mandate import PasswordMandate 54 52 from waeup.kofa.university.interfaces import ( 55 53 IDepartment, ICertificate, ICourse) 54 from waeup.kofa.university.certificate import ( 55 VirtualCertificateExportJobContainer) 56 from waeup.kofa.university.department import ( 57 VirtualDepartmentExportJobContainer) 56 58 from waeup.kofa.university.faculty import VirtualFacultyExportJobContainer 57 from waeup.kofa.university.department import VirtualDepartmentExportJobContainer58 59 from waeup.kofa.university.facultiescontainer import ( 59 VirtualFacultiesExportJobContainer, FacultiesContainer) 60 from waeup.kofa.university.certificate import ( 61 VirtualCertificateExportJobContainer,) 60 VirtualFacultiesExportJobContainer) 62 61 from waeup.kofa.university.course import ( 63 62 VirtualCourseExportJobContainer,) 64 63 from waeup.kofa.university.vocabularies import course_levels 65 64 from waeup.kofa.utils.batching import VirtualExportJobContainer 66 from waeup.kofa.utils.helpers import get_current_principal, to_timezone, now 65 from waeup.kofa.utils.helpers import get_current_principal, now 66 from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget 67 67 from waeup.kofa.students.interfaces import ( 68 IStudentsContainer, IStudent, 69 IUGStudentClearance,IPGStudentClearance, 68 IStudentsContainer, IStudent, IUGStudentClearance, IPGStudentClearance, 70 69 IStudentPersonal, IStudentPersonalEdit, IStudentBase, IStudentStudyCourse, 71 70 IStudentStudyCourseTransfer, IStudentStudyCourseTranscript, 72 IStudentAccommodation, IStudentStudyLevel, 73 I CourseTicket, ICourseTicketAdd, IStudentPaymentsContainer,74 IStudent OnlinePayment, IStudentPreviousPayment, IStudentBalancePayment,75 I BedTicket, IStudentsUtils, IStudentRequestPW, IStudentTranscript71 IStudentAccommodation, IStudentStudyLevel, ICourseTicket, ICourseTicketAdd, 72 IStudentPaymentsContainer, IStudentOnlinePayment, IStudentPreviousPayment, 73 IStudentBalancePayment, IBedTicket, IStudentsUtils, IStudentRequestPW, 74 IStudentTranscript 76 75 ) 77 76 from waeup.kofa.students.catalog import search, StudentQueryResultItem 78 from waeup.kofa.students.studylevel import StudentStudyLevel, CourseTicket79 77 from waeup.kofa.students.vocabularies import StudyLevelSource 80 from waeup.kofa.students.workflow import (CREATED, ADMITTED, PAID, 81 CLEARANCE, REQUESTED, RETURNING, CLEARED, REGISTERED, VALIDATED, 82 GRADUATED, TRANSCRIPT, FORBIDDEN_POSTGRAD_TRANS) 83 84 85 grok.context(IKofaObject) # Make IKofaObject the default context 78 from waeup.kofa.students.workflow import ( 79 ADMITTED, PAID, CLEARANCE, REQUESTED, RETURNING, CLEARED, REGISTERED, 80 VALIDATED, GRADUATED, TRANSCRIPT, FORBIDDEN_POSTGRAD_TRANS 81 ) 82 83 84 grok.context(IKofaObject) # Make IKofaObject the default context 85 86 86 87 87 # Save function used for save methods in pages … … 90 90 # Turn list of lists into single list 91 91 if changed_fields: 92 changed_fields = reduce(lambda x, y: x+y, changed_fields.values())92 changed_fields = reduce(lambda x, y: x+y, changed_fields.values()) 93 93 # Inform catalog if certificate has changed 94 94 # (applyData does this only for the context) … … 1199 1199 def label(self): 1200 1200 # Here we know that the cookie has been set 1201 lang = self.request.cookies.get('kofa.language')1202 1201 return _('${a}: Transcript Data', mapping = { 1203 1202 'a':self.context.student.display_fullname}) … … 1397 1396 def render(self): 1398 1397 portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE 1399 Term = translate(_('Term'), 'waeup.kofa', target_language=portal_language)1400 1398 Code = translate(_('Code'), 'waeup.kofa', target_language=portal_language) 1401 1399 Title = translate(_('Title'), 'waeup.kofa', target_language=portal_language) … … 3104 3102 return list(coursetickets) 3105 3103 3104 def _extract_uploadfile(self, uploadfile): 3105 """Get a mapping of student-ids to scores. 3106 3107 The mapping is constructed by reading contents from `uploadfile`. 3108 3109 We expect uploadfile to be a regular CSV file with columns 3110 ``student_id`` and ``score`` (other cols are ignored). 3111 """ 3112 result = dict() 3113 data = StringIO(uploadfile.read()) # ensure we have something seekable 3114 reader = csv.DictReader(data) 3115 for row in reader: 3116 if not 'student_id' in row or not 'score' in row: 3117 continue 3118 result[row['student_id']] = row['score'] 3119 return result 3120 3106 3121 def update(self, *args, **kw): 3107 3122 form = self.request.form 3108 ob_class = self.__implemented__.__name__.replace('waeup.kofa.', '')3123 ob_class = self.__implemented__.__name__.replace('waeup.kofa.', '') 3109 3124 self.current_academic_session = grok.getSite()[ 3110 3125 'configuration'].current_academic_session … … 3124 3139 self.redirect(self.url(self.context)) 3125 3140 return 3126 if 'UPDATE' in form: 3127 error = '' 3128 if not editable_tickets: 3129 return 3130 scores = form['scores'] 3131 sids = form['sids'] 3132 if isinstance(scores, basestring): 3133 scores = [scores] 3134 if isinstance(sids, basestring): 3135 sids = [sids] 3136 formvals = dict([(sids[i], scores[i]) for i in range(len(sids))]) 3137 for ticket in editable_tickets: 3138 score = ticket.score 3139 sid = ticket.student.student_id 3140 if formvals[sid] == '': 3141 score = None 3142 else: 3143 try: 3144 score = int(formvals[sid]) 3145 except ValueError: 3146 error += '%s, ' % ticket.student.display_fullname 3147 if ticket.score != score: 3148 ticket.score = score 3149 ticket.student.__parent__.logger.info( 3150 '%s - %s %s/%s score updated (%s)' % 3151 (ob_class, ticket.student.student_id, 3152 ticket.level, ticket.code, score)) 3153 #notify(grok.ObjectModifiedEvent(ticket)) 3154 if error: 3155 self.flash(_('Error: Score(s) of %s have not be updated. ' 3156 'Only integers are allowed.' % error.strip(', ')), 3157 type="danger") 3158 return 3141 if not 'UPDATE' in form: 3142 return 3143 error = '' 3144 if not editable_tickets: 3145 return 3146 formvals = dict(zip(form['sids'], form['scores'])) 3147 if form['uploadfile']: 3148 try: 3149 formvals = self._extract_uploadfile(form['uploadfile']) 3150 except: 3151 self.flash( 3152 _('Uploaded file contains illegal data. Ignored'), 3153 type="danger") 3154 for ticket in editable_tickets: 3155 score = ticket.score 3156 sid = ticket.student.student_id 3157 if sid not in formvals: 3158 continue 3159 if formvals[sid] == '': 3160 score = None 3161 else: 3162 try: 3163 score = int(formvals[sid]) 3164 except ValueError: 3165 error += '%s, ' % ticket.student.display_fullname 3166 if ticket.score != score: 3167 ticket.score = score 3168 ticket.student.__parent__.logger.info( 3169 '%s - %s %s/%s score updated (%s)' % ( 3170 ob_class, ticket.student.student_id, 3171 ticket.level, ticket.code, score) 3172 ) 3173 if error: 3174 self.flash( 3175 _('Error: Score(s) of following students have not been ' 3176 'updated (only integers are allowed): %s.' % error.strip(', ')), 3177 type="danger") 3178 return 3179 3159 3180 3160 3181 class DownloadScoresView(UtilityView, grok.View): … … 3166 3187 3167 3188 def update(self): 3168 ob_class = self.__implemented__.__name__.replace('waeup.kofa.','')3169 3189 self.current_academic_session = grok.getSite()[ 3170 3190 'configuration'].current_academic_session … … 3350 3370 date_format = '%d/%m/%Y' 3351 3371 try: 3352 d ummy = datetime.strptime(payments_start, date_format)3353 d ummy = datetime.strptime(payments_end, date_format)3372 datetime.strptime(payments_start, date_format) 3373 datetime.strptime(payments_end, date_format) 3354 3374 except ValueError: 3355 3375 self.flash(_('Payment dates do not match format d/m/Y.'),
Note: See TracChangeset for help on using the changeset viewer.