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

Last change on this file since 6838 was 6837, checked in by Henrik Bettermann, 13 years ago

Ensure that only update mode can be used for StudentStudyCourse? imports. Import mode is automatically set to 'update' if the processor's util_name contains 'update'. We can use the same technique for other processors and modes (to be implemented).

  • Property svn:keywords set to Id
File size: 4.2 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    @property
35    def req(self):
36        result = dict(
37            create = self.required_fields,
38            update = self.location_fields,
39            remove = self.location_fields,
40        )
41        return result
42
43    def parentsExist(self, row, site):
44        return 'students' in site.keys()
45
46    # The entry never exists in create mode.
47    def entryExists(self, row, site):
48        if row.has_key('student_id'):
49            return row['student_id'] in site['students'].keys()
50        return False
51
52    def getParent(self, row, site):
53        return site['students']
54
55    def getEntry(self, row, site):
56        if not self.entryExists(row, site):
57            return None
58        parent = self.getParent(row, site)
59        return parent.get(row['student_id'])
60
61    def addEntry(self, obj, row, site):
62        parent = self.getParent(row, site)
63        parent.addStudent(obj)
64        return
65
66    def delEntry(self, row, site):
67        parent = self.getParent(row, site)
68        del parent[row['student_id']]
69        pass
70
71class StudentStudyCourseProcessor(BatchProcessor):
72    """A batch processor for IStudentStudyCourse objects.
73    """
74    grok.implements(IBatchProcessor)
75    grok.provides(IBatchProcessor)
76    grok.context(Interface)
77    util_name = 'studycourseupdater'
78    grok.name(util_name)
79
80    name = u'StudentStudyCourse Importer (update only)'
81    iface = IStudentStudyCourseImport
82    factory_name = 'waeup.StudentStudyCourse'
83
84    @property
85    def available_fields(self):
86        result = []
87        return sorted(list(set(
88            ['student_id','reg_number'] + getFields(self.iface).keys())))
89
90    def checkHeaders(self, headerfields, mode='ignore'):
91        if not 'reg_number' in headerfields and not 'student_id' in headerfields:
92            raise FatalCSVError(
93                "Need at least columns student_id or reg_number for import!")
94        # Check for fields to be ignored...
95        not_ignored_fields = [x for x in headerfields
96                              if not x.startswith('--')]
97        if len(set(not_ignored_fields)) < len(not_ignored_fields):
98            raise FatalCSVError(
99                "Double headers: each column name may only appear once.")
100        return True
101
102    def parentsExist(self, row, site):
103        if not 'students' in site.keys():
104            return False
105        if 'student_id' in row.keys():
106            if row['student_id'] in site['students']:
107                student = site['students'][row['student_id']]
108                return student
109        else:
110            # Here we know that the reg_number is in row
111            reg_number = row['reg_number']
112            cat = queryUtility(ICatalog, name='students_catalog')
113            results = list(
114                cat.searchResults(reg_number=(reg_number, reg_number)))
115            if results:
116                return results[0]
117        return False
118
119    def entryExists(self, row, site):
120        student = self.parentsExist(row, site)
121        if not student:
122            return False
123        if 'studycourse' in student:
124            return student
125        return False
126
127    def getEntry(self, row, site):
128        student = self.entryExists(row, site)
129        if not student:
130            return None
131        return student.get('studycourse')
Note: See TracBrowser for help on using the repository browser.