Portal Customization

Portal customization requires profound knowledge of the Python programming language. Customization is part of the portal deployment process. It can only be done by the custom package manager and activated by the system administrator, who is allowed to update/upgrade the package on the server and restart the portal. Usually, custom packages are not designed for regular reconfiguration. Due to the complexity of school fee computation at Nigerian universities, however, a lot of configuration had to be done in the Python code and can thus not be subject to online configuration. Technically speaking, the parameters are only loaded and registered once during start-up and are not stored in the database like the configuration parameters described in Portal Configuration.

Kofa must not be customized by manipulating original Kofa code, i.e. by editing Python files, Zope page templates or ZCML configuration files in the Kofa base package. Customization is done by deploying a custom package which can inherit all the Python classes from the base package, in order to override distinct attributes and methods and register these customized classes instead of the orginal classes during start-up. It would go beyond the scope of the user handbook to explain, how to build such a Kofa custom package. This will be done in the Developer Handbook. Here we roughly describe the three different customization approaches with a focus on the third approach, the customization of utility attributes and methods.

Localization

The base language of the Kofa User Interface (Kofa UI) is English. The English language regime has been specified by WAeUP’s first customer, the University of Benin in Nigeria. Kofa is language-aware, which means it has been translated into different languages (German and French so far), and the preferred language can be selected via the UI. The Kofa UI translations and also the English language regime can be localized in custom packages by overriding single entries of the language files. Headlines, field labels, field descriptions, navigation tabs, buttons, page comments, flash messages etc. can be easily adjusted to the needs of the institution which wants to deploy Kofa.

Kofa is using the GNU gettext utilities for translation and localization. Translation is done via po text files which are located in the locales folder of a package. Each language has its own subfolder. Localized English Kofa terms, for instance, can be found in locales/en/LC_MESSAGES/waeup.kofa.po. A single entry/message consists of two lines.

Example:

msgid "Login"
msgstr "Let me in"

msgid contains the original term from the base package, msgstr contains its localized/translated version, which results into a renamed login tab on the right side of the navigation bar.

po files must be compiled before restarting the portal. Editing and compilation of po files can be done with a nice tool called ‘Poedit’ which is available for various operating systems.

Zope Interfaces

Adding further schema field attributes to content components can be done by inheriting Zope interfaces from the base package and adding new schema fields to these custom interfaces, see note. This sounds simple, but it isn’t. There are many things to think about, when customizing interfaces:

  1. A customized interface alone doesn’t have any effect, beause the content classes still implement the original interfaces. Thus, also all content classes, which are supposed to implement the extended interfaces, must be customized, and must be registered instead of the orginal classes which they inherit from. Drawback is, that this must be done before the first start-up of the portal. Otherwise, instances of the original content classes might have been created which cannot be changed afterwards.
  2. Also the forms which are being auto-generated by grok.AutoFields (see Views, Pages and Form Pages), must be customized and use the new and extended interfaces. Otherwise added fields won’t appear on form pages.
  3. The same holds for exporters and importers. They also consider the fields from interfaces when processing the data. If we forget to customize exporter or batch processor classes, only the fields from the original interfaces will be exported or reimported.

Zope Utilities

Kofa’s global utilities are perfectly suited for customization. Their attributes and methods can be easily overridden in custom packages.

Kofa Utils

The central KofaUtils utility contains not only most dictionaries used for sources (see API) but also configuration attributes like:

KofaUtils.PORTAL_LANGUAGE = 'en'

This the only place where we define the portal language which is used for the translation of system messages (e.g. object histories) pdf slips.

KofaUtils.tzinfo

Time zone of the university.

KofaUtils.SYSTEM_MAX_LOAD = {'virt-mem': None, 'cpu-load': 100.0, 'swap-mem': None}

Set positive number for allowed max, negative for required min avail. Use integer for bytes value, float for percent value. cpu-load, of course, accepts float values only. swap-mem = Swap Memory, virt-mem = Virtual Memory, cpu-load = CPU load in percent.

