source: main/waeup.kofa/branches/uli-py3/src/waeup/kofa/applicants/pdf.py @ 17341

Last change on this file since 17341 was 15587, checked in by Henrik Bettermann, 5 years ago

Do not print picture on application slip if application is without passport picture.

  • Property svn:keywords set to Id
File size: 9.0 KB
Line 
1## $Id: pdf.py 15587 2019-09-17 07:30:51Z 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 reportlab.platypus import Paragraph, Spacer, Table
23from reportlab.lib.units import cm
24from zope.component import getUtility
25from zope.i18n import translate
26from waeup.kofa.applicants.interfaces import IApplicant, IApplicantsUtils
27from waeup.kofa.browser import DEFAULT_PASSPORT_IMAGE_PATH
28from waeup.kofa.browser.interfaces import IPDFCreator
29from waeup.kofa.browser.pdf import SMALL_PARA_STYLE, ENTRY1_STYLE, get_qrcode
30from waeup.kofa.interfaces import IExtFileStore, IPDF, IKofaUtils
31from waeup.kofa.interfaces import MessageFactory as _
32from waeup.kofa.widgets.datewidget import FriendlyDateDisplayWidget
33
34SLIP_STYLE = [
35    ('VALIGN',(0,0),(-1,-1),'TOP'),
36    #('FONT', (0,0), (-1,-1), 'Helvetica', 11),
37    ]
38
39class PDFApplicationSlip(grok.Adapter):
40    """Create a PDF application slip for applicants.
41    """
42    # XXX: Many things in here are reusable. We might want to split
43    # things. Possibly move parts to IPDFCreator?
44    grok.context(IApplicant)
45    grok.implements(IPDF)
46    grok.name('application_slip')
47
48    form_fields =  grok.AutoFields(IApplicant).omit(
49        'locked', 'course_admitted', 'suspended',
50        )
51    form_fields['date_of_birth'].custom_widget = FriendlyDateDisplayWidget('le')
52    column_two_fields = ('applicant_id', 'reg_number',
53        'firstname', 'middlename', 'lastname')
54    two_columns_design_fields = []
55
56    @property
57    def note(self):
58        note = getattr(self.context.__parent__, 'application_slip_notice', None)
59        if note:
60            return '<br /><br />' + note
61        return
62
63    @property
64    def target(self):
65        return getattr(self.context.__parent__, 'prefix', None)
66
67    @property
68    def title(self):
69        container_title = self.context.__parent__.title
70        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
71        ar_translation = translate(_('Application Record'),
72            'waeup.kofa', target_language=portal_language)
73        return '%s - %s %s' % (container_title,
74            ar_translation, self.context.application_number)
75
76    def _getCourseAdmittedLink(self, view):
77        """Return link, title and code in html format to the certificate
78           admitted.
79        """
80        course_admitted = self.context.course_admitted
81        if view is not None and getattr(course_admitted, '__parent__',None):
82            url = view.url(course_admitted)
83            title = course_admitted.title
84            code = course_admitted.code
85            return '<a href="%s">%s - %s</a>' %(url,code,title)
86        return ''
87
88    def _getDeptAndFaculty(self):
89        """Return long titles of department and faculty.
90
91        Returns a list [department_title, faculty_title]
92
93        If the context applicant has no course admitted or dept. and
94        faculty cannot be determined, ``None`` is returned.
95        """
96        course_admitted = self.context.course_admitted
97        dept = getattr(
98                getattr(course_admitted, '__parent__', None),
99                '__parent__', None)
100        faculty = getattr(dept, '__parent__', None)
101        return [x is not None and x.longtitle or x for x in dept, faculty]
102
103    def _addLoginInformation(self):
104        if self.context.state == 'created':
105            comment = translate(_(
106                '\n Proceed to the login page of the portal' +
107                ' and enter your new credentials:' +
108                ' user name= ${a}, password = ${b}. ' +
109                'Change your password when you have logged in.',
110                mapping = {
111                    'a':self.context.student_id,
112                    'b':self.context.application_number}
113                ))
114            return comment
115        return
116
117    def _getPDFCreator(self):
118        return getUtility(IPDFCreator)
119
120    def __call__(self, view=None, note=None):
121        """Return a PDF representation of the context applicant.
122
123        If no `view` is given, the course admitted field will be an
124        empty string and author will be set as ``'unknown'``.
125
126        If a `view` is given, author will be set as the calling
127        principal.
128        """
129        doc_title = '\n'.join([x.strip() for x in self.title.split(' - ')])
130        data = []
131        topMargin = 1.5
132        if len(self.title.split(' - ')) > 2:
133            topMargin = 1.8
134        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
135        separators = getUtility(IApplicantsUtils).SEPARATORS_DICT
136        creator = self._getPDFCreator()
137
138        # append history
139        data.extend(creator.fromStringList(self.context.history.messages))
140        data.append(Spacer(1, 5))
141
142        if self.context.__parent__.with_picture:
143
144            # create three-column header table
145            # append photograph to the left
146            img_path = getattr(
147                getUtility(IExtFileStore).getFileByContext(self.context),
148                'name', DEFAULT_PASSPORT_IMAGE_PATH)
149            data_left = [[creator.getImage(img_path)]]
150            table_left = Table(data_left,style=SLIP_STYLE)
151
152            # append base data table to the middle
153            fields = [
154                field for field in self.form_fields
155                    if field.__name__ in self.column_two_fields]
156            table_middle = creator.getWidgetsTable(
157                fields, self.context, None, lang=portal_language,
158                separators=None, colWidths=[5*cm, 4.5*cm])
159
160            # append QR code to the right
161            if view is not None:
162                url = view.url(self.context, 'application_slip.pdf')
163                data_right = [[get_qrcode(url, width=70.0)]]
164                table_right = Table(data_right,style=SLIP_STYLE)
165            else:
166                table_right = None
167
168            header_table = Table(
169                [[table_left, table_middle, table_right],],style=SLIP_STYLE)
170            data.append(header_table)
171
172        else:
173            fields = [
174                field for field in self.form_fields
175                    if field.__name__ in self.column_two_fields]
176            data.append(creator.getWidgetsTable(
177                fields, self.context, None, lang=portal_language,
178                separators=None, colWidths=[7*cm, 10*cm]))
179
180        # append widgets except those already added in column two
181        # and those in two_columns_design_fields
182        dept, faculty = self._getDeptAndFaculty()
183        fields = [
184            field for field in self.form_fields
185                if not field.__name__ in self.column_two_fields and
186                not field.__name__ in self.two_columns_design_fields]
187        data.append(creator.getWidgetsTable(
188            fields, self.context, view, lang=portal_language,
189            domain='waeup.kofa', separators=separators,
190            course_label='Admitted Course of Study:',
191            course_link=self._getCourseAdmittedLink(view),
192            dept=dept, faculty=faculty, colWidths=[7*cm, 10*cm]))
193
194        # append two-column table of widgets of those fields defined in
195        # two_columns_design_fields
196        if len(self.two_columns_design_fields):
197            fields = [
198                field for field in self.form_fields
199                    if not field.__name__ in self.column_two_fields and
200                    field.__name__ in self.two_columns_design_fields]
201            if fields:
202                data.append(creator.getWidgetsTable(
203                    fields, self.context, view, lang=portal_language,
204                    domain='waeup.kofa', separators=separators,
205                    twoDataCols=True))
206
207        # append QR Code if without picture
208        if not self.context.__parent__.with_picture and view is not None:
209            data.append(Spacer(1, 5))
210            url = view.url(self.context, 'application_slip.pdf')
211            data_right = [[get_qrcode(url, width=70.0)]]
212            table_right = Table(data_right,style=SLIP_STYLE)
213            data.append(get_qrcode(url, width=70.0))
214
215        # append login information
216        note = None
217        login_information = self._addLoginInformation()
218        if not None in (self.note, login_information):
219            note = self.note + login_information
220        elif self.note:
221            note = self.note
222        elif login_information:
223            note = login_information
224
225        return creator.create_pdf(data, None, doc_title, note=note,
226            topMargin=topMargin)
Note: See TracBrowser for help on using the repository browser.