source: main/waeup.sirp/trunk/src/waeup/sirp/applicants/pdf.py @ 9988

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

Insert a br tag if widgets contain div tags which are not supported by reportlab.

  • Property svn:keywords set to Id
File size: 8.8 KB
Line 
1## $Id: pdf.py 7804 2012-03-08 16:30:34Z 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##
18"""
19Generate PDF docs for applicants.
20"""
21import grok
22from datetime import datetime
23from zope.component import getUtility
24from zope.i18n import translate
25from reportlab.pdfgen import canvas
26from reportlab.lib.units import cm
27from reportlab.lib.pagesizes import A4
28from reportlab.lib.styles import getSampleStyleSheet
29from reportlab.platypus import Frame, Paragraph, Image, Table, Spacer
30from reportlab.platypus.tables import TableStyle
31from zope.component import getUtility
32from zope.formlib.form import setUpEditWidgets
33from zope.publisher.browser import TestRequest
34from waeup.sirp.applicants.interfaces import IApplicant
35from waeup.sirp.browser import DEFAULT_PASSPORT_IMAGE_PATH
36from waeup.sirp.interfaces import IExtFileStore, IPDF, ISIRPUtils
37from waeup.sirp.interfaces import MessageFactory as _
38
39SLIP_STYLE = TableStyle(
40    [('VALIGN',(0,0),(-1,-1),'TOP')]
41    )
42
43
44class PDFApplicationSlip(grok.Adapter):
45
46    grok.context(IApplicant)
47    grok.implements(IPDF)
48    grok.name('application_slip')
49
50    form_fields =  grok.AutoFields(IApplicant).omit(
51        'locked', 'course_admitted')
52
53    @property
54    def title(self):
55        container_title = self.context.__parent__.title
56        portal_language = getUtility(ISIRPUtils).PORTAL_LANGUAGE
57        ar_translation = translate(_('Application Record'),
58            'waeup.sirp', target_language=portal_language)
59        return '%s - %s %s' % (container_title,
60            ar_translation, self.context.application_number)
61
62    def _setUpWidgets(self):
63        """Setup simple display widgets.
64
65        Returns the list of widgets.
66        """
67        request = TestRequest()
68        return setUpEditWidgets(
69            self.form_fields, 'form', self.context, request, {},
70            for_display=True, ignore_request=True
71            )
72
73    def _getCourseAdmittedLink(self, view):
74        """Return link, title and code in html format to the certificate
75           admitted.
76        """
77        course_admitted = self.context.course_admitted
78        if view is not None and getattr(course_admitted, '__parent__',None):
79            url = view.url(course_admitted)
80            title = course_admitted.title
81            code = course_admitted.code
82            return '<a href="%s">%s - %s</a>' %(url,code,title)
83        return ''
84
85    def _addPassportImage(self, data):
86        """Add passport image to data stream.
87
88        If no image exists yet the default image is added.
89        """
90        img = getUtility(IExtFileStore).getFileByContext(self.context)
91        if img is None:
92            img = open(DEFAULT_PASSPORT_IMAGE_PATH, 'rb')
93        doc_img = Image(img.name, width=4*cm, height=3*cm, kind='bound')
94        data.append([doc_img])
95        data.append([Spacer(1, 18)])
96        return data
97
98    def _addDeptAndFaculty(self, data):
99        """If we have a valid course admitted, add dept. and faculty to data
100           stream.
101        """
102        style = getSampleStyleSheet()
103        course_admitted = self.context.course_admitted
104        dept = getattr(
105                getattr(course_admitted, '__parent__', None),
106                '__parent__', None)
107        if dept is None:
108            return data
109        portal_language = getUtility(ISIRPUtils).PORTAL_LANGUAGE
110        dp_translation = translate(_('Department:'),
111            'waeup.sirp', target_language=portal_language)
112        f_label = '<font size=12>%s</font>' % dp_translation
113        f_text = '<font size=12>%s</font>' % dept.longtitle()
114        f_label = Paragraph(f_label, style["Normal"])
115        f_text = Paragraph(f_text, style["Normal"])
116        data.append([f_label,f_text])
117
118        faculty = getattr(dept, '__parent__', None)
119        if faculty is None:
120            return data
121        fc_translation = translate(_('Faculty:'),
122            'waeup.sirp', target_language=portal_language)
123        f_label = '<font size=12>%s</font>' % fc_translation
124        f_text = '<font size=12>%s</font>' % faculty.longtitle()
125        f_label = Paragraph(f_label, style["Normal"])
126        f_text = Paragraph(f_text, style["Normal"])
127        data.append([f_label,f_text])
128        return data
129
130    def __call__(self, view=None):
131        """Return a PDF representation of the context applicant.
132
133        If no `view` is given, the course admitted field will be an
134        empty string and author will be set as ``'unknown'``.
135
136        If a `view` is given, author will be set as the calling
137        principal.
138        """
139        pdf = canvas.Canvas('application_slip.pdf',pagesize=A4)
140        pdf.setTitle(self.title)
141        pdf.setSubject('Application')
142        if view is None:
143            pdf.setAuthor('unknown')
144        if view is not None:
145            pdf.setAuthor('%s (%s)' % (view.request.principal.title,
146                view.request.principal.id))
147        pdf.setCreator('SIRP')
148        width, height = A4
149        style = getSampleStyleSheet()
150        pdf.line(1*cm,height-(1.8*cm),width-(1*cm),height-(1.8*cm))
151
152        story = []
153        frame_header = Frame(1*cm,1*cm,width-(1.7*cm),height-(1.7*cm))
154        header_title = getattr(grok.getSite(), 'name', u'Sample University')
155        story.append(Paragraph(header_title, style["Heading1"]))
156        frame_header.addFromList(story,pdf)
157
158        story = []
159        frame_body = Frame(1*cm,1*cm,width-(2*cm),height-(3.5*cm))
160        story.append(Paragraph(self.title, style["Heading2"]))
161        story.append(Spacer(1, 18))
162        for msg in self.context.history.messages:
163            f_msg = '<font face="Courier" size=10>%s</font>' % msg
164            story.append(Paragraph(f_msg, style["Normal"]))
165        story.append(Spacer(1, 24))
166
167        # Setup table data
168        data = []
169        # Insert passport photograph
170        data = self._addPassportImage(data)
171        # Render widget fields
172        widgets = self._setUpWidgets()
173        portal_language = getUtility(ISIRPUtils).PORTAL_LANGUAGE
174        for widget in widgets: # self.widgets:
175            f_label = '<font size=12>%s</font>:' % translate(
176                widget.label.strip(), 'waeup.sirp',
177                target_language=portal_language)
178            f_label = Paragraph(f_label, style["Normal"])
179            f_text = '<font size=12>%s</font>' % widget()
180            # Add br tag if widgets contain div tags
181            # which are not supported by reportlab
182            f_text = f_text.replace('</div>', '<br /></div>')
183            f_text = Paragraph(f_text, style["Normal"])
184            data.append([f_label,f_text])
185        adm_translation = translate(_('Admitted Course of Study:'),
186                'waeup.sirp', target_language=portal_language)
187        f_label = '<font size=12>%s</font>' % adm_translation
188        f_text = '<font size=12>%s</font>' % (
189            self._getCourseAdmittedLink(view),)
190        f_label = Paragraph(f_label, style["Normal"])
191        f_text = Paragraph(f_text, style["Normal"])
192        data.append([f_label,f_text])
193
194        # Add dept. and faculty if applicable
195        data = self._addDeptAndFaculty(data)
196
197        # Create table
198        table = Table(data,style=SLIP_STYLE)
199        story.append(table)
200
201        # Add some comments
202        if self.context.state == 'created':
203            comment1 = _(
204                '<font size=10>Proceed to the login page of the portal' +
205                ' and enter your new credentials:' +
206                ' user name= ${a}, password = ${b}.</font>', mapping = {
207                'a':self.context.student_id, 'b':self.context.application_number}
208                )
209            comment2 = _(
210                '<font size=10>Change your password when you have ' +
211                ' logged in.</font>'
212                )
213            comment1 = Paragraph(comment1, style["Normal"])
214            comment2 = Paragraph(comment2, style["Normal"])
215            story.append(Spacer(1, 18))
216            story.append(comment1)
217            story.append(comment2)
218
219        frame_body.addFromList(story,pdf)
220
221        story = []
222        frame_footer = Frame(1*cm,0,width-(2*cm),1*cm)
223        timestamp = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
224        f_text = '<font size=10>%s</font>' % timestamp
225        story.append(Paragraph(f_text, style["Normal"]))
226        frame_footer.addFromList(story,pdf)
227        return pdf.getpdfdata()
Note: See TracBrowser for help on using the repository browser.