Ignore:
Timestamp:
21 Sep 2012, 08:19:35 (12 years ago)
Author:
uli
Message:

Rollback r9209. Looks like multiple merges from trunk confuse svn when merging back into trunk.

Location:
main/waeup.kofa/branches/uli-zc-async
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.kofa/branches/uli-zc-async

  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/students/utils.py

    r9209 r9211  
    1919"""
    2020import grok
     21from random import SystemRandom as r
    2122from time import time
     23from datetime import datetime
     24from zope.i18n import translate
     25from zope.component import getUtility, createObject
     26from reportlab.pdfgen import canvas
    2227from reportlab.lib import colors
    2328from reportlab.lib.units import cm
     29from reportlab.lib.enums import TA_RIGHT
    2430from reportlab.lib.pagesizes import A4
    25 from reportlab.lib.styles import getSampleStyleSheet
    26 from reportlab.platypus import Paragraph, Image, Table, Spacer
    27 from zope.component import getUtility, createObject
     31from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
     32from reportlab.platypus import (Frame, Paragraph, Image, PageBreak, Table,
     33                                Spacer)
     34from reportlab.platypus.tables import TableStyle
     35from reportlab.platypus.flowables import PageBreak
     36from zope.component import getUtility
    2837from zope.formlib.form import setUpEditWidgets
    29 from zope.i18n import translate
     38
    3039from waeup.kofa.interfaces import (
    3140    IExtFileStore, IKofaUtils, RETURNING, PAID, CLEARED)
    3241from waeup.kofa.interfaces import MessageFactory as _
    3342from waeup.kofa.students.interfaces import IStudentsUtils
     43from waeup.kofa.utils.helpers import now
    3444
    3545SLIP_STYLE = [
     
    117127    #data.append([Spacer(1, 12)])
    118128    portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
    119 
    120     f_label = formatted_label(size=12) % _('Name')
    121     f_label = Paragraph(f_label, style["Normal"])
    122     f_text = formatted_text(studentview.context.display_fullname, size=12)
    123     f_text = Paragraph(f_text, style["Normal"])
    124     data_right.append([f_label,f_text])
    125 
    126129    for widget in studentview.widgets:
    127         if 'name' in widget.name:
     130        if widget.name == 'form.adm_code':
    128131            continue
    129132        f_label = formatted_label(size=12) % translate(
     
    134137        f_text = Paragraph(f_text, style["Normal"])
    135138        data_right.append([f_label,f_text])
    136 
    137     if hasattr(studentview.context, 'certcode'):
    138         f_label = formatted_label(size=12) % _('Study Course')
    139         f_label = Paragraph(f_label, style["Normal"])
    140         f_text = formatted_text(
    141             studentview.context['studycourse'].certificate.longtitle(), size=12)
    142         f_text = Paragraph(f_text, style["Normal"])
    143         data_right.append([f_label,f_text])
    144 
    145         f_label = formatted_label(size=12) % _('Department')
    146         f_label = Paragraph(f_label, style["Normal"])
    147         f_text = formatted_text(
    148             studentview.context[
    149             'studycourse'].certificate.__parent__.__parent__.longtitle(),
    150             size=12)
    151         f_text = Paragraph(f_text, style["Normal"])
    152         data_right.append([f_label,f_text])
    153 
    154         f_label = formatted_label(size=12) % _('Faculty')
    155         f_label = Paragraph(f_label, style["Normal"])
    156         f_text = formatted_text(
    157             studentview.context[
    158             'studycourse'].certificate.__parent__.__parent__.__parent__.longtitle(),
    159             size=12)
    160         f_text = Paragraph(f_text, style["Normal"])
    161         data_right.append([f_label,f_text])
    162 
    163139    table_left = Table(data_left,style=SLIP_STYLE)
    164140    table_right = Table(data_right,style=SLIP_STYLE, colWidths=[5*cm, 6*cm])
     
    189165    return table
    190166
    191 def get_signature_table(signatures, lang='en'):
    192     """Return a reportlab table containing signature fields (with date).
    193     """
    194     style = getSampleStyleSheet()
    195     space_width = 0.4  # width in cm of space between signatures
    196     table_width = 16.0 # supposed width of signature table in cms
    197     # width of signature cells in cm...
    198     sig_col_width = table_width - ((len(signatures) - 1) * space_width)
    199     sig_col_width = sig_col_width / len(signatures)
    200     data = []
    201     col_widths = [] # widths of columns
    202 
    203     sig_style = [
    204         ('VALIGN',(0,-1),(-1,-1),'TOP'),
    205         ('FONT', (0,0), (-1,-1), 'Helvetica-BoldOblique', 12),
    206         ('BOTTOMPADDING', (0,0), (-1,0), 36),
    207         ('TOPPADDING', (0,-1), (-1,-1), 0),
    208         ]
    209     for num, elem in enumerate(signatures):
    210         # draw a line above each signature cell (not: empty cells in between)
    211         sig_style.append(
    212             ('LINEABOVE', (num*2,-1), (num*2, -1), 1, colors.black))
    213 
    214     row = []
    215     for signature in signatures:
    216         row.append(trans(_('Date:'), lang))
    217         row.append('')
    218         if len(signatures) > 1:
    219             col_widths.extend([sig_col_width*cm, space_width*cm])
    220         else:
    221             col_widths.extend([sig_col_width/2*cm, sig_col_width/2*cm])
    222             row.append('') # empty spaceholder on right
    223     data.append(row[:-1])
    224     data.extend(([''],)*3) # insert 3 empty rows...
    225     row = []
    226     for signature in signatures:
    227         row.append(Paragraph(trans(signature, lang), style["Normal"]))
    228         row.append('')
    229     data.append(row[:-1])
    230     table = Table(data, style=sig_style, repeatRows=len(data),
    231                   colWidths=col_widths)
    232     return table
    233 
    234167def docs_as_flowables(view, lang='en'):
    235168    """Create reportlab flowables out of scanned docs.
     
    257190            if img_path is None:
    258191                pass
    259             elif not img_path[-4:] in ('.jpg', '.JPG'):
     192            elif not img_path.endswith('.jpg'):
    260193                # reportlab requires jpg images, I think.
    261                 f_text = Paragraph('%s (not displayable)' % (
     194                f_text = Paragraph('%s (Not displayable)' % (
    262195                    viewlet.title,), ENTRY1_STYLE)
    263196            else:
     
    269202    return data
    270203
     204def insert_footer(pdf,width,style,text=None, number_of_pages=1):
     205      """Render the whole footer frame.
     206      """
     207      story = []
     208      frame_footer = Frame(1*cm,0,width-(2*cm),1*cm)
     209      tz = getUtility(IKofaUtils).tzinfo
     210      timestamp = now(tz).strftime("%d/%m/%Y %H:%M:%S %Z")
     211      left_text = '<font size=10>%s</font>' % timestamp
     212      story.append(Paragraph(left_text, style["Normal"]))
     213      frame_footer.addFromList(story,pdf)
     214      story = []
     215      frame_footer = Frame(1*cm,0,width-(2*cm),1*cm)
     216      portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
     217      right_text = translate(_('<font size=10>${a} Page ${b} of ${c}</font>',
     218          mapping = {'a':text, 'b':pdf.getPageNumber(), 'c':number_of_pages}),
     219          'waeup.kofa', target_language=portal_language)
     220      story.append(Paragraph(right_text, style["Right"]))
     221      frame_footer.addFromList(story,pdf)
     222
    271223class StudentsUtils(grok.GlobalUtility):
    272224    """A collection of methods subject to customization.
     
    275227
    276228    def getReturningData(self, student):
    277         """ Define what happens after school fee payment
     229        """ This method defines what happens after school fee payment
    278230        depending on the student's senate verdict.
    279231
     
    286238
    287239    def setReturningData(self, student):
    288         """ Define what happens after school fee payment
    289         depending on the student's senate verdict.
    290 
    291         This method folllows the same algorithm as getReturningData but
    292         it also sets the new values.
     240        """ This method defines what happens after school fee payment
     241        depending on the student's senate verdict. It folllows
     242        the same algorithm as getReturningData but it also sets the new
     243        values
     244
     245        In the base configuration current level is always increased
     246        by 100 no matter which verdict has been assigned.
    293247        """
    294248        new_session, new_level = self.getReturningData(student)
     
    296250        student['studycourse'].current_session = new_session
    297251        verdict = student['studycourse'].current_verdict
    298         student['studycourse'].current_verdict = '0'
     252        student['studycourse'].current_verdict = 'NY'
    299253        student['studycourse'].previous_verdict = verdict
    300254        return
    301255
    302     def setPaymentDetails(self, category, student,
    303             previous_session, previous_level):
     256    def setPaymentDetails(self, category, student):
    304257        """Create Payment object and set the payment data of a student for
    305258        the payment category specified.
    306259
    307260        """
     261        details = {}
    308262        p_item = u''
    309263        amount = 0.0
    310         if previous_session:
    311             p_session = previous_session
    312             p_level = previous_level
    313             p_current = False
    314         else:
    315             p_session = student['studycourse'].current_session
    316             p_level = student['studycourse'].current_level
    317             p_current = True
     264        error = u''
     265        p_session = student['studycourse'].current_session
     266        p_level = student['studycourse'].current_level
    318267        session = str(p_session)
    319268        try:
     
    327276            except (AttributeError, TypeError):
    328277                return _('Study course data are incomplete.'), None
    329             if previous_session:
    330                 if previous_session < student['studycourse'].entry_session:
    331                     return _('The previous session must not fall below '
    332                              'your entry session.'), None
    333                 if previous_session > student['studycourse'].current_session - 1:
    334                     return _('This is not a previous session.'), None
    335                 if previous_level == 100:
    336                     amount = getattr(certificate, 'school_fee_1', 0.0)
    337                 else:
    338                     amount = getattr(certificate, 'school_fee_2', 0.0)
    339             else:
    340                 if student.state == CLEARED:
    341                     amount = getattr(certificate, 'school_fee_1', 0.0)
    342                 elif student.state == RETURNING:
    343                     # In case of returning school fee payment the payment session
    344                     # and level contain the values of the session the student
    345                     # has paid for.
    346                     p_session, p_level = self.getReturningData(student)
    347                     amount = getattr(certificate, 'school_fee_2', 0.0)
    348                 elif student.is_postgrad and student.state == PAID:
    349                     # Returning postgraduate students also pay for the next session
    350                     # but their level always remains the same.
    351                     p_session += 1
    352                     amount = getattr(certificate, 'school_fee_2', 0.0)
     278            if student.state == CLEARED:
     279                amount = getattr(certificate, 'school_fee_1', 0.0)
     280            elif student.state == RETURNING:
     281                # In case of returning school fee payment the payment session
     282                # and level contain the values of the session the student
     283                # has paid for.
     284                p_session, p_level = self.getReturningData(student)
     285                amount = getattr(certificate, 'school_fee_2', 0.0)
     286            elif student.is_postgrad and student.state == PAID:
     287                # Returning postgraduate students also pay for the next session
     288                # but their level always remains the same.
     289                p_session += 1
     290                amount = getattr(certificate, 'school_fee_2', 0.0)
    353291        elif category == 'clearance':
    354             try:
    355                 p_item = student['studycourse'].certificate.code
    356             except (AttributeError, TypeError):
    357                 return _('Study course data are incomplete.'), None
     292            p_item = student['studycourse'].certificate.code
    358293            amount = academic_session.clearance_fee
    359294        elif category == 'bed_allocation':
     
    361296            amount = academic_session.booking_fee
    362297        if amount in (0.0, None):
    363             return _('Amount could not be determined.' +
    364                      ' Would you like to pay for a previous session?'), None
     298            return _(u'Amount could not be determined.'), None
    365299        for key in student['payments'].keys():
    366300            ticket = student['payments'][key]
     
    369303               ticket.p_item == p_item and \
    370304               ticket.p_session == p_session:
    371                   return _('This type of payment has already been made.' +
    372                            ' Would you like to pay for a previous session?'), None
     305                  return _('This type of payment has already been made.'), None
    373306        payment = createObject(u'waeup.StudentOnlinePayment')
    374         timestamp = ("%d" % int(time()*10000))[1:]
     307        timestamp = "%d" % int(time()*1000)
    375308        payment.p_id = "p%s" % timestamp
    376309        payment.p_category = category
     
    378311        payment.p_session = p_session
    379312        payment.p_level = p_level
    380         payment.p_current = p_current
    381313        payment.amount_auth = amount
    382314        return None, payment
     
    398330        entry_session = studycourse.entry_session
    399331        current_level = studycourse.current_level
    400         if None in (entry_session, current_level, certificate):
    401             return d
     332        if not (entry_session and current_level and certificate):
     333            return
    402334        end_level = certificate.end_level
    403         if current_level == 10:
    404             bt = 'pr'
    405         elif entry_session == grok.getSite()['hostels'].accommodation_session:
     335        if entry_session == grok.getSite()['hostels'].accommodation_session:
    406336            bt = 'fr'
    407337        elif current_level >= end_level:
     
    425355        return available_beds[0]
    426356
    427     def renderPDFAdmissionLetter(self, view, student=None):
    428         """Render pdf admission letter.
    429         """
    430         # XXX: we have to fix the import problems here.
    431         from waeup.kofa.browser.interfaces import IPDFCreator
    432         from waeup.kofa.browser.pdf import format_html, NOTE_STYLE
    433         if student is None:
    434             return
    435         style = getSampleStyleSheet()
    436         creator = getUtility(IPDFCreator)
    437         data = []
    438         doc_title = view.label
    439         author = '%s (%s)' % (view.request.principal.title,
    440                               view.request.principal.id)
    441         footer_text = view.label
    442         if getattr(student, 'student_id', None) is not None:
    443             footer_text = "%s - %s - " % (student.student_id, footer_text)
    444 
    445         # Admission text
    446         portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
    447         inst_name = grok.getSite()['configuration'].name
    448         text = trans(_(
    449             'This is to inform you that you have been provisionally'
    450             ' admitted into ${a} as follows:', mapping = {'a': inst_name}),
    451             portal_language)
    452         html = format_html(text)
    453         data.append(Paragraph(html, NOTE_STYLE))
    454         data.append(Spacer(1, 20))
    455 
    456         # Student data
    457         data.append(render_student_data(view))
    458 
    459         # Insert history
    460         data.append(Spacer(1, 20))
    461         datelist = student.history.messages[0].split()[0].split('-')
    462         creation_date = u'%s/%s/%s' % (datelist[2], datelist[1], datelist[0])
    463         text = trans(_(
    464             'Your Kofa student record was created on ${a}.',
    465             mapping = {'a': creation_date}),
    466             portal_language)
    467         html = format_html(text)
    468         data.append(Paragraph(html, NOTE_STYLE))
    469 
    470         # Create pdf stream
    471         view.response.setHeader(
    472             'Content-Type', 'application/pdf')
    473         pdf_stream = creator.create_pdf(
    474             data, None, doc_title, author=author, footer=footer_text,
    475             note=None)
    476         return pdf_stream
    477 
    478357    def renderPDF(self, view, filename='slip.pdf', student=None,
    479358                  studentview=None, tableheader=None, tabledata=None,
    480                   note=None, signatures=None):
     359                  note=None):
    481360        """Render pdf slips for various pages.
    482361        """
     
    494373            footer_text = "%s - %s - " % (student.student_id, footer_text)
    495374
    496         # Insert history
    497         if not filename.startswith('payment'):
    498             data.extend(creator.fromStringList(student.history.messages))
    499 
    500375        # Insert student data table
    501376        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
     
    506381
    507382        # Insert widgets
    508         if view.form_fields:
    509             data.append(Paragraph(view.title, style["Heading3"]))
    510             portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
    511             separators = getattr(self, 'SEPARATORS_DICT', {})
    512             table = creator.getWidgetsTable(
    513                 view.form_fields, view.context, None, lang=portal_language,
    514                 separators=separators)
    515             data.append(table)
     383        data.append(Paragraph(view.title, style["Heading3"]))
     384        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
     385        separators = getattr(self, 'SEPARATORS_DICT', {})
     386        table = creator.getWidgetsTable(
     387            view.form_fields, view.context, None, lang=portal_language,
     388            separators=separators)
     389        data.append(table)
    516390
    517391        # Insert scanned docs
     
    525399            contenttable = render_table_data(tableheader,tabledata)
    526400            data.append(contenttable)
    527 
    528         # Insert signatures
    529         if signatures:
    530             data.append(Spacer(1, 20))
    531             signaturetable = get_signature_table(signatures)
    532             data.append(signaturetable)
    533401
    534402        view.response.setHeader(
     
    544412
    545413    VERDICTS_DICT = {
    546         '0': _('(not yet)'),
     414        'NY': _('(not yet)'),
    547415        'A': 'Successful student',
    548416        'B': 'Student with carryover courses',
Note: See TracChangeset for help on using the changeset viewer.