Exemple #1
0
def changeWorkflowState(content, wf_id, state_id, **kw):
    """Change the workflow state of an object
    @param content: Content obj which state will be changed
    @param state_id: name of the state to put on content
    @param kw: change the values of same name of the state mapping
    @return: True if succeed. Otherwise, False
    """
    portal_workflow = api.get_tool("portal_workflow")
    workflow = portal_workflow.getWorkflowById(wf_id)
    if not workflow:
        logger.error("%s: Cannot find workflow id %s" % (content, wf_id))
        return False

    wf_state = {
        'action': kw.get("action", None),
        'actor': kw.get("actor",
                        api.get_current_user().id),
        'comments': "Setting state to %s" % state_id,
        'review_state': state_id,
        'time': DateTime()
    }

    # Get old and new state info
    old_state = workflow._getWorkflowStateOf(content)
    new_state = workflow.states.get(state_id, None)
    if new_state is None:
        raise WorkflowException(
            "Destination state undefined: {}".format(state_id))

    # Change status and update permissions
    portal_workflow.setStatusOf(wf_id, content, wf_state)
    workflow.updateRoleMappingsFor(content)

    # Notify the object has been transitioned
    notify(
        AfterTransitionEvent(content, workflow, old_state, new_state, None,
                             wf_state, None))

    # Map changes to catalog
    indexes = ["allowedRolesAndUsers", "review_state", "is_active"]
    content.reindexObject(idxs=indexes)
    return True
Exemple #2
0
def fix_items_stuck_in_sample_prep_states(portal, ut):
    """Removing sample preparation workflows from the system may have
    left some samples ARs and Analyses in the state 'sample_prep'.  These
    should be transitioned to 'sample_due'  so that they can be receieved
    normally.
    :param portal: portal object
    :return: None
    """
    wftool = api.get_tool('portal_workflow')
    catalog_ids = [
        'bika_catalog', 'bika_analysis_catalog',
        'bika_catalog_analysisrequest_listing'
    ]
    for catalog_id in catalog_ids:
        catalog = api.get_tool(catalog_id)
        brains = catalog(review_state='sample_prep')
        for brain in brains:
            instance = brain.getObject()
            wfid = get_workflows_for(instance)[0]
            wf = wftool[wfid]
            # get event properties for last event that is not sample_prep
            rh = wftool.getInfoFor(instance, 'review_history')
            event = [
                x for x in rh
                if 'prep' not in x['review_state'] and not x['comments']
            ][-1]
            state_id, action_id = event['review_state'], event['action']
            # set state
            changeWorkflowState(instance, wfid, state_id)
            # fire transition handler for the action that originally was fired.
            old_sdef = new_sdef = wf.states[state_id]
            if action_id is not None:
                tdef = wf.transitions[action_id]
                notify(
                    AfterTransitionEvent(instance, wf, old_sdef, new_sdef,
                                         tdef, event, {}))
            # check AR state matches the analyses
            if IAnalysisRequest.providedBy(instance):
                fix_ar_sample_workflow(instance)
        logger.info("Removed sample_prep state from {} items in {}.".format(
            len(brains), catalog_id))
Exemple #3
0
                value = expr(econtext)
            status[id] = value

        # Update state.
        status[self.state_var] = new_state
        tool = aq_parent(aq_inner(self))
        tool.setStatusOf(self.id, ob, status)

        # Update role to permission assignments.
        self.updateRoleMappingsFor(ob)

        # Execute the "after" script.
        if tdef is not None and tdef.after_script_name:
            script = self.scripts[tdef.after_script_name]
            # Pass lots of info to the script in a single parameter.
            sci = StateChangeInfo(
                ob, self, status, tdef, old_sdef, new_sdef, kwargs)
            script(sci)  # May throw an exception.

        # Fire "after" event
        notify(AfterTransitionEvent(ob, self, old_sdef, new_sdef, tdef, status, kwargs))

        # Return the new state object.
        if moved_exc is not None:
            # Propagate the notification that the object has moved.
            raise moved_exc
        else:
            return new_sdef

InitializeClass(DCWorkflowDefinition)
Exemple #4
0
    def _executeTransition(self, ob, tdef=None, kwargs=None):
        '''
        Private method.
        Puts object in a new state.
        '''
        sci = None
        econtext = None
        moved_exc = None

        # Figure out the old and new states.
        old_sdef = self._getWorkflowStateOf(ob)
        old_state = old_sdef.getId()
        if tdef is None:
            new_state = self.initial_state
            former_status = {}
        else:
            new_state = tdef.new_state_id
            if not new_state:
                # Stay in same state.
                new_state = old_state
            former_status = self._getStatusOf(ob)
        new_sdef = self.states.get(new_state, None)
        if new_sdef is None:
            msg = _(u'Destination state undefined: ${state_id}',
                    mapping={'state_id': new_state})
            raise WorkflowException(msg)

        # Fire "before" event
        notify(BeforeTransitionEvent(ob, self, old_sdef, new_sdef, tdef,
                                     former_status, kwargs))

        # Execute the "before" script.
        if tdef is not None and tdef.script_name:
            script = self.scripts[tdef.script_name]
            # Pass lots of info to the script in a single parameter.
            sci = StateChangeInfo(
                ob, self, former_status, tdef, old_sdef, new_sdef, kwargs)
            try:
                script(sci)  # May throw an exception.
            except ObjectMoved as moved_exc:
                ob = moved_exc.getNewObject()
                # Re-raise after transition

        # Update variables.
        state_values = new_sdef.var_values
        if state_values is None:
            state_values = {}
        tdef_exprs = None
        if tdef is not None:
            tdef_exprs = tdef.var_exprs
        if tdef_exprs is None:
            tdef_exprs = {}
        status = {}
        for id, vdef in self.variables.items():
            if not vdef.for_status:
                continue
            expr = None
            if id in state_values:
                value = state_values[id]
            elif id in tdef_exprs:
                expr = tdef_exprs[id]
            elif not vdef.update_always and id in former_status:
                # Preserve former value
                value = former_status[id]
            else:
                if vdef.default_expr is not None:
                    expr = vdef.default_expr
                else:
                    value = vdef.default_value
            if expr is not None:
                # Evaluate an expression.
                if econtext is None:
                    # Lazily create the expression context.
                    if sci is None:
                        sci = StateChangeInfo(
                            ob, self, former_status, tdef,
                            old_sdef, new_sdef, kwargs)
                    econtext = createExprContext(sci)
                value = expr(econtext)
            status[id] = value

        # Update state.
        status[self.state_var] = new_state
        tool = aq_parent(aq_inner(self))
        tool.setStatusOf(self.id, ob, status)

        # Update role to permission assignments.
        self.updateRoleMappingsFor(ob)

        # Execute the "after" script.
        if tdef is not None and tdef.after_script_name:
            script = self.scripts[tdef.after_script_name]
            # Pass lots of info to the script in a single parameter.
            sci = StateChangeInfo(
                ob, self, status, tdef, old_sdef, new_sdef, kwargs)
            script(sci)  # May throw an exception.

        # Fire "after" event
        notify(AfterTransitionEvent(ob, self, old_sdef, new_sdef, tdef, status,
                                    kwargs))

        # Return the new state object.
        if moved_exc is not None:
            # Propagate the notification that the object has moved.
            raise moved_exc
        else:
            return new_sdef