"""WAeUP portal certificates """ import grok from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState try: from zope.catalog.interfaces import ICatalog except ImportError: # BBB from zope.app.catalog.interfaces import ICatalog from zope.component import getUtility from zope.component.interfaces import IFactory, ComponentLookupError from zope.interface import implementedBy from waeup.sirp.university.interfaces import ( ICertificate, ICertificateCourse, ICourse) class Certificate(grok.Container): """A certificate. """ grok.implements(ICertificate) def __init__(self, code=u'NA', title=u'Unnamed Certificate', study_mode=None, start_level=None, end_level=None, application_category=None, max_pass = u''): super(Certificate, self).__init__() self.code = code self.title = title self.study_mode = study_mode self.start_level = start_level self.end_level = end_level self.application_category = application_category self.max_pass = max_pass # Initialize workflow state... self.setReviewState('unchecked') def check(self): """Set Review State to ``checked``. """ self.setReviewState(state='checked') def getReviewState(self): return IWorkflowState(self).getState() def setReviewState(self, state=None): """Try to set new state. Instead of simply setting a value, we fire a transition of a workflow. This might fail if, for instance, the required state is not part of the workflow or unreachable from current state. """ if state == self.getReviewState(): # Accept staying in the same state, even if workflow does # not allow this. return info = IWorkflowInfo(self) info.fireTransitionToward(state) return review_state = property(getReviewState, setReviewState) def addCourseRef(self, course, level=100, core_or_elective=True): """Add a course reference. """ code = "%s_%s" % (course.code, level) self[code] = CertificateCourse(course, level, core_or_elective) self[code].__parent__ = self self[code].__name__ = code self._p_changed = True def delCourseRef(self, code, level=None): """Delete a course denoted by its code. """ for key in self.keys(): if self[key].getCourseCode() != code: continue if level is not None and str(self[key].level) != str(level): # found a course with correct key but wrong level... continue del self[key] self._p_changed = True return class CertificateFactory(grok.GlobalUtility): """A factory for certificates. """ grok.implements(IFactory) grok.name(u'waeup.Certificate') title = u"Create a new certificate.", description = u"This factory instantiates new certificate instances." def __call__(self, *args, **kw): return Certificate(*args, **kw) def getInterfaces(self): return implementedBy(Certificate) class CertificateCourse(grok.Model): grok.implements(ICertificateCourse) def __init__(self, course=None, level=100, core_or_elective=True): self.course = course self.level = level self.core_or_elective = core_or_elective def getCourseCode(self): """Get code of a course. """ return self.course.code class CertificateCourseFactory(grok.GlobalUtility): """A factory for certificate courses. """ grok.implements(IFactory) grok.name(u'waeup.CertificateCourse') title = u"Create a new certificate course.", description = u"This factory instantiates new certificate courses." def __call__(self, *args, **kw): return CertificateCourse(*args, **kw) def getInterfaces(self): return implementedBy(CertificateCourse) @grok.subscribe(ICourse, grok.IObjectRemovedEvent) def removedCourseHandler(course, event): """If a course is deleted, we make sure that also references in a certificatecontainer are removed. """ code = course.code # Find all certcourses that reference the given course... try: cat = getUtility(ICatalog, name='certcourses_catalog') except ComponentLookupError: # catalog not available. This might happen during tests. return results = cat.searchResults(course_code=(code, code)) for certcourse in results: # Remove that reference... cert = certcourse.__parent__ cert.delCourseRef(code) cert._p_changed = True return