"""WAeUP portal certificates """ import grok from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState 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.interfaces import ICertificate, ICertificateCourse, ICourse class Certificate(grok.Container): """A certificate. """ grok.implements(ICertificate) def __init__(self, code=u'NA', title=u'Unnamed Certificate', category=None, 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.category = category 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