source: main/waeup.kofa/trunk/src/waeup/kofa/university/certificate.py @ 10079

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

Add more local course adviser roles.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.2 KB
Line 
1## $Id: certificate.py 10064 2013-04-06 04:53:30Z 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"""Kofa certificates and certificate courses
19"""
20import grok
21import zope.location.location
22from zope.event import notify
23from zope.catalog.interfaces import ICatalog
24from zope.intid.interfaces import IIntIds
25from zope.schema import getFields
26from zope.component import getUtility
27from zope.component.interfaces import IFactory, ComponentLookupError
28from zope.interface import implementedBy
29from waeup.kofa.interfaces import IKofaPluggable
30from waeup.kofa.university.interfaces import (
31    ICertificate, ICertificateAdd, ICertificateCourse)
32from waeup.kofa.university.vocabularies import course_levels
33from waeup.kofa.utils.batching import VirtualExportJobContainer
34
35class VirtualCertificateExportJobContainer(VirtualExportJobContainer):
36    """A virtual export job container for certificates.
37    """
38
39class Certificate(grok.Container):
40    """A certificate.
41    """
42    grok.implements(ICertificate, ICertificateAdd)
43
44    local_roles = [
45        'waeup.local.CourseAdviser100',
46        'waeup.local.CourseAdviser200',
47        'waeup.local.CourseAdviser300',
48        'waeup.local.CourseAdviser400',
49        'waeup.local.CourseAdviser500',
50        'waeup.local.CourseAdviser600',
51        'waeup.local.CourseAdviser700',
52        'waeup.local.CourseAdviser800',
53        ]
54
55    def __init__(self, code=u'NA', title=u'Unnamed Certificate',
56                 study_mode=None, start_level=None,
57                 end_level=None, application_category=None,
58                 school_fee_1=None, school_fee_2=None,
59                 school_fee_3=None, school_fee_4=None):
60        super(Certificate, self).__init__()
61        self.code = code
62        self.title = title
63        self.study_mode = study_mode
64        self.start_level = start_level
65        self.end_level = end_level
66        self.application_category = application_category
67        self.school_fee_1 = school_fee_1
68        self.school_fee_2 = school_fee_2
69        self.school_fee_3 = school_fee_3
70        self.school_fee_4 = school_fee_4
71
72    def traverse(self, name):
73        """Deliver appropriate containers.
74        """
75        if name == 'exports':
76            # create a virtual exports container and return it
77            container = VirtualCertificateExportJobContainer()
78            zope.location.location.located(container, self, 'exports')
79            return container
80        return None
81
82    def longtitle(self):
83        return "%s (%s)" % (self.title,self.code)
84
85    def addCertCourse(self, course, level=100, mandatory=True):
86        """Add a certificate course.
87        """
88        code = "%s_%s" % (course.code, level)
89        self[code] = CertificateCourse(course, level, mandatory)
90        self[code].__parent__ = self
91        self[code].__name__ = code
92        self._p_changed = True
93
94    def delCertCourses(self, code, level=None):
95        """Delete certificate courses.
96
97        We might have more than one certificate course for a course.
98        If level is not provided all certificate courses referring
99        to the same course will be deleted.
100        """
101        keys = list(self.keys()) # create list copy
102        for key in keys:
103            if self[key].getCourseCode() != code:
104                continue
105            if level is not None and str(self[key].level) != str(level):
106                # found a course with correct key but wrong level...
107                continue
108            del self[key]
109            self._p_changed = True
110        return
111
112    def moveCertificate(self, fac, dep):
113        self.moved = True
114        cert = self
115        del self.__parent__[cert.code]
116        grok.getSite()['faculties'][fac][dep].certificates[cert.code] = cert
117        self.__parent__._p_changed = True
118        cat = getUtility(ICatalog, name='students_catalog')
119        results = cat.searchResults(certcode=(cert.code, cert.code))
120        for student in results:
121            notify(grok.ObjectModifiedEvent(student))
122            student.__parent__.logger.info(
123                '%s - Certificate moved' % student.__name__)
124
125        return
126
127class CertificateFactory(grok.GlobalUtility):
128    """A factory for certificates.
129    """
130    grok.implements(IFactory)
131    grok.name(u'waeup.Certificate')
132    title = u"Create a new certificate.",
133    description = u"This factory instantiates new certificate instances."
134
135    def __call__(self, *args, **kw):
136        return Certificate(*args, **kw)
137
138    def getInterfaces(self):
139        return implementedBy(Certificate)
140
141class CertificateCourse(grok.Model):
142    grok.implements(ICertificateCourse)
143
144    def __init__(self, course=None, level=100, mandatory=True):
145        self.course = course
146        self.level = level
147        self.mandatory = mandatory
148
149    def getCourseCode(self):
150        """Get code of a course.
151        """
152        return self.course.code
153
154    def longtitle(self):
155        return "%s in level %s" % (self.course.code,
156                   course_levels.getTerm(self.level).title)
157
158class CertificateCourseFactory(grok.GlobalUtility):
159    """A factory for certificate courses.
160    """
161    grok.implements(IFactory)
162    grok.name(u'waeup.CertificateCourse')
163    title = u"Create a new certificate course.",
164    description = u"This factory instantiates new certificate courses."
165
166    def __call__(self, *args, **kw):
167        return CertificateCourse(*args, **kw)
168
169    def getInterfaces(self):
170        return implementedBy(CertificateCourse)
171
172@grok.subscribe(ICertificate, grok.IObjectRemovedEvent)
173def handle_certificate_removed(certificate, event):
174    """If a certificate is deleted, we make sure that also referrers to
175    student studycourse objects are removed.
176    """
177    # Do not remove referrer if certificate is going to move
178    if getattr(certificate, 'moved', False):
179        return
180
181    code = certificate.code
182
183    # Find all student studycourses that refer to given certificate...
184    try:
185        cat = getUtility(ICatalog, name='students_catalog')
186    except ComponentLookupError:
187        # catalog not available. This might happen during tests.
188        return
189
190    results = cat.searchResults(certcode=(code, code))
191    for student in results:
192        # Remove that referrer...
193        studycourse = student['studycourse']
194        studycourse.certificate = None
195        notify(grok.ObjectModifiedEvent(student))
196        student.__parent__.logger.info(
197            'ObjectRemovedEvent - %s - removed: certificate' % student.__name__)
198    return
199
200class CertificatesPlugin(grok.GlobalUtility):
201    """A plugin that updates certificates.
202    """
203
204    grok.implements(IKofaPluggable)
205    grok.name('certificates')
206
207    deprecated_attributes = []
208
209    def setup(self, site, name, logger):
210        return
211
212    def update(self, site, name, logger):
213        cat = getUtility(ICatalog, name='certificates_catalog')
214        results = cat.apply({'code':(None,None)})
215        uidutil = getUtility(IIntIds, context=cat)
216        items = getFields(ICertificate).items()
217        for r in results:
218            o = uidutil.getObject(r)
219            # Add new attributes
220            for i in items:
221                if not hasattr(o,i[0]):
222                    setattr(o,i[0],i[1].missing_value)
223                    logger.info(
224                        'CertificatesPlugin: %s attribute %s added.' % (
225                        o.code,i[0]))
226            # Remove deprecated attributes
227            for i in self.deprecated_attributes:
228                try:
229                    delattr(o,i)
230                    logger.info(
231                        'CertificatesPlugin: %s attribute %s deleted.' % (
232                        o.code,i))
233                except AttributeError:
234                    pass
235        return
Note: See TracBrowser for help on using the repository browser.