students.batching - Student Import and Export Components

Batch processing components for student objects.

Batch processors eat CSV files to add, update or remove large numbers of certain kinds of objects at once.

Here we define the processors for students specific objects like students, studycourses, payment tickets and accommodation tickets.

class waeup.kofa.students.batching.CourseTicketProcessor[source]

Bases: waeup.kofa.students.batching.StudentProcessorBase

The Course Ticket Processor imports course tickets, the subobjects of student study levels (= course lists).

An imported course ticket contains a copy of the original course data. During import only a few attributes can be set/overwritten.

Like all other student data importers, this processor also requires either student_id, reg_number or matric_number to find the student. Then it needs level and code to localize the course ticket.

checkConversion first searches the courses catalog for the imported code and ensures that a course with such a code really exists in the academic section. It furthermore checks if level_session in the row corresponds with the session of the parent student study level object. It fails if one of the conditions is not met.

In create mode fcode, dcode, title, credits, passmark and semester are taken from the course found in the academic section. fcode and dcode can nevermore be changed, neither via the user interface nor by import. Other values can be overwritten by import.

__doc__ = 'The Course Ticket Processor imports course tickets, the subobjects\n of student study levels (= course lists).\n\n An imported course ticket contains a copy of the original course data.\n During import only a few attributes can be set/overwritten.\n\n Like all other student data importers, this processor also requires\n either `student_id`, `reg_number` or `matric_number` to find the student.\n Then it needs `level` and `code` to localize the course ticket.\n\n `checkConversion` first searches the courses catalog for the imported\n `code` and ensures that a course with such a code really exists\n in the academic section. It furthermore checks if `level_session` in\n the row corresponds with the session of the parent student\n study level object. It fails if one of the conditions is not met.\n\n In create mode `fcode`, `dcode`, `title`, `credits`, `passmark` and\n `semester` are taken from the course found in the academic section.\n `fcode` and `dcode` can nevermore be changed, neither via the user interface\n nor by import. Other values can be overwritten by import.\n '
__implemented__ = <implementedBy waeup.kofa.students.batching.CourseTicketProcessor>
__module__ = 'waeup.kofa.students.batching'
__provides__

Special descriptor for class __provides__

The descriptor caches the implementedBy info, so that we can get declarations for objects without instance-specific interfaces a bit quicker.

For example:

>>> from zope.interface import Interface
>>> class IFooFactory(Interface):
...     pass
>>> class IFoo(Interface):
...     pass
>>> class C(object):
...     implements(IFoo)
...     classProvides(IFooFactory)
>>> [i.getName() for i in C.__provides__]
['IFooFactory']
>>> [i.getName() for i in C().__provides__]
['IFoo']
addEntry(obj, row, site)[source]
additional_fields = ['level', 'code']
additional_fields_required = ['level', 'code']
available_fields
checkConversion(row, mode='ignore')[source]

Validates all values in row.

delEntry(row, site)[source]
factory_name = 'waeup.CourseTicket'
getEntry(row, site)[source]
getParent(row, site)[source]
iface = <InterfaceClass waeup.kofa.students.interfaces.ICourseTicketImport>
name = u'CourseTicket Processor'
updateEntry(obj, row, site, filename)[source]

Update obj to the values given in row.

util_name = 'courseticketprocessor'
class waeup.kofa.students.batching.StudentOnlinePaymentProcessor[source]

Bases: waeup.kofa.students.batching.StudentProcessorBase

The Student Online Payment Processor imports student payment tickets. The tickets are located in the payments subfolder of the student container. The only additional locator is p_id, the object id.

The checkConversion method checks the format of the payment identifier. In create mode it does also ensures that same p_id does not exist elsewhere. It must be portal-wide unique.

When adding a payment ticket, the addEntry method checks if the same payment has already been made. It compares p_category and p_session in the row with the corresponding attributes of existing payment tickets in state paid. If they match, a DuplicationError is raised.

