source: main/waeup.sirp/trunk/src/waeup/sirp/students/studycourse.py @ 6830

Last change on this file since 6830 was 6822, checked in by Henrik Bettermann, 13 years ago

We need a StudentStudyCourseFactory? for imports (only).

  • Property svn:keywords set to Id
File size: 5.9 KB
Line 
1## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
2## This program is free software; you can redistribute it and/or modify
3## it under the terms of the GNU General Public License as published by
4## the Free Software Foundation; either version 2 of the License, or
5## (at your option) any later version.
6##
7## This program is distributed in the hope that it will be useful,
8## but WITHOUT ANY WARRANTY; without even the implied warranty of
9## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10## GNU General Public License for more details.
11##
12## You should have received a copy of the GNU General Public License
13## along with this program; if not, write to the Free Software
14## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15##
16"""
17Container which holds the data of the student study courses
18and contains the (student) study level objects.
19"""
20import grok
21from grok import index
22from zope.component.interfaces import IFactory
23from zope.securitypolicy.interfaces import IPrincipalRoleManager
24from waeup.sirp.students.interfaces import (
25    IStudentStudyCourse, IStudentNavigation, IStudentStudyLevel)
26from waeup.sirp.students.studylevel import CourseTicket
27from waeup.sirp.utils.helpers import attrs_to_fields
28
29class StudentStudyCourse(grok.Container):
30    """This is a container for study levels.
31    """
32    grok.implements(IStudentStudyCourse, IStudentNavigation)
33    grok.provides(IStudentStudyCourse)
34
35    def __init__(self):
36        super(StudentStudyCourse, self).__init__()
37        return
38
39    def getStudent(self):
40        return self.__parent__
41
42    def addStudentStudyLevel(self, cert, studylevel):
43        """Add a study level object.
44        """
45        if not IStudentStudyLevel.providedBy(studylevel):
46            raise TypeError(
47                'StudentStudyCourses contain only IStudentStudyLevel instances')
48        self[str(studylevel.level)] = studylevel
49
50        #Create course tickets automatically
51        for key, val in cert.items():
52            if val.level != studylevel.level:
53                continue
54            ticket = CourseTicket()
55            ticket.code = val.getCourseCode()
56            ticket.automatic = True
57            ticket.core_or_elective = val.core_or_elective
58            ticket.title = val.course.title
59            ticket.faculty = val.course.__parent__.__parent__.__parent__.title
60            ticket.department = val.course.__parent__.__parent__.title
61            ticket.credits = val.course.credits
62            ticket.passmark = val.course.passmark
63            ticket.semester = val.course.semester
64            self[str(studylevel.level)][val.getCourseCode()] = ticket
65        return
66
67StudentStudyCourse = attrs_to_fields(StudentStudyCourse)
68
69@grok.subscribe(IStudentStudyCourse, grok.IObjectAddedEvent)
70def handle_studycourse_added(obj, event):
71    """When a studycourse is added, update the local roles.
72    """
73    cert = getattr(obj, 'certificate', None)
74    if cert is None:
75        # cert never set yet, no need to update local roles
76        return
77    update_local_roles(obj)
78    return
79
80@grok.subscribe(IStudentStudyCourse, grok.IObjectModifiedEvent)
81def handle_studycourse_modified(obj, event):
82    """When a studycourse is changed, also update the local roles.
83    """
84    update_local_roles(obj)
85    return
86
87def update_local_roles(studycourse):
88    """Update local roles of given studycourse.
89    """
90    student = getattr(studycourse, '__parent__', None)
91    if student is None:
92        # not part of student, no need to update local roles
93        return
94    replace_local_clearance_officers(student)
95    return
96
97def replace_local_clearance_officers(student):
98    """Set local roles of given student.
99
100    The local roles are determined by looking up desired
101    principals. Then we remove those principals from local roles that
102    are not wanted/outdated and add those wanted.
103    """
104    prm = IPrincipalRoleManager(student)
105    curr_officers = prm.getPrincipalsForRole(
106        'waeup.local.ClearanceOfficer')
107    new_officers = get_valid_clearance_officers(student)
108    #print "STUD %s, CURR: %s, NEW: %s" % (student, curr_officers,
109    #                                      new_officers)
110    for officer in curr_officers:
111        if officer in new_officers:
112            continue
113        prm.unsetRoleForPrincipal('waeup.local.ClearanceOfficer', officer)
114    for officer in new_officers:
115        if officer in curr_officers:
116            continue
117        prm.assignRoleToPrincipal('waeup.local.ClearanceOfficer', officer)
118
119    return
120
121def get_valid_clearance_officers(student):
122    """Lookup desired clearance officers for `student`.
123
124    We look up the connected certificate, then its dept. and faculty
125    to see which local roles are required: students get the clearance
126    officers assigned to their certificate.
127
128    Not sure, though, whether we really have to set the real clearance
129    officer role for the wanted principals on the dept and faculty.
130    """
131    cert = getattr(student, 'certificate', None)
132    if cert is None:
133        return []
134    dept = getattr(getattr(cert, '__parent__', None), '__parent__', None)
135    fac = getattr(dept, '__parent__', None)
136    if dept is None or fac is None:
137        # not a serious cert
138        return []
139    # get officers (principals) responsible for the dept and faculty
140    dept_officers = IPrincipalRoleManager(dept).getPrincipalsForRole(
141        'waeup.local.ClearanceOfficer')
142    fac_officers =  IPrincipalRoleManager(fac).getPrincipalsForRole(
143        'waeup.local.ClearanceOfficer')
144    return dept_officers + fac_officers
145
146class StudentStudyCourseFactory(grok.GlobalUtility):
147    """A factory for students.
148    """
149    grok.implements(IFactory)
150    grok.name(u'waeup.StudentStudyCourse')
151    title = u"Create a new student study course.",
152    description = u"This factory instantiates new student study course instances."
153
154    def __call__(self, *args, **kw):
155        return StudentStudyCourse()
156
157    def getInterfaces(self):
158        return implementedBy(StudentStudyCourse)
Note: See TracBrowser for help on using the repository browser.