Ignore:
Timestamp:
18 Nov 2016, 07:19:25 (8 years ago)
Author:
Henrik Bettermann
Message:

Lecturers can edit current session and previous session courses whenever they like. All restrictions are removed.

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  
    1818
    1919import grok
    20 from waeup.kofa.interfaces import IKofaObject
    21 from waeup.kofa.browser.viewlets import PrimaryNavTab
     20from waeup.kofa.interfaces import IKofaObject, academic_sessions_vocab
     21from waeup.kofa.browser.viewlets import (
     22    PrimaryNavTab, ManageActionButton, UpdateScoresActionButton)
    2223from waeup.aaue.interfaces import MessageFactory as _
    2324
     
    4142            return self.view.application_url('applicants') + '/checkstatus'
    4243        return
     44
     45
     46class 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  
    2828from waeup.kofa.browser.layout import UtilityView
    2929from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
    30 from waeup.kofa.interfaces import IKofaUtils, academic_sessions_vocab
     30from waeup.kofa.interfaces import (
     31    IKofaUtils, academic_sessions_vocab, ICSVExporter)
    3132from waeup.kofa.students.interfaces import IStudentsUtils, IStudent
    3233from waeup.kofa.students.workflow import PAID, REGISTERED, RETURNING
     
    4950    ExportPDFScoresSlip,
    5051    StudyCourseTranscriptPage,
     52    DownloadScoresView,
    5153    )
    5254from kofacustom.nigeria.students.browser import (
     
    668670        return result
    669671
    670     def update(self,  *args, **kw):
    671         form = self.request.form
     672    def _update_scores(self, form):
    672673        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 = ''
    697675        if 'UPDATE_FILE' in form:
    698676            if form['uploadfile']:
     
    703681                        _('Uploaded file contains illegal data. Ignored'),
    704682                        type="danger")
    705                     return
     683                    return False
    706684            else:
    707685                self.flash(
    708686                    _('No file provided.'), type="danger")
    709                 return
     687                return False
    710688        else:
    711689            formvals = dict(zip(form['sids'], zip(form['scores'], form['cas'])))
    712         error = ''
    713         # In AAUE only editable tickets are shown, see also customized
    714         # pagetemplate
    715690        for ticket in self.editable_tickets:
    716691            ticket_error = False
     
    754729            self.flash(_('Error: Score(s) and CA(s) of %s have not be updated. '
    755730              % error.strip(', ')), type="danger")
     731        return True
     732
     733class 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))
    756744            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.'))
    758766        return
    759767
     
    783791                   _('Grade'),
    784792                   ],]
     793        sorted_tickets = sorted(editable_tickets,
     794            key=lambda ticket: ticket.student.certcode +
     795                ticket.student.display_fullname + str(ticket.level))
     796        no = 1
    785797        tickets = []
    786         no = 1
    787798        # In AAUE only editable tickets can be printed
    788         for ticket in editable_tickets:
     799        for ticket in sorted_tickets:
    789800            if None in (ticket.score, ticket.ca):
    790801                total = 'n/a'
     
    808819            tickets.append(row)
    809820            no += 1
    810         return header + sorted(tickets,
    811             key=lambda value: value[5] + value[3] + str(value[6]))
     821        return header + tickets
     822
     823class 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  
    44  (press 'Help' for further information) or by
    55  changing score or CA values in the table below. Only scores and CAs
    6   of students in state 'courses validated' and current session
     6  of students in current session
    77  <span  i18n:name="current_academic_session"
    88         tal:replace="view/session_title"></span>
     
    6161          <strong>Note:</strong>
    6262          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>
    6466          can be modified. Additional data will just be ignored.
    6567        </div>
  • main/waeup.aaue/trunk/src/waeup/aaue/students/studylevel.py

    r14266 r14288  
    312312            return self.score + self.ca
    313313
     314    @property
     315    def editable_by_lecturer(self):
     316        """True if lecturer is allowed to edit the ticket.
     317        """
     318        return True
     319
    314320CustomCourseTicket = attrs_to_fields(CustomCourseTicket)
    315321
  • main/waeup.aaue/trunk/src/waeup/aaue/students/tests/test_browser.py

    r14266 r14288  
    7979            'http://localhost/app/faculties/fac1/dep1/courses/COURSE1')
    8080        self.edit_scores_url = '%s/edit_scores' % self.course_url
     81        self.edit_prev_scores_url = '%s/edit_prev_scores' % self.course_url
    8182        # Set standard parameters
    8283        self.app['configuration'].current_academic_session = 2004
     
    363364        self.student['studycourse']['100']['COURSE1'].score = 55
    364365        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)
    365393        upload_ctrl = self.browser.getControl(name='uploadfile:file')
    366394        upload_file = StringIO(UPLOAD_CSV_TEMPLATE % ('65','22'))
  • main/waeup.aaue/trunk/src/waeup/aaue/students/viewlets.py

    r14207 r14288  
    2727    StudentPassportActionButton,
    2828    StudyCourseTranscriptActionButton,
    29     TranscriptSlipActionButton)
     29    TranscriptSlipActionButton,
     30    DownloadCSVFileActionButton,
     31    DownloadTicketOverviewActionButton)
    3032from waeup.kofa.students.browser import StudyLevelDisplayFormPage
    3133
     
    129131    grok.require('waeup.viewStudent')
    130132    grok.name('transcript_slip')
     133
     134class 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
     144class 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.