source: main/waeup.kofa/trunk/src/waeup/kofa/students/vocabularies.py @ 8515

Last change on this file since 8515 was 8471, checked in by Henrik Bettermann, 12 years ago

Add new workflow transitions for postgraduate students. Take care for correct payment. Since pg students bypass course registration, we need new names and titles for session activation button and page.

  • Property svn:keywords set to Id
File size: 6.7 KB
RevLine 
[7191]1## $Id: vocabularies.py 8471 2012-05-20 05:46:07Z 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##
[6648]18"""Vocabularies and sources for the student section.
19"""
[6787]20from zope.component import getUtility, queryUtility
[6648]21from zope.catalog.interfaces import ICatalog
[6787]22from zope.interface import implements, directlyProvides
23from zope.schema.interfaces import ISource, IContextSourceBinder
24from zope.schema.interfaces import ValidationError
[6648]25from zc.sourcefactory.basic import BasicSourceFactory
26from zc.sourcefactory.contextual import BasicContextualSourceFactory
[7819]27from waeup.kofa.interfaces import SimpleKofaVocabulary
[7811]28from waeup.kofa.interfaces import MessageFactory as _
[8069]29from waeup.kofa.utils.helpers import get_sorted_preferred
30from waeup.kofa.utils.countries import COUNTRIES
[7811]31from waeup.kofa.university.vocabularies import course_levels
[6648]32
33
[8069]34#: a tuple of tuples (<COUNTRY-NAME>, <ISO-CODE>) with Nigeria first.
35COUNTRIES = get_sorted_preferred(COUNTRIES, ['NG'])
36nats_vocab = SimpleKofaVocabulary(*COUNTRIES)
[7523]37
[6725]38def study_levels(studycourse):
[7532]39    if studycourse.certificate is not None:
[6725]40        start_level = int(studycourse.certificate.start_level)
41        end_level = int(studycourse.certificate.end_level)
[8471]42        if start_level == 999 or end_level == 999:
43            levels = [999]
44        elif start_level == 10:
[7625]45            levels = [10,] + [level for level in range(100,end_level+200,10)
46                if level % 100 < 30]
47        else:
48            levels = [level for level in range(start_level,end_level+200,10)
49                if level % 100 < 30]
[7532]50    else:
[7625]51        # default level range
[8098]52        levels = [level for level in range(100,1000,10) if level % 100 < 30]
[7532]53    return levels
[6787]54
[7532]55
[6725]56class StudyLevelSource(BasicContextualSourceFactory):
57    """The StudyLevelSource is based on and extends the
58    course_levels vocabulary defined in the university package.
59    Repeating study levels are denoted by increments of 10, the
60    first spillover level by the certificate's end level plus 100
61    and the second spillover level by the end level plus 110.
62    """
63    def getValues(self, context):
64        return study_levels(context)
[6724]65
[6725]66    def getToken(self, context, value):
67        return str(value)
68
69    def getTitle(self, context, value):
[7532]70        if context.certificate is not None:
[7617]71            start_level = int(context.certificate.start_level)
[7532]72            end_level = int(context.certificate.end_level)
73        else:
[7625]74            # default level range
75            start_level = 100
[8098]76            end_level = 1000
[8471]77        if start_level == 999 or end_level == 999:
78            if value != 999:
79                return _('Error: wrong level id ${value}',
80                    mapping={'value': value})
81            return course_levels.by_value[999].title
[7625]82        if value < start_level or value > end_level + 120:
[7691]83            return _('Error: level id ${value} out of range',
84                mapping={'value': value})
[7625]85        # Special treatment for pre-studies level
[7617]86        if value == 10:
87            return course_levels.by_value[value].title
[6725]88        level,repeat = divmod(value, 100)
89        level = level * 100
90        repeat = repeat//10
91        title = course_levels.by_value[level].title
[7625]92        if level > end_level and repeat == 1:
[7617]93            title = course_levels.by_value[level - 100].title
[7691]94            return _('${title} 2nd spillover', mapping={'title': title})
[7625]95        if level > end_level and repeat == 2:
96            title = course_levels.by_value[level - 100].title
[7691]97            return _('${title} 3rd spillover', mapping={'title': title})
[7617]98        if level > end_level:
99            title = course_levels.by_value[level - 100].title
[7691]100            return  _('${title} 1st spillover', mapping={'title': title})
[7625]101        if repeat == 1:
[7691]102            return _('${title} on 1st probation', mapping={'title': title})
[7625]103        if repeat == 2:
[7691]104            return _('${title} on 2nd probation', mapping={'title': title})
[6725]105        return title
106
[6648]107class GenderSource(BasicSourceFactory):
108    """A gender source delivers basically a mapping
109       ``{'m': 'Male', 'f': 'Female'}``
110
111       Using a source, we make sure that the tokens (which are
112       stored/expected for instance from CSV files) are something one
113       can expect and not cryptic IntIDs.
114    """
115    def getValues(self):
116        return ['m', 'f']
117
118    def getToken(self, value):
119        return value[0].lower()
120
121    def getTitle(self, value):
122        if value == 'm':
[7872]123            return _('male')
[6648]124        if value == 'f':
[7872]125            return _('female')
[6787]126
127class RegNumNotInSource(ValidationError):
128    """Registration number exists already
129    """
130    # The docstring of ValidationErrors is used as error description
131    # by zope.formlib.
132    pass
133
134class MatNumNotInSource(ValidationError):
135    """Matriculation number exists already
136    """
137    # The docstring of ValidationErrors is used as error description
138    # by zope.formlib.
139    pass
140
141class RegNumberSource(object):
142    implements(ISource)
143    cat_name = 'students_catalog'
144    field_name = 'reg_number'
145    validation_error = RegNumNotInSource
146    def __init__(self, context):
147        self.context = context
148        return
149
150    def __contains__(self, value):
151        cat = queryUtility(ICatalog, self.cat_name)
152        if cat is None:
153            return True
154        kw = {self.field_name: (value, value)}
155        results = cat.searchResults(**kw)
156        for entry in results:
157            if entry.student_id != self.context.student_id:
158                # XXX: sources should simply return False.
159                #      But then we get some stupid error message in forms
160                #      when validation fails.
161                raise self.validation_error(value)
162                #return False
163        return True
164
165def contextual_reg_num_source(context):
166    source = RegNumberSource(context)
167    return source
168directlyProvides(contextual_reg_num_source, IContextSourceBinder)
169
170class MatNumberSource(RegNumberSource):
171    field_name = 'matric_number'
172    validation_error = MatNumNotInSource
173
174def contextual_mat_num_source(context):
175    source = MatNumberSource(context)
176    return source
177directlyProvides(contextual_mat_num_source, IContextSourceBinder)
Note: See TracBrowser for help on using the repository browser.