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

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

getVerdictsDict should be part of the students package. The only way to reach this ist to move the VerdictSource? to interfaces in order to avoid circular imports.

  • Property svn:keywords set to Id
File size: 6.2 KB
Line 
1## $Id: vocabularies.py 7620 2012-02-09 19:29:24Z 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            start_level = int(context.certificate.start_level)
66            end_level = int(context.certificate.end_level)
67        else:
68            start_level = 10
69            end_level = 800
70        if value < start_level or value > end_level + 110:
71            return "Error: level id %s out of range" % value
72        if value == 10:
73            return course_levels.by_value[value].title
74        level,repeat = divmod(value, 100)
75        level = level * 100
76        repeat = repeat//10
77        title = course_levels.by_value[level].title
78        if level > end_level and repeat:
79            title = course_levels.by_value[level - 100].title
80            return "%s 2nd spillover" % title
81        if level > end_level:
82            title = course_levels.by_value[level - 100].title
83            return  "%s spillover" % title
84        if repeat:
85            return "%s on %d. probation" % (title, repeat)
86        return title
87
88class CertificateSource(BasicContextualSourceFactory):
89    """A certificate source delivers all certificates provided
90    in the portal.
91    """
92    def getValues(self, context):
93        catalog = getUtility(ICatalog, name='certificates_catalog')
94        return sorted(list(
95                catalog.searchResults(
96                    code=('', 'z*'))),
97                    key=lambda value: value.code)
98
99    def getToken(self, context, value):
100        return value.code
101
102    def getTitle(self, context, value):
103        return "%s - %s" % (value.code, value.title[:64])
104
105
106class GenderSource(BasicSourceFactory):
107    """A gender source delivers basically a mapping
108       ``{'m': 'Male', 'f': 'Female'}``
109
110       Using a source, we make sure that the tokens (which are
111       stored/expected for instance from CSV files) are something one
112       can expect and not cryptic IntIDs.
113    """
114    def getValues(self):
115        return ['m', 'f']
116
117    def getToken(self, value):
118        return value[0].lower()
119
120    def getTitle(self, value):
121        if value == 'm':
122            return 'Male'
123        if value == 'f':
124            return 'Female'
125
126class RegNumNotInSource(ValidationError):
127    """Registration number exists already
128    """
129    # The docstring of ValidationErrors is used as error description
130    # by zope.formlib.
131    pass
132
133class MatNumNotInSource(ValidationError):
134    """Matriculation number exists already
135    """
136    # The docstring of ValidationErrors is used as error description
137    # by zope.formlib.
138    pass
139
140class RegNumberSource(object):
141    implements(ISource)
142    cat_name = 'students_catalog'
143    field_name = 'reg_number'
144    validation_error = RegNumNotInSource
145    def __init__(self, context):
146        self.context = context
147        return
148
149    def __contains__(self, value):
150        cat = queryUtility(ICatalog, self.cat_name)
151        if cat is None:
152            return True
153        kw = {self.field_name: (value, value)}
154        results = cat.searchResults(**kw)
155        for entry in results:
156            if entry.student_id != self.context.student_id:
157                # XXX: sources should simply return False.
158                #      But then we get some stupid error message in forms
159                #      when validation fails.
160                raise self.validation_error(value)
161                #return False
162        return True
163
164def contextual_reg_num_source(context):
165    source = RegNumberSource(context)
166    return source
167directlyProvides(contextual_reg_num_source, IContextSourceBinder)
168
169class MatNumberSource(RegNumberSource):
170    field_name = 'matric_number'
171    validation_error = MatNumNotInSource
172
173def contextual_mat_num_source(context):
174    source = MatNumberSource(context)
175    return source
176directlyProvides(contextual_mat_num_source, IContextSourceBinder)
Note: See TracBrowser for help on using the repository browser.