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

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

Extend level range.

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