Customizable utility methods are:

KofaUtils.sendContactForm(from_name, from_addr, rcpt_name, rcpt_addr, from_username, usertype, portal, body, subject, bcc_to=None)[source]

Send an email with data provided by forms.

KofaUtils.fullname(firstname, lastname, middlename=None)[source]

Construct fullname.

KofaUtils.genPassword(length=4, chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')[source]

Generate a random password.

KofaUtils.sendCredentials(user, password=None, url_info=None, msg=None)[source]

Send credentials as email. Input is the user for which credentials are sent and the password. Method returns True or False to indicate successful operation.

KofaUtils.getPaymentItem(payment)[source]

Return payment item. This method can be used to customize the display_item property attribute, e.g. in order to hide bed coordinates if maintenance fee is not paid.

Students Utilities

StudentsUtils contains the following configuration attributes:

StudentsUtils.STUDENT_ID_PREFIX = u'K'

A prefix used when generating new student ids. Each student id will start with this string. The default is ‘K’ for Kofa.

StudentsUtils.SKIP_UPLOAD_VIEWLETS = ()

A tuple containing names of file upload viewlets which are not shown on the StudentClearanceManageFormPage. Nothing is being skipped in the base package. This attribute makes only sense, if intermediate custom packages are being used, like we do for all Nigerian portals.

StudentsUtils.PORTRAIT_CHANGE_STATES = ('admitted',)

A tuple containing the names of registration states in which changing of passport pictures is allowed.

StudentsUtils.SEPARATORS_DICT = {}

A dictionary which maps widget names to headlines. The headline is rendered in forms and on pdf slips above the respective display or input widget. There are no separating headlines in the base package.

StudentsUtils.STUDENT_EXPORTER_NAMES = ('students', 'studentstudycourses', 'studentstudycourses_1', 'studentstudylevels', 'coursetickets', 'studentpayments', 'bedtickets', 'trimmed', 'outstandingcourses', 'unpaidpayments', 'sfpaymentsoverview', 'sessionpaymentsoverview', 'studylevelsoverview', 'combocard', 'bursary', 'accommodationpayments', 'transcriptdata', 'trimmedpayments')

A tuple containing all exporter names referring to students or subobjects thereof.

StudentsUtils.STUDENT_BACKUP_EXPORTER_NAMES = ('students', 'studentstudycourses', 'studentstudycourses_1', 'studentstudycourses_2', 'studentstudylevels', 'studentstudylevels_1', 'studentstudylevels_2', 'coursetickets', 'coursetickets_1', 'coursetickets_2', 'studentpayments', 'bedtickets')

A tuple containing all exporter names needed for backing up student data

Customizable utility methods are:

StudentsUtils.getReturningData(student)[source]

Define what happens after school fee payment depending on the student’s senate verdict. In the base configuration current level is always increased by 100 no matter which verdict has been assigned.

StudentsUtils.setReturningData(student)[source]

Define what happens after school fee payment depending on the student’s senate verdict. This method follows the same algorithm as getReturningData but it also sets the new values.

StudentsUtils.setPaymentDetails(category, student, previous_session=None, previous_level=None, combi=[])[source]

Create a payment ticket and set the payment data of a student for the payment category specified.

StudentsUtils.setBalanceDetails(category, student, balance_session, balance_level, balance_amount)[source]

Create a balance payment ticket and set the payment data as selected by the student.

StudentsUtils.increaseMatricInteger(student)[source]

Increase counter for matric numbers. This counter can be a centrally stored attribute or an attribute of faculties, departments or certificates. In the base package the counter is as an attribute of the site configuration container.

StudentsUtils.constructMatricNumber(student)[source]

Fetch the matric number counter which fits the student and construct the new matric number of the student. In the base package the counter is returned which is as an attribute of the site configuration container.

StudentsUtils.setMatricNumber(student)[source]

Set matriculation number of student. If the student’s matric number is unset a new matric number is constructed according to the matriculation number construction rules defined in the constructMatricNumber method. The new matric number is set, the students catalog updated. The corresponding matric number counter is increased by one.

This method is tested but not used in the base package. It can be used in custom packages by adding respective views and by customizing increaseMatricInteger and constructMatricNumber according to the university’s matriculation number construction rules.

The method can be disabled by setting the counter to zero.

StudentsUtils.getAccommodationDetails(student)[source]

Determine the accommodation data of a student.

StudentsUtils.selectBed(available_beds)[source]

Select a bed from a filtered list of available beds. In the base configuration beds are sorted by the sort id of the hostel and the bed number. The first bed found in this sorted list is taken.

StudentsUtils.getPDFCreator(context)[source]

Get a pdf creator suitable for context. The default implementation always returns the default creator.

StudentsUtils.renderPDF(view, filename='slip.pdf', student=None, studentview=None, tableheader=[], tabledata=[], note=None, signatures=None, sigs_in_footer=(), show_scans=True, topMargin=1.5, omit_fields=(), mergefiles=None, watermark=None, pagebreak=False)[source]

Render pdf slips for various pages (also some pages in the applicants module).

StudentsUtils.renderPDFAdmissionLetter(view, student=None, omit_fields=(), pre_text=None, post_text=None, topMargin=1.5, letterhead_path=None, mergefiles=None, watermark=None)[source]

Render pdf admission letter.

StudentsUtils.renderPDFCourseticketsOverview(view, name, session, data, lecturers, orientation, title_length, note)[source]

Render pdf slip of course tickets for a lecturer.

StudentsUtils.renderPDFTranscript(view, filename='transcript.pdf', student=None, studentview=None, note=None, signatures=(), sigs_in_footer=(), digital_sigs=(), show_scans=True, topMargin=1.5, omit_fields=(), tableheader=None, no_passport=False, save_file=False)[source]

Render pdf slip of a transcripts.

StudentsUtils.getDegreeClassNumber(level_obj)[source]

Get degree class number (used for SessionResultsPresentation reports).

StudentsUtils.warnCreditsOOR(studylevel, course=None)[source]

Return message if credits are out of range. In the base package only maximum credits is set.

StudentsUtils.getBedCoordinates(bedticket)[source]

Return descriptive bed coordinates. This method can be used to customize the display_coordinates property method in order to display a customary description of the bed space.

StudentsUtils.clearance_disabled_message(student)[source]

Render message if clearance is disabled.

Applicants Utililties

ApplicantsUtils contains the following configuration attributes:

ApplicantsUtils.APP_TYPES_DICT = {'app': ['General Studies', 'APP'], 'special': ['Special Application', 'SPE']}

A dictionary containing application type names, titles and access code prefixes (meanwhile deprecated).

ApplicantsUtils.SEPARATORS_DICT = {'form.course1': u'Desired Study Courses', 'form.referees': u'Referees (automatically invited by email after final submission of this form)', 'form.applicant_id': u'Base Data', 'form.notice': u'Application Process Data'}

A dictionary which maps widget names to headlines. The headline is rendered in forms and on pdf slips above the respective display or input widget.

Customizable utility methods are:

ApplicantsUtils.setPaymentDetails(container, payment, applicant)[source]

Set the payment data of an applicant. In contrast to its StudentsUtils counterpart, the payment ticket must exist and is an argument of this method.

ApplicantsUtils.getApplicantsStatistics(container)[source]

Count applicants in applicants containers.

ApplicantsUtils.sortCertificates(context, resultset)[source]

Sort already filtered certificates in AppCatCertificateSource. Display also current course even if certificate in the academic section has been removed.

ApplicantsUtils.getCertTitle(context, value)[source]

Compose the titles in AppCatCertificateSource.