__doc__ = 'The Student Online Payment Processor imports student payment tickets.\n The tickets are located in the ``payments`` subfolder of the student\n container. The only additional locator is `p_id`, the object id.\n\n The `checkConversion` method checks the format of the payment identifier.\n In create mode it does also ensures that same `p_id` does not exist\n elsewhere. It must be portal-wide unique.\n\n When adding a payment ticket, the `addEntry` method checks if the same\n payment has already been made. It compares `p_category` and `p_session`\n in the row with the corresponding attributes of existing payment\n tickets in state ``paid``. If they match, a `DuplicationError` is raised.\n '
__implemented__ = <implementedBy waeup.kofa.students.batching.StudentOnlinePaymentProcessor>
__module__ = 'waeup.kofa.students.batching'
__provides__

Special descriptor for class __provides__

The descriptor caches the implementedBy info, so that we can get declarations for objects without instance-specific interfaces a bit quicker.

For example:

>>> from zope.interface import Interface
>>> class IFooFactory(Interface):
...     pass
>>> class IFoo(Interface):
...     pass
>>> class C(object):
...     implements(IFoo)
...     classProvides(IFooFactory)
>>> [i.getName() for i in C.__provides__]
['IFooFactory']
>>> [i.getName() for i in C().__provides__]
['IFoo']
addEntry(obj, row, site)[source]
additional_fields = ['p_id']
available_fields
checkConversion(row, mode='ignore')[source]

Validates all values in row.

checkHeaders(headerfields, mode='ignore')[source]
delEntry(row, site)[source]
factory_name = 'waeup.StudentOnlinePayment'
getEntry(row, site)[source]
getParent(row, site)[source]
iface = <InterfaceClass waeup.kofa.students.interfaces.IStudentOnlinePayment>
name = u'StudentOnlinePayment Processor'
parentsExist(row, site)[source]
samePaymentMade(student, category, p_session)[source]
updateEntry(obj, row, site, filename)[source]

Update obj to the values given in row.

util_name = 'paymentprocessor'
class waeup.kofa.students.batching.StudentProcessor[source]

Bases: waeup.kofa.utils.batching.BatchProcessor

The Student Processor imports student base data.

In create mode no locator is required. If no student_id is given, the portal automatically assigns a new student id.

In update or remove mode the processor uses either the student_id, reg_number or matric_number to localize the student object, exactly in this order. If student_id is given and an object can be found, reg_number and matric_number will be overwritten by the values provided in the import file. If student_id is missing, reg_number is used to localize the object and only matric_number will be overwritten. matric_number is used as locator only if both student_id and reg_number are missing. student_id can’t be changed by the batch processor.

There are two ways to change the workflow state of the student, an unsafe and a safe way. The safe way makes use of workflow transitions. Transitions are only possible between allowed workflow states. Only transitions ensure that the registration workflow is maintained.

Always prefer the safe way!

__doc__ = "The Student Processor imports student base data.\n\n In create mode no locator is required. If no `student_id` is given,\n the portal automatically assigns a new student id.\n\n In update or remove mode the processor uses\n either the `student_id`, `reg_number` or `matric_number` to localize the \n student object, exactly in this order. If `student_id` is given and an\n object can be found, `reg_number` and `matric_number` will be overwritten\n by the values provided in the import file. If `student_id` is missing,\n `reg_number` is used to localize the object and only `matric_number`\n will be overwritten. `matric_number` is used as locator only if both\n `student_id` and `reg_number` are missing. `student_id` can't be changed\n by the batch processor.\n\n There are two ways to change the workflow state of the student,\n an unsafe and a safe way. The safe way makes use of workflow transitions.\n Transitions are only possible between allowed workflow states. Only\n transitions ensure that the registration workflow is maintained.\n\n **Always prefer the safe way!**\n "
__implemented__ = <implementedBy waeup.kofa.students.batching.StudentProcessor>
__module__ = 'waeup.kofa.students.batching'
__provides__

Special descriptor for class __provides__

