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

Last change on this file since 16827 was 16780, checked in by Henrik Bettermann, 3 years ago

Add plag test payment category.

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