source: main/waeup.uniben/trunk/src/waeup/uniben/students/utils.py @ 17421

Last change on this file since 17421 was 17396, checked in by Henrik Bettermann, 17 months ago

Add NYSCExporter.

  • Property svn:keywords set to Id
File size: 31.7 KB
Line 
1## $Id: utils.py 17396 2023-04-27 13:52:09Z henrik $
2##
3## Copyright (C) 2011 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 time import time
20from reportlab.platypus import Paragraph, Table
21from zope.component import createObject, getUtility
22from reportlab.lib.styles import getSampleStyleSheet
23from waeup.kofa.browser.pdf import ENTRY1_STYLE
24from waeup.kofa.interfaces import (IKofaUtils, ADMITTED, CLEARANCE,
25    CLEARED, REQUESTED, RETURNING, PAID, REGISTERED, VALIDATED, GRADUATED)
26from waeup.kofa.utils.helpers import to_timezone
27from waeup.kofa.students.utils import (
28    trans, render_student_data, formatted_text, render_transcript_data,
29    SLIP_STYLE)
30from kofacustom.nigeria.students.utils import NigeriaStudentsUtils
31from waeup.uniben.interfaces import MessageFactory as _
32
33class CustomStudentsUtils(NigeriaStudentsUtils):
34    """A collection of customized methods.
35
36    """
37
38    SEPARATORS_DICT = {
39        'form.fst_sit_fname': _(u'First Sitting Record'),
40        'form.scd_sit_fname': _(u'Second Sitting Record'),
41        'form.alr_fname': _(u'Advanced Level Record'),
42        'form.hq_type': _(u'Higher Education Record'),
43        'form.hq2_type': _(u'Second Higher Education Record'),
44        'form.nysc_year': _(u'NYSC Information'),
45        'form.employer': _(u'Employment History'),
46        'form.former_matric': _(u'Former Student'),
47        'form.fever': _(u'History of Symptoms'),
48        'form.asthma': _(u'Medical History'),
49        'form.lagos_abuja': _(u'Travel History'),
50        'form.company_suspected': _(u'History of Contact/Infection'),
51        'form.genotype': _(u'TISHIP Registration Form Data'),
52        }
53
54    def getReturningData(self, student):
55        """ This method defines what happens after school fee payment
56        of returning students depending on the student's senate verdict.
57        """
58        prev_level = student['studycourse'].current_level
59        cur_verdict = student['studycourse'].current_verdict
60        if cur_verdict == 'N' and prev_level in (100, 200):
61            new_level = prev_level
62        elif cur_verdict in ('A','B','L','M','N','Z',):
63            # Successful student
64            new_level = divmod(int(prev_level),100)[0]*100 + 100
65        elif cur_verdict == 'C':
66            # Student on probation
67            new_level = int(prev_level) + 10
68        else:
69            # Student is somehow in an undefined state.
70            # Level has to be set manually.
71            new_level = prev_level
72        new_session = student['studycourse'].current_session + 1
73        return new_session, new_level
74
75
76    def checkAccommodationRequirements(self, student, acc_details):
77        if acc_details.get('expired', False):
78            startdate = acc_details.get('startdate')
79            enddate = acc_details.get('enddate')
80            if startdate and enddate:
81                tz = getUtility(IKofaUtils).tzinfo
82                startdate = to_timezone(
83                    startdate, tz).strftime("%d/%m/%Y %H:%M:%S")
84                enddate = to_timezone(
85                    enddate, tz).strftime("%d/%m/%Y %H:%M:%S")
86                return _("Outside booking period: ${a} - ${b}",
87                         mapping = {'a': startdate, 'b': enddate})
88            else:
89                return _("Outside booking period.")
90        if not student.is_postgrad and student.current_mode != 'ug_ft':
91            return _("Only undergraduate full-time students are eligible to book accommodation.")
92        bt = acc_details.get('bt')
93        if not bt:
94            return _("Your data are incomplete.")
95        if not student.state in acc_details['allowed_states']:
96            return _("You are in the wrong registration state.")
97        #if student['studycourse'].current_session != acc_details[
98        #    'booking_session']:
99        #    return _('Your current session does not '
100        #             'match accommodation session.')
101        if  acc_details['booking_session'] - student[
102            'studycourse'].current_session > self.ACCOMMODATION_SPAN:
103            return _('Your current session does not allow ' + \
104                    'to book accommodation.')
105        stage = bt.split('_')[2]
106        if not student.is_postgrad and stage != 'fr' and not student[
107            'studycourse'].previous_verdict in (
108                'A', 'B', 'F', 'J', 'L', 'M', 'C', 'Z'):
109            return _("Your are not eligible to book accommodation.")
110        bsession = str(acc_details['booking_session'])
111        if bsession in student['accommodation'].keys() \
112            and not 'booking expired' in \
113            student['accommodation'][bsession].bed_coordinates:
114            return _('You already booked a bed space in '
115                     'current accommodation session.')
116        return
117
118    def getAccommodationDetails(self, student):
119        """Determine the accommodation data of a student.
120        """
121        d = {}
122        d['error'] = u''
123        hostels = grok.getSite()['hostels']
124        d['booking_session'] = hostels.accommodation_session
125        d['allowed_states'] = hostels.accommodation_states
126        d['startdate'] = hostels.startdate
127        d['enddate'] = hostels.enddate
128        d['expired'] = hostels.expired
129        # Determine bed type
130        studycourse = student['studycourse']
131        certificate = getattr(studycourse,'certificate',None)
132        entry_session = studycourse.entry_session
133        current_level = studycourse.current_level
134        if None in (entry_session, current_level, certificate):
135            return d
136        if student.sex == 'f':
137            sex = 'female'
138        else:
139            sex = 'male'
140        if student.is_postgrad:
141            bt = 'all'
142            special_handling = 'pg'
143        else:
144            end_level = certificate.end_level
145            if current_level == 10:
146                bt = 'pr'
147            elif entry_session == grok.getSite()['hostels'].accommodation_session:
148                bt = 'fr'
149            elif current_level >= end_level:
150                bt = 'fi'
151            else:
152                bt = 're'
153            special_handling = 'regular'
154            desired_hostel = student['accommodation'].desired_hostel
155            if student.faccode in ('MED', 'DEN') and (
156                not desired_hostel or desired_hostel.startswith('clinical')):
157                special_handling = 'clinical'
158            elif student.certcode in ('BARTMAS', 'BARTTHR', 'BARTFAA',
159                                      'BAEDFAA', 'BSCEDECHED', 'BAFAA',
160                                      'BARTMUS', 'BSCEDECHED'):
161                special_handling = 'ekenwan'
162        d['bt'] = u'%s_%s_%s' % (special_handling,sex,bt)
163        return d
164
165    def _paymentMade(self, student, session):
166        if len(student['payments']):
167            for ticket in student['payments'].values():
168                if ticket.p_state == 'paid' and \
169                    ticket.p_category == 'schoolfee' and \
170                    ticket.p_session == session:
171                    return True
172        return False
173
174    def _isPaymentDisabled(self, p_session, category, student):
175        academic_session = self._getSessionConfiguration(p_session)
176        if category == 'schoolfee':
177            if 'sf_all' in academic_session.payment_disabled:
178                return True
179            if student.state == RETURNING and \
180                'sf_return' in academic_session.payment_disabled:
181                return True
182            if student.current_mode == 'found' and \
183                'sf_found' in academic_session.payment_disabled:
184                return True
185            if student.is_postgrad:
186                if 'sf_pg' in academic_session.payment_disabled:
187                    return True
188                return False
189            if student.current_mode.endswith('ft') and \
190                'sf_ft' in academic_session.payment_disabled:
191                return True
192            if student.current_mode.endswith('pt') and \
193                'sf_pt' in academic_session.payment_disabled:
194                return True
195            if student.current_mode.startswith('dp') and \
196                'sf_dp' in academic_session.payment_disabled:
197                return True
198            if student.current_mode.endswith('sw') and \
199                'sf_sw' in academic_session.payment_disabled:
200                return True
201        if category == 'hostel_maintenance' and \
202            'maint_all' in academic_session.payment_disabled:
203            return True
204        if category == 'clearance':
205            if 'cl_all' in academic_session.payment_disabled:
206                return True
207            if student.is_jupeb and \
208                'cl_jupeb' in academic_session.payment_disabled:
209                return True
210            if not student.is_jupeb and \
211                'cl_allexj' in academic_session.payment_disabled:
212                return True
213        return False
214
215    #def _hostelApplicationPaymentMade(self, student, session):
216    #    if len(student['payments']):
217    #        for ticket in student['payments'].values():
218    #            if ticket.p_state == 'paid' and \
219    #                ticket.p_category == 'hostel_application' and \
220    #                ticket.p_session == session:
221    #                return True
222    #    return False
223
224    def _pharmdInstallments(self, student):
225        installments = 0.0
226        if len(student['payments']):
227            for ticket in student['payments'].values():
228                if ticket.p_state == 'paid' and \
229                    ticket.p_category.startswith('pharmd') and \
230                    ticket.p_session == student.current_session:
231                    installments += ticket.amount_auth
232        return installments
233
234    def samePaymentMade(self, student, category, p_item, p_session):
235        if category in ('bed_allocation', 'transcript'):
236            return False
237        for key in student['payments'].keys():
238            ticket = student['payments'][key]
239            if ticket.p_state == 'paid' and\
240               ticket.p_category == category and \
241               ticket.p_item == p_item and \
242               ticket.p_session == p_session:
243                  return True
244        return False
245
246    def setPaymentDetails(self, category, student,
247            previous_session, previous_level, combi):
248        """Create Payment object and set the payment data of a student for
249        the payment category specified.
250
251        """
252        p_item = u''
253        amount = 0.0
254        if previous_session:
255            if previous_session < student['studycourse'].entry_session:
256                return _('The previous session must not fall below '
257                         'your entry session.'), None
258            if category == 'schoolfee':
259                # School fee is always paid for the following session
260                if previous_session > student['studycourse'].current_session:
261                    return _('This is not a previous session.'), None
262            else:
263                if previous_session > student['studycourse'].current_session - 1:
264                    return _('This is not a previous session.'), None
265            p_session = previous_session
266            p_level = previous_level
267            p_current = False
268        else:
269            p_session = student['studycourse'].current_session
270            p_level = student['studycourse'].current_level
271            p_current = True
272        academic_session = self._getSessionConfiguration(p_session)
273        if academic_session == None:
274            return _(u'Session configuration object is not available.'), None
275        # Determine fee.
276        if category.startswith('pharmd') \
277            and student.current_mode == 'special_ft':
278            amount = 80000.0
279        elif category == 'plag_test':
280            amount = 2500.0
281            if student.is_postgrad:
282                amount = 5000.0
283        #elif category == 'develop' and student.is_postgrad:
284        #    amount = academic_session.development_fee
285        elif category == 'bed_allocation':
286            acco_details = self.getAccommodationDetails(student)
287            p_session = acco_details['booking_session']
288            p_item = acco_details['bt']
289            desired_hostel = student['accommodation'].desired_hostel
290            if not desired_hostel:
291                return _(u'Select your favoured hostel first.'), None
292            if desired_hostel and desired_hostel != 'no':
293                p_item = u'%s (%s)' % (p_item, desired_hostel)
294            amount = academic_session.booking_fee
295            if student.is_postgrad:
296                amount += 500
297        elif category == 'hostel_maintenance':
298            amount = 0.0
299            booking_session = grok.getSite()['hostels'].accommodation_session
300            bedticket = student['accommodation'].get(str(booking_session), None)
301            if bedticket is not None and bedticket.bed is not None:
302                p_item = bedticket.bed_coordinates
303                p_session = booking_session
304                if bedticket.bed.__parent__.maint_fee > 0:
305                    amount = bedticket.bed.__parent__.maint_fee
306                else:
307                    # fallback
308                    amount = academic_session.maint_fee
309            else:
310                return _(u'No bed allocated.'), None
311        #elif category == 'hostel_application':
312        #    amount = 1000.0
313        #elif category.startswith('tempmaint'):
314        #    if not self._hostelApplicationPaymentMade(
315        #        student, student.current_session):
316        #        return _(
317        #            'You have not yet paid the hostel application fee.'), None
318        #    if category == 'tempmaint_1':
319        #        amount = 8150.0
320        #    elif category == 'tempmaint_2':
321        #        amount = 12650.0
322        #    elif category == 'tempmaint_3':
323        #        amount = 9650.0
324        elif category == 'clearance':
325            p_item = student.certcode
326            if p_item is None:
327                return _('Study course data are incomplete.'), None
328            if student.is_jupeb:
329                amount = 50000.0
330            elif student.faccode.startswith('FCETA'):
331                # ASABA and AKOKA
332                amount = 35000.0
333            elif student.depcode == 'DMIC':
334                amount = 70000.0
335            elif student.faccode in ('BMS', 'MED', 'DEN') \
336                and not student.is_postgrad:
337                amount = 80000.0
338            elif student.faccode == 'DCOEM':
339                return _('Acceptance fee payment not necessary.'), None
340            else:
341                amount = 60000.0
342        elif category == 'schoolfee':
343            try:
344                certificate = student['studycourse'].certificate
345                p_item = certificate.code
346            except (AttributeError, TypeError):
347                return _('Study course data are incomplete.'), None
348            discount_year = 2017
349            if student.is_postgrad:
350                discount_year = 2020
351            if previous_session:
352                # Students can pay for previous sessions in all workflow states.
353                # Fresh students are excluded by the update method of the
354                # PreviousPaymentAddFormPage.
355                if previous_session == student['studycourse'].entry_session:
356                    if student.is_foreigner:
357                        amount = getattr(certificate, 'school_fee_3', 0.0)
358                    else:
359                        amount = getattr(certificate, 'school_fee_1', 0.0)
360                        # Old new students get a discount.
361                        if student.entry_session < discount_year \
362                            and certificate.custom_float_1:
363                            amount -= certificate.custom_float_1                       
364                else:
365                    if student.is_foreigner:
366                        amount = getattr(certificate, 'school_fee_4', 0.0)
367                    else:
368                        amount = getattr(certificate, 'school_fee_2', 0.0)
369                        # Old returning students get a discount.
370                        if student.entry_session < discount_year \
371                            and certificate.custom_float_2:
372                            amount -= certificate.custom_float_2
373            else:
374                if student.state == CLEARED:
375                    if student.is_foreigner:
376                        amount = getattr(certificate, 'school_fee_3', 0.0)
377                    else:
378                        amount = getattr(certificate, 'school_fee_1', 0.0)
379                        # Old new students get a discount.
380                        if student.entry_session < discount_year \
381                            and certificate.custom_float_1:
382                            amount -= certificate.custom_float_1                             
383                elif student.state == PAID and student.is_postgrad:
384                    p_session += 1
385                    academic_session = self._getSessionConfiguration(p_session)
386                    if academic_session == None:
387                        return _(u'Session configuration object is not available.'), None
388
389                    # Students are only allowed to pay for the next session
390                    # if current session payment
391                    # has really been made, i.e. payment object exists.
392                    #if not self._paymentMade(
393                    #    student, student.current_session):
394                    #    return _('You have not yet paid your current/active' +
395                    #             ' session. Please use the previous session' +
396                    #             ' payment form first.'), None
397
398                    if student.is_foreigner:
399                        amount = getattr(certificate, 'school_fee_4', 0.0)
400                    else:
401                        amount = getattr(certificate, 'school_fee_2', 0.0)
402                        # Old returning students might get a discount.
403                        if student.entry_session < discount_year \
404                            and certificate.custom_float_2:
405                            amount -= certificate.custom_float_2
406                elif student.state == RETURNING:
407                    # In case of returning school fee payment the payment session
408                    # and level contain the values of the session the student
409                    # has paid for.
410                    p_session, p_level = self.getReturningData(student)
411                    academic_session = self._getSessionConfiguration(p_session)
412                    if academic_session == None:
413                        return _(u'Session configuration object is not available.'), None
414
415                    # Students are only allowed to pay for the next session
416                    # if current session payment has really been made,
417                    # i.e. payment object exists and is paid.
418                    #if not self._paymentMade(
419                    #    student, student.current_session):
420                    #    return _('You have not yet paid your current/active' +
421                    #             ' session. Please use the previous session' +
422                    #             ' payment form first.'), None
423
424                    if student.is_foreigner:
425                        amount = getattr(certificate, 'school_fee_4', 0.0)
426                    else:
427                        amount = getattr(certificate, 'school_fee_2', 0.0)
428                        # Old returning students might get a discount.
429                        if student.entry_session < discount_year \
430                            and certificate.custom_float_2:
431                            amount -= certificate.custom_float_2
432                # PHARMD school fee amount is fixed and previously paid
433                # installments in current session are deducted.
434                if student.current_mode == 'special_ft' \
435                    and student.state in (RETURNING, CLEARED):
436                    if student.is_foreigner:
437                        amount = 260000.0 - self._pharmdInstallments(student)
438                    else:
439                        amount = 160000.0 - self._pharmdInstallments(student)
440            # Give 50% school fee discount to staff members.
441            if student.is_staff:
442                amount /= 2
443        else:
444            fee_name = category + '_fee'
445            amount = getattr(academic_session, fee_name, 0.0)
446        if amount in (0.0, None):
447            return _('Amount could not be determined.'), None
448        # Add session specific penalty fee.
449        if category == 'schoolfee' and student.is_postgrad:
450            amount += academic_session.penalty_pg
451            amount += academic_session.development_fee
452        elif category == 'schoolfee' and student.current_mode == ('ug_ft'):
453            amount += academic_session.penalty_ug_ft
454        elif category == 'schoolfee' and student.current_mode == ('ug_pt'):
455            amount += academic_session.penalty_ug_pt
456        elif category == 'schoolfee' and student.current_mode == ('ug_sw'):
457            amount += academic_session.penalty_sw
458        elif category == 'schoolfee' and student.current_mode in (
459            'dp_ft', 'dp_pt'):
460            amount += academic_session.penalty_dp
461        if category.startswith('tempmaint'):
462            p_item = getUtility(IKofaUtils).PAYMENT_CATEGORIES[category]
463            p_item = unicode(p_item)
464            # Now we change the category because tempmaint payments
465            # will be obsolete when Uniben returns to Kofa bed allocation.
466            category = 'hostel_maintenance'
467        # Create ticket.
468        if self.samePaymentMade(student, category, p_item, p_session):
469            return _('This type of payment has already been made.'), None
470        if self._isPaymentDisabled(p_session, category, student):
471            return _('This category of payments has been disabled.'), None
472        payment = createObject(u'waeup.StudentOnlinePayment')
473        timestamp = ("%d" % int(time()*10000))[1:]
474        payment.p_id = "p%s" % timestamp
475        payment.p_category = category
476        payment.p_item = p_item
477        payment.p_session = p_session
478        payment.p_level = p_level
479        payment.p_current = p_current
480        payment.amount_auth = amount
481        return None, payment
482
483    def warnCreditsOOR(self, studylevel, course=None):
484        studycourse = studylevel.__parent__
485        certificate = getattr(studycourse,'certificate', None)
486        current_level = studycourse.current_level
487        if None in (current_level, certificate):
488            return
489        if studylevel.__parent__.previous_verdict == 'R':
490            return
491        end_level = certificate.end_level
492        if studylevel.student.faccode in (
493            'MED', 'DEN', 'BMS') and studylevel.level == 200:
494            limit = 61
495        elif current_level >= end_level:
496            limit = 51
497        else:
498            limit = 50
499        if course and studylevel.total_credits + course.credits > limit:
500            return _('Maximum credits exceeded.')
501        elif studylevel.total_credits > limit:
502            return _('Maximum credits exceeded.')
503        return
504
505    def warnCourseAlreadyPassed(self, studylevel, course):
506        """Return message if course has already been passed at
507        previous levels.
508        """
509
510        # med: we may need to put this matter on hold and allow
511        # all the students to register.
512        return False
513
514        previous_verdict = studylevel.__parent__.previous_verdict
515        if previous_verdict in ('C', 'M'):
516            return False
517        for slevel in studylevel.__parent__.values():
518            for cticket in slevel.values():
519                if cticket.code == course.code \
520                    and cticket.total_score >= cticket.passmark:
521                    return _('Course has already been passed at previous level.')
522        return False
523
524    def clearance_disabled_message(self, student):
525        if student.is_postgrad:
526            return None
527        try:
528            session_config = grok.getSite()[
529                'configuration'][str(student.current_session)]
530        except KeyError:
531            return _('Session configuration object is not available.')
532        if not session_config.clearance_enabled:
533            return _('Clearance is disabled for this session.')
534        return None
535
536    def renderPDFTranscript(self, view, filename='transcript.pdf',
537                  student=None,
538                  studentview=None,
539                  note=None,
540                  signatures=(),
541                  sigs_in_footer=(),
542                  digital_sigs=(),
543                  show_scans=True, topMargin=1.5,
544                  omit_fields=(),
545                  tableheader=None,
546                  no_passport=False,
547                  save_file=False):
548        """Render pdf slip of a transcripts.
549        """
550        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
551        # XXX: tell what the different parameters mean
552        style = getSampleStyleSheet()
553        creator = self.getPDFCreator(student)
554        data = []
555        doc_title = view.label
556        author = '%s (%s)' % (view.request.principal.title,
557                              view.request.principal.id)
558        footer_text = view.label.split('\n')
559        if len(footer_text) > 2:
560            # We can add a department in first line
561            footer_text = footer_text[1]
562        else:
563            # Only the first line is used for the footer
564            footer_text = footer_text[0]
565        if getattr(student, 'student_id', None) is not None:
566            footer_text = "%s - %s - " % (student.student_id, footer_text)
567
568        # Insert student data table
569        if student is not None:
570            #bd_translation = trans(_('Base Data'), portal_language)
571            #data.append(Paragraph(bd_translation, HEADING_STYLE))
572            data.append(render_student_data(
573                studentview, view.context,
574                omit_fields, lang=portal_language,
575                slipname=filename,
576                no_passport=no_passport))
577
578        transcript_data = view.context.getTranscriptData()
579        levels_data = transcript_data[0]
580
581        contextdata = []
582        f_label = trans(_('Course of Study:'), portal_language)
583        f_label = Paragraph(f_label, ENTRY1_STYLE)
584        f_text = formatted_text(view.context.certificate.longtitle)
585        f_text = Paragraph(f_text, ENTRY1_STYLE)
586        contextdata.append([f_label,f_text])
587
588        f_label = trans(_('Faculty:'), portal_language)
589        f_label = Paragraph(f_label, ENTRY1_STYLE)
590        f_text = formatted_text(
591            view.context.certificate.__parent__.__parent__.__parent__.longtitle)
592        f_text = Paragraph(f_text, ENTRY1_STYLE)
593        contextdata.append([f_label,f_text])
594
595        f_label = trans(_('Department:'), portal_language)
596        f_label = Paragraph(f_label, ENTRY1_STYLE)
597        f_text = formatted_text(
598            view.context.certificate.__parent__.__parent__.longtitle)
599        f_text = Paragraph(f_text, ENTRY1_STYLE)
600        contextdata.append([f_label,f_text])
601
602        f_label = trans(_('Entry Session:'), portal_language)
603        f_label = Paragraph(f_label, ENTRY1_STYLE)
604        f_text = formatted_text(
605            view.session_dict.get(view.context.entry_session))
606        f_text = Paragraph(f_text, ENTRY1_STYLE)
607        contextdata.append([f_label,f_text])
608
609        f_label = trans(_('Final Session:'), portal_language)
610        f_label = Paragraph(f_label, ENTRY1_STYLE)
611        f_text = formatted_text(
612            view.session_dict.get(view.context.current_session))
613        f_text = Paragraph(f_text, ENTRY1_STYLE)
614        contextdata.append([f_label,f_text])
615
616        f_label = trans(_('Entry Mode:'), portal_language)
617        f_label = Paragraph(f_label, ENTRY1_STYLE)
618        f_text = formatted_text(view.studymode_dict.get(
619            view.context.entry_mode))
620        f_text = Paragraph(f_text, ENTRY1_STYLE)
621        contextdata.append([f_label,f_text])
622
623        f_label = trans(_('Final Verdict:'), portal_language)
624        f_label = Paragraph(f_label, ENTRY1_STYLE)
625        f_text = formatted_text(view.studymode_dict.get(
626            view.context.current_verdict))
627        f_text = Paragraph(f_text, ENTRY1_STYLE)
628        contextdata.append([f_label,f_text])
629
630        f_label = trans(_('Cumulative GPA:'), portal_language)
631        f_label = Paragraph(f_label, ENTRY1_STYLE)
632        format_float = getUtility(IKofaUtils).format_float
633        cgpa = format_float(transcript_data[1], 3)
634        if student.state == GRADUATED:
635            f_text = formatted_text('%s (%s)' % (
636                cgpa, self.getClassFromCGPA(transcript_data[1], student)[1]))
637        else:
638            f_text = formatted_text('%s' % cgpa)
639        f_text = Paragraph(f_text, ENTRY1_STYLE)
640        contextdata.append([f_label,f_text])
641
642        contexttable = Table(contextdata,style=SLIP_STYLE)
643        data.append(contexttable)
644
645        transcripttables = render_transcript_data(
646            view, tableheader, levels_data, lang=portal_language)
647        data.extend(transcripttables)
648
649        # Insert signatures
650        # XXX: We are using only sigs_in_footer in waeup.kofa, so we
651        # do not have a test for the following lines.
652        if signatures and not sigs_in_footer:
653            data.append(Spacer(1, 20))
654            # Render one signature table per signature to
655            # get date and signature in line.
656            for signature in signatures:
657                signaturetables = get_signature_tables(signature)
658                data.append(signaturetables[0])
659
660        # Insert digital signatures
661        if digital_sigs:
662            data.append(Spacer(1, 20))
663            sigs = digital_sigs.split('\n')
664            for sig in sigs:
665                data.append(Paragraph(sig, NOTE_STYLE))
666
667        view.response.setHeader(
668            'Content-Type', 'application/pdf')
669        try:
670            pdf_stream = creator.create_pdf(
671                data, None, doc_title, author=author, footer=footer_text,
672                note=note, sigs_in_footer=sigs_in_footer, topMargin=topMargin,
673                view=view)
674        except IOError:
675            view.flash(_('Error in image file.'))
676            return view.redirect(view.url(view.context))
677        if save_file:
678            self._saveTranscriptPDF(student, pdf_stream)
679            return
680        return pdf_stream
681
682    #: A tuple containing the names of registration states in which changing of
683    #: passport pictures is allowed.
684    PORTRAIT_CHANGE_STATES = (CLEARANCE, REQUESTED)
685
686    #: A tuple containing the names of registration states in which changing of
687    #: scanned signatures is allowed.
688    SIGNATURE_CHANGE_STATES = (CLEARED, RETURNING, PAID, REGISTERED, VALIDATED, )
689
690    # Uniben prefix
691    @property
692    def STUDENT_ID_PREFIX(self):
693        if grok.getSite().__name__ == 'uniben-cdl':
694            return u'C'
695        return u'B'
696
697    STUDENT_EXPORTER_NAMES = (
698            'students',
699            'studentstudycourses',
700            'studentstudycourses_1',
701            'studentstudylevels',
702            #'studentstudylevels_1',
703            'coursetickets',
704            #'coursetickets_1',
705            'studentpayments',
706            'bedtickets',
707            'trimmed',
708            'outstandingcourses',
709            'unpaidpayments',
710            'sfpaymentsoverview',
711            'sessionpaymentsoverview',
712            'studylevelsoverview',
713            'combocard',
714            'bursary',
715            'accommodationpayments',
716            'transcriptdata',
717            'trimmedpayments',
718            'medicalhistory',
719            'nysc',
720            )
Note: See TracBrowser for help on using the repository browser.