The descriptor caches the implementedBy info, so that we can get declarations for objects without instance-specific interfaces a bit quicker.

For example:

>>> from zope.interface import Interface
>>> class IFooFactory(Interface):
...     pass
>>> class IFoo(Interface):
...     pass
>>> class C(object):
...     implements(IFoo)
...     classProvides(IFooFactory)
>>> [i.getName() for i in C.__provides__]
['IFooFactory']
>>> [i.getName() for i in C().__provides__]
['IFoo']
addEntry(obj, row, site)[source]
available_fields
checkConversion(row, mode='create')[source]

Validates all values in row.

checkHeaders(headerfields, mode='create')[source]
checkUpdateRequirements(obj, row, site)[source]

Checks requirements the object must fulfill when being updated.

This method is not used in case of deleting or adding objects.

Returns error messages as strings in case of requirement problems.

delEntry(row, site)[source]
entryExists(row, site)[source]
factory_name = 'waeup.Student'
getEntry(row, site)[source]
getLocator(row)[source]
getMapping(path, headerfields, mode)[source]

Get a mapping from CSV file headerfields to actually used fieldnames.

getParent(row, site)[source]
iface = <InterfaceClass waeup.kofa.students.interfaces.IStudent>
iface_bymatricnumber = <InterfaceClass waeup.kofa.students.interfaces.IStudentUpdateByMatricNo>
iface_byregnumber = <InterfaceClass waeup.kofa.students.interfaces.IStudentUpdateByRegNo>
name = u'Student Processor'
parentsExist(row, site)[source]
updateEntry(obj, row, site, filename)[source]

Update obj to the values given in row.

util_name = 'studentprocessor'
class waeup.kofa.students.batching.StudentProcessorBase[source]

Bases: waeup.kofa.utils.batching.BatchProcessor

A base for student subitem processor.

Helps reducing redundancy.

__doc__ = 'A base for student subitem processor.\n\n Helps reducing redundancy.\n '
__implemented__ = <implementedBy waeup.kofa.students.batching.StudentProcessorBase>
__module__ = 'waeup.kofa.students.batching'
__provides__

Special descriptor for class __provides__

The descriptor caches the implementedBy info, so that we can get declarations for objects without instance-specific interfaces a bit quicker.

For example:

>>> from zope.interface import Interface
>>> class IFooFactory(Interface):
...     pass
>>> class IFoo(Interface):
...     pass
>>> class C(object):
...     implements(IFoo)
...     classProvides(IFooFactory)
>>> [i.getName() for i in C.__provides__]
['IFooFactory']
>>> [i.getName() for i in C().__provides__]
['IFoo']
_getStudent(row, site)[source]
additional_fields = []
additional_fields_required = []
available_fields
checkConversion(row, mode='ignore')[source]

Validates all values in row.

checkHeaders(headerfields, mode='ignore')[source]
entryExists(row, site)[source]
getMapping(path, headerfields, mode)[source]

Get a mapping from CSV file headerfields to actually used fieldnames.

parentsExist(row, site)[source]
class waeup.kofa.students.batching.StudentStudyCourseProcessor[source]

Bases: waeup.kofa.students.batching.StudentProcessorBase

The Student Study Course Processor imports data which refer to the student’s course of study. The study course container data describe the current state of the course of study and it stores the entry conditions, i.e. when the student started the course.

Most important is the certificate attribute which tells us which course the student is studying. The terms ‘study course’ and ‘course of study’ are used synonymously. The ‘certificate’ is the study programme described in the acadmic section. The study course object stores a referrer to a certificate in the acadmic section.

When importing a new certificate code, checkConversion does not only check whether a certificate with the same code exists, it also proves if current_level is inside the level range of the certificate. For example, some study programmes start at level 200. The imported current level must thus be 200 or higher.

checkUpdateRequirements looks up if the imported values match the certificate already stored with the study course object. The imported current_level must be in the range of the certificate already stored.

Note

