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

Last change on this file since 10650 was 10650, checked in by Henrik Bettermann, 11 years ago

Convert longtitle() into property attribute.

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