source: main/waeup.aaue/trunk/src/waeup/aaue/students/browser.py @ 13859

Last change on this file since 13859 was 13834, checked in by Henrik Bettermann, 9 years ago

Further customizations for taking the ca into consideration and displaying the ca on all forms and slips.

  • Property svn:keywords set to Id
File size: 24.7 KB
Line 
1## $Id: browser.py 13834 2016-04-19 06:42:26Z henrik $
2##
3## Copyright (C) 2012 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18import grok
19from zope.i18n import translate
20from zope.component import getUtility
21from zope.security import checkPermission
22from zope.formlib.textwidgets import BytesDisplayWidget
23from waeup.kofa.browser.layout import UtilityView
24from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
25from waeup.kofa.interfaces import IKofaUtils
26from waeup.kofa.students.interfaces import IStudentsUtils, IStudent
27from waeup.kofa.students.workflow import PAID, REGISTERED
28from waeup.kofa.students.browser import (
29    StartClearancePage,
30    StudentBasePDFFormPage,
31    CourseTicketAddFormPage,
32    StudyLevelDisplayFormPage,
33    StudyLevelManageFormPage,
34    StudyLevelEditFormPage,
35    ExportPDFTranscriptSlip,
36    ExportPDFAdmissionSlip,
37    BedTicketAddPage,
38    StudentFilesUploadPage,
39    PaymentsManageFormPage,
40    CourseTicketDisplayFormPage,
41    CourseTicketManageFormPage,
42    EditScoresPage
43    )
44from kofacustom.nigeria.students.browser import (
45    NigeriaOnlinePaymentDisplayFormPage,
46    NigeriaOnlinePaymentAddFormPage,
47    NigeriaExportPDFPaymentSlip,
48    NigeriaExportPDFCourseRegistrationSlip,
49    NigeriaExportPDFClearanceSlip,
50    NigeriaStudentPersonalDisplayFormPage,
51    NigeriaStudentPersonalEditFormPage,
52    NigeriaStudentPersonalManageFormPage,
53    NigeriaStudentClearanceEditFormPage,
54    NigeriaAccommodationManageFormPage,
55    NigeriaStudentBaseDisplayFormPage,
56    NigeriaStudentBaseManageFormPage
57    )
58from waeup.aaue.students.interfaces import (
59    ICustomStudentOnlinePayment,
60    ICustomStudentStudyLevel,
61    ICustomStudent,
62    ICustomStudentPersonal,
63    ICustomStudentPersonalEdit,
64    ICustomUGStudentClearance,
65    ICustomCourseTicket,
66    ICustomStudentBase)
67from waeup.aaue.interswitch.browser import gateway_net_amt
68from waeup.aaue.interfaces import MessageFactory as _
69
70class CustomStudentBaseDisplayFormPage(NigeriaStudentBaseDisplayFormPage):
71    """ Page to display student base data
72    """
73    form_fields = grok.AutoFields(ICustomStudentBase).omit(
74        'password', 'suspended', 'suspended_comment', 'flash_notice')
75    form_fields[
76        'financial_clearance_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
77
78class CustomStudentBaseManageFormPage(NigeriaStudentBaseManageFormPage):
79    """ View to manage student base data
80    """
81    form_fields = grok.AutoFields(ICustomStudentBase).omit(
82        'student_id', 'adm_code', 'suspended',
83        'financially_cleared_by', 'financial_clearance_date')
84
85class CustomStudentPersonalDisplayFormPage(NigeriaStudentPersonalDisplayFormPage):
86    """ Page to display student personal data
87    """
88    form_fields = grok.AutoFields(ICustomStudentPersonal)
89    form_fields['perm_address'].custom_widget = BytesDisplayWidget
90    form_fields['father_address'].custom_widget = BytesDisplayWidget
91    form_fields['mother_address'].custom_widget = BytesDisplayWidget
92    form_fields['next_kin_address'].custom_widget = BytesDisplayWidget
93    form_fields[
94        'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
95
96class CustomStudentPersonalEditFormPage(NigeriaStudentPersonalEditFormPage):
97    """ Page to edit personal data
98    """
99    form_fields = grok.AutoFields(ICustomStudentPersonalEdit).omit('personal_updated')
100
101class CustomStudentPersonalManageFormPage(NigeriaStudentPersonalManageFormPage):
102    """ Page to edit personal data
103    """
104    form_fields = grok.AutoFields(ICustomStudentPersonal)
105    form_fields['personal_updated'].for_display = True
106    form_fields[
107        'personal_updated'].custom_widget = FriendlyDatetimeDisplayWidget('le')
108
109class CustomStudentClearanceEditFormPage(NigeriaStudentClearanceEditFormPage):
110    """ View to edit student clearance data by student
111    """
112
113    @property
114    def form_fields(self):
115        if self.context.is_postgrad:
116            form_fields = grok.AutoFields(ICustomPGStudentClearance).omit(
117            'clearance_locked', 'nysc_location', 'clr_code', 'officer_comment',
118            'physical_clearance_date')
119        else:
120            form_fields = grok.AutoFields(ICustomUGStudentClearance).omit(
121            'clearance_locked', 'clr_code', 'officer_comment',
122            'physical_clearance_date')
123        return form_fields
124
125class CustomStartClearancePage(StartClearancePage):
126    with_ac = False
127
128    @property
129    def all_required_fields_filled(self):
130        if not self.context.email:
131            return _("Email address is missing."), 'edit_base'
132        if not self.context.phone:
133            return _("Phone number is missing."), 'edit_base'
134        if not self.context.father_name:
135            return _("Personal data form is not properly filled."), 'edit_personal'
136        return
137
138class CustomOnlinePaymentDisplayFormPage(NigeriaOnlinePaymentDisplayFormPage):
139    """ Page to view an online payment ticket
140    """
141    grok.context(ICustomStudentOnlinePayment)
142    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
143        'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item')
144    form_fields[
145        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
146    form_fields[
147        'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
148
149class CustomOnlinePaymentAddFormPage(NigeriaOnlinePaymentAddFormPage):
150    """ Page to add an online payment ticket
151    """
152    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).select(
153        'p_category')
154
155class CustomPaymentsManageFormPage(PaymentsManageFormPage):
156    """ Page to manage the student payments.
157
158    This manage form page is for both students and students officers.
159    """
160    @property
161    def manage_payments_allowed(self):
162        return checkPermission('waeup.manageStudent', self.context)
163
164class CustomExportPDFPaymentSlip(NigeriaExportPDFPaymentSlip):
165    """Deliver a PDF slip of the context.
166    """
167    grok.context(ICustomStudentOnlinePayment)
168    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).omit(
169        'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item')
170    form_fields['creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
171    form_fields['payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
172
173    @property
174    def note(self):
175        p_session = self.context.p_session
176        try:
177            academic_session = grok.getSite()['configuration'][str(p_session)]
178        except KeyError:
179            academic_session = None
180        text =  '\n\n The Amount Authorized is inclusive of: '
181        if self.context.p_category in ('schoolfee_incl', 'schoolfee_1') \
182            and academic_session:
183            welfare_fee = gateway_net_amt(academic_session.welfare_fee)
184            union_fee = gateway_net_amt(academic_session.union_fee)
185            text += ('School Fee, '
186                     '%s Naira Student Union Dues, '
187                     '%s Naira Student Welfare Assurance Fee and '
188                     % (union_fee, welfare_fee))
189        elif self.context.p_category in (
190            'clearance_incl', 'clearance_medical_incl') and academic_session:
191            matric_gown_fee = gateway_net_amt(academic_session.matric_gown_fee)
192            lapel_fee = gateway_net_amt(academic_session.lapel_fee)
193            text += ('Acceptance Fee, '
194                     '%s Naira Matriculation Gown Fee, '
195                     '%s Naira Lapel/File Fee and '
196                     % (matric_gown_fee, lapel_fee))
197        return text + '250.0 Naira Transaction Charge.'
198
199class CustomStudyLevelDisplayFormPage(StudyLevelDisplayFormPage):
200    """ Page to display student study levels
201    """
202    grok.context(ICustomStudentStudyLevel)
203    form_fields = grok.AutoFields(ICustomStudentStudyLevel).omit(
204        'total_credits', 'gpa', 'level')
205    form_fields[
206        'validation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
207
208class CustomStudyLevelManageFormPage(StudyLevelManageFormPage):
209    """ Page to edit the student study level data
210    """
211    grok.context(ICustomStudentStudyLevel)
212
213class CustomStudyLevelEditFormPage(StudyLevelEditFormPage):
214    """ Page to edit the student study level data by students
215    """
216    grok.context(ICustomStudentStudyLevel)
217
218class CustomExportPDFCourseRegistrationSlip(
219    NigeriaExportPDFCourseRegistrationSlip):
220    """Deliver a PDF slip of the context.
221    """
222    grok.context(ICustomStudentStudyLevel)
223    form_fields = grok.AutoFields(ICustomStudentStudyLevel).omit(
224        'level_session', 'level_verdict',
225        'validated_by', 'validation_date', 'gpa', 'level')
226
227    omit_fields = ('password', 'suspended', 'suspended_comment',
228        'phone', 'adm_code', 'sex', 'email', 'date_of_birth',
229        'department', 'current_mode', 'current_level', 'flash_notice')
230
231    def update(self):
232        if self.context.student.state != REGISTERED \
233            and self.context.student.current_level == self.context.level:
234            self.flash(_('Forbidden'), type="warning")
235            self.redirect(self.url(self.context))
236
237    @property
238    def label(self):
239        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
240        lang = self.request.cookies.get('kofa.language', portal_language)
241        level_title = translate(self.context.level_title, 'waeup.kofa',
242            target_language=lang)
243        line0 = ''
244        if self.context.student.is_postgrad:
245            line0 = 'SCHOOL OF POSTGRADUATE STUDIES\n'
246        elif self.context.student.current_mode.endswith('_pt'):
247            line0 = 'DIRECTORATE OF PART-TIME DEGREE PROGRAMMES\n'
248        line1 = translate(_('Course Registration Slip'),
249            'waeup.kofa', target_language=portal_language) \
250            + ' %s' % level_title
251        line2 = translate(_('Session'),
252            'waeup.kofa', target_language=portal_language) \
253            + ' %s' % self.context.getSessionString
254        return '%s%s\n%s' % (line0, line1, line2)
255
256    @property
257    def title(self):
258        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
259        return translate(_('Units Registered'), 'waeup.kofa',
260            target_language=portal_language)
261
262    def _signatures(self):
263        if self.context.student.current_mode.endswith('_pt') \
264            or self.context.student.current_mode == 'found':
265            return (
266                [('I have selected the course on the advise of my Head of '
267                 'Department. <br>', _('Student\'s Signature'), '<br>')],
268                [('This student has satisfied the department\'s requirements. '
269                 'I recommend to approve the course registration. <br>',
270                 _('Head of Department\'s Signature'), '<br>')],
271                [('' , _('Principal Assistant Registrar\'s Signature'), '<br>')],
272                [('', _('Director\'s Signature'))]
273                )
274        if self.context.student.current_mode in (
275            'de_ft', 'ug_ft', 'dp_ft', 'transfer'):
276            return ([_('Academic Adviser\'s Signature'),
277                _('Faculty Officer\'s Signature'),
278                _('Student\'s Signature')],)
279
280        if self.context.student.current_mode in ('special_pg_ft', 'special_pg_pt'):
281            return (
282                [('I declare that all items of information supplied above are correct:' ,
283                    _('Student\'s Signature'), '<br>')],
284                [('We approved the above registration:',
285                    _('Major Supervisor (Name / Signature)'), '')],
286                [('', _('Co-Supervisor (Name / Signature)'), '')],
287                [('', _('Head of Department'), '<br>')],
288                [('The student has satisfied the conditions for renewal of '
289                  'registration for graduate school programme in this university:',
290                  _('Secretary <br /> (School of Postgraduate Studies)'), '')],
291                [('', _('Dean <br /> (School of Postgraduate Studies)'), '')],
292                )
293        return None
294
295
296    def render(self):
297        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
298        Sem = translate('Sem.', 'waeup.kofa', target_language=portal_language)
299        Code = translate('Code', 'waeup.kofa', target_language=portal_language)
300        Title = translate('Title', 'waeup.kofa', target_language=portal_language)
301        Cred = translate('Cred.', 'waeup.kofa', target_language=portal_language)
302        Score = translate('Score', 'waeup.kofa', target_language=portal_language)
303        CA = translate('CA', 'waeup.kofa', target_language=portal_language)
304        Grade = translate('Grade', 'waeup.kofa', target_language=portal_language)
305        Signature = translate(_('Lecturer\'s Signature'), 'waeup.aaue',
306            target_language=portal_language)
307        studentview = StudentBasePDFFormPage(self.context.student,
308            self.request, self.omit_fields)
309        students_utils = getUtility(IStudentsUtils)
310
311        tabledata = []
312        tableheader = []
313        contenttitle = []
314        for i in range(1,7):
315            tabledata.append(sorted(
316                [value for value in self.context.values() if value.semester == i],
317                key=lambda value: str(value.semester) + value.code))
318            tableheader.append([(Code,'code', 2.0),
319                               (Title,'title', 7),
320                               (Cred, 'credits', 1.5),
321                               (Score, 'score', 1.4),
322                               (CA, 'ca', 1.4),
323                               (Grade, 'grade', 1.4),
324                               (Signature, 'dummy', 3),
325                               ])
326        if len(self.label.split('\n')) == 3:
327            topMargin = 1.9
328        elif len(self.label.split('\n')) == 2:
329            topMargin = 1.7
330        else:
331            topMargin = 1.5
332        return students_utils.renderPDF(
333            self, 'course_registration_slip.pdf',
334            self.context.student, studentview,
335            tableheader=tableheader,
336            tabledata=tabledata,
337            signatures=self._signatures(),
338            topMargin=topMargin,
339            omit_fields=self.omit_fields
340            )
341
342class CustomExportPDFTranscriptSlip(ExportPDFTranscriptSlip):
343    """Deliver a PDF slip of the context.
344    """
345
346    def _sigsInFooter(self):
347        return []
348
349    def _signatures(self):
350        return ([(
351            'Akhimien Felicia O. (MANUPA) <br /> Principal Assistant Registrar  <br /> '
352            'Exams, Records and Data Processing Division <br /> For: Registrar')],)
353
354    def render(self):
355        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
356        Term = translate(_('Term'), 'waeup.kofa', target_language=portal_language)
357        Code = translate(_('Code'), 'waeup.kofa', target_language=portal_language)
358        Title = translate(_('Title'), 'waeup.kofa', target_language=portal_language)
359        Cred = translate(_('Credits'), 'waeup.kofa', target_language=portal_language)
360        Score = translate(_('Score'), 'waeup.kofa', target_language=portal_language)
361        CA = translate(_('CA'), 'waeup.kofa', target_language=portal_language)
362        Grade = translate(_('Grade'), 'waeup.kofa', target_language=portal_language)
363        studentview = StudentBasePDFFormPage(self.context.student,
364            self.request, self.omit_fields)
365        students_utils = getUtility(IStudentsUtils)
366
367        tableheader = [(Code,'code', 2.5),
368                         (Title,'title', 7),
369                         (Term, 'semester', 1.5),
370                         (Cred, 'credits', 1.5),
371                         (Score, 'score', 1.5),
372                         (CA, 'ca', 1.5),
373                         (Grade, 'grade', 1.5),
374                         ]
375
376        return students_utils.renderPDFTranscript(
377            self, 'transcript.pdf',
378            self.context.student, studentview,
379            omit_fields=self.omit_fields,
380            tableheader=tableheader,
381            signatures=self._signatures(),
382            sigs_in_footer=self._sigsInFooter(),
383            )
384
385class CustomExportPDFAdmissionSlip(ExportPDFAdmissionSlip):
386    """Deliver a PDF Admission slip.
387    """
388
389    @property
390    def label(self):
391        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
392        return translate(_('e-Admission Slip \n'),
393            'waeup.kofa', target_language=portal_language) \
394            + ' %s' % self.context.display_fullname
395
396class CustomExportPDFClearanceSlip(NigeriaExportPDFClearanceSlip):
397    """Deliver a PDF slip of the context.
398    """
399
400    @property
401    def label(self):
402        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
403        return translate(_('Clearance Slip\n'),
404            'waeup.kofa', target_language=portal_language) \
405            + ' %s' % self.context.display_fullname
406
407class StudentGetMatricNumberPage(UtilityView, grok.View):
408    """ Construct and set the matriculation number.
409    """
410    grok.context(IStudent)
411    grok.name('get_matric_number')
412    grok.require('waeup.viewStudent')
413
414    def update(self):
415        students_utils = getUtility(IStudentsUtils)
416        msg, mnumber = students_utils.setMatricNumber(self.context)
417        if msg:
418            self.flash(msg, type="danger")
419        else:
420            self.flash(_('Matriculation number %s assigned.' % mnumber))
421            self.context.writeLogMessage(self, '%s assigned' % mnumber)
422        self.redirect(self.url(self.context))
423        return
424
425    def render(self):
426        return
427
428class ExportPDFMatricNumberSlip(UtilityView, grok.View):
429    """Deliver a PDF notification slip.
430    """
431    grok.context(ICustomStudent)
432    grok.name('matric_number_slip.pdf')
433    grok.require('waeup.viewStudent')
434    prefix = 'form'
435
436    form_fields = grok.AutoFields(ICustomStudent).select(
437        'student_id', 'matric_number')
438    omit_fields = ('date_of_birth', 'current_level', 'flash_notice')
439
440    @property
441    def title(self):
442        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
443        return translate(_('Matriculation Number'), 'waeup.kofa',
444            target_language=portal_language)
445
446    @property
447    def label(self):
448        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
449        return translate(_('Matriculation Number Slip\n'),
450            'waeup.kofa', target_language=portal_language) \
451            + ' %s' % self.context.display_fullname
452
453    def render(self):
454        if self.context.state not in (PAID,) or not self.context.is_fresh \
455            or not self.context.matric_number:
456            self.flash('Not allowed.', type="danger")
457            self.redirect(self.url(self.context))
458            return
459        students_utils = getUtility(IStudentsUtils)
460        pre_text = _('Congratulations! Your acceptance fee and school fees ' +
461                     'payments have been received and your matriculation ' +
462                     'number generated with details as follows.')
463        return students_utils.renderPDFAdmissionLetter(self,
464            self.context.student, omit_fields=self.omit_fields,
465            pre_text=pre_text, post_text='')
466
467class ExportPersonalDataSlip(UtilityView, grok.View):
468    """Deliver a PDF notification slip.
469    """
470    grok.context(ICustomStudent)
471    grok.name('personal_data_slip.pdf')
472    grok.require('waeup.viewStudent')
473    prefix = 'form'
474    note = None
475
476    form_fields = grok.AutoFields(ICustomStudentPersonal).omit('personal_updated')
477    omit_fields = ('suspended', 'suspended_comment', 'adm_code',
478                   'certificate', 'flash_notice')
479
480    @property
481    def title(self):
482        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
483        return translate(_('Personal Data'), 'waeup.kofa',
484            target_language=portal_language)
485
486    @property
487    def label(self):
488        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
489        return translate(_('Personal Data Slip\n'),
490            'waeup.kofa', target_language=portal_language) \
491            + ' %s' % self.context.display_fullname
492
493    def render(self):
494        studentview = StudentBasePDFFormPage(self.context.student,
495            self.request, self.omit_fields)
496        students_utils = getUtility(IStudentsUtils)
497        return students_utils.renderPDF(self, 'personal_data_slip.pdf',
498            self.context.student, studentview, note=self.note,
499            omit_fields=self.omit_fields)
500
501class CustomAccommodationManageFormPage(NigeriaAccommodationManageFormPage):
502    """ Page to manage bed tickets.
503    This manage form page is for both students and students officers.
504    """
505    with_hostel_selection = True
506
507class CustomBedTicketAddPage(BedTicketAddPage):
508    with_ac = False
509
510class CustomStudentFilesUploadPage(StudentFilesUploadPage):
511    """ View to upload files by student. Inherit from same class in
512    base package, not from kofacustom.nigeria which
513    requires that no application slip exists.
514    """
515
516class CustomCourseTicketDisplayFormPage(CourseTicketDisplayFormPage):
517    """ Page to display course tickets
518    """
519    form_fields = grok.AutoFields(ICustomCourseTicket)
520
521class CustomCourseTicketManageFormPage(CourseTicketManageFormPage):
522    """ Page to manage course tickets
523    """
524    form_fields = grok.AutoFields(ICustomCourseTicket)
525    form_fields['title'].for_display = True
526    form_fields['fcode'].for_display = True
527    form_fields['dcode'].for_display = True
528    form_fields['semester'].for_display = True
529    form_fields['passmark'].for_display = True
530    form_fields['credits'].for_display = True
531    form_fields['mandatory'].for_display = False
532    form_fields['automatic'].for_display = True
533    form_fields['carry_over'].for_display = True
534
535class CustomEditScoresPage(EditScoresPage):
536    """Page that filters and lists students.
537    """
538    grok.template('editscorespage')
539
540    def update(self,  *args, **kw):
541        form = self.request.form
542        ob_class = self.__implemented__.__name__.replace('waeup.kofa.','')
543        self.current_academic_session = grok.getSite()[
544            'configuration'].current_academic_session
545        if self.context.__parent__.__parent__.score_editing_disabled:
546            self.flash(_('Score editing disabled.'), type="warning")
547            self.redirect(self.url(self.context))
548            return
549        if not self.current_academic_session:
550            self.flash(_('Current academic session not set.'), type="warning")
551            self.redirect(self.url(self.context))
552            return
553        self.tickets = self._searchCatalog(self.current_academic_session)
554        editable_tickets = [
555            ticket for ticket in self.tickets if ticket.editable_by_lecturer]
556        if not self.tickets:
557            self.flash(_('No student found.'), type="warning")
558            self.redirect(self.url(self.context))
559            return
560        if 'UPDATE' in form:
561            tno = 0
562            error = ''
563            if not editable_tickets:
564                return
565            scores = form['scores']
566            cas = form['cas']
567            if isinstance(scores, basestring):
568                scores = [scores]
569            if isinstance(cas, basestring):
570                cas = [cas]
571            for ticket in editable_tickets:
572                ticket_error = False
573                score = ticket.score
574                ca = ticket.ca
575                if scores[tno] == '':
576                    score = None
577                if cas[tno] == '':
578                    ca = None
579                try:
580                    if scores[tno]:
581                        score = int(scores[tno])
582                    if cas[tno]:
583                        ca = int(cas[tno])
584                except ValueError:
585                    error += '%s, ' % ticket.student.display_fullname
586                    ticket_error = True
587                if not ticket_error and ticket.score != score:
588                    ticket.score = score
589                    ticket.student.__parent__.logger.info(
590                        '%s - %s %s/%s score updated (%s)' %
591                        (ob_class, ticket.student.student_id,
592                         ticket.level, ticket.code, score))
593                if not ticket_error and ticket.ca != ca:
594                    ticket.ca = ca
595                    ticket.student.__parent__.logger.info(
596                        '%s - %s %s/%s ca updated (%s)' %
597                        (ob_class, ticket.student.student_id,
598                         ticket.level, ticket.code, ca))
599                tno += 1
600            if error:
601                self.flash(_('Error: Score(s) and CA(s) of %s have not be updated. '
602                  'Only integers are allowed.' % error.strip(', ')),
603                  type="danger")
604        return
Note: See TracBrowser for help on using the repository browser.