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

Last change on this file since 6848 was 6846, checked in by Henrik Bettermann, 13 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
Line 
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
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)
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
34    mode = None
35
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):
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]
71        return False
72
73    def getParent(self, row, site):
74        return site['students']
75
76    def getEntry(self, row, site):
77        return self.entryExists(row, site)
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):
85        student = self.entryExists(row, site)
86        if student:
87            parent = self.getParent(row, site)
88            del parent[student.student_id]
89        pass
90
91class StudentStudyCourseProcessor(BatchProcessor):
92    """A batch processor for IStudentStudyCourse objects.
93    """
94    grok.implements(IBatchProcessor)
95    grok.provides(IBatchProcessor)
96    grok.context(Interface)
97    util_name = 'studycourseupdater'
98    grok.name(util_name)
99
100    name = u'StudentStudyCourse Importer (update only)'
101    iface = IStudentStudyCourseImport
102    factory_name = 'waeup.StudentStudyCourse'
103
104    mode = None
105
106    @property
107    def available_fields(self):
108        result = []
109        return sorted(list(set(
110            ['student_id','reg_number','matric_number'] + getFields(
111                self.iface).keys())))
112
113    def checkHeaders(self, headerfields, mode='ignore'):
114        if not 'reg_number' in headerfields and not 'student_id' in headerfields and not 'matric_number' in headerfields:
115            raise FatalCSVError(
116                "Need at least columns student_id or reg_number or matric_number for import!")
117        # Check for fields to be ignored...
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):
126        if not 'students' in site.keys():
127            return False
128        if 'student_id' in row.keys() and row['student_id']:
129            if row['student_id'] in site['students']:
130                student = site['students'][row['student_id']]
131                return student
132        elif 'reg_number' in row.keys() and row['reg_number']:
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]
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]
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.