Changeset 10576


Ignore:
Timestamp:
2 Sep 2013, 06:42:16 (11 years ago)
Author:
Henrik Bettermann
Message:

Add browser components.

Location:
main/waeup.kofa/trunk/src/waeup/kofa/students
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.kofa/trunk/src/waeup/kofa/students/reports/level_results_presentation.py

    r10574 r10576  
    2525from waeup.kofa.students.interfaces import IStudentsUtils
    2626from waeup.kofa.interfaces import MessageFactory as _
     27from waeup.kofa.browser.pdf import get_signature_tables
    2728from waeup.kofa.reports import IReport
    28 from waeup.kofa.browser.pdf import get_signature_tables
     29from waeup.kofa.students.reports.level_report import (
     30    ILevelReport, LevelReportGeneratorPage)
     31from waeup.kofa.students.reports.student_statistics import (
     32    StudentStatisticsReportPDFView)
    2933
     34
     35class ISessionResultsPresentation(ILevelReport):
     36
     37    """ Same interface as for level reports.
     38    """
    3039
    3140def get_students(faccode, depcode, session, level=None):
     
    5867                continue
    5968        else:
     69            # XXX: Not yet supported by by generator page
    6070            itemcount = 0
    6171            for item in stud['studycourse'].values():
     
    7383    return table
    7484
     85from reportlab.lib import colors
     86from reportlab.lib.styles import getSampleStyleSheet
     87from reportlab.lib.units import cm
     88from reportlab.platypus import Paragraph, Table, Spacer
     89from reportlab.platypus.flowables import Flowable
     90from waeup.kofa.reports import IReport, IReportGenerator
     91from waeup.kofa.reports import Report
     92from waeup.kofa.browser.interfaces import IPDFCreator
     93from waeup.kofa.university.vocabularies import course_levels
     94
     95STYLE = getSampleStyleSheet()
     96
     97TABLE_STYLE = [
     98    ('FONT', (0,0), (-1,-1), 'Helvetica', 8),
     99    ('FONT', (0,0), (-1,0), 'Helvetica-Bold', 8), # 1st row
     100    ('ALIGN', (3,1), (-1,-1), 'RIGHT'),
     101    #('ALIGN', (1,0), (1,-1), 'LEFT'),
     102    #('ALIGN', (2,0), (2,-1), 'LEFT'),
     103    #('INNERGRID', (0,1), (-1,-1), 0.25, colors.black),
     104    #('BOX', (0,1), (-1,-1), 1, colors.black),
     105    ]
     106
     107@implementer(ISessionResultsPresentation)
     108class SessionResultsPresentation(Report):
     109    data = None
     110    session = None
     111    level = None
     112    faccode = None
     113    depcode = None
     114
     115    def __init__(self, faccode, depcode, session, level, author='System'):
     116        super(SessionResultsPresentation, self).__init__(
     117            args=[faccode, depcode, session, level], kwargs={'author':author})
     118        site = grok.getSite()
     119        self.session = academic_sessions_vocab.getTerm(session).title
     120        self.level = course_levels.getTerm(level).title
     121        self.levelcode = level
     122        self.sessioncode = session
     123        self.faccode = faccode
     124        self.depcode = depcode
     125        self.factitle = site['faculties'][faccode].longtitle()
     126        self.deptitle = site['faculties'][faccode][depcode].longtitle()
     127        self.author = author
     128        self.creation_dt_string = self.creation_dt.astimezone(
     129            getUtility(IKofaUtils).tzinfo).strftime("%Y-%m-%d %H:%M:%S %Z")
     130        self.data = get_students(faccode, depcode, session, level)
     131
     132    def create_pdf(self):
     133        creator = getUtility(IPDFCreator)
     134        #col_widths = [2*cm, 4*cm, 5*cm, 0.8*cm, 0.8*cm, 0.8*cm, 6*cm, ]
     135        pdf_data = [Paragraph('<b>%s</b>' % self.creation_dt_string,
     136                              STYLE["Normal"]),
     137                    Spacer(1, 12),]
     138        pdf_data += [Paragraph('%s<br />%s<br />Level: %s<br />Session: %s' % (
     139                    self.factitle, self.deptitle, self.level, self.session),
     140                    STYLE["Normal"]),
     141                    Spacer(1, 12),]
     142
     143        for table in self.data:
     144            table_data = [('Student Id', 'Matric No.', 'Name')] + table
     145            pdf_data += [
     146                Table(table_data, style=TABLE_STYLE)]    #, colWidths=col_widths)]
     147        doc_title = 'Presentation of Session Results'
     148
     149        pdf_data.append(Spacer(1, 40))
     150        signatures = ['Ag. Head of Department', 'External Examiner', 'Dean of Faculty']
     151        signaturetables = get_signature_tables(signatures)
     152        pdf_data.append(signaturetables[0])
     153
     154        pdf = creator.create_pdf(
     155            pdf_data, None, doc_title, self.author,
     156            'Session Results Presentation %s/%s/%s/%s' % (
     157            self.faccode, self.depcode, self.levelcode, self.sessioncode)
     158            )
     159        return pdf
     160
     161@implementer(IReportGenerator)
     162class SessionResultsPresentationGenerator(grok.GlobalUtility):
     163
     164    title = _('Session Results Presentation')
     165    grok.name('session_results_presentation')
     166
     167    def generate(self, site, faccode=None, depcode=None,
     168                 session=None, level=None, author=None):
     169        result = SessionResultsPresentation(faccode=faccode, depcode=depcode,
     170                             session=session, level=level, author=author)
     171        return result
     172
     173###############################################################
     174## Browser related stuff
     175##
     176## XXX: move to local browser module
     177###############################################################
     178from waeup.kofa.browser.layout import KofaPage
     179from waeup.kofa.interfaces import academic_sessions_vocab
     180from waeup.kofa.reports import get_generators
     181grok.templatedir('browser_templates')
     182class SessionResultsPresentationGeneratorPage(LevelReportGeneratorPage):
     183
     184    grok.context(SessionResultsPresentationGenerator)
     185    grok.template('levelreportgeneratorpage')
     186    label = _('Create session results presentation')
     187
     188class SessionResultsPresentationPDFView(StudentStatisticsReportPDFView):
     189
     190    grok.context(ISessionResultsPresentation)
     191    grok.name('pdf')
     192    grok.require('waeup.Public')
     193    prefix = 'SessionResultsPresentation'
     194
     195    def _filename(self):
     196        return 'SessionResultsPresentation_%s_%s_%s_%s_%s.pdf' % (
     197            self.context.faccode, self.context.depcode,
     198            self.context.sessioncode, self.context.levelcode,
     199            self.context.creation_dt_string)
  • main/waeup.kofa/trunk/src/waeup/kofa/students/reports/tests/test_level_results_presentation.py

    r10574 r10576  
    66from waeup.kofa.interfaces import IJobManager
    77from waeup.kofa.students.reports.level_results_presentation import (
    8     get_students)
     8    get_students, SessionResultsPresentation, ISessionResultsPresentation)
    99from waeup.kofa.students.tests.test_catalog import CatalogTestSetup
    1010from waeup.kofa.students.tests.test_browser import StudentsFullSetup
     
    1414from waeup.kofa.students.studylevel import StudentStudyLevel
    1515
    16 class LevelReportTests(CatalogTestSetup):
     16class SessionResultsPresentationTests(CatalogTestSetup):
    1717
    1818    layer = FunctionalLayer
     19
     20    def test_iface(self):
     21        # ensure we fullfill interface contracts
     22        obj = SessionResultsPresentation('fac1', 'dep1', 2010, 100)
     23        verifyClass(ISessionResultsPresentation, SessionResultsPresentation)
     24        verifyObject(ISessionResultsPresentation, obj)
     25        return
    1926
    2027    def test_get_students(self):
     
    4855        return
    4956
     57    def test_create_pdf(self):
     58        report = SessionResultsPresentation('fac1', 'dep1', 2010, 100)
     59        result = report.create_pdf()
     60        self.assertTrue(result.startswith('%PDF-'))
     61        path = os.path.join(samples_dir(), 'session_results_presentation.pdf')
     62        open(path, 'wb').write(result)
     63        print "Sample session_results_presentation.pdf written to %s" % path
     64        return
     65
     66class SessionResultsPresentationUITests(StudentsFullSetup, FunctionalAsyncTestCase):
     67
     68    layer = FunctionalLayer
     69
     70    def wait_for_report_job_completed(self):
     71        # helper function waiting until the current export job is completed
     72        manager = getUtility(IJobManager)
     73        job_id = self.app['reports'].running_report_jobs[0][0]
     74        job = manager.get(job_id)
     75        wait_for_result(job)
     76        return job_id
     77
     78    def stored_in_reports(self, job_id):
     79        # tell whether job_id is stored in reports's running jobs list
     80        for entry in list(self.app['reports'].running_report_jobs):
     81            if entry[0] == job_id:
     82                return True
     83        return False
     84
     85    def trigger_report_creation(self):
     86        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
     87        self.browser.open('http://localhost/app/reports')
     88        self.assertEqual(self.browser.headers['Status'], '200 Ok')
     89        self.browser.getLink("Create new report").click()
     90        self.browser.getControl(name="generator").value = ['session_results_presentation']
     91        self.browser.getControl("Configure").click()
     92        self.browser.getControl(name="level").value = ['100']
     93        self.browser.getControl(name="session").value = ['2010']
     94        self.browser.getControl(name="faccode_depcode").value = ['fac1_dep1']
     95        self.browser.getControl("Create").click()
     96        return
     97
     98    def test_report_download(self):
     99        # We can download a generated report
     100        self.trigger_report_creation()
     101        # When the job is finished and we reload the page...
     102        job_id = self.wait_for_report_job_completed()
     103        self.browser.open('http://localhost/app/reports')
     104        # ... the pdf file can be downloaded ...
     105        self.browser.getControl("Download").click()
     106        self.assertEqual(self.browser.headers['content-type'],
     107                         'application/pdf')
     108        self.assertTrue(
     109            'filename="SessionResultsPresentation_fac1_dep1_2010_100_' in
     110            self.browser.headers['content-disposition'])
     111        self.assertEqual(len(self.app['reports'].running_report_jobs), 1)
     112        job_id = self.app['reports'].running_report_jobs[0][0]
     113        # ... and discarded
     114        self.browser.open('http://localhost/app/reports')
     115        self.browser.getControl("Discard").click()
     116        self.assertEqual(len(self.app['reports'].running_report_jobs), 0)
     117        # Creation, downloading and discarding is logged
     118        logfile = os.path.join(
     119            self.app['datacenter'].storage, 'logs', 'main.log')
     120        logcontent = open(logfile).read()
     121        self.assertTrue(
     122            'INFO - zope.mgr - students.reports.level_results_presentation.SessionResultsPresentationGeneratorPage - '
     123            'report %s created: Session Results Presentation (faculty=fac1, department=dep1, session=2010, level=100)'
     124            % job_id in logcontent
     125            )
     126        self.assertTrue(
     127            'INFO - zope.mgr - students.reports.level_results_presentation.SessionResultsPresentationPDFView - '
     128            'report %s downloaded: SessionResultsPresentation_fac1_dep1_2010_100_'
     129            % job_id in logcontent
     130            )
     131        self.assertTrue(
     132            'INFO - zope.mgr - browser.reports.ReportsContainerPage - '
     133            'report %s discarded' % job_id in logcontent
     134            )
     135        return
  • main/waeup.kofa/trunk/src/waeup/kofa/students/utils.py

    r10479 r10576  
    663663        return pdf_stream
    664664
     665    gpa_boundaries = (1, 1.5, 2.4, 3.5, 4.5, 5)
     666
    665667    def getClassFromCGPA(self, gpa):
    666         if gpa < 1:
    667             return 'Fail'
    668         if gpa < 1.5:
    669             return 'Pass'
    670         if gpa < 2.4:
    671             return '3rd Class'
    672         if gpa < 3.5:
    673             return '2nd Class Lower'
    674         if gpa < 4.5:
    675             return '2nd Class Upper'
    676         if gpa <= 5:
    677             return '1st Class'
    678         return 'N/A'
     668        if gpa < self.gpa_boundaries[0]:
     669            return 0, 'Fail'
     670        if gpa < self.gpa_boundaries[1]:
     671            return 1, 'Pass'
     672        if gpa < self.gpa_boundaries[2]:
     673            return 2, '3rd Class'
     674        if gpa < self.gpa_boundaries[3]:
     675            return 3, '2nd Class Lower'
     676        if gpa < self.gpa_boundaries[4]:
     677            return 4, '2nd Class Upper'
     678        if gpa <= self.gpa_boundaries[5]:
     679            return 5, '1st Class'
     680        return 999, 'N/A'
    679681
    680682    def renderPDFTranscript(self, view, filename='transcript.pdf',
     
    754756        f_label = trans(_('Cumulative GPA:'), portal_language)
    755757        f_label = Paragraph(f_label, ENTRY1_STYLE)
    756         f_text = formatted_text('%s (%s)' % (gpa, self.getClassFromCGPA(gpa)))
     758        f_text = formatted_text('%s (%s)' % (gpa, self.getClassFromCGPA(gpa)[1]))
    757759        f_text = Paragraph(f_text, ENTRY1_STYLE)
    758760        contextdata.append([f_label,f_text])
Note: See TracChangeset for help on using the changeset viewer.