Ignore:
Timestamp:
11 Dec 2019, 09:40:24 (5 years ago)
Author:
Henrik Bettermann
Message:

Reorganize pdf render utility methods.

File:
1 edited

Legend:

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

    r15873 r15879  
    675675        return sorted_beds[0]
    676676
     677    def GPABoundaries(self, faccode=None, depcode=None, certcode=None):
     678        return ((1, 'Fail'),
     679               (1.5, 'Pass'),
     680               (2.4, '3rd Class'),
     681               (3.5, '2nd Class Lower'),
     682               (4.5, '2nd Class Upper'),
     683               (5, '1st Class'))
     684
     685    def getClassFromCGPA(self, gpa, student):
     686        """Determine the class of degree. In some custom packages
     687        this class depends on e.g. the entry session of the student. In the
     688        base package, it does not.
     689        """
     690        if gpa < self.GPABoundaries()[0][0]:
     691            return 0, self.GPABoundaries()[0][1]
     692        if gpa < self.GPABoundaries()[1][0]:
     693            return 1, self.GPABoundaries()[1][1]
     694        if gpa < self.GPABoundaries()[2][0]:
     695            return 2, self.GPABoundaries()[2][1]
     696        if gpa < self.GPABoundaries()[3][0]:
     697            return 3, self.GPABoundaries()[3][1]
     698        if gpa < self.GPABoundaries()[4][0]:
     699            return 4, self.GPABoundaries()[4][1]
     700        if gpa <= self.GPABoundaries()[5][0]:
     701            return 5, self.GPABoundaries()[5][1]
     702        return
     703
     704    def getDegreeClassNumber(self, level_obj):
     705        """Get degree class number (used for SessionResultsPresentation
     706        reports).
     707        """
     708        if level_obj.gpa_params[1] == 0:
     709            # No credits weighted
     710            return 6
     711        return self.getClassFromCGPA(
     712            level_obj.cumulative_params[0], level_obj.student)[0]
     713
     714    def _saveTranscriptPDF(self, student, transcript):
     715        """Create a transcript PDF file and store it in student folder.
     716        """
     717        file_store = getUtility(IExtFileStore)
     718        file_id = IFileStoreNameChooser(student).chooseName(
     719            attr="final_transcript.pdf")
     720        file_store.createFile(file_id, StringIO(transcript))
     721        return
     722
     723    def warnCreditsOOR(self, studylevel, course=None):
     724        """Return message if credits are out of range. In the base
     725        package only maximum credits is set.
     726        """
     727        if course and studylevel.total_credits + course.credits > 50:
     728            return _('Maximum credits exceeded.')
     729        elif studylevel.total_credits > 50:
     730            return _('Maximum credits exceeded.')
     731        return
     732
     733    def getBedCoordinates(self, bedticket):
     734        """Return descriptive bed coordinates.
     735        This method can be used to customize the `display_coordinates`
     736        property method in order to  display a
     737        customary description of the bed space.
     738        """
     739        return bedticket.bed_coordinates
     740
     741    def clearance_disabled_message(self, student):
     742        """Render message if clearance is disabled.
     743        """
     744        try:
     745            session_config = grok.getSite()[
     746                'configuration'][str(student.current_session)]
     747        except KeyError:
     748            return _('Session configuration object is not available.')
     749        if not session_config.clearance_enabled:
     750            return _('Clearance is disabled for this session.')
     751        return None
     752
     753    def getPDFCreator(self, context):
     754        """Get a pdf creator suitable for `context`.
     755        The default implementation always returns the default creator.
     756        """
     757        return getUtility(IPDFCreator)
     758
     759    def renderPDF(self, view, filename='slip.pdf', student=None,
     760                  studentview=None,
     761                  tableheader=[], tabledata=[],
     762                  note=None, signatures=None, sigs_in_footer=(),
     763                  show_scans=True, topMargin=1.5,
     764                  omit_fields=()):
     765        """Render pdf slips for various pages (also some pages
     766        in the applicants module).
     767        """
     768        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
     769        # XXX: tell what the different parameters mean
     770        style = getSampleStyleSheet()
     771        creator = self.getPDFCreator(student)
     772        data = []
     773        doc_title = view.label
     774        author = '%s (%s)' % (view.request.principal.title,
     775                              view.request.principal.id)
     776        footer_text = view.label.split('\n')
     777        if len(footer_text) > 1:
     778            # We can add a department in first line, second line is used
     779            footer_text = footer_text[1]
     780        else:
     781            # Only the first line is used for the footer
     782            footer_text = footer_text[0]
     783        if getattr(student, 'student_id', None) is not None:
     784            footer_text = "%s - %s - " % (student.student_id, footer_text)
     785
     786        # Insert student data table
     787        if student is not None:
     788            bd_translation = trans(_('Base Data'), portal_language)
     789            data.append(Paragraph(bd_translation, HEADING_STYLE))
     790            data.append(render_student_data(
     791                studentview, view.context, omit_fields, lang=portal_language,
     792                slipname=filename))
     793
     794        # Insert widgets
     795        if view.form_fields:
     796            data.append(Paragraph(view.title, HEADING_STYLE))
     797            separators = getattr(self, 'SEPARATORS_DICT', {})
     798            table = creator.getWidgetsTable(
     799                view.form_fields, view.context, None, lang=portal_language,
     800                separators=separators)
     801            data.append(table)
     802
     803        # Insert scanned docs
     804        if show_scans:
     805            data.extend(docs_as_flowables(view, portal_language))
     806
     807        # Insert history
     808        if filename == 'clearance_slip.pdf':
     809            hist_translation = trans(_('Workflow History'), portal_language)
     810            data.append(Paragraph(hist_translation, HEADING_STYLE))
     811            data.extend(creator.fromStringList(student.history.messages))
     812
     813        # Insert content tables (optionally on second page)
     814        if hasattr(view, 'tabletitle'):
     815            for i in range(len(view.tabletitle)):
     816                if tabledata[i] and tableheader[i]:
     817                    #data.append(PageBreak())
     818                    #data.append(Spacer(1, 20))
     819                    data.append(Paragraph(view.tabletitle[i], HEADING_STYLE))
     820                    data.append(Spacer(1, 8))
     821                    contenttable = render_table_data(tableheader[i],tabledata[i])
     822                    data.append(contenttable)
     823
     824        # Insert signatures
     825        # XXX: We are using only sigs_in_footer in waeup.kofa, so we
     826        # do not have a test for the following lines.
     827        if signatures and not sigs_in_footer:
     828            data.append(Spacer(1, 20))
     829            # Render one signature table per signature to
     830            # get date and signature in line.
     831            for signature in signatures:
     832                signaturetables = get_signature_tables(signature)
     833                data.append(signaturetables[0])
     834
     835        view.response.setHeader(
     836            'Content-Type', 'application/pdf')
     837        try:
     838            pdf_stream = creator.create_pdf(
     839                data, None, doc_title, author=author, footer=footer_text,
     840                note=note, sigs_in_footer=sigs_in_footer, topMargin=topMargin)
     841        except IOError:
     842            view.flash('Error in image file.')
     843            return view.redirect(view.url(view.context))
     844        except LayoutError, err:
     845            view.flash(
     846                'PDF file could not be created. Reportlab error message: %s'
     847                % escape(err.message),
     848                type="danger")
     849            return view.redirect(view.url(view.context))
     850        return pdf_stream
     851
    677852    def _admissionText(self, student, portal_language):
    678853        inst_name = grok.getSite()['configuration'].name
     
    739914            note=post_text)
    740915        return pdf_stream
    741 
    742     def getPDFCreator(self, context):
    743         """Get a pdf creator suitable for `context`.
    744         The default implementation always returns the default creator.
    745         """
    746         return getUtility(IPDFCreator)
    747 
    748     def renderPDF(self, view, filename='slip.pdf', student=None,
    749                   studentview=None,
    750                   tableheader=[], tabledata=[],
    751                   note=None, signatures=None, sigs_in_footer=(),
    752                   show_scans=True, topMargin=1.5,
    753                   omit_fields=()):
    754         """Render pdf slips for various pages (also some pages
    755         in the applicants module).
    756         """
    757         portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
    758         # XXX: tell what the different parameters mean
    759         style = getSampleStyleSheet()
    760         creator = self.getPDFCreator(student)
    761         data = []
    762         doc_title = view.label
    763         author = '%s (%s)' % (view.request.principal.title,
    764                               view.request.principal.id)
    765         footer_text = view.label.split('\n')
    766         if len(footer_text) > 1:
    767             # We can add a department in first line, second line is used
    768             footer_text = footer_text[1]
    769         else:
    770             # Only the first line is used for the footer
    771             footer_text = footer_text[0]
    772         if getattr(student, 'student_id', None) is not None:
    773             footer_text = "%s - %s - " % (student.student_id, footer_text)
    774 
    775         # Insert student data table
    776         if student is not None:
    777             bd_translation = trans(_('Base Data'), portal_language)
    778             data.append(Paragraph(bd_translation, HEADING_STYLE))
    779             data.append(render_student_data(
    780                 studentview, view.context, omit_fields, lang=portal_language,
    781                 slipname=filename))
    782 
    783         # Insert widgets
    784         if view.form_fields:
    785             data.append(Paragraph(view.title, HEADING_STYLE))
    786             separators = getattr(self, 'SEPARATORS_DICT', {})
    787             table = creator.getWidgetsTable(
    788                 view.form_fields, view.context, None, lang=portal_language,
    789                 separators=separators)
    790             data.append(table)
    791 
    792         # Insert scanned docs
    793         if show_scans:
    794             data.extend(docs_as_flowables(view, portal_language))
    795 
    796         # Insert history
    797         if filename == 'clearance_slip.pdf':
    798             hist_translation = trans(_('Workflow History'), portal_language)
    799             data.append(Paragraph(hist_translation, HEADING_STYLE))
    800             data.extend(creator.fromStringList(student.history.messages))
    801 
    802         # Insert content tables (optionally on second page)
    803         if hasattr(view, 'tabletitle'):
    804             for i in range(len(view.tabletitle)):
    805                 if tabledata[i] and tableheader[i]:
    806                     #data.append(PageBreak())
    807                     #data.append(Spacer(1, 20))
    808                     data.append(Paragraph(view.tabletitle[i], HEADING_STYLE))
    809                     data.append(Spacer(1, 8))
    810                     contenttable = render_table_data(tableheader[i],tabledata[i])
    811                     data.append(contenttable)
    812 
    813         # Insert signatures
    814         # XXX: We are using only sigs_in_footer in waeup.kofa, so we
    815         # do not have a test for the following lines.
    816         if signatures and not sigs_in_footer:
    817             data.append(Spacer(1, 20))
    818             # Render one signature table per signature to
    819             # get date and signature in line.
    820             for signature in signatures:
    821                 signaturetables = get_signature_tables(signature)
    822                 data.append(signaturetables[0])
    823 
    824         view.response.setHeader(
    825             'Content-Type', 'application/pdf')
    826         try:
    827             pdf_stream = creator.create_pdf(
    828                 data, None, doc_title, author=author, footer=footer_text,
    829                 note=note, sigs_in_footer=sigs_in_footer, topMargin=topMargin)
    830         except IOError:
    831             view.flash('Error in image file.')
    832             return view.redirect(view.url(view.context))
    833         except LayoutError, err:
    834             view.flash(
    835                 'PDF file could not be created. Reportlab error message: %s'
    836                 % escape(err.message),
    837                 type="danger")
    838             return view.redirect(view.url(view.context))
    839         return pdf_stream
    840 
    841     def GPABoundaries(self, faccode=None, depcode=None, certcode=None):
    842         return ((1, 'Fail'),
    843                (1.5, 'Pass'),
    844                (2.4, '3rd Class'),
    845                (3.5, '2nd Class Lower'),
    846                (4.5, '2nd Class Upper'),
    847                (5, '1st Class'))
    848 
    849     def getClassFromCGPA(self, gpa, student):
    850         """Determine the class of degree. In some custom packages
    851         this class depends on e.g. the entry session of the student. In the
    852         base package, it does not.
    853         """
    854         if gpa < self.GPABoundaries()[0][0]:
    855             return 0, self.GPABoundaries()[0][1]
    856         if gpa < self.GPABoundaries()[1][0]:
    857             return 1, self.GPABoundaries()[1][1]
    858         if gpa < self.GPABoundaries()[2][0]:
    859             return 2, self.GPABoundaries()[2][1]
    860         if gpa < self.GPABoundaries()[3][0]:
    861             return 3, self.GPABoundaries()[3][1]
    862         if gpa < self.GPABoundaries()[4][0]:
    863             return 4, self.GPABoundaries()[4][1]
    864         if gpa <= self.GPABoundaries()[5][0]:
    865             return 5, self.GPABoundaries()[5][1]
    866         return
    867 
    868     def getDegreeClassNumber(self, level_obj):
    869         """Get degree class number (used for SessionResultsPresentation
    870         reports).
    871         """
    872         if level_obj.gpa_params[1] == 0:
    873             # No credits weighted
    874             return 6
    875         return self.getClassFromCGPA(
    876             level_obj.cumulative_params[0], level_obj.student)[0]
    877 
    878     def _saveTranscriptPDF(self, student, transcript):
    879         """Create a transcript PDF file and store it in student folder.
    880         """
    881         file_store = getUtility(IExtFileStore)
    882         file_id = IFileStoreNameChooser(student).chooseName(
    883             attr="final_transcript.pdf")
    884         file_store.createFile(file_id, StringIO(transcript))
    885         return
    886916
    887917    def renderPDFTranscript(self, view, filename='transcript.pdf',
     
    10931123        return pdf_stream
    10941124
    1095     def warnCreditsOOR(self, studylevel, course=None):
    1096         """Return message if credits are out of range. In the base
    1097         package only maximum credits is set.
    1098         """
    1099         if course and studylevel.total_credits + course.credits > 50:
    1100             return _('Maximum credits exceeded.')
    1101         elif studylevel.total_credits > 50:
    1102             return _('Maximum credits exceeded.')
    1103         return
    1104 
    1105     def getBedCoordinates(self, bedticket):
    1106         """Return descriptive bed coordinates.
    1107         This method can be used to customize the `display_coordinates`
    1108         property method in order to  display a
    1109         customary description of the bed space.
    1110         """
    1111         return bedticket.bed_coordinates
    1112 
    1113     def clearance_disabled_message(self, student):
    1114         """Render message if clearance is disabled.
    1115         """
    1116         try:
    1117             session_config = grok.getSite()[
    1118                 'configuration'][str(student.current_session)]
    1119         except KeyError:
    1120             return _('Session configuration object is not available.')
    1121         if not session_config.clearance_enabled:
    1122             return _('Clearance is disabled for this session.')
    1123         return None
    1124 
    11251125    #: A dictionary which maps widget names to headlines. The headline
    11261126    #: is rendered in forms and on pdf slips above the respective
Note: See TracChangeset for help on using the changeset viewer.