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

Last change on this file since 13907 was 13907, checked in by Henrik Bettermann, 8 years ago

Sort table.

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