source: main/waeup.sirp/trunk/src/waeup/sirp/students/vocabularies.py @ 6850

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

Set default value of verdicts.

  • Property svn:keywords set to Id
File size: 6.1 KB
Line 
1"""Vocabularies and sources for the student section.
2"""
3from datetime import datetime
4from zope.component import getUtility, queryUtility
5from zope.catalog.interfaces import ICatalog
6from zope.interface import implements, directlyProvides
7from zope.schema.interfaces import ISource, IContextSourceBinder
8from zope.schema.interfaces import ValidationError
9from zc.sourcefactory.basic import BasicSourceFactory
10from zc.sourcefactory.contextual import BasicContextualSourceFactory
11from waeup.sirp.interfaces import SimpleWAeUPVocabulary
12from waeup.sirp.students.lgas import LGAS
13from waeup.sirp.university.vocabularies import course_levels
14
15
16
17def year_range():
18    curr_year = datetime.now().year
19    return range(curr_year - 2, curr_year + 5)
20
21def academic_sessions():
22    curr_year = datetime.now().year
23    year_range = range(curr_year - 10, curr_year + 2)
24    return [('%s/%s' % (year,year+1), year) for year in year_range]
25
26academic_sessions_vocab = SimpleWAeUPVocabulary(*academic_sessions())
27
28lgas_vocab = SimpleWAeUPVocabulary(
29    *sorted([(x[1],x[0]) for x in LGAS]))
30
31def study_levels(studycourse):
32    try:
33        start_level = int(studycourse.certificate.start_level)
34        end_level = int(studycourse.certificate.end_level)
35        levels = [level for level in range(start_level,end_level+200,10)
36                   if level % 100 < 30 and level < end_level + 120]
37        return levels
38    except AttributeError:
39        return []
40
41class StudyLevelSource(BasicContextualSourceFactory):
42    """The StudyLevelSource is based on and extends the
43    course_levels vocabulary defined in the university package.
44    Repeating study levels are denoted by increments of 10, the
45    first spillover level by the certificate's end level plus 100
46    and the second spillover level by the end level plus 110.
47    """
48    def getValues(self, context):
49        return study_levels(context)
50
51    def getToken(self, context, value):
52        return str(value)
53
54    def getTitle(self, context, value):
55        end_level = int(context.certificate.end_level)
56        level,repeat = divmod(value, 100)
57        level = level * 100
58        repeat = repeat//10
59        title = course_levels.by_value[level].title
60        if level > end_level and repeat:
61            title = course_levels.by_value[level-100].title
62            title = "%s 2nd spillover" % title
63        elif level > end_level:
64            title = course_levels.by_value[level-100].title
65            title = "%s spillover" % title
66        elif repeat:
67            title = "%s on %d. probation" % (title, repeat)
68        return title
69
70verdicts = SimpleWAeUPVocabulary(
71    ('not yet','0'),
72    ('Successful student','A'),
73    ('Student with carryover courses','B'),
74    ('Student on probation','C'),
75    ('Student who were previously on probation','E'),
76    ('Medical case','F'),
77    ('Absent from examination','G'),
78    ('Withheld results','H'),
79    ('Expelled/rusticated/suspended student','I'),
80    ('Temporary withdrawn from the university','J'),
81    ('Unregistered student','K'),
82    ('Referred student','L'),
83    ('Reinstatement','M'),
84    ('Student on transfer','N'),
85    ('NCE-III repeater','O'),
86    ('New 300 level student','X'),
87    ('No previous verdict','Y'),
88    ('Successful student (provisional)','Z'),
89    ('First Class','A1'),
90    ('Second Class Upper','A2'),
91    ('Second Class Lower','A3'),
92    ('Third Class','A4'),
93    ('Pass','A5'),
94    ('Distinction','A6'),
95    ('Credit','A7'),
96    ('Merit','A8'),
97    )
98
99
100class CertificateSource(BasicContextualSourceFactory):
101    """A certificate source delivers all certificates provided
102    in the portal.
103    """
104    def getValues(self, context):
105        catalog = getUtility(ICatalog, name='certificates_catalog')
106        return sorted(list(
107                catalog.searchResults(
108                    code=('', 'z*'))),
109                    key=lambda value: value.code)
110
111    def getToken(self, context, value):
112        return value.code
113
114    def getTitle(self, context, value):
115        return "%s - %s" % (value.code, value.title[:64])
116
117
118class GenderSource(BasicSourceFactory):
119    """A gender source delivers basically a mapping
120       ``{'m': 'Male', 'f': 'Female'}``
121
122       Using a source, we make sure that the tokens (which are
123       stored/expected for instance from CSV files) are something one
124       can expect and not cryptic IntIDs.
125    """
126    def getValues(self):
127        return ['m', 'f']
128
129    def getToken(self, value):
130        return value[0].lower()
131
132    def getTitle(self, value):
133        if value == 'm':
134            return 'Male'
135        if value == 'f':
136            return 'Female'
137
138class RegNumNotInSource(ValidationError):
139    """Registration number exists already
140    """
141    # The docstring of ValidationErrors is used as error description
142    # by zope.formlib.
143    pass
144
145class MatNumNotInSource(ValidationError):
146    """Matriculation number exists already
147    """
148    # The docstring of ValidationErrors is used as error description
149    # by zope.formlib.
150    pass
151
152class RegNumberSource(object):
153    implements(ISource)
154    cat_name = 'students_catalog'
155    field_name = 'reg_number'
156    validation_error = RegNumNotInSource
157    def __init__(self, context):
158        self.context = context
159        return
160
161    def __contains__(self, value):
162        cat = queryUtility(ICatalog, self.cat_name)
163        if cat is None:
164            return True
165        kw = {self.field_name: (value, value)}
166        results = cat.searchResults(**kw)
167        for entry in results:
168            if entry.student_id != self.context.student_id:
169                # XXX: sources should simply return False.
170                #      But then we get some stupid error message in forms
171                #      when validation fails.
172                raise self.validation_error(value)
173                #return False
174        return True
175
176def contextual_reg_num_source(context):
177    source = RegNumberSource(context)
178    return source
179directlyProvides(contextual_reg_num_source, IContextSourceBinder)
180
181class MatNumberSource(RegNumberSource):
182    field_name = 'matric_number'
183    validation_error = MatNumNotInSource
184
185def contextual_mat_num_source(context):
186    source = MatNumberSource(context)
187    return source
188directlyProvides(contextual_mat_num_source, IContextSourceBinder)
Note: See TracBrowser for help on using the repository browser.