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

Last change on this file since 17016 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
RevLine 
[7195]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##
[4789]18"""Courses.
19"""
20import grok
[9843]21import zope.location.location
[7207]22from zope.catalog.interfaces import ICatalog
[4789]23from zope.interface import implementedBy
[9220]24from zope.schema import getFields
25from zope.intid.interfaces import IIntIds
[7207]26from zope.component import getUtility
27from zope.component.interfaces import IFactory, ComponentLookupError
[9220]28from waeup.kofa.interfaces import IKofaPluggable
[10685]29from waeup.kofa.university.interfaces import ICourse
[9843]30from waeup.kofa.utils.batching import VirtualExportJobContainer
[4789]31
[9843]32class VirtualCourseExportJobContainer(VirtualExportJobContainer):
33    """A virtual export job container for courses.
34    """
35
[4789]36class Course(grok.Model):
37    """A university course.
38    """
[10685]39    grok.implements(ICourse)
[4789]40
[9002]41    local_roles = ['waeup.local.Lecturer']
[8996]42
[4789]43    def __init__(self,
44                 title=u'Unnamed Course',
45                 code=u'NA',
46                 credits=0,
47                 passmark=40,
[9220]48                 semester=1,
49                 former_course=False,
50                 **kw):
[4789]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
[9220]57        self.former_course = former_course
[15422]58        self.results_validated_by = None
59        self.results_validation_date = None
60        self.results_validation_session = None
[15629]61        self.score_editing_disabled = False
[6566]62
[9843]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
[10650]73    @property
[6008]74    def longtitle(self):
[6566]75        return "%s (%s)" % (self.title,self.code)
76
[4789]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)
[7207]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
[7333]94       certificatescontainer are removed.
[7207]95    """
96    code = course.code
97
[9824]98    # Find all certificatecourses that refer to given course
[7207]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))
[9828]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:
[9826]112        cert.delCertCourses(code)
[7811]113    return
[9220]114
[9227]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
[9220]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
[9828]159        return
Note: See TracBrowser for help on using the repository browser.