source: main/waeup.kofa/trunk/src/waeup/kofa/university/course.py @ 17650

Last change on this file since 17650 was 15629, checked in by Henrik Bettermann, 5 years ago

Add score_editing_disabled switch at course level. Plugins must be updated!

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 5.2 KB
Line 
1## $Id: course.py 15629 2019-10-01 10:22:33Z 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"""Courses.
19"""
20import grok
21import zope.location.location
22from zope.catalog.interfaces import ICatalog
23from zope.interface import implementedBy
24from zope.schema import getFields
25from zope.intid.interfaces import IIntIds
26from zope.component import getUtility
27from zope.component.interfaces import IFactory, ComponentLookupError
28from waeup.kofa.interfaces import IKofaPluggable
29from waeup.kofa.university.interfaces import ICourse
30from waeup.kofa.utils.batching import VirtualExportJobContainer
31
32class VirtualCourseExportJobContainer(VirtualExportJobContainer):
33    """A virtual export job container for courses.
34    """
35
36class Course(grok.Model):
37    """A university course.
38    """
39    grok.implements(ICourse)
40
41    local_roles = ['waeup.local.Lecturer']
42
43    def __init__(self,
44                 title=u'Unnamed Course',
45                 code=u'NA',
46                 credits=0,
47                 passmark=40,
48                 semester=1,
49                 former_course=False,
50                 **kw):
51        super(Course, self).__init__(**kw)
52        self.title = title
53        self.code = code
54        self.credits = credits
55        self.passmark = passmark
56        self.semester = semester
57        self.former_course = former_course
58        self.results_validated_by = None
59        self.results_validation_date = None
60        self.results_validation_session = None
61        self.score_editing_disabled = False
62
63    def traverse(self, name):
64        """Deliver appropriate containers.
65        """
66        if name == 'exports':
67            # create a virtual exports container and return it
68            container = VirtualCourseExportJobContainer()
69            zope.location.location.located(container, self, 'exports')
70            return container
71        return None
72
73    @property
74    def longtitle(self):
75        return "%s (%s)" % (self.title,self.code)
76
77class CourseFactory(grok.GlobalUtility):
78    """A factory for courses.
79    """
80    grok.implements(IFactory)
81    grok.name(u'waeup.Course')
82    title = u"Create a new course.",
83    description = u"This factory instantiates new course instances."
84
85    def __call__(self, *args, **kw):
86        return Course(*args, **kw)
87
88    def getInterfaces(self):
89        return implementedBy(Course)
90
91@grok.subscribe(ICourse, grok.IObjectRemovedEvent)
92def handle_course_removed(course, event):
93    """If a course is deleted, we make sure that also referrers in a
94       certificatescontainer are removed.
95    """
96    code = course.code
97
98    # Find all certificatecourses that refer to given course
99    try:
100        cat = getUtility(ICatalog, name='certcourses_catalog')
101    except ComponentLookupError:
102        # catalog not available. This might happen during tests.
103        return
104
105    results = cat.searchResults(course_code=(code, code))
106
107    # remove each found referrer (certs might refer to same course multiple
108    # times)
109    certs = [x.__parent__ for x in results]
110    unique_certs = list(set(certs))
111    for cert in unique_certs:
112        cert.delCertCourses(code)
113    return
114
115@grok.subscribe(ICourse, grok.IObjectModifiedEvent)
116def handle_set_former_course(course, event):
117    """If a former course attribute is set, we make sure that referrers in a
118       certificatescontainer are removed.
119    """
120    if event.object.former_course:
121        handle_course_removed(course, event)
122    return
123
124class CoursesPlugin(grok.GlobalUtility):
125    """A plugin that updates courses.
126    """
127
128    grok.implements(IKofaPluggable)
129    grok.name('courses')
130
131    deprecated_attributes = []
132
133    def setup(self, site, name, logger):
134        return
135
136    def update(self, site, name, logger):
137        cat = getUtility(ICatalog, name='courses_catalog')
138        results = cat.apply({'code':(None,None)})
139        uidutil = getUtility(IIntIds, context=cat)
140        items = getFields(ICourse).items()
141        for r in results:
142            o = uidutil.getObject(r)
143            # Add new attributes
144            for i in items:
145                if not hasattr(o,i[0]):
146                    setattr(o,i[0],i[1].missing_value)
147                    logger.info(
148                        'CoursesPlugin: %s attribute %s added.' % (
149                        o.code,i[0]))
150            # Remove deprecated attributes
151            for i in self.deprecated_attributes:
152                try:
153                    delattr(o,i)
154                    logger.info(
155                        'CoursesPlugin: %s attribute %s deleted.' % (
156                        o.code,i))
157                except AttributeError:
158                    pass
159        return
Note: See TracBrowser for help on using the repository browser.