The processor does only offer an update mode. An ‘empty’ study course object is automatically created when the student object is added. So this object always exists. It can neither be added a second time nor be removed.

Students can be transferred by import. A transfer is initialized if the entry_mode value is transfer. In this case checkConversion uses a different interface for data validation and checkUpdateRequirements ensures that a student can only be transferred twice. The student transfer process is described elsewhere.

__doc__ = "The Student Study Course Processor imports data which refer\n to the student's course of study. The study course container data\n describe the current state of the course of study and it stores the\n entry conditions, i.e. when the student started the course.\n\n Most important is the `certificate` attribute which tells us which course \n the student is studying. The terms 'study course' and 'course of study'\n are used synonymously. The 'certificate' is the study programme described\n in the acadmic section. The study course object stores a referrer to a\n certificate in the acadmic section.\n\n When importing a new certificate code, `checkConversion` does not only\n check whether a certificate with the same code exists, it also\n proves if `current_level` is inside the level range of the certificate.\n For example, some study programmes start at level 200. The imported\n current level must thus be 200 or higher.\n\n `checkUpdateRequirements` looks up if the imported values match the\n certificate already stored with the study course object. The imported\n `current_level` must be in the range of the certificate already\n stored.\n\n .. note::\n\n The processor does only offer an update mode. An 'empty' study course \n object is automatically created when the student object is added. So this\n object always exists. It can neither be added a second time nor\n be removed.\n\n Students can be transferred by import. A transfer is initialized if the\n `entry_mode` value is ``transfer``. In this case `checkConversion` uses a\n different interface for data validation and `checkUpdateRequirements`\n ensures that a student can only be transferred twice. The student transfer\n process is described elsewhere.\n "
__implemented__ = <implementedBy waeup.kofa.students.batching.StudentStudyCourseProcessor>
__module__ = 'waeup.kofa.students.batching'
__provides__

Special descriptor for class __provides__

The descriptor caches the implementedBy info, so that we can get declarations for objects without instance-specific interfaces a bit quicker.

For example:

>>> from zope.interface import Interface
>>> class IFooFactory(Interface):
...     pass
>>> class IFoo(Interface):
...     pass
>>> class C(object):
...     implements(IFoo)
...     classProvides(IFooFactory)
>>> [i.getName() for i in C.__provides__]
['IFooFactory']
>>> [i.getName() for i in C().__provides__]
['IFoo']
checkConversion(row, mode='ignore')[source]

Validates all values in row.

checkUpdateRequirements(obj, row, site)[source]

Checks requirements the object must fulfill when being updated. Returns error messages as strings in case of requirement problems.

factory_name = 'waeup.StudentStudyCourse'
getEntry(row, site)[source]
getParent(row, site)[source]
iface = <InterfaceClass waeup.kofa.students.interfaces.IStudentStudyCourse>
iface_transfer = <InterfaceClass waeup.kofa.students.interfaces.IStudentStudyCourseTransfer>
name = u'StudentStudyCourse Processor (update only)'
updateEntry(obj, row, site, filename)[source]

Update obj to the values given in row.

util_name = 'studycourseupdater'
class waeup.kofa.students.batching.StudentStudyLevelProcessor[source]

Bases: waeup.kofa.students.batching.StudentProcessorBase

The Student Study Level Processor imports study level data. It overwrites the container attributes but not the content of the container, i.e. the course tickets stored inside the container. There is nothing special about this processor.

__doc__ = 'The Student Study Level Processor imports study level data.\n It overwrites the container attributes but not the content of the container,\n i.e. the course tickets stored inside the container. There is nothing\n special about this processor.\n '
__implemented__ = <implementedBy waeup.kofa.students.batching.StudentStudyLevelProcessor>
__module__ = 'waeup.kofa.students.batching'
__provides__

Special descriptor for class __provides__

The descriptor caches the implementedBy info, so that we can get declarations for objects without instance-specific interfaces a bit quicker.

For example:

