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

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

Add custom fields to certificates (not used in base package).

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