source: main/waeup.kofa/trunk/src/waeup/kofa/applicants/pdf.py @ 8050

Last change on this file since 8050 was 8050, checked in by Henrik Bettermann, 12 years ago

Change column widths.

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