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

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

Add BSCEDECHEDU to the list of Ekenwan certificates.

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