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

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

Implement local student data exports in courses.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 5.0 KB
Line 
1## $Id: course.py 9843 2013-01-08 11:38:14Z 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, ICourseAdd
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, ICourseAdd)
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
59    def traverse(self, name):
60        """Deliver appropriate containers.
61        """
62        if name == 'exports':
63            # create a virtual exports container and return it
64            container = VirtualCourseExportJobContainer()
65            zope.location.location.located(container, self, 'exports')
66            return container
67        return None
68
69    def longtitle(self):
70        return "%s (%s)" % (self.title,self.code)
71
72class CourseFactory(grok.GlobalUtility):
73    """A factory for courses.
74    """
75    grok.implements(IFactory)
76    grok.name(u'waeup.Course')
77    title = u"Create a new course.",
78    description = u"This factory instantiates new course instances."
79
80    def __call__(self, *args, **kw):
81        return Course(*args, **kw)
82
83    def getInterfaces(self):
84        return implementedBy(Course)
85
86@grok.subscribe(ICourse, grok.IObjectRemovedEvent)
87def handle_course_removed(course, event):
88    """If a course is deleted, we make sure that also referrers in a
89       certificatescontainer are removed.
90    """
91    code = course.code
92
93    # Find all certificatecourses that refer to given course
94    try:
95        cat = getUtility(ICatalog, name='certcourses_catalog')
96    except ComponentLookupError:
97        # catalog not available. This might happen during tests.
98        return
99
100    results = cat.searchResults(course_code=(code, code))
101
102    # remove each found referrer (certs might refer to same course multiple
103    # times)
104    certs = [x.__parent__ for x in results]
105    unique_certs = list(set(certs))
106    for cert in unique_certs:
107        cert.delCertCourses(code)
108    return
109
110@grok.subscribe(ICourse, grok.IObjectModifiedEvent)
111def handle_set_former_course(course, event):
112    """If a former course attribute is set, we make sure that referrers in a
113       certificatescontainer are removed.
114    """
115    if event.object.former_course:
116        handle_course_removed(course, event)
117    return
118
119class CoursesPlugin(grok.GlobalUtility):
120    """A plugin that updates courses.
121    """
122
123    grok.implements(IKofaPluggable)
124    grok.name('courses')
125
126    deprecated_attributes = []
127
128    def setup(self, site, name, logger):
129        return
130
131    def update(self, site, name, logger):
132        cat = getUtility(ICatalog, name='courses_catalog')
133        results = cat.apply({'code':(None,None)})
134        uidutil = getUtility(IIntIds, context=cat)
135        items = getFields(ICourse).items()
136        for r in results:
137            o = uidutil.getObject(r)
138            # Add new attributes
139            for i in items:
140                if not hasattr(o,i[0]):
141                    setattr(o,i[0],i[1].missing_value)
142                    logger.info(
143                        'CoursesPlugin: %s attribute %s added.' % (
144                        o.code,i[0]))
145            # Remove deprecated attributes
146            for i in self.deprecated_attributes:
147                try:
148                    delattr(o,i)
149                    logger.info(
150                        'CoursesPlugin: %s attribute %s deleted.' % (
151                        o.code,i))
152                except AttributeError:
153                    pass
154        return
Note: See TracBrowser for help on using the repository browser.