source: main/waeup.sirp/trunk/src/waeup/sirp/students/batching.py @ 6847

Last change on this file since 6847 was 6846, checked in by Henrik Bettermann, 14 years ago

Enable locating students by reg_number or matric_number for update and removal.

Allow adding students by pre-selecting the student_id and bypassing the random student_id generator. This is important for the migration of student data.

Further tests are needed and will follow!

  • Property svn:keywords set to Id
File size: 5.5 KB
RevLine 
[6821]1"""Batch processing components for academics objects.
2
3Batch processors eat CSV files to add, update or remove large numbers
4of certain kinds of objects at once.
5
6Here we define the processors for academics specific objects like
7faculties, departments and the like.
8"""
9import grok
10from zope.interface import Interface
[6825]11from zope.schema import getFields
12from zope.component import queryUtility
13from zope.catalog.interfaces import ICatalog
14from waeup.sirp.interfaces import IBatchProcessor, FatalCSVError
15from waeup.sirp.students.interfaces import (
16    IStudent, IStudentStudyCourse, IStudentStudyCourseImport)
[6821]17from waeup.sirp.utils.batching import BatchProcessor
18
19class StudentProcessor(BatchProcessor):
20    """A batch processor for IStudent objects.
21    """
22    grok.implements(IBatchProcessor)
23    grok.provides(IBatchProcessor)
24    grok.context(Interface)
25    util_name = 'studentimporter'
26    grok.name(util_name)
27
28    name = u'Student Importer'
29    iface = IStudent
30
31    location_fields = ['student_id',]
32    factory_name = 'waeup.Student'
33
[6841]34    mode = None
35
[6821]36    @property
37    def req(self):
38        result = dict(
39            create = self.required_fields,
40            update = self.location_fields,
41            remove = self.location_fields,
42        )
43        return result
44
45    def parentsExist(self, row, site):
46        return 'students' in site.keys()
47
48    # The entry never exists in create mode.
49    def entryExists(self, row, site):
[6846]50        if not 'students' in site.keys():
51            return False
52        if 'student_id' in row.keys() and row['student_id']:
53            if row['student_id'] in site['students']:
54                student = site['students'][row['student_id']]
55                return student
56        elif 'reg_number' in row.keys() and row['reg_number']:
57            reg_number = row['reg_number']
58            cat = queryUtility(ICatalog, name='students_catalog')
59            results = list(
60                cat.searchResults(reg_number=(reg_number, reg_number)))
61            if results:
62                return results[0]
63        elif 'matric_number' in row.keys() and row['matric_number']:
64            #import pdb; pdb.set_trace()
65            matric_number = row['matric_number']
66            cat = queryUtility(ICatalog, name='students_catalog')
67            results = list(
68                cat.searchResults(matric_number=(matric_number, matric_number)))
69            if results:
70                return results[0]
[6821]71        return False
72
73    def getParent(self, row, site):
74        return site['students']
75
76    def getEntry(self, row, site):
[6846]77        return self.entryExists(row, site)
[6821]78
79    def addEntry(self, obj, row, site):
80        parent = self.getParent(row, site)
81        parent.addStudent(obj)
82        return
83
84    def delEntry(self, row, site):
[6846]85        student = self.entryExists(row, site)
86        if student:
87            parent = self.getParent(row, site)
88            del parent[student.student_id]
[6821]89        pass
[6825]90
91class StudentStudyCourseProcessor(BatchProcessor):
92    """A batch processor for IStudentStudyCourse objects.
93    """
94    grok.implements(IBatchProcessor)
95    grok.provides(IBatchProcessor)
96    grok.context(Interface)
[6837]97    util_name = 'studycourseupdater'
[6825]98    grok.name(util_name)
99
[6837]100    name = u'StudentStudyCourse Importer (update only)'
[6825]101    iface = IStudentStudyCourseImport
102    factory_name = 'waeup.StudentStudyCourse'
103
[6841]104    mode = None
105
[6825]106    @property
107    def available_fields(self):
108        result = []
109        return sorted(list(set(
[6843]110            ['student_id','reg_number','matric_number'] + getFields(
111                self.iface).keys())))
[6825]112
[6837]113    def checkHeaders(self, headerfields, mode='ignore'):
[6843]114        if not 'reg_number' in headerfields and not 'student_id' in headerfields and not 'matric_number' in headerfields:
[6825]115            raise FatalCSVError(
[6843]116                "Need at least columns student_id or reg_number or matric_number for import!")
[6834]117        # Check for fields to be ignored...
[6825]118        not_ignored_fields = [x for x in headerfields
119                              if not x.startswith('--')]
120        if len(set(not_ignored_fields)) < len(not_ignored_fields):
121            raise FatalCSVError(
122                "Double headers: each column name may only appear once.")
123        return True
124
125    def parentsExist(self, row, site):
[6846]126        if not 'students' in site.keys():
[6825]127            return False
[6846]128        if 'student_id' in row.keys() and row['student_id']:
[6825]129            if row['student_id'] in site['students']:
130                student = site['students'][row['student_id']]
131                return student
[6843]132        elif 'reg_number' in row.keys() and row['reg_number']:
[6825]133            reg_number = row['reg_number']
134            cat = queryUtility(ICatalog, name='students_catalog')
135            results = list(
136                cat.searchResults(reg_number=(reg_number, reg_number)))
137            if results:
138                return results[0]
[6843]139        elif 'matric_number' in row.keys() and row['matric_number']:
140            matric_number = row['matric_number']
141            cat = queryUtility(ICatalog, name='students_catalog')
142            results = list(
143                cat.searchResults(matric_number=(matric_number, matric_number)))
144            if results:
145                return results[0]
[6825]146        return False
147
148    def entryExists(self, row, site):
149        student = self.parentsExist(row, site)
150        if not student:
151            return False
152        if 'studycourse' in student:
153            return student
154        return False
155
156    def getEntry(self, row, site):
157        student = self.entryExists(row, site)
158        if not student:
159            return None
160        return student.get('studycourse')
Note: See TracBrowser for help on using the repository browser.