Changeset 15422 for main/waeup.kofa
- Timestamp:
- 24 May 2019, 09:11:40 (5 years ago)
- Location:
- main/waeup.kofa/trunk
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
main/waeup.kofa/trunk/CHANGES.txt
r15417 r15422 4 4 1.6.1.dev0 (unreleased) 5 5 ======================= 6 7 * Implement course result validation workflow for lecturers. 6 8 7 9 * Add graduated students filter. -
main/waeup.kofa/trunk/src/waeup/kofa/app.py
r14671 r15422 87 87 XXX: Tests for this method were disabled. 88 88 """ 89 for name in ['faculties', 'departments', 'certificates', 'certcourses', 89 for name in ['faculties', 'departments', 'certificates', 90 'certcourses', 'courses', 90 91 'site-pluggable-auth']: 91 92 getUtility(IKofaPluggable, name=name).update( -
main/waeup.kofa/trunk/src/waeup/kofa/browser/pages.py
r15287 r15422 44 44 from zope.password.interfaces import IPasswordManager 45 45 from waeup.kofa.utils.helpers import html2dict 46 from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget 46 47 from waeup.kofa.browser.layout import ( 47 48 KofaPage, KofaFormPage, KofaEditFormPage, KofaAddFormPage, … … 2484 2485 pnav = 1 2485 2486 form_fields = grok.AutoFields(ICourse) 2487 form_fields[ 2488 'results_validation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le') 2486 2489 2487 2490 @property … … 2505 2508 2506 2509 form_fields = grok.AutoFields(ICourse).omit('code') 2510 form_fields['results_validated_by'].for_display = True 2511 form_fields['results_validation_date'].for_display = True 2512 #form_fields['results_validation_session'].for_display = True 2513 form_fields[ 2514 'results_validation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le') 2507 2515 2508 2516 @action(_('Save'), style='primary') -
main/waeup.kofa/trunk/src/waeup/kofa/browser/viewlets.py
r15163 r15422 31 31 DepartmentPage, CoursePage, CertificatePage, CertificateCoursePage, 32 32 UsersContainerPage, UserManageFormPage, DatacenterImportStep1) 33 from waeup.kofa.students.browser import EditScoresPage 33 34 from waeup.kofa.interfaces import MessageFactory as _ 34 35 from waeup.kofa.interfaces import ( … … 615 616 return _('Update session ${a} scores', mapping = {'a':st}) 616 617 618 class DownloadTicketOverviewActionButton(ManageActionButton): 619 """ 'Download ticket overview' button for courses. 620 """ 621 grok.context(ICourse) 622 grok.view(CoursePage) 623 grok.name('coursetickets') 624 grok.require('waeup.showStudents') 625 icon = 'actionicon_pdf.png' 626 text = _('Download course tickets overview') 627 target = 'coursetickets.pdf' 628 grok.order(5) 629 630 class DownloadCSVFileActionButton(ManageActionButton): 631 """ 'Download csv file' button for courses. 632 """ 633 grok.context(ICourse) 634 grok.view(EditScoresPage) 635 grok.name('downloadcsv') 636 grok.require('waeup.editScores') 637 icon = 'actionicon_down.png' 638 text = _('Download csv file (editable scores only)') 639 target = 'download_scores' 640 grok.order(7) 617 641 618 642 class ManageCertificateActionButton(ManageActionButton): -
main/waeup.kofa/trunk/src/waeup/kofa/permissions.py
r15277 r15422 433 433 grok.title(u'Lecturer') 434 434 grok.permissions('waeup.editScores', 435 'waeup.showStudents', 435 436 'waeup.viewAcademics', 436 437 'waeup.exportData') -
main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py
r15419 r15422 33 33 from zope.schema.interfaces import ConstraintNotSatisfied, RequiredMissing 34 34 from zope.security import checkPermission 35 from zope.securitypolicy.interfaces import IPrincipalRoleManager 35 36 from waeup.kofa.accesscodes import invalidate_accesscode, get_access_code 36 37 from waeup.kofa.accesscodes.workflow import USED … … 3379 3380 return 3380 3381 3381 3382 3382 class EditScoresPage(KofaPage): 3383 3383 """Page that allows to edit batches of scores. … … 3464 3464 return True 3465 3465 3466 def _validate_results(self, form): 3467 ob_class = self.__implemented__.__name__.replace('waeup.kofa.', '') 3468 user = get_current_principal() 3469 if user is None: 3470 usertitle = 'system' 3471 else: 3472 usertitle = getattr(user, 'public_name', None) 3473 if not usertitle: 3474 usertitle = user.title 3475 self.context.results_validated_by = usertitle 3476 self.context.results_validation_date = datetime.utcnow() 3477 self.context.results_validation_session = self.current_academic_session 3478 return 3479 3480 def _results_editable(self, results_validation_session, 3481 current_academic_session): 3482 user = get_current_principal() 3483 prm = IPrincipalRoleManager(self.context) 3484 roles = [x[0] for x in prm.getRolesForPrincipal(user.id)] 3485 if 'waeup.local.LocalStudentsManager' in roles: 3486 return True 3487 if results_validation_session \ 3488 and results_validation_session >= current_academic_session: 3489 return False 3490 return True 3491 3466 3492 def update(self, *args, **kw): 3467 3493 form = self.request.form … … 3476 3502 self.redirect(self.url(self.context)) 3477 3503 return 3504 vs = self.context.results_validation_session 3505 if not self._results_editable(vs, self.current_academic_session): 3506 self.flash( 3507 _('Course results have already been ' 3508 'validated and can no longer be changed.'), 3509 type="danger") 3510 self.redirect(self.url(self.context)) 3511 return 3478 3512 self.session_title = academic_sessions_vocab.getTerm( 3479 3513 self.current_academic_session).title … … 3485 3519 self.editable_tickets = [ 3486 3520 ticket for ticket in self.tickets if ticket.editable_by_lecturer] 3487 if not 'UPDATE_TABLE' in form and not 'UPDATE_FILE' in form: 3521 if not 'UPDATE_TABLE' in form and not 'UPDATE_FILE' in form\ 3522 and not 'VALIDATE_RESULTS' in form: 3523 return 3524 if 'VALIDATE_RESULTS' in form: 3525 if vs and vs >= self.current_academic_session: 3526 self.flash( 3527 _('Course results have already been validated.'), 3528 type="danger") 3529 return 3530 self._validate_results(form) 3531 self.flash(_('You successfully validated the course results.')) 3532 self.redirect(self.url(self.context)) 3488 3533 return 3489 3534 if not self.editable_tickets: … … 3494 3539 return 3495 3540 3496 3497 3541 class DownloadScoresView(UtilityView, grok.View): 3498 3542 """View that exports scores. … … 3501 3545 grok.require('waeup.editScores') 3502 3546 grok.name('download_scores') 3547 3548 def _results_editable(self, results_validation_session, 3549 current_academic_session): 3550 user = get_current_principal() 3551 prm = IPrincipalRoleManager(self.context) 3552 roles = [x[0] for x in prm.getRolesForPrincipal(user.id)] 3553 if 'waeup.local.LocalStudentsManager' in roles: 3554 return True 3555 if results_validation_session \ 3556 and results_validation_session >= current_academic_session: 3557 return False 3558 return True 3503 3559 3504 3560 def update(self): … … 3511 3567 if not self.current_academic_session: 3512 3568 self.flash(_('Current academic session not set.'), type="warning") 3569 self.redirect(self.url(self.context)) 3570 return 3571 vs = self.context.results_validation_session 3572 if not self._results_editable(vs, self.current_academic_session): 3573 self.flash( 3574 _('Course results have already been ' 3575 'validated and can no longer be changed.'), 3576 type="danger") 3513 3577 self.redirect(self.url(self.context)) 3514 3578 return … … 3537 3601 grok.context(ICourse) 3538 3602 grok.name('coursetickets.pdf') 3539 grok.require('waeup. editScores')3603 grok.require('waeup.showStudents') 3540 3604 3541 3605 @property -
main/waeup.kofa/trunk/src/waeup/kofa/students/browser_templates/editscorespage.pt
r14287 r15422 108 108 value="Update scores from table" class="btn btn-primary" 109 109 /> 110 111 <input type="submit" name="VALIDATE_RESULTS" i18n:translate="" 112 value="Validate course results" class="btn btn-primary" 113 /> 110 114 </form> -
main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py
r15421 r15422 4458 4458 self.assertTrue('COURSE1 score updated (None)' in logcontent) 4459 4459 4460 def test_lecturer_can_validate_courses(self): 4461 # the form is locked after validation 4462 self.login_as_lecturer() 4463 self.student['studycourse']['100']['COURSE1'].score = None 4464 self.browser.open(self.edit_scores_url) 4465 self.browser.getControl(name="scores:list", index=0).value = '' 4466 self.browser.getControl("Update scores").click() 4467 self.browser.getControl("Validate").click() 4468 self.assertTrue( 4469 'You successfully validated the course results' 4470 in self.browser.contents) 4471 self.assertEqual(self.course.results_validation_session, 2004) 4472 self.assertEqual(self.course.results_validated_by, 'Mercedes Benz') 4473 self.assertEqual(self.browser.url, self.course_url) 4474 # Lecturer can't open edit_scores again 4475 self.browser.getLink("Update session 2004/2005 scores").click() 4476 self.assertEqual(self.browser.url, self.course_url) 4477 self.assertTrue( 4478 'Course results have already been validated' 4479 ' and can no longer be changed.' 4480 in self.browser.contents) 4481 # Also DownloadScoresView is blocked 4482 self.browser.open(self.browser.url + '/download_scores') 4483 self.assertEqual(self.browser.url, self.course_url) 4484 self.assertTrue( 4485 'Course results have already been validated' 4486 ' and can no longer be changed.' 4487 in self.browser.contents) 4488 # Students Manager can open page ... 4489 prmlocal = IPrincipalRoleManager(self.course) 4490 prmlocal.assignRoleToPrincipal( 4491 'waeup.local.LocalStudentsManager', 'mrslecturer') 4492 self.browser.getLink("Update session 2004/2005 scores").click() 4493 self.assertEqual(self.browser.url, self.edit_scores_url) 4494 self.browser.getLink("Download csv file").click() 4495 self.assertEqual(self.browser.headers['Status'], '200 Ok') 4496 self.assertEqual(self.browser.headers['Content-Type'], 4497 'text/csv; charset=UTF-8') 4498 # ... but can't validate courses a second time 4499 self.browser.open(self.edit_scores_url) 4500 self.browser.getControl("Validate").click() 4501 self.assertTrue( 4502 'Course results have already been validated.' 4503 in self.browser.contents) 4504 4460 4505 def test_lecturers_can_download_course_tickets(self): 4461 4506 # A course ticket slip can be downloaded -
main/waeup.kofa/trunk/src/waeup/kofa/students/viewlets.py
r15175 r15422 32 32 OnlinePaymentDisplayFormPage, BedTicketDisplayFormPage, 33 33 StudentClearanceEditFormPage, StudentPersonalEditFormPage, 34 PaymentsManageFormPage, StudyCourseTranscriptPage , EditScoresPage)34 PaymentsManageFormPage, StudyCourseTranscriptPage) 35 35 from waeup.kofa.students.interfaces import ( 36 36 IStudentsContainer, IStudent, IStudentStudyCourse, IStudentStudyLevel, … … 41 41 ADMITTED, PAID, REQUESTED, CLEARED, REGISTERED, VALIDATED, GRADUATED, 42 42 TRANSREQ, TRANSVAL, TRANSREL) 43 from waeup.kofa.university.interfaces import ICourse44 43 45 44 … … 922 921 ] 923 922 return targets 924 925 926 class DownloadCSVFileActionButton(ManageActionButton):927 """ 'Download csv file' button for courses.928 """929 grok.context(ICourse)930 grok.view(EditScoresPage)931 grok.name('downloadcsv')932 grok.require('waeup.editScores')933 icon = 'actionicon_down.png'934 text = _('Download csv file (editable scores only)')935 target = 'download_scores'936 grok.order(1)937 938 939 class DownloadTicketOverviewActionButton(ManageActionButton):940 """ 'Download ticket overview' button for courses.941 """942 grok.context(ICourse)943 grok.view(EditScoresPage)944 grok.name('coursetickets')945 grok.require('waeup.editScores')946 icon = 'actionicon_pdf.png'947 text = _('Download pdf file')948 target = 'coursetickets.pdf'949 grok.order(2) -
main/waeup.kofa/trunk/src/waeup/kofa/university/course.py
r10685 r15422 56 56 self.semester = semester 57 57 self.former_course = former_course 58 self.results_validated_by = None 59 self.results_validation_date = None 60 self.results_validation_session = None 58 61 59 62 def traverse(self, name): -
main/waeup.kofa/trunk/src/waeup/kofa/university/export.py
r14511 r15422 116 116 117 117 fields = ('code', 'faculty_code', 'department_code', 'title', 'credits', 118 'passmark', 'semester', 'users_with_local_roles', 'former_course') 118 'passmark', 'semester', 'users_with_local_roles', 'former_course', 119 'results_validated_by', 'results_validation_date', 120 'results_validation_session') 119 121 120 122 title = _(u'Courses') -
main/waeup.kofa/trunk/src/waeup/kofa/university/interfaces.py
r14638 r15422 21 21 from zope import schema 22 22 from zope.interface import Attribute, invariant, Invalid 23 from waeup.kofa.interfaces import IKofaObject, IKofaContainer, validate_id 23 from waeup.kofa.interfaces import ( 24 IKofaObject, IKofaContainer, validate_id, academic_sessions_vocab) 24 25 from waeup.kofa.interfaces import MessageFactory as _ 25 26 from waeup.kofa.university.vocabularies import ( … … 189 190 ) 190 191 192 results_validated_by = schema.TextLine( 193 title = _(u'Results validated by'), 194 default = None, 195 required = False, 196 ) 197 198 results_validation_date = schema.Datetime( 199 title = _(u'Results validation date'), 200 required = False, 201 readonly = False, 202 ) 203 204 results_validation_session = schema.Choice( 205 title = _(u'Results validation session'), 206 source = academic_sessions_vocab, 207 required = False, 208 readonly = False, 209 ) 191 210 192 211 class ICertificate(IKofaObject): -
main/waeup.kofa/trunk/src/waeup/kofa/university/tests/test_export.py
r14511 r15422 281 281 result, 282 282 'code,faculty_code,department_code,title,credits,' 283 'passmark,semester,users_with_local_roles,former_course\r\n' 284 'C1,F1,D1,Cheese Basics,0,40,1,[],0\r\n' 283 'passmark,semester,users_with_local_roles,former_course,' 284 'results_validated_by,results_validation_date,' 285 'results_validation_session\r\n' 286 'C1,F1,D1,Cheese Basics,0,40,1,[],0,,,\r\n' 285 287 ) 286 288 return … … 293 295 result, 294 296 'code,faculty_code,department_code,title,credits,passmark,' 295 'semester,users_with_local_roles,former_course\r\n' 296 'C1,F1,D1,Cheese Basics,0,40,1,[],0\r\n' 297 'C2,F1,D1,Advanced Cheese Making,0,40,1,[],0\r\n' 297 'semester,users_with_local_roles,former_course,' 298 'results_validated_by,results_validation_date,' 299 'results_validation_session\r\n' 300 'C1,F1,D1,Cheese Basics,0,40,1,[],0,,,\r\n' 301 'C2,F1,D1,Advanced Cheese Making,0,40,1,[],0,,,\r\n' 298 302 ) 299 303 return … … 307 311 result, 308 312 'code,faculty_code,department_code,title,credits,passmark,' 309 'semester,users_with_local_roles,former_course\r\n' 310 'C1,F1,D1,Cheese Basics,0,40,1,[],0\r\n' 311 'C2,F1,D1,Advanced Cheese Making,0,40,1,[],0\r\n' 312 'C3,F1,D2,Selling Cheese,0,40,1,[],0\r\n' 313 'semester,users_with_local_roles,former_course,' 314 'results_validated_by,results_validation_date,' 315 'results_validation_session\r\n' 316 'C1,F1,D1,Cheese Basics,0,40,1,[],0,,,\r\n' 317 'C2,F1,D1,Advanced Cheese Making,0,40,1,[],0,,,\r\n' 318 'C3,F1,D2,Selling Cheese,0,40,1,[],0,,,\r\n' 313 319 ) 314 320 return … … 321 327 result, 322 328 'code,faculty_code,department_code,title,credits,passmark,' 323 'semester,users_with_local_roles,former_course\r\n' 324 'C1,F1,D1,Cheese Basics,0,40,1,[],0\r\n' 325 'C2,F1,D1,Advanced Cheese Making,0,40,1,[],0\r\n' 326 'C3,F1,D2,Selling Cheese,0,40,1,[],0\r\n' 329 'semester,users_with_local_roles,former_course,' 330 'results_validated_by,results_validation_date,' 331 'results_validation_session\r\n' 332 'C1,F1,D1,Cheese Basics,0,40,1,[],0,,,\r\n' 333 'C2,F1,D1,Advanced Cheese Making,0,40,1,[],0,,,\r\n' 334 'C3,F1,D2,Selling Cheese,0,40,1,[],0,,,\r\n' 327 335 ) 328 336 return
Note: See TracChangeset for help on using the changeset viewer.