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

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

Add field which can be used to compute installments.

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