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

Last change on this file since 9919 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
RevLine 
[7195]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##
[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
[7811]29from waeup.kofa.university.interfaces import ICourse, ICourseAdd
[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    """
[5953]39    grok.implements(ICourse, ICourseAdd)
[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
[6566]58
[9843]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
[6008]69    def longtitle(self):
[6566]70        return "%s (%s)" % (self.title,self.code)
71
[4789]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)
[7207]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
[7333]89       certificatescontainer are removed.
[7207]90    """
91    code = course.code
92
[9824]93    # Find all certificatecourses that refer to given course
[7207]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))
[9828]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:
[9826]107        cert.delCertCourses(code)
[7811]108    return
[9220]109
[9227]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
[9220]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
[9828]154        return
Note: See TracBrowser for help on using the repository browser.