source: main/waeup.sirp/trunk/src/waeup/sirp/students/utils.py @ 7308

Last change on this file since 7308 was 7304, checked in by Henrik Bettermann, 13 years ago

Insert container content table on pdf slips. Use this automatic insertion for course ticket lists on ExportPDFCourseRegistrationSlipPages.

ToDo?: The table does not show up if there are too many lines and it thus doesn't fit on the page.

  • Property svn:keywords set to Id
File size: 10.4 KB
RevLine 
[7191]1## $Id: utils.py 7304 2011-12-07 08:53:50Z 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##
[6651]18"""General helper functions for the student section.
19"""
[7150]20import grok
[6662]21from random import SystemRandom as r
[7256]22from datetime import datetime
[7019]23from reportlab.pdfgen import canvas
24from reportlab.lib.units import cm
25from reportlab.lib.pagesizes import A4
26from reportlab.lib.styles import getSampleStyleSheet
27from reportlab.platypus import (Frame, Paragraph, Image,
28    Table, Spacer)
29from reportlab.platypus.tables import TableStyle
[7280]30from zope.component import getUtility
[7019]31from zope.formlib.form import setUpEditWidgets
[7280]32from waeup.sirp.interfaces import IExtFileStore
[7150]33from waeup.sirp.students.interfaces import IStudentsUtils
[6651]34
[7019]35SLIP_STYLE = TableStyle(
36    [('VALIGN',(0,0),(-1,-1),'TOP')]
37    )
38
[7304]39CONTENT_STYLE = TableStyle(
40    [('VALIGN',(0,0),(-1,-1),'TOP')]
41    )
42
[6749]43def generate_student_id(students,letter):
[6651]44    if letter == '?':
[6664]45        letter= r().choice('ABCDEFGHKLMNPQRSTUVWXY')
46    sid = u"%c%d" % (letter,r().randint(99999,1000000))
[6749]47    while sid in students.keys():
[6664]48        sid = u"%c%d" % (letter,r().randint(99999,1000000))
[6662]49    return sid
[6742]50
51def set_returning_data(student):
52    student['studycourse'].current_level += 100
53    student['studycourse'].current_session += 1
54    verdict = student['studycourse'].current_verdict
[6804]55    student['studycourse'].current_verdict = '0'
[6742]56    student['studycourse'].previous_verdict = verdict
57    return
[6876]58
[7186]59def set_up_widgets(view, ignore_request=False):
[7019]60    view.adapters = {}
61    view.widgets = setUpEditWidgets(
62        view.form_fields, view.prefix, view.context, view.request,
63        adapters=view.adapters, for_display=True,
64        ignore_request=ignore_request
65        )
66
[7145]67def render_student_data(student, studentview):
[7186]68    set_up_widgets(studentview, ignore_request=True)
[7019]69    data = []
70    style = getSampleStyleSheet()
[7280]71    img = getUtility(IExtFileStore).getFileByContext(
72        studentview.context, attr='passport.jpg')
73    if img is None:
74        from waeup.sirp.browser import DEFAULT_PASSPORT_IMAGE_PATH
75        img = open(DEFAULT_PASSPORT_IMAGE_PATH, 'rb')
76    doc_img = Image(img.name, width=4*cm, height=3*cm, kind='bound')
77    data.append([doc_img])
78    data.append([Spacer(1, 12)])
[7019]79    for widget in studentview.widgets:
80        if widget.name == 'form.adm_code':
81            continue
[7304]82        f_label = '<font size=12>%s</font>:' % (
83            widget.label.strip())
[7019]84        f_label = Paragraph(f_label, style["Normal"])
85        f_text = '<font size=12>%s</font>' % widget()
86        f_text = Paragraph(f_text, style["Normal"])
87        data.append([f_label,f_text])
88    table = Table(data,style=SLIP_STYLE)
89    return table
90
[7304]91def render_table_data(tableheader,tabledata):
92    data = []
93    data.append([Spacer(1, 12)])
94    line = []
95    style = getSampleStyleSheet()
96    for element in tableheader:
97        field = '<strong><font size=10>%s</font></strong>' % element[0]
98        field = Paragraph(field, style["BodyText"])
99        line.append(field)
100    data.append(line)
101    for ticket in tabledata:
102        line = []
103        for element in tableheader:
104              fieldcontent = getattr(ticket,element[1],u' ')
105              field = '<font size=10>%s</font>' % fieldcontent
106              field = Paragraph(field, style["BodyText"])
107              line.append(field)
108        data.append(line)
109    # ToDo: The table does not show up if there are too many line
110    # and it thus doesn't fit on the page
111    table = Table(data,splitByRow=True,style=CONTENT_STYLE)
112    return table
113
[7150]114class StudentsUtils(grok.GlobalUtility):
115    """A collection of methods subject to customization.
116    """
117    grok.implements(IStudentsUtils)
[7019]118
[7186]119    def getPaymentDetails(self,category, student):
[7150]120        d = {}
121        d['p_item'] = u''
122        d['amount'] = 0
123        d['error'] = u''
124        d['p_session'] = student['studycourse'].current_session
125        session = str(d['p_session'])
126        try:
127            academic_session = grok.getSite()['configuration'][session]
128        except KeyError:
129            d['error'] = u'Session configuration object is not available.'
130            return d
131        d['surcharge_1'] = academic_session.surcharge_1
132        d['surcharge_2'] = academic_session.surcharge_2
133        d['surcharge_3'] = academic_session.surcharge_3
134        if category == 'schoolfee':
135            d['amount'] = academic_session.school_fee_base
136            d['p_item'] = student['studycourse'].certificate.code
137        elif category == 'clearance':
138            d['p_item'] = student['studycourse'].certificate.code
139            d['amount'] = academic_session.clearance_fee
140        elif category == 'bed_allocation':
[7186]141            d['p_item'] = self.getAccommodationDetails(student)['bt']
[7150]142            d['amount'] = academic_session.booking_fee
143        return d
[7019]144
[7186]145    def getAccommodationDetails(self, student):
[7150]146        d = {}
147        d['error'] = u''
148        site_confoguration = grok.getSite()['configuration']
149        d['booking_session'] = site_confoguration.accommodation_session
150        d['allowed_states'] = site_confoguration.accommodation_states
151        # Determine bed type
152        studycourse = student['studycourse']
153        entry_session = studycourse.entry_session
154        current_level = studycourse.current_level
155        end_level = studycourse.certificate.end_level
156        if entry_session == grok.getSite()['configuration'].accommodation_session:
157            bt = 'fr'
158        elif current_level >= end_level:
159            bt = 'fi'
160        else:
161            bt = 're'
162        if student.sex == 'f':
163            sex = 'female'
164        else:
165            sex = 'male'
166        special_handling = 'regular'
167        d['bt'] = u'%s_%s_%s' % (special_handling,sex,bt)
168        return d
[7019]169
[7150]170    # In the standard configuration we select the first bed found,
171    # but can also randomize the selection if we like.
[7186]172    def selectBed(self, available_beds):
[7150]173        return available_beds[0]
174
[7186]175    def renderPDF(self, view, subject='', filename='slip.pdf',
[7304]176        student=None, studentview=None, tableheader=None, tabledata=None):
[7150]177        # (0,0),(-1,-1) = whole table
178        # (0,0),(0,-1) = first column
179        # (-1,0),(-1,-1) = last column
180        # (0,0),(-1,0) = first row
181        # (0,-1),(-1,-1) = last row
182
183        pdf = canvas.Canvas(filename,pagesize=A4)
184        pdf.setTitle(view.label)
185        pdf.setSubject(subject)
186        pdf.setAuthor('%s (%s)' % (view.request.principal.title,
187            view.request.principal.id))
188        pdf.setCreator('WAeUP SIRP')
189        width, height = A4
190        style = getSampleStyleSheet()
191        pdf.line(1*cm,height-(1.8*cm),width-(1*cm),height-(1.8*cm))
192
193        story = []
194        frame_header = Frame(1*cm,1*cm,width-(1.7*cm),height-(1.7*cm))
195        header_title = getattr(grok.getSite(), 'name', u'Sample University')
196        story.append(Paragraph(header_title, style["Heading1"]))
197        frame_header.addFromList(story,pdf)
198
199        story = []
200        frame_body = Frame(1*cm,1*cm,width-(2*cm),height-(3.5*cm))
201        story.append(Paragraph(view.label, style["Heading2"]))
[7304]202
203        # Insert student data table
[7150]204        if student:
[7280]205            story.append(Spacer(1, 12))
[7150]206            studenttable = render_student_data(student, studentview)
207            story.append(studenttable)
[7304]208
[7280]209        story.append(Spacer(1, 12))
[7186]210        set_up_widgets(view)
[7150]211        data = []
212        for widget in view.widgets:
213            f_label = '<font size=12>%s</font>:' % widget.label.strip()
214            f_label = Paragraph(f_label, style["Normal"])
215            f_text = '<font size=12>%s</font>' % widget()
216            f_text = Paragraph(f_text, style["Normal"])
217            data.append([f_label,f_text])
[7280]218        # First, import browser components locally
219        # to avoid circular import
220        from waeup.sirp.students.viewlets import FileManager
221        from waeup.sirp.browser import DEFAULT_IMAGE_PATH
222        fm = FileManager(view.context, view.request, view)
223        # Collect viewlets
224        fm.update()
225        # Insert list of scanned documents
226        for viewlet in fm.viewlets:
227            f_label = '<font size=12>%s</font>' % viewlet.label
228            f_label = Paragraph(f_label, style["Normal"])
229            if viewlet.template.__grok_name__ == 'imagedisplay':
230                # In case we define FileDisplay viewlets with
231                # an imagedisplay template in the customization package
232                img = getUtility(IExtFileStore).getFileByContext(
233                    view.context, attr=viewlet.download_name)
234                if img is None:
235                    img = open(DEFAULT_IMAGE_PATH, 'rb')
236                doc_img = Image(img.name, width=2*cm, height=1*cm, kind='bound')
237                data.append([f_label,doc_img])
238            else:
239                f_text = '<font size=12>%s</font>' % viewlet.title
240                f_text = Paragraph(f_text, style["Normal"])
241                data.append([f_label,f_text])
[7150]242        table = Table(data,style=SLIP_STYLE)
243        story.append(table)
[7280]244        try:
245            frame_body.addFromList(story,pdf)
246        except IOError:
247            view.flash('Error in image file.')
248            return view.redirect(view.url(view.context))
[7304]249
250        # Insert content table
251        if tabledata and tableheader:
252            story = []
253            story.append(Spacer(1, 12))
254            contenttable = render_table_data(tableheader,tabledata)
255            story.append(contenttable)
256            #import pdb; pdb.set_trace()
257            frame_body.addFromList(story,pdf)
258
[7150]259        story = []
260        frame_footer = Frame(1*cm,0,width-(2*cm),1*cm)
261        timestamp = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
262        f_text = '<font size=10>%s</font>' % timestamp
263        story.append(Paragraph(f_text, style["Normal"]))
264        frame_footer.addFromList(story,pdf)
265        view.response.setHeader(
266            'Content-Type', 'application/pdf')
267        return pdf.getpdfdata()
Note: See TracBrowser for help on using the repository browser.