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

Last change on this file since 7392 was 7390, checked in by uli, 13 years ago

Put PDF-related stuff into own module for applicants.

File size: 7.1 KB
RevLine 
[7390]1##
2## pdf.py
3## Login : <uli@pu.smp.net>
4## Started on  Mon Dec 19 09:30:43 2011 Uli Fouquet
5## $Id$
6##
7## Copyright (C) 2011 Uli Fouquet
8## This program is free software; you can redistribute it and/or modify
9## it under the terms of the GNU General Public License as published by
10## the Free Software Foundation; either version 2 of the License, or
11## (at your option) any later version.
12##
13## This program is distributed in the hope that it will be useful,
14## but WITHOUT ANY WARRANTY; without even the implied warranty of
15## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16## GNU General Public License for more details.
17##
18## You should have received a copy of the GNU General Public License
19## along with this program; if not, write to the Free Software
20## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21##
22"""
23Generate PDF docs for applicants.
24"""
25import grok
26from datetime import datetime
27from reportlab.pdfgen import canvas
28from reportlab.lib.units import cm
29from reportlab.lib.pagesizes import A4
30from reportlab.lib.styles import getSampleStyleSheet
31from reportlab.platypus import Frame, Paragraph, Image, Table, Spacer
32from reportlab.platypus.tables import TableStyle
33from zope.component import getUtility
34from zope.formlib.form import setUpEditWidgets
35from zope.interface import Interface
36from zope.publisher.browser import TestRequest
37from waeup.sirp.applicants.interfaces import IApplicant
38from waeup.sirp.browser import DEFAULT_PASSPORT_IMAGE_PATH
39from waeup.sirp.interfaces import IExtFileStore, IPDF
40
41SLIP_STYLE = TableStyle(
42    [('VALIGN',(0,0),(-1,-1),'TOP')]
43    )
44
45
46class PDFApplicationSlip(grok.Adapter):
47
48    grok.context(IApplicant)
49    grok.implements(IPDF)
50    grok.name('application_slip')
51
52    form_fields =  grok.AutoFields(IApplicant).omit(
53        'locked', 'course_admitted')
54
55    @property
56    def title(self):
57        container_title = self.context.__parent__.title
58        return '%s Application Record %s' % (
59            container_title, self.context.application_number)
60
61    def _setUpWidgets(self):
62        """Setup simple display widgets.
63
64        Returns the list of widgets.
65        """
66        request = TestRequest()
67        return setUpEditWidgets(
68            self.form_fields, 'form', self.context, request, {},
69            for_display=True, ignore_request=True
70            )
71
72    def _getCourseAdmittedLink(self, view):
73        """Return link, title and code in html format to the certificate
74           admitted.
75        """
76        course_admitted = self.context.course_admitted
77        if view is not None and getattr(course_admitted, '__parent__',None):
78            url = view.url(course_admitted)
79            title = course_admitted.title
80            code = course_admitted.code
81            return '<a href="%s">%s - %s</a>' %(url,code,title)
82        return ''
83
84    def _addPassportImage(self, data):
85        """Add passport image to data stream.
86
87        If no image exists yet the default image is added.
88        """
89        img = getUtility(IExtFileStore).getFileByContext(self.context)
90        if img is None:
91            img = open(DEFAULT_PASSPORT_IMAGE_PATH, 'rb')
92        doc_img = Image(img.name, width=4*cm, height=3*cm, kind='bound')
93        data.append([doc_img])
94        data.append([Spacer(1, 18)])
95        return data
96
97    def _addDeptAndFaculty(self, data):
98        """If we have a valid course admitted, add dept. and faculty to data
99           stream.
100        """
101        style = getSampleStyleSheet()
102        course_admitted = self.context.course_admitted
103        dept = getattr(
104                getattr(course_admitted, '__parent__', None),
105                '__parent__', None)
106        if dept is None:
107            return data
108        f_label = '<font size=12>Department:</font>'
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
117        f_label = '<font size=12>Faculty:</font>'
118        f_text = '<font size=12>%s</font>' % faculty.longtitle()
119        f_label = Paragraph(f_label, style["Normal"])
120        f_text = Paragraph(f_text, style["Normal"])
121        data.append([f_label,f_text])
122        return data
123
124    def __call__(self, view=None):
125        """Return a PDF representation of the context applicant.
126
127        If no `view` is given, the course admitted field will be an
128        empty string and author will be set as ``'unknown'``.
129
130        If a `view` is given, author will be set as the calling
131        principal.
132        """
133        pdf = canvas.Canvas('application_slip.pdf',pagesize=A4)
134        pdf.setTitle(self.title)
135        pdf.setSubject('Application')
136        if view is None:
137            pdf.setAuthor('unknown')
138        if view is not None:
139            pdf.setAuthor('%s (%s)' % (view.request.principal.title,
140                                      view.request.principal.id))
141        pdf.setCreator('SIRP')
142        width, height = A4
143        style = getSampleStyleSheet()
144        pdf.line(1*cm,height-(1.8*cm),width-(1*cm),height-(1.8*cm))
145
146        story = []
147        frame_header = Frame(1*cm,1*cm,width-(1.7*cm),height-(1.7*cm))
148        header_title = getattr(grok.getSite(), 'name', u'Sample University')
149        story.append(Paragraph(header_title, style["Heading1"]))
150        frame_header.addFromList(story,pdf)
151
152        story = []
153        frame_body = Frame(1*cm,1*cm,width-(2*cm),height-(3.5*cm))
154        story.append(Paragraph(self.title, style["Heading2"]))
155        story.append(Spacer(1, 18))
156        for msg in self.context.history.messages:
157            f_msg = '<font face="Courier" size=10>%s</font>' % msg
158            story.append(Paragraph(f_msg, style["Normal"]))
159        story.append(Spacer(1, 24))
160
161        # Setup table data
162        data = []
163        # Insert passport photograph
164        data = self._addPassportImage(data)
165        # Render widget fields
166        widgets = self._setUpWidgets()
167        for widget in widgets: # self.widgets:
168            f_label = '<font size=12>%s</font>:' % widget.label.strip()
169            f_label = Paragraph(f_label, style["Normal"])
170            f_text = '<font size=12>%s</font>' % widget()
171            f_text = Paragraph(f_text, style["Normal"])
172            data.append([f_label,f_text])
173        f_label = '<font size=12>Admitted Course of Study:</font>'
174        f_text = '<font size=12>%s</font>' % (
175            self._getCourseAdmittedLink(view),)
176        f_label = Paragraph(f_label, style["Normal"])
177        f_text = Paragraph(f_text, style["Normal"])
178        data.append([f_label,f_text])
179
180        # Add dept. and faculty if applicable
181        data = self._addDeptAndFaculty(data)
182
183        # Create table
184        table = Table(data,style=SLIP_STYLE)
185        story.append(table)
186        frame_body.addFromList(story,pdf)
187
188        story = []
189        frame_footer = Frame(1*cm,0,width-(2*cm),1*cm)
190        timestamp = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
191        f_text = '<font size=10>%s</font>' % timestamp
192        story.append(Paragraph(f_text, style["Normal"]))
193        frame_footer.addFromList(story,pdf)
194        return pdf.getpdfdata()
Note: See TracBrowser for help on using the repository browser.