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

Last change on this file since 16445 was 16445, checked in by Henrik Bettermann, 4 years ago

Change PORTRAIT_CHANGE_STATES.

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