source: main/waeup.kofa/branches/0.2/src/waeup/kofa/students/reports/level_report.py

Last change on this file was 10650, checked in by Henrik Bettermann, 11 years ago

Convert longtitle() into property attribute.

  • Property svn:keywords set to Id
File size: 10.6 KB
Line 
1## $Id: level_report.py 10650 2013-09-25 06:46:53Z henrik $
2##
3## Copyright (C) 2013 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##
18import grok
19from zope.catalog.interfaces import ICatalog
20from zope.component import queryUtility, getUtility
21from zope.interface import implementer, Interface, Attribute
22from waeup.kofa.interfaces import (
23    IKofaUtils,
24    academic_sessions_vocab, registration_states_vocab)
25from waeup.kofa.interfaces import MessageFactory as _
26from waeup.kofa.reports import IReport
27from waeup.kofa.browser.pdf import get_signature_tables
28from waeup.kofa.students.reports.student_statistics import (
29    StudentStatisticsReportPDFView)
30
31class ILevelReport(IReport):
32
33    session = Attribute('Session to report')
34    level = Attribute('Level to report')
35    faccode = Attribute('Faculty to report')
36    depcode = Attribute('Department to report')
37    creation_dt_string = Attribute('Human readable report creation datetime')
38
39def get_students(faccode, depcode, session, level):
40    """Get students in a certain department who registered courses
41    in a certain session at a certain level.
42
43    Returns a list of student data tuples.
44    """
45    site = grok.getSite()
46    cat = queryUtility(ICatalog, name="students_catalog")
47    result = cat.searchResults(
48        depcode = (depcode, depcode), faccode = (faccode, faccode)
49        )
50    table = []
51    for stud in result:
52        if not stud['studycourse'].has_key(str(level)):
53            continue
54        level_obj = stud['studycourse'][str(level)]
55        if level_obj.level_session != session:
56            continue
57        passed_params = level_obj.passed_params
58        line = (
59                #stud.student_id,
60                stud.matric_number,
61                stud.display_fullname,
62                level_obj.total_credits,
63                passed_params[2],
64                level_obj.gpa,
65                passed_params[4],
66                level_obj.cumulative_params[3],
67                level_obj.cumulative_params[4],
68                level_obj.cumulative_params[0],
69                )
70        table.append(line)
71    return sorted(table, key=lambda value:value[0])
72
73from reportlab.lib import colors
74from reportlab.lib.styles import getSampleStyleSheet
75from reportlab.lib.units import cm
76from reportlab.platypus import Paragraph, Table, Spacer
77from reportlab.platypus.flowables import Flowable
78from waeup.kofa.reports import IReport, IReportGenerator
79from waeup.kofa.reports import Report
80from waeup.kofa.browser.interfaces import IPDFCreator
81from waeup.kofa.university.vocabularies import course_levels
82
83STYLE = getSampleStyleSheet()
84
85class TTR(Flowable): #TableTextRotate
86    '''Rotates a text in a table cell.'''
87
88    def __init__(self, text):
89        Flowable.__init__(self)
90        self.text=text
91
92    def draw(self):
93        canvas = self.canv
94        canvas.rotate(45)
95        canvas.drawString( 0, -1, self.text)
96
97    #def wrap(self,aW,aH):
98    #    canv = self.canv
99    #    return canv._leading, canv.stringWidth(self.text)
100
101def tbl_data_to_table(data):
102    result = []
103    col_names = (
104            #'Student Id',
105            'S/N',
106            'Matric No.',
107            'Name',
108            TTR('Total Credits'),
109            TTR('Total Credits Passed'),
110            TTR('GPA'),
111            'Courses Failed',
112            TTR('Cum. Credits Taken'),
113            TTR('Cum. Credits Passed'),
114            TTR('CGPA'))
115    table = [col_names]
116    sn = 1
117    for line in data:
118        line = (sn,) + line
119        table.append(line)
120        sn += 1
121    return table
122
123TABLE_STYLE = [
124    ('FONT', (0,0), (-1,-1), 'Helvetica', 8),
125    #('FONT', (0,0), (0,-1), 'Helvetica-Bold', 8), # 1st column
126    ('FONT', (0,0), (-1,0), 'Helvetica-Bold', 8), # 1st row
127    #('FONT', (0,-1), (-1,-1), 'Helvetica-Bold', 8), # last row
128    #('FONT', (-1,0), (-1,-1), 'Helvetica-Bold', 8), # last column
129    ('ALIGN', (3,1), (-1,-1), 'RIGHT'),
130    ('ALIGN', (0,0), (0,-1), 'RIGHT'),
131    ('ALIGN', (6,0), (6,-1), 'LEFT'),
132    ('INNERGRID', (0,1), (-1,-1), 0.25, colors.black),
133    ('BOX', (0,1), (-1,-1), 1, colors.black),
134    ]
135
136@implementer(ILevelReport)
137class LevelReport(Report):
138    data = None
139    session = None
140    level = None
141    faccode = None
142    depcode = None
143
144    def __init__(self, faccode, depcode, session, level, author='System'):
145        super(LevelReport, self).__init__(
146            args=[faccode, depcode, session, level], kwargs={'author':author})
147        site = grok.getSite()
148        self.session = academic_sessions_vocab.getTerm(session).title
149        self.level = course_levels.getTerm(level).title
150        self.levelcode = level
151        self.sessioncode = session
152        self.faccode = faccode
153        self.depcode = depcode
154        self.factitle = site['faculties'][faccode].longtitle
155        self.deptitle = site['faculties'][faccode][depcode].longtitle
156        self.author = author
157        self.creation_dt_string = self.creation_dt.astimezone(
158            getUtility(IKofaUtils).tzinfo).strftime("%Y-%m-%d %H:%M:%S %Z")
159        self.data = get_students(faccode, depcode, session, level)
160
161    def create_pdf(self):
162        creator = getUtility(IPDFCreator, name='landscape')
163        table_data = tbl_data_to_table(self.data)
164        #col_widths = [3.5*cm] * len(self.data[0])
165        col_widths = [1*cm, 4*cm, 5*cm, 0.8*cm, 0.8*cm, 0.8*cm,
166                      6*cm, 0.8*cm, 0.8*cm, 0.8*cm]
167        pdf_data = [Paragraph('<b>%s</b>' % self.creation_dt_string,
168                              STYLE["Normal"]),
169                    Spacer(1, 12),]
170        pdf_data += [Paragraph('%s<br />%s<br />Level: %s<br />Session: %s' % (
171                    self.factitle, self.deptitle, self.level, self.session),
172                    STYLE["Normal"]),
173                    Spacer(1, 12),]
174        pdf_data += [
175            Table(table_data, style=TABLE_STYLE, colWidths=col_widths)]
176        doc_title = 'Level Report'
177
178        pdf_data.append(Spacer(1, 40))
179        signatures = ['Ag. Head of Department', 'Dean of Faculty']
180        signaturetables = get_signature_tables(signatures, landscape=True)
181        pdf_data.append(signaturetables[0])
182
183        pdf = creator.create_pdf(
184            pdf_data, None, doc_title, self.author,
185            'Level Report %s/%s/%s/%s' % (
186            self.faccode, self.depcode, self.levelcode, self.sessioncode)
187            )
188        return pdf
189
190@implementer(IReportGenerator)
191class LevelReportGenerator(grok.GlobalUtility):
192
193    title = _('Level Report')
194    grok.name('level_report')
195
196    def generate(self, site, faccode=None, depcode=None,
197                 session=None, level=None, author=None):
198        result = LevelReport(faccode=faccode, depcode=depcode,
199                             session=session, level=level, author=author)
200        return result
201
202###############################################################
203## Browser related stuff
204##
205## XXX: move to local browser module
206###############################################################
207from waeup.kofa.browser.layout import KofaPage
208from waeup.kofa.interfaces import academic_sessions_vocab
209from waeup.kofa.reports import get_generators
210grok.templatedir('browser_templates')
211class LevelReportGeneratorPage(KofaPage):
212
213    grok.context(LevelReportGenerator)
214    grok.name('index.html')
215    grok.require('waeup.manageReports')
216
217    label = _('Create level report')
218
219    @property
220    def generator_name(self):
221        for name, gen in get_generators():
222            if gen == self.context:
223                return name
224        return None
225
226    def update(self, CREATE=None, faccode_depcode=None,
227               session=None, level=None):
228        self.parent_url = self.url(self.context.__parent__)
229        self._set_session_values()
230        self._set_level_values()
231        self._set_faccode_depcode_values()
232        if CREATE and session:
233            # create a new report job for students by session
234            faccode = faccode_depcode.split('_')[0]
235            depcode = faccode_depcode.split('_')[1]
236            container = self.context.__parent__
237            user_id = self.request.principal.id
238            if level is not None:
239                level = int(level)
240            if session is not None:
241                session = int(session)
242            kw = dict(
243                session=session,
244                level=level,
245                faccode=faccode,
246                depcode=depcode)
247            self.flash(_('New report is being created in background'))
248            job_id = container.start_report_job(
249                self.generator_name, user_id, kw=kw)
250            ob_class = self.__implemented__.__name__.replace('waeup.kofa.','')
251            grok.getSite().logger.info(
252                '%s - report %s created: %s (faculty=%s, department=%s, session=%s, level=%s)' % (
253                ob_class, job_id, self.context.title, faccode, depcode, session, level))
254            self.redirect(self.parent_url)
255            return
256        return
257
258    def _set_session_values(self):
259        vocab_terms = academic_sessions_vocab.by_value.values()
260        self.sessions = [(x.title, x.token) for x in vocab_terms]
261        return
262
263    def _set_level_values(self):
264        vocab_terms = course_levels.by_value.values()
265        self.levels = sorted([(x.title, x.token) for x in vocab_terms])
266        return
267
268    def _set_faccode_depcode_values(self):
269        faccode_depcodes = []
270        faculties = grok.getSite()['faculties']
271        for fac in faculties.values():
272            for dep in fac.values():
273                faccode_depcodes.append(
274                    ('%s (%s)' %(dep.longtitle, fac.longtitle),
275                     '%s_%s' %(fac.code, dep.code)))
276        self.faccode_depcodes = sorted(
277            faccode_depcodes, key=lambda value: value[0])
278        return
279
280class LevelReportPDFView(StudentStatisticsReportPDFView):
281
282    grok.context(ILevelReport)
283    grok.name('pdf')
284    grok.require('waeup.Public')
285    prefix = 'LevelReport'
286
287    def _filename(self):
288        return 'LevelReport_%s_%s_%s_%s_%s.pdf' % (
289            self.context.faccode, self.context.depcode,
290            self.context.sessioncode, self.context.levelcode,
291            self.context.creation_dt_string)
292
Note: See TracBrowser for help on using the repository browser.