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

Last change on this file since 8069 was 8059, checked in by uli, 13 years ago

Improve pdf generation: a global pdf generator, watermarks and more.

  • Property svn:keywords set to Id
File size: 9.3 KB
RevLine 
[7415]1## $Id: pdf.py 8059 2012-04-07 08:15:16Z uli $
[7390]2##
[7398]3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
[7390]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
[8059]22from reportlab.lib.styles import getSampleStyleSheet
[7390]23from reportlab.lib.units import cm
[8059]24from reportlab.platypus import Paragraph, Image, Table, Spacer
[7390]25from zope.component import getUtility
26from zope.formlib.form import setUpEditWidgets
[8059]27from zope.i18n import translate
[7390]28from zope.publisher.browser import TestRequest
[8046]29from waeup.kofa.applicants.interfaces import IApplicant, IApplicantsUtils
[7811]30from waeup.kofa.browser import DEFAULT_PASSPORT_IMAGE_PATH
[8059]31from waeup.kofa.browser.interfaces import IPDFCreator
[7819]32from waeup.kofa.interfaces import IExtFileStore, IPDF, IKofaUtils
[7811]33from waeup.kofa.interfaces import MessageFactory as _
[8059]34from waeup.kofa.widgets.datewidget import FriendlyDateDisplayWidget
[7390]35
36class PDFApplicationSlip(grok.Adapter):
[8059]37    """Create a PDF application slip for applicants.
38    """
39    # XXX: Many things in here are reusable. We might want to split
40    # things. Possibly move parts to IPDFCreator?
[7390]41    grok.context(IApplicant)
42    grok.implements(IPDF)
43    grok.name('application_slip')
44
45    form_fields =  grok.AutoFields(IApplicant).omit(
46        'locked', 'course_admitted')
[8013]47    form_fields['date_of_birth'].custom_widget = FriendlyDateDisplayWidget('le')
[7390]48
49    @property
50    def title(self):
51        container_title = self.context.__parent__.title
[7819]52        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
[7714]53        ar_translation = translate(_('Application Record'),
[7811]54            'waeup.kofa', target_language=portal_language)
[7714]55        return '%s - %s %s' % (container_title,
56            ar_translation, self.context.application_number)
[7390]57
58    def _setUpWidgets(self):
59        """Setup simple display widgets.
60
61        Returns the list of widgets.
62        """
63        request = TestRequest()
64        return setUpEditWidgets(
65            self.form_fields, 'form', self.context, request, {},
66            for_display=True, ignore_request=True
67            )
68
69    def _getCourseAdmittedLink(self, view):
70        """Return link, title and code in html format to the certificate
71           admitted.
72        """
73        course_admitted = self.context.course_admitted
74        if view is not None and getattr(course_admitted, '__parent__',None):
75            url = view.url(course_admitted)
76            title = course_admitted.title
77            code = course_admitted.code
78            return '<a href="%s">%s - %s</a>' %(url,code,title)
79        return ''
80
81    def _addPassportImage(self, data):
82        """Add passport image to data stream.
83
84        If no image exists yet the default image is added.
85        """
86        img = getUtility(IExtFileStore).getFileByContext(self.context)
87        if img is None:
88            img = open(DEFAULT_PASSPORT_IMAGE_PATH, 'rb')
89        doc_img = Image(img.name, width=4*cm, height=3*cm, kind='bound')
90        data.append([doc_img])
91        data.append([Spacer(1, 18)])
92        return data
93
94    def _addDeptAndFaculty(self, data):
95        """If we have a valid course admitted, add dept. and faculty to data
96           stream.
97        """
98        style = getSampleStyleSheet()
99        course_admitted = self.context.course_admitted
100        dept = getattr(
101                getattr(course_admitted, '__parent__', None),
102                '__parent__', None)
103        if dept is None:
104            return data
[7819]105        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
[7714]106        dp_translation = translate(_('Department:'),
[7811]107            'waeup.kofa', target_language=portal_language)
[7714]108        f_label = '<font size=12>%s</font>' % dp_translation
[7390]109        f_text = '<font size=12>%s</font>' % dept.longtitle()
110        f_label = Paragraph(f_label, style["Normal"])
111        f_text = Paragraph(f_text, style["Normal"])
112        data.append([f_label,f_text])
113
114        faculty = getattr(dept, '__parent__', None)
115        if faculty is None:
116            return data
[7714]117        fc_translation = translate(_('Faculty:'),
[7811]118            'waeup.kofa', target_language=portal_language)
[7714]119        f_label = '<font size=12>%s</font>' % fc_translation
[7390]120        f_text = '<font size=12>%s</font>' % faculty.longtitle()
121        f_label = Paragraph(f_label, style["Normal"])
122        f_text = Paragraph(f_text, style["Normal"])
123        data.append([f_label,f_text])
124        return data
125
[8059]126    def _getWidgetsTable(self, view):
127        """Return a reportlab table buildt of widgets.
[7390]128        """
129        style = getSampleStyleSheet()
[8059]130        table_data = []
131        table_style = [('LEFTPADDING', (0,0), (0,-1), 0),
132                       ('VALIGN', (0,0), (-1,-1), 'TOP'),
133                       ]
134        row_num = 0
[7390]135        widgets = self._setUpWidgets()
[7819]136        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
[8059]137        for widget in widgets:
[8046]138            separators = getUtility(IApplicantsUtils).SEPARATORS_DICT
139            if separators and separators.get(widget.name):
140                f_headline = ('<font size=12><strong>%s</strong></font>'
141                    % translate(separators[widget.name], 'waeup.kofa',
142                    target_language=portal_language))
143                f_headline = Paragraph(f_headline, style["Normal"])
[8059]144                table_data.append([f_headline ])
145                table_style.append(('SPAN', (0,row_num), (-1,row_num)),)
146                table_style.append(
147                    ('TOPPADDING', (0,row_num), (-1,row_num), 12),)
148                row_num += 1
[7714]149            f_label = '<font size=12>%s</font>:' % translate(
[7811]150                widget.label.strip(), 'waeup.kofa',
[7714]151                target_language=portal_language)
[7390]152            f_label = Paragraph(f_label, style["Normal"])
153            f_text = '<font size=12>%s</font>' % widget()
[7804]154            # Add br tag if widgets contain div tags
155            # which are not supported by reportlab
[7835]156            f_text = f_text.replace('</div>', '</div><br />')
157            f_text = f_text.replace('\n', '')
[7390]158            f_text = Paragraph(f_text, style["Normal"])
[8059]159            table_data.append([f_label,f_text])
160            row_num += 1
[7714]161        adm_translation = translate(_('Admitted Course of Study:'),
[7811]162                'waeup.kofa', target_language=portal_language)
[7714]163        f_label = '<font size=12>%s</font>' % adm_translation
[7390]164        f_text = '<font size=12>%s</font>' % (
165            self._getCourseAdmittedLink(view),)
166        f_label = Paragraph(f_label, style["Normal"])
167        f_text = Paragraph(f_text, style["Normal"])
[8059]168        table_data.append([f_label,f_text])
169        row_num += 1
[7390]170
171        # Add dept. and faculty if applicable
[8059]172        table_data = self._addDeptAndFaculty(table_data)
[7390]173
174        # Create table
[8059]175        table = Table(table_data,style=table_style)
176        table.hAlign = 'LEFT'
177        return table
[7409]178
[8059]179    def _addComments(self, data):
180        style = getSampleStyleSheet()
[7409]181        if self.context.state == 'created':
[7714]182            comment1 = _(
[7409]183                '<font size=10>Proceed to the login page of the portal' +
184                ' and enter your new credentials:' +
[7714]185                ' user name= ${a}, password = ${b}.</font>', mapping = {
[8059]186                    'a':self.context.student_id,
187                    'b':self.context.application_number}
[7409]188                )
[7714]189            comment2 = _(
[7409]190                '<font size=10>Change your password when you have ' +
191                ' logged in.</font>'
192                )
193            comment1 = Paragraph(comment1, style["Normal"])
194            comment2 = Paragraph(comment2, style["Normal"])
[8059]195            data.extend([Spacer(1, 18), comment1, comment2])
196        return data
[7409]197
[8059]198    def __call__(self, view=None):
199        """Return a PDF representation of the context applicant.
[7390]200
[8059]201        If no `view` is given, the course admitted field will be an
202        empty string and author will be set as ``'unknown'``.
203
204        If a `view` is given, author will be set as the calling
205        principal.
206        """
207        doc_title = self.title.replace('-', '\n')
208        style = getSampleStyleSheet()
209        data = []
210
211        # append history
212        for msg in self.context.history.messages:
213            f_msg = '<font face="Courier" size=10>%s</font>' % msg
214            data.append(Paragraph(f_msg, style["Normal"]))
215        data.append(Spacer(1, 20))
216
217        # append photograph
218        img_path = getattr(
219            getUtility(IExtFileStore).getFileByContext(self.context),
220            'name', DEFAULT_PASSPORT_IMAGE_PATH)
221        doc_img = Image(img_path, width=4*cm, height=3*cm, kind='bound')
222        doc_img.hAlign='LEFT'
223        data.append(doc_img)
224
225        # append widgets
226        data.append(self._getWidgetsTable(view))
227
228        # append comments
229        data = self._addComments(data)
230
231        creator = getUtility(IPDFCreator)
232        return creator.create_pdf(data, None, doc_title)
Note: See TracBrowser for help on using the repository browser.