diff --git a/CHANGES.rst b/CHANGES.rst index bbb913790d..9df24f60b3 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -6,6 +6,7 @@ Changelog **Added** +- #1455 Added support for adapters in guard handler - #1436 Setting in setup for auto-reception of samples upon creation - #1433 Added Submitter column in Sample's analyses listing - #1441 Added Auto ID Behavior for Dexterity Contents diff --git a/bika/lims/interfaces/__init__.py b/bika/lims/interfaces/__init__.py index af08447d44..47b41b1a9b 100644 --- a/bika/lims/interfaces/__init__.py +++ b/bika/lims/interfaces/__init__.py @@ -954,3 +954,12 @@ class IInternalUse(Interface): class IDetachedPartition(Interface): """Marker interface for samples that have been detached from its primary """ + + +class IGuardAdapter(Interface): + """Marker interface for guard adapters + """ + + def guard(self, transition): + """Return False if you want to block the transition + """ diff --git a/bika/lims/workflow/__init__.py b/bika/lims/workflow/__init__.py index 89174e2ba3..2a5e777d99 100644 --- a/bika/lims/workflow/__init__.py +++ b/bika/lims/workflow/__init__.py @@ -28,7 +28,7 @@ from bika.lims import logger from bika.lims.browser import ulocalized_time from bika.lims.decorators import synchronized -from bika.lims.interfaces import IActionHandlerPool +from bika.lims.interfaces import IActionHandlerPool, IGuardAdapter from bika.lims.interfaces import IJSONReadExtender from bika.lims.jsonapi import get_include_fields from bika.lims.utils import changeWorkflowState # noqa @@ -37,6 +37,7 @@ from Products.Archetypes.config import UID_CATALOG from Products.CMFCore.utils import getToolByName from Products.CMFCore.WorkflowCore import WorkflowException +from zope.component import getAdapters from zope.interface import implements from ZPublisher.HTTPRequest import HTTPRequest @@ -386,6 +387,13 @@ def guard_handler(instance, transition_id): """ if not instance: return True + + # If adapters are found, core's guard will only be evaluated if, and only + # if, ALL "pre-guards" return True + for name, ad in getAdapters((instance,), IGuardAdapter): + if ad.guard(transition_id) is False: + return False + clazz_name = instance.portal_type # Inspect if bika.lims.workflow.. module exists wf_module = _load_wf_module('{0}.guards'.format(clazz_name.lower()))