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

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

Disable schoolfee payments of returning students only.

  • Property svn:keywords set to Id
File size: 30.0 KB
Line 
1## $Id: utils.py 16516 2021-06-27 09:33:08Z 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 == 100:
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 == 'develop' and student.is_postgrad:
286        #    amount = academic_session.development_fee
287        elif category == 'bed_allocation':
288            p_item = self.getAccommodationDetails(student)['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            bedticket = student['accommodation'].get(
300                str(student.current_session), None)
301            if bedticket is not None and bedticket.bed is not None:
302                p_item = bedticket.bed_coordinates
303                if bedticket.bed.__parent__.maint_fee > 0:
304                    amount = bedticket.bed.__parent__.maint_fee
305                else:
306                    # fallback
307                    amount = academic_session.maint_fee
308            else:
309                return _(u'No bed allocated.'), None
310        #elif category == 'hostel_application':
311        #    amount = 1000.0
312        #elif category.startswith('tempmaint'):
313        #    if not self._hostelApplicationPaymentMade(
314        #        student, student.current_session):
315        #        return _(
316        #            'You have not yet paid the hostel application fee.'), None
317        #    if category == 'tempmaint_1':
318        #        amount = 8150.0
319        #    elif category == 'tempmaint_2':
320        #        amount = 12650.0
321        #    elif category == 'tempmaint_3':
322        #        amount = 9650.0
323        elif category == 'clearance':
324            p_item = student.certcode
325            if p_item is None:
326                return _('Study course data are incomplete.'), None
327            if student.is_jupeb:
328                amount = 50000.0
329            elif student.faccode.startswith('FCETA'):
330                # ASABA and AKOKA
331                amount = 35000.0
332            elif student.faccode in ('BMS', 'MED', 'DEN'):
333            #elif p_item in ('BSCANA', 'BSCMBC', 'BMLS', 'BSCNUR', 'BSCPHS', 'BDS',
334            #    'MBBSMED', 'MBBSNDU', 'BSCPTY', 'BSCPST'):
335                amount = 80000.0
336            elif student.faccode == 'DCOEM':
337                return _('Acceptance fee payment not necessary.'), None
338            else:
339                amount = 60000.0
340        elif category == 'schoolfee':
341            try:
342                certificate = student['studycourse'].certificate
343                p_item = certificate.code
344            except (AttributeError, TypeError):
345                return _('Study course data are incomplete.'), None
346            if previous_session:
347                # Students can pay for previous sessions in all workflow states.
348                # Fresh students are excluded by the update method of the
349                # PreviousPaymentAddFormPage.
350                if previous_session == student['studycourse'].entry_session:
351                    if student.is_foreigner:
352                        amount = getattr(certificate, 'school_fee_3', 0.0)
353                    else:
354                        amount = getattr(certificate, 'school_fee_1', 0.0)
355                else:
356                    if student.is_foreigner:
357                        amount = getattr(certificate, 'school_fee_4', 0.0)
358                    else:
359                        amount = getattr(certificate, 'school_fee_2', 0.0)
360                        # Old returning students might get a discount.
361                        if student.entry_session < 2017 \
362                            and certificate.custom_float_1:
363                            amount -= certificate.custom_float_1
364            else:
365                if student.state == CLEARED:
366                    if student.is_foreigner:
367                        amount = getattr(certificate, 'school_fee_3', 0.0)
368                    else:
369                        amount = getattr(certificate, 'school_fee_1', 0.0)
370                elif student.state == PAID and student.is_postgrad:
371                    p_session += 1
372                    academic_session = self._getSessionConfiguration(p_session)
373                    if academic_session == None:
374                        return _(u'Session configuration object is not available.'), None
375
376                    # Students are only allowed to pay for the next session
377                    # if current session payment
378                    # has really been made, i.e. payment object exists.
379                    #if not self._paymentMade(
380                    #    student, student.current_session):
381                    #    return _('You have not yet paid your current/active' +
382                    #             ' session. Please use the previous session' +
383                    #             ' payment form first.'), None
384
385                    if student.is_foreigner:
386                        amount = getattr(certificate, 'school_fee_4', 0.0)
387                    else:
388                        amount = getattr(certificate, 'school_fee_2', 0.0)
389                elif student.state == RETURNING:
390                    # In case of returning school fee payment the payment session
391                    # and level contain the values of the session the student
392                    # has paid for.
393                    p_session, p_level = self.getReturningData(student)
394                    academic_session = self._getSessionConfiguration(p_session)
395                    if academic_session == None:
396                        return _(u'Session configuration object is not available.'), None
397
398                    # Students are only allowed to pay for the next session
399                    # if current session payment has really been made,
400                    # i.e. payment object exists and is paid.
401                    #if not self._paymentMade(
402                    #    student, student.current_session):
403                    #    return _('You have not yet paid your current/active' +
404                    #             ' session. Please use the previous session' +
405                    #             ' payment form first.'), None
406
407                    if student.is_foreigner:
408                        amount = getattr(certificate, 'school_fee_4', 0.0)
409                    else:
410                        amount = getattr(certificate, 'school_fee_2', 0.0)
411                        # Old returning students might get a discount.
412                        if student.entry_session < 2017 \
413                            and certificate.custom_float_1:
414                            amount -= certificate.custom_float_1
415                # PHARMD school fee amount is fixed and previously paid
416                # installments in current session are deducted.
417                if student.current_mode == 'special_ft' \
418                    and student.state in (RETURNING, CLEARED):
419                    if student.is_foreigner:
420                        amount = 260000.0 - self._pharmdInstallments(student)
421                    else:
422                        amount = 160000.0 - self._pharmdInstallments(student)
423            # Give 50% school fee discount to staff members.
424            if student.is_staff:
425                amount /= 2
426        if amount in (0.0, None):
427            return _('Amount could not be determined.'), None
428        # Add session specific penalty fee.
429        if category == 'schoolfee' and student.is_postgrad:
430            amount += academic_session.penalty_pg
431            amount += academic_session.development_fee
432        elif category == 'schoolfee' and student.current_mode == ('ug_ft'):
433            amount += academic_session.penalty_ug_ft
434        elif category == 'schoolfee' and student.current_mode == ('ug_pt'):
435            amount += academic_session.penalty_ug_pt
436        elif category == 'schoolfee' and student.current_mode == ('ug_sw'):
437            amount += academic_session.penalty_sw
438        elif category == 'schoolfee' and student.current_mode in (
439            'dp_ft', 'dp_pt'):
440            amount += academic_session.penalty_dp
441        if category.startswith('tempmaint'):
442            p_item = getUtility(IKofaUtils).PAYMENT_CATEGORIES[category]
443            p_item = unicode(p_item)
444            # Now we change the category because tempmaint payments
445            # will be obsolete when Uniben returns to Kofa bed allocation.
446            category = 'hostel_maintenance'
447        # Create ticket.
448        if self.samePaymentMade(student, category, p_item, p_session):
449            return _('This type of payment has already been made.'), None
450        if self._isPaymentDisabled(p_session, category, student):
451            return _('This category of payments has been disabled.'), None
452        payment = createObject(u'waeup.StudentOnlinePayment')
453        timestamp = ("%d" % int(time()*10000))[1:]
454        payment.p_id = "p%s" % timestamp
455        payment.p_category = category
456        payment.p_item = p_item
457        payment.p_session = p_session
458        payment.p_level = p_level
459        payment.p_current = p_current
460        payment.amount_auth = amount
461        return None, payment
462
463    def warnCreditsOOR(self, studylevel, course=None):
464        studycourse = studylevel.__parent__
465        certificate = getattr(studycourse,'certificate', None)
466        current_level = studycourse.current_level
467        if None in (current_level, certificate):
468            return
469        if studylevel.__parent__.previous_verdict == 'R':
470            return
471        end_level = certificate.end_level
472        if studylevel.student.faccode in (
473            'MED', 'DEN', 'BMS') and studylevel.level == 200:
474            limit = 61
475        elif current_level >= end_level:
476            limit = 51
477        else:
478            limit = 50
479        if course and studylevel.total_credits + course.credits > limit:
480            return _('Maximum credits exceeded.')
481        elif studylevel.total_credits > limit:
482            return _('Maximum credits exceeded.')
483        return
484
485    def warnCourseAlreadyPassed(self, studylevel, course):
486        """Return message if course has already been passed at
487        previous levels.
488        """
489
490        # med: we may need to put this matter on hold and allow
491        # all the students to register.
492        return False
493
494        previous_verdict = studylevel.__parent__.previous_verdict
495        if previous_verdict in ('C', 'M'):
496            return False
497        for slevel in studylevel.__parent__.values():
498            for cticket in slevel.values():
499                if cticket.code == course.code \
500                    and cticket.total_score >= cticket.passmark:
501                    return _('Course has already been passed at previous level.')
502        return False
503
504    def clearance_disabled_message(self, student):
505        if student.is_postgrad:
506            return None
507        try:
508            session_config = grok.getSite()[
509                'configuration'][str(student.current_session)]
510        except KeyError:
511            return _('Session configuration object is not available.')
512        if not session_config.clearance_enabled:
513            return _('Clearance is disabled for this session.')
514        return None
515
516    def renderPDFTranscript(self, view, filename='transcript.pdf',
517                  student=None,
518                  studentview=None,
519                  note=None,
520                  signatures=(),
521                  sigs_in_footer=(),
522                  digital_sigs=(),
523                  show_scans=True, topMargin=1.5,
524                  omit_fields=(),
525                  tableheader=None,
526                  no_passport=False,
527                  save_file=False):
528        """Render pdf slip of a transcripts.
529        """
530        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
531        # XXX: tell what the different parameters mean
532        style = getSampleStyleSheet()
533        creator = self.getPDFCreator(student)
534        data = []
535        doc_title = view.label
536        author = '%s (%s)' % (view.request.principal.title,
537                              view.request.principal.id)
538        footer_text = view.label.split('\n')
539        if len(footer_text) > 2:
540            # We can add a department in first line
541            footer_text = footer_text[1]
542        else:
543            # Only the first line is used for the footer
544            footer_text = footer_text[0]
545        if getattr(student, 'student_id', None) is not None:
546            footer_text = "%s - %s - " % (student.student_id, footer_text)
547
548        # Insert student data table
549        if student is not None:
550            #bd_translation = trans(_('Base Data'), portal_language)
551            #data.append(Paragraph(bd_translation, HEADING_STYLE))
552            data.append(render_student_data(
553                studentview, view.context,
554                omit_fields, lang=portal_language,
555                slipname=filename,
556                no_passport=no_passport))
557
558        transcript_data = view.context.getTranscriptData()
559        levels_data = transcript_data[0]
560
561        contextdata = []
562        f_label = trans(_('Course of Study:'), portal_language)
563        f_label = Paragraph(f_label, ENTRY1_STYLE)
564        f_text = formatted_text(view.context.certificate.longtitle)
565        f_text = Paragraph(f_text, ENTRY1_STYLE)
566        contextdata.append([f_label,f_text])
567
568        f_label = trans(_('Faculty:'), portal_language)
569        f_label = Paragraph(f_label, ENTRY1_STYLE)
570        f_text = formatted_text(
571            view.context.certificate.__parent__.__parent__.__parent__.longtitle)
572        f_text = Paragraph(f_text, ENTRY1_STYLE)
573        contextdata.append([f_label,f_text])
574
575        f_label = trans(_('Department:'), portal_language)
576        f_label = Paragraph(f_label, ENTRY1_STYLE)
577        f_text = formatted_text(
578            view.context.certificate.__parent__.__parent__.longtitle)
579        f_text = Paragraph(f_text, ENTRY1_STYLE)
580        contextdata.append([f_label,f_text])
581
582        f_label = trans(_('Entry Session:'), portal_language)
583        f_label = Paragraph(f_label, ENTRY1_STYLE)
584        f_text = formatted_text(
585            view.session_dict.get(view.context.entry_session))
586        f_text = Paragraph(f_text, ENTRY1_STYLE)
587        contextdata.append([f_label,f_text])
588
589        f_label = trans(_('Final Session:'), portal_language)
590        f_label = Paragraph(f_label, ENTRY1_STYLE)
591        f_text = formatted_text(
592            view.session_dict.get(view.context.current_session))
593        f_text = Paragraph(f_text, ENTRY1_STYLE)
594        contextdata.append([f_label,f_text])
595
596        f_label = trans(_('Entry Mode:'), portal_language)
597        f_label = Paragraph(f_label, ENTRY1_STYLE)
598        f_text = formatted_text(view.studymode_dict.get(
599            view.context.entry_mode))
600        f_text = Paragraph(f_text, ENTRY1_STYLE)
601        contextdata.append([f_label,f_text])
602
603        f_label = trans(_('Final Verdict:'), portal_language)
604        f_label = Paragraph(f_label, ENTRY1_STYLE)
605        f_text = formatted_text(view.studymode_dict.get(
606            view.context.current_verdict))
607        f_text = Paragraph(f_text, ENTRY1_STYLE)
608        contextdata.append([f_label,f_text])
609
610        f_label = trans(_('Cumulative GPA:'), portal_language)
611        f_label = Paragraph(f_label, ENTRY1_STYLE)
612        format_float = getUtility(IKofaUtils).format_float
613        cgpa = format_float(transcript_data[1], 3)
614        if student.state == GRADUATED:
615            f_text = formatted_text('%s (%s)' % (
616                cgpa, self.getClassFromCGPA(transcript_data[1], student)[1]))
617        else:
618            f_text = formatted_text('%s' % cgpa)
619        f_text = Paragraph(f_text, ENTRY1_STYLE)
620        contextdata.append([f_label,f_text])
621
622        contexttable = Table(contextdata,style=SLIP_STYLE)
623        data.append(contexttable)
624
625        transcripttables = render_transcript_data(
626            view, tableheader, levels_data, lang=portal_language)
627        data.extend(transcripttables)
628
629        # Insert signatures
630        # XXX: We are using only sigs_in_footer in waeup.kofa, so we
631        # do not have a test for the following lines.
632        if signatures and not sigs_in_footer:
633            data.append(Spacer(1, 20))
634            # Render one signature table per signature to
635            # get date and signature in line.
636            for signature in signatures:
637                signaturetables = get_signature_tables(signature)
638                data.append(signaturetables[0])
639
640        # Insert digital signatures
641        if digital_sigs:
642            data.append(Spacer(1, 20))
643            sigs = digital_sigs.split('\n')
644            for sig in sigs:
645                data.append(Paragraph(sig, NOTE_STYLE))
646
647        view.response.setHeader(
648            'Content-Type', 'application/pdf')
649        try:
650            pdf_stream = creator.create_pdf(
651                data, None, doc_title, author=author, footer=footer_text,
652                note=note, sigs_in_footer=sigs_in_footer, topMargin=topMargin)
653        except IOError:
654            view.flash(_('Error in image file.'))
655            return view.redirect(view.url(view.context))
656        if save_file:
657            self._saveTranscriptPDF(student, pdf_stream)
658            return
659        return pdf_stream
660
661    #: A tuple containing the names of registration states in which changing of
662    #: passport pictures is allowed.
663    PORTRAIT_CHANGE_STATES = (CLEARANCE, REQUESTED)
664
665    # Uniben prefix
666    STUDENT_ID_PREFIX = u'B'
667
668    STUDENT_EXPORTER_NAMES = (
669            'students',
670            'studentstudycourses',
671            'studentstudylevels',
672            'coursetickets',
673            'studentpayments',
674            'bedtickets',
675            'trimmed',
676            'outstandingcourses',
677            'unpaidpayments',
678            'sfpaymentsoverview',
679            'sessionpaymentsoverview',
680            'studylevelsoverview',
681            'combocard',
682            'bursary',
683            'accommodationpayments',
684            'transcriptdata',
685            'trimmedpayments',
686            'medicalhistory',
687            )
Note: See TracBrowser for help on using the repository browser.