>>> from zope.interface import Interface
>>> class IFooFactory(Interface):
...     pass
>>> class IFoo(Interface):
...     pass
>>> class C(object):
...     implements(IFoo)
...     classProvides(IFooFactory)
>>> [i.getName() for i in C.__provides__]
['IFooFactory']
>>> [i.getName() for i in C().__provides__]
['IFoo']
addEntry(obj, row, site)[source]
available_fields
delEntry(row, site)[source]
factory_name = 'waeup.StudentStudyLevel'
getEntry(row, site)[source]
getParent(row, site)[source]
iface = <InterfaceClass waeup.kofa.students.interfaces.IStudentStudyLevel>
name = u'StudentStudyLevel Processor'
updateEntry(obj, row, site, filename)[source]

Update obj to the values given in row.

util_name = 'studylevelprocessor'
class waeup.kofa.students.batching.StudentVerdictProcessor[source]

Bases: waeup.kofa.students.batching.StudentStudyCourseProcessor

The Student Verdict Processor inherits from the Student Study Course Processor. It’s a pure updater. Import step 2 raises a warning message if a datacenter manager tries to select another mode. But it does more than only overwriting study course attributes.

The Student Verdict Processor is the only processor which cannot be used for restoring data. Purpose is to announce a verdict at the end of each academic session. The processor does not only import a verdict, it also conditions the student data so that the student can pay for the next session and proceed to the next study level.

The checkUpdateRequirements method ensures that the imported data really correspond to the actual state of the student. current_level and current_session in the row must be on par with the attributes of the study course object. Thus, the processor does not use these values to overwrite the attributes of the study course but to control that the verdict is really meant for the current session of the student. The verdict is only imported if a corresponding study level object exists and the student is in the right registration state, either courses validated or courses registered. Course registration can be bypassed by setting bypass_validation to True.

The updateEntry method does not only update the current verdict of the student study course, it also updates the matching student study level object. It saves the current verdict as level_verdict and sets the validated_by and validation_date attributes, whereas validated_by is taken from the row of the import file and validation_date is set to the actual UTC datetime. Finally, the student is moved to state returning.

__doc__ = "The Student Verdict Processor inherits from the Student Study\n Course Processor. It's a pure updater. Import step 2 raises a warning\n message if a datacenter manager tries to select another mode.\n But it does more than only overwriting study course attributes.\n\n The Student Verdict Processor is the only processor which cannot be\n used for restoring data. Purpose is to announce a verdict at the end of\n each academic session. The processor does not only import a verdict,\n it also conditions the student data so that the student can pay for the\n next session and proceed to the next study level.\n\n The `checkUpdateRequirements` method ensures that the imported data\n really correspond to the actual state of the student.\n `current_level` and `current_session` in the row must be on par\n with the attributes of the study course object. Thus, the processor\n does not use these values to overwrite the attributes of the study course\n but to control that the verdict is really meant for the current session of\n the student. The verdict is only imported if a corresponding study level\n object exists and the student is in the right registration state,\n either ``courses validated`` or ``courses registered``. Course registration\n can be bypassed by setting `bypass_validation` to ``True``.\n\n The `updateEntry` method does not only update the current verdict of\n the student study course, it also updates the matching student study\n level object. It saves the current verdict as `level_verdict` and sets\n the `validated_by` and `validation_date` attributes, whereas `validated_by` \n is taken from the row of the import file and `validation_date` is set to the\n actual UTC datetime. Finally, the student is moved to state ``returning``.\n "
__module__ = 'waeup.kofa.students.batching'
checkUpdateRequirements(obj, row, site)[source]

Checks requirements the studycourse and the student must fulfill before being updated.

factory_name = 'waeup.StudentStudyCourse'
iface = <InterfaceClass waeup.kofa.students.interfaces.IStudentVerdictUpdate>
name = u'Verdict Processor (special processor, update only)'
updateEntry(obj, row, site, filename)[source]

Update obj to the values given in row.

util_name = 'verdictupdater'