Changeset 14496 for main/waeup.aaue


Ignore:
Timestamp:
2 Feb 2017, 08:15:48 (8 years ago)
Author:
Henrik Bettermann
Message:

Customize raw score report components of base package.

Location:
main/waeup.aaue/trunk/src/waeup/aaue
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.aaue/trunk/src/waeup/aaue/browser/pdf.py

    r14454 r14496  
    2323import grok
    2424from reportlab.lib.pagesizes import A4, A3, landscape, portrait
    25 from waeup.kofa.browser.pdf import PDFCreator, LandscapePDFCreator
     25from waeup.kofa.browser.pdf import (
     26    PDFCreator, LandscapePDFCreator, A3LandscapePDFCreator)
    2627
    2728class CustomPDFCreator(PDFCreator):
     
    5051    logo_pos = [750, 465, 60]
    5152
    52 class A3LandscapePDFCreator(LandscapePDFCreator):
     53class CustomA3LandscapePDFCreator(A3LandscapePDFCreator):
    5354    """A utility to help with generating PDF docs in
    5455    A3 landscape format. No watermark is shown.
    5556    """
    56 
    57     grok.name('A3landscape')
    5857
    5958    header_logo_path = os.path.join(
  • main/waeup.aaue/trunk/src/waeup/aaue/students/reports/raw_score_report.py

    r14489 r14496  
    1616## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    1717##
    18 import grok
    19 import textwrap
    20 from zope.i18n import translate
    21 from zope.catalog.interfaces import ICatalog
    22 from zope.component import queryUtility, getUtility
    23 from zope.interface import implementer, Interface, Attribute
    24 from waeup.kofa.interfaces import (
    25     IKofaUtils,
    26     academic_sessions_vocab, registration_states_vocab)
    27 from waeup.kofa.interfaces import MessageFactory as _
    28 from waeup.kofa.reports import IReport
    29 from waeup.kofa.browser.pdf import get_signature_tables
    30 from waeup.kofa.students.vocabularies import StudyLevelSource
    31 from waeup.kofa.students.reports.level_report import LevelReportGeneratorPage
    32 from waeup.kofa.students.reports.student_statistics import (
    33     StudentStatisticsReportPDFView)
    3418
    35 class IRawScoreReport(IReport):
     19from waeup.kofa.students.reports.raw_score_report import (
     20    RawScoreReport, RawScoreReportGenerator)
    3621
    37     session = Attribute('Session to report')
    38     level = Attribute('Level to report')
    39     faccode = Attribute('Faculty to report')
    40     depcode = Attribute('Department to report')
    41     certcode = Attribute('Certzificate to report')
    42     creation_dt_string = Attribute('Human readable report creation datetime')
    4322
    44 def get_courses(faccode, depcode, certcode, session, level):
    45     """Method 1: Get certificate courses of a
    46     certain department/certificate at a certain level.
    47     """
    48     site = grok.getSite()
    49     course_codes = []
    50     department = site['faculties'][faccode][depcode]
    51     if certcode == 'all':
    52         for cert in department.certificates.values():
    53             for certcourse in cert.values():
    54                 if certcourse.level == level:
    55                     course_codes.append(certcourse.getCourseCode())
    56     else:
    57         certificate = site['faculties'][faccode][depcode].certificates[certcode]
    58         for certcourse in certificate.values():
    59             if certcourse.level == level:
    60                 course_codes.append(certcourse.getCourseCode())
    61     return course_codes
     23class CustomRawScoreReport(RawScoreReport):
    6224
    63 def get_students(faccode, depcode, certcode, session, level, course_codes):
    64     """Get students in a certain department/certificate who registered courses
    65     in a certain session at a certain level.
     25    signatures = ['Head of Department', 'Dean of Faculty']
    6626
    67     Returns a list of student data tuples.
    68     """
    69     cat = queryUtility(ICatalog, name="students_catalog")
    70     if certcode == 'all':
    71         certcode = None
    72     result = cat.searchResults(
    73         depcode = (depcode, depcode), faccode = (faccode, faccode),
    74         certcode = (certcode, certcode)
    75         )
    76     table = []
    77     for stud in result:
    78         if not stud['studycourse'].has_key(str(level)):
    79             continue
    80         level_obj = stud['studycourse'][str(level)]
    81         if level_obj.level_session != session:
    82             continue
    83         scores = dict()
    84         for ticket in level_obj.values():
    85             if ticket.code in course_codes:
    86                 if not None in (ticket.score, ticket.ca):
    87                     scores[ticket.code] = (
    88                         ticket.score + ticket.ca, ticket.grade)
    89                 else:
    90                     scores[ticket.code] = ('NIL', '')
    91         fullname = textwrap.fill(stud.display_fullname, 26)
    92         line = (
    93                 stud.matric_number,
    94                 fullname,
    95                 scores,
    96                 )
    97         table.append(line)
    98     return sorted(table, key=lambda value:value[0])
    9927
    100 from reportlab.lib import colors
    101 from reportlab.lib.styles import getSampleStyleSheet
    102 from reportlab.lib.units import cm
    103 from reportlab.platypus import Paragraph, Table, Spacer
    104 from reportlab.platypus.flowables import Flowable
    105 from waeup.kofa.reports import IReport, IReportGenerator
    106 from waeup.kofa.reports import Report
    107 from waeup.kofa.browser.interfaces import IPDFCreator
    108 
    109 STYLE = getSampleStyleSheet()
    110 
    111 class TTR(Flowable): #TableTextRotate
    112     '''Rotates a text in a table cell.'''
    113 
    114     def __init__(self, text):
    115         Flowable.__init__(self)
    116         self.text=text
    117 
    118     def draw(self):
    119         canvas = self.canv
    120         canvas.rotate(25)
    121         canvas.drawString( 0, -1, self.text)
    122 
    123     #def wrap(self,aW,aH):
    124     #    canv = self.canv
    125     #    return canv._leading, canv.stringWidth(self.text)
    126 
    127 def tbl_data_to_table(data, course_codes):
    128     col_names = (
    129             #'Student Id',
    130             'S/N',
    131             'Matric No.',
    132             'Name',
    133             )
    134     catalog = getUtility(ICatalog, name='courses_catalog')
    135     for code in course_codes:
    136         course = list(catalog.searchResults(code=(code, code)))[0]
    137         col_names += (TTR('%s (%s)' % (code, course.credits)),)
    138     table = [col_names]
    139     sn = 1
    140     for line in data:
    141         scores = tuple()
    142         composed_line = (sn,) + line[:-1]
    143         for code in course_codes:
    144             result = line[-1].get(code)
    145             if not result:
    146                 scores += ('N/R',)
    147             else:
    148                 scores += ('%s%s' % (result[0], result[1]),)
    149         composed_line += scores
    150         table.append(composed_line)
    151         sn += 1
    152     return table
    153 
    154 TABLE_STYLE = [
    155     ('FONT', (0,0), (-1,-1), 'Helvetica', 8),
    156     ('VALIGN', (0, 1), (-1,-1), 'TOP'),
    157     #('FONT', (0,0), (0,-1), 'Helvetica-Bold', 8), # 1st column
    158     ('FONT', (0,0), (-1,0), 'Helvetica-Bold', 8), # 1st row
    159     #('FONT', (0,-1), (-1,-1), 'Helvetica-Bold', 8), # last row
    160     #('FONT', (-1,0), (-1,-1), 'Helvetica-Bold', 8), # last column
    161     ('ALIGN', (3,1), (-1,-1), 'RIGHT'),
    162     ('ALIGN', (0,0), (0,-1), 'RIGHT'),
    163     #('ALIGN', (6,0), (6,-1), 'LEFT'),
    164     ('INNERGRID', (0,1), (-1,-1), 0.25, colors.black),
    165     ('BOX', (0,1), (-1,-1), 1, colors.black),
    166     ]
    167 
    168 @implementer(IRawScoreReport)
    169 class RawScoreReport(Report):
    170     data = None
    171     session = None
    172     level = None
    173     faccode = None
    174     depcode = None
    175     certcode = None
    176 
    177     note = ""
    178 
    179 #    note = """
    180 #<br /><br /><br /><br />
    181 #<font size='10'>
    182 #<strong>Note:</strong> This copy is subject to correction for typographical errors and ratification by the departmental board.
    183 #</font>
    184 #"""
    185 
    186     signatures = [
    187         translate(_('Head of Department')),
    188         translate(_('Dean of Faculty'))]
    189 
    190     def __init__(self, faccode, depcode, certcode, session, level,
    191                  author='System'):
    192         super(RawScoreReport, self).__init__(
    193             args=[faccode, depcode, certcode, session, level],
    194                   kwargs={'author':author})
    195         site = grok.getSite()
    196         self.studylevelsource = StudyLevelSource().factory
    197         self.portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
    198         self.session = academic_sessions_vocab.getTerm(session).title
    199         self.levelcode = level
    200         self.sessioncode = session
    201         self.faccode = faccode
    202         self.depcode = depcode
    203         self.certcode = certcode
    204         self.factitle = site['faculties'][faccode].longtitle
    205         self.deptitle = site['faculties'][faccode][depcode].longtitle
    206         if self.certcode == 'all':
    207             self.certtitle = translate(
    208                 _('All Certificates'), 'waeup.kofa',
    209                 target_language=self.portal_language)
    210             self.level = translate(
    211                 self.studylevelsource.getTitle(None, int(level)),
    212                 'waeup.kofa', target_language=self.portal_language)
    213         else:
    214             certificate = site[
    215                 'faculties'][faccode][depcode].certificates[certcode]
    216             self.certtitle = certificate.longtitle
    217             self.level = translate(
    218                 self.studylevelsource.getTitle(certificate, int(level)),
    219                 'waeup.kofa', target_language=self.portal_language)
    220         self.author = author
    221         self.creation_dt_string = self.creation_dt.astimezone(
    222             getUtility(IKofaUtils).tzinfo).strftime("%Y-%m-%d %H:%M:%S %Z")
    223         self.past_levels = range(int(level/100)*100, 0, -100)
    224         self.course_codes = dict()
    225         self.data = dict()
    226         for level in self.past_levels:
    227             course_codes = get_courses(
    228                 faccode, depcode, certcode, session, level)
    229             self.course_codes[level] = course_codes
    230             self.data[level] = get_students(
    231                 faccode, depcode, certcode, session, self.levelcode, course_codes)
    232 
    233     def create_pdf(self, job_id):
    234         creator = getUtility(IPDFCreator, name='A3landscape')
    235         table_data = dict()
    236         for level in self.past_levels:
    237             table_data[level] = tbl_data_to_table(
    238                 self.data[level], self.course_codes[level])
    239         col_widths = [1*cm, 4*cm, 5*cm] + [1*cm] * len(self.course_codes)
    240         pdf_data = [Paragraph('<b>%s - Report %s</b>'
    241                               % (self.creation_dt_string, job_id),
    242                               STYLE["Normal"]),
    243                     Spacer(1, 12),]
    244         pdf_data += [Paragraph(
    245                     translate(
    246                         '${a}<br />${b}<br />${c}<br /><br />Session: ${d}<br />Level: ${e}',
    247                         mapping = {'a':self.certtitle,
    248                                    'b':self.deptitle,
    249                                    'c':self.factitle,
    250                                    'd':self.session,
    251                                    'e':self.level,
    252                                    }),
    253                     STYLE["Normal"]),
    254                     Spacer(1, 12),]
    255 
    256         for level in self.past_levels:
    257             pdf_data.append(Spacer(1, 40))
    258             pdf_data += [Paragraph('<b>Level %s Courses</b>' % level,
    259                         STYLE["Normal"]), Spacer(1, 20),]
    260             pdf_data += [
    261                 Table(table_data[level],
    262                       style=TABLE_STYLE,
    263                       colWidths=col_widths)]
    264         doc_title = translate(_('Raw Score Report'))
    265         pdf_data.append(Spacer(1, 40))
    266         if self.signatures:
    267             signaturetables = get_signature_tables(
    268                 self.signatures, landscape=True)
    269             pdf_data.append(signaturetables[0])
    270 
    271         pdf = creator.create_pdf(
    272             pdf_data, None, doc_title, self.author,
    273             doc_title + ' - %s/%s/%s - %s - %s -' % (
    274             self.faccode, self.depcode, self.certcode,
    275             self.levelcode, self.sessioncode),
    276             note=self.note
    277             )
    278         return pdf
    279 
    280 @implementer(IReportGenerator)
    281 class RawScoreReportGenerator(grok.GlobalUtility):
    282 
    283     title = _('RAW Score Report')
    284     grok.name('raw_score_report')
     28class RawScoreReportGenerator(RawScoreReportGenerator):
    28529
    28630    def generate(self, site, faccode=None, depcode=None, certcode=None,
    28731                 session=None, level=None, author=None):
    288         result = RawScoreReport(faccode=faccode, depcode=depcode,
     32        result = CustomRawScoreReport(faccode=faccode, depcode=depcode,
    28933            certcode=certcode, session=session, level=level, author=author)
    29034        return result
    291 
    292 ###############################################################
    293 ## Browser related stuff
    294 ##
    295 ## XXX: move to local browser module
    296 ###############################################################
    297 from waeup.kofa.browser.layout import KofaPage
    298 from waeup.kofa.interfaces import academic_sessions_vocab
    299 from waeup.kofa.reports import get_generators
    300 from waeup.kofa.browser.breadcrumbs import Breadcrumb
    301 grok.templatedir('browser_templates')
    302 class RawScoreReportGeneratorPage(LevelReportGeneratorPage):
    303 
    304     grok.context(RawScoreReportGenerator)
    305 
    306     label = _('Create raw score report')
    307 
    308 class RawScoreReportPDFView(StudentStatisticsReportPDFView):
    309 
    310     grok.context(IRawScoreReport)
    311     grok.name('pdf')
    312     grok.require('waeup.handleReports')
    313     prefix = 'RawScoreReport'
    314 
    315     def _filename(self):
    316         return 'RawScoreReport_%s_%s_%s_%s_%s_%s.pdf' % (
    317             self.context.faccode, self.context.depcode, self.context.certcode,
    318             self.context.sessioncode, self.context.levelcode,
    319             self.context.creation_dt_string)
    320 
    321 class RawScoreReportBreadcrumb(Breadcrumb):
    322     """A breadcrumb for reports.
    323     """
    324     grok.context(RawScoreReportGenerator)
    325     title = _(u'Raw Score Report')
    326     target = None
  • main/waeup.aaue/trunk/src/waeup/aaue/students/reports/tests/test_raw_score_report.py

    r14483 r14496  
    88from waeup.kofa.tests.test_async import FunctionalAsyncTestCase
    99from waeup.kofa.browser.tests.test_pdf import samples_dir
    10 
    11 from waeup.aaue.students.reports.raw_score_report import (
    12     get_students, RawScoreReport, IRawScoreReport,
    13     get_courses)
     10from waeup.kofa.students.reports.raw_score_report import (
     11    get_students, IRawScoreReport, get_courses)
     12from waeup.aaue.students.reports.raw_score_report import CustomRawScoreReport
    1413from waeup.aaue.testing import FunctionalLayer
    1514
     
    2221        self.course = createObject('waeup.Course')
    2322        self.course.code = 'Course1'
     23        self.course.credits = 25
    2424        self.app['faculties']['fac1']['dep1'].courses.addCourse(
    2525            self.course)
     
    2929    def test_iface(self):
    3030        # ensure we fullfill interface contracts
    31         obj = RawScoreReport('fac1', 'dep1', 'CERT1', 2010, 100)
    32         verifyClass(IRawScoreReport, RawScoreReport)
     31        obj = CustomRawScoreReport('fac1', 'dep1', 'CERT1', 2010, 100)
     32        verifyClass(IRawScoreReport, CustomRawScoreReport)
    3333        verifyObject(IRawScoreReport, obj)
    3434        return
     
    5656        self.course = createObject('waeup.Course')
    5757        self.course.code = 'Course2'
     58        self.course.credits = 30
    5859        self.app['faculties']['fac1']['dep1'].courses.addCourse(
    5960            self.course)
     
    7273        self.student.firstname = u'Osahenokese Tessy'
    7374        self.student.lastname = u'Emwinyomwanru'
    74         report = RawScoreReport('fac1', 'dep1', 'CERT1', 2011, 200)
     75        report = CustomRawScoreReport('fac1', 'dep1', 'CERT1', 2011, 200)
    7576        result = report.create_pdf('JOB_ID')
    7677        self.assertTrue(result.startswith('%PDF-'))
Note: See TracChangeset for help on using the changeset viewer.