def _execute(cr, workitem, activity, ident, stack): result = True # # send a signal to parent workflow (signal: subflow.signal_name) # signal_todo = [] if (workitem['state']=='active') and activity['signal_send']: cr.execute("select i.id,w.osv,i.res_id from wkf_instance i left join wkf w on (i.wkf_id=w.id) where i.id IN (select inst_id from wkf_workitem where subflow_id=%s)", (workitem['inst_id'],)) for i in cr.fetchall(): signal_todo.append((i[0], (ident[0],i[1],i[2]), activity['signal_send'])) if activity['kind']=='dummy': if workitem['state']=='active': _state_set(cr, workitem, activity, 'complete', ident) if activity['action_id']: res2 = wkf_expr.execute_action(cr, ident, workitem, activity) if res2: stack.append(res2) result=res2 elif activity['kind']=='function': if workitem['state']=='active': _state_set(cr, workitem, activity, 'running', ident) returned_action = wkf_expr.execute(cr, ident, workitem, activity) if type(returned_action) in (dict,): stack.append(returned_action) if activity['action_id']: res2 = wkf_expr.execute_action(cr, ident, workitem, activity) # A client action has been returned if res2: stack.append(res2) result=res2 _state_set(cr, workitem, activity, 'complete', ident) elif activity['kind']=='stopall': if workitem['state']=='active': _state_set(cr, workitem, activity, 'running', ident) cr.execute('delete from wkf_workitem where inst_id=%s and id<>%s', (workitem['inst_id'], workitem['id'])) if activity['action']: wkf_expr.execute(cr, ident, workitem, activity) _state_set(cr, workitem, activity, 'complete', ident) elif activity['kind']=='subflow': if workitem['state']=='active': _state_set(cr, workitem, activity, 'running', ident) if activity.get('action', False): id_new = wkf_expr.execute(cr, ident, workitem, activity) if not id_new: cr.execute('delete from wkf_workitem where id=%s', (workitem['id'],)) return False assert type(id_new)==type(1) or type(id_new)==type(1L), 'Wrong return value: '+str(id_new)+' '+str(type(id_new)) cr.execute('select id from wkf_instance where res_id=%s and wkf_id=%s', (id_new,activity['subflow_id'])) id_new = cr.fetchone()[0] else: id_new = instance.create(cr, ident, activity['subflow_id']) cr.execute('update wkf_workitem set subflow_id=%s where id=%s', (id_new, workitem['id'])) workitem['subflow_id'] = id_new if workitem['state']=='running': cr.execute("select state from wkf_instance where id=%s", (workitem['subflow_id'],)) state= cr.fetchone()[0] if state=='complete': _state_set(cr, workitem, activity, 'complete', ident) for t in signal_todo: instance.validate(cr, t[0], t[1], t[2], force_running=True) return result
def _execute(cr, workitem, activity, ident, stack): """ Execute wkf_activity's action on a given workitem @param cr: database handle @param workitem: dict of the wkf_workitem to process @param activity: dict of the wkf_activity @param ident: tuple of (uid, dotted model name, resource id ) @param stack: ??? There are 4 different types of activities: * dummy: blank state, no processing required stack is used to return data from an ir.act.server function call if action_id is set * function: executes a particular function on a workitem note that while the function is executing the system will mark the wkf_workitem's state as 'running' to prevent doubled up work * stopall: deletes the current workitem from the database * subflow: creates a new subflow if required """ result = True # # send a signal to parent workflow (signal: subflow.signal_name) # signal_todo = [] if (workitem['state'] == 'active') and activity['signal_send']: cr.execute( "select i.id,w.osv,i.res_id from wkf_instance i left join wkf w on (i.wkf_id=w.id) where i.id IN (select inst_id from wkf_workitem where subflow_id=%s)", (workitem['inst_id'], )) for i in cr.fetchall(): signal_todo.append( (i[0], (ident[0], i[1], i[2]), activity['signal_send'])) if config['debug_workflow']: exec_started = datetime.datetime.now() _logger.debug(" execute {a[kind]} {i[1]},{i[2]} {d}".format( i=ident, w=workitem, a=activity, d=exec_started)) # ACTIVITY: dummy if activity['kind'] == 'dummy': if workitem['state'] == 'active': _state_set(cr, workitem, activity, 'complete', ident) if activity['action_id']: res2 = wkf_expr.execute_action(cr, ident, workitem, activity) if res2: stack.append(res2) result = res2 # ACTIVITY: function elif activity['kind'] == 'function': if workitem['state'] == 'active': if config['debug_workflow']: _logger.debug(" function {i[1]},{i[2]}: {a[action]}".format( i=ident, w=workitem, a=activity)) _state_set(cr, workitem, activity, 'running', ident) returned_action = wkf_expr.execute(cr, ident, workitem, activity) if type(returned_action) in (dict, ): stack.append(returned_action) if activity['action_id']: res2 = wkf_expr.execute_action(cr, ident, workitem, activity) # A client action has been returned if res2: stack.append(res2) result = res2 _state_set(cr, workitem, activity, 'complete', ident) # ACTIVITY: stopall elif activity['kind'] == 'stopall': if workitem['state'] == 'active': _state_set(cr, workitem, activity, 'running', ident) cr.execute('delete from wkf_workitem where inst_id=%s and id<>%s', (workitem['inst_id'], workitem['id'])) if activity['action']: wkf_expr.execute(cr, ident, workitem, activity) _state_set(cr, workitem, activity, 'complete', ident) # ACTIVITY: subflow elif activity['kind'] == 'subflow': # If the state is currently marked as 'active' it means that the node # has yet to start the subflow. So let's create it. if workitem['state'] == 'active': _state_set(cr, workitem, activity, 'running', ident) # action will be a python function on the wkf_instance's res_type model # What we expect from this function is the new target record's ID # As we expect that the new record will have its own workflow, we just # need to know what workflow this object will be launched into. We know # the new record's workflow id because the current wkf_activity has # wkf_activity.subflow_id references the target sub-object's wkf record if activity.get('action', False): id_new = wkf_expr.execute(cr, ident, workitem, activity) # If we don't get a new record id, stop the workflow and drop out if not (id_new): cr.execute('delete from wkf_workitem where id=%s', (workitem['id'], )) return False assert type(id_new) == type(1) or type(id_new) == type( 1L), 'Wrong return value: ' + str(id_new) + ' ' + str( type(id_new)) cr.execute( 'select id from wkf_instance where res_id=%s and wkf_id=%s', (id_new, activity['subflow_id'])) id_new = cr.fetchone()[0] # If there is no function, we just put the current object on the subflow. # TODO: this seems a little perilous if the workflow references some other model else: id_new = instance.create(cr, ident, activity['subflow_id']) cr.execute('update wkf_workitem set subflow_id=%s where id=%s', (id_new, workitem['id'])) workitem['subflow_id'] = id_new # If the state is running, we're waiting for the subflow to complete. Check the subflow # to see what the status it happens to be and if the subflow is marked 'complete', we can # finally mark this activity as complete as well if workitem['state'] == 'running': cr.execute("select state from wkf_instance where id=%s", (workitem['subflow_id'], )) state = cr.fetchone()[0] if state == 'complete': _state_set(cr, workitem, activity, 'complete', ident) for t in signal_todo: instance.validate(cr, t[0], t[1], t[2], force_running=True) if config['debug_workflow']: _logger.debug(" /execute {a[kind]} {i[1]},{i[2]} started {d}".format( i=ident, w=workitem, a=activity, d=exec_started)) return result
def _execute(cr, workitem, activity, ident, stack): result = True # # send a signal to parent workflow (signal: subflow.signal_name) # signal_todo = [] if (workitem["state"] == "active") and activity["signal_send"]: cr.execute( "select i.id,w.osv,i.res_id from wkf_instance i left join wkf w on (i.wkf_id=w.id) where i.id IN (select inst_id from wkf_workitem where subflow_id=%s)", (workitem["inst_id"],), ) for i in cr.fetchall(): signal_todo.append((i[0], (ident[0], i[1], i[2]), activity["signal_send"])) if activity["kind"] == "dummy": if workitem["state"] == "active": _state_set(cr, workitem, activity, "complete", ident) if activity["action_id"]: res2 = wkf_expr.execute_action(cr, ident, workitem, activity) if res2: stack.append(res2) result = res2 elif activity["kind"] == "function": if workitem["state"] == "active": _state_set(cr, workitem, activity, "running", ident) returned_action = wkf_expr.execute(cr, ident, workitem, activity) if type(returned_action) in (dict,): stack.append(returned_action) if activity["action_id"]: res2 = wkf_expr.execute_action(cr, ident, workitem, activity) # A client action has been returned if res2: stack.append(res2) result = res2 _state_set(cr, workitem, activity, "complete", ident) elif activity["kind"] == "stopall": if workitem["state"] == "active": _state_set(cr, workitem, activity, "running", ident) cr.execute("delete from wkf_workitem where inst_id=%s and id<>%s", (workitem["inst_id"], workitem["id"])) if activity["action"]: wkf_expr.execute(cr, ident, workitem, activity) _state_set(cr, workitem, activity, "complete", ident) elif activity["kind"] == "subflow": if workitem["state"] == "active": _state_set(cr, workitem, activity, "running", ident) if activity.get("action", False): id_new = wkf_expr.execute(cr, ident, workitem, activity) if not (id_new): cr.execute("delete from wkf_workitem where id=%s", (workitem["id"],)) return False assert type(id_new) == type(1) or type(id_new) == type(1L), ( "Wrong return value: " + str(id_new) + " " + str(type(id_new)) ) cr.execute( "select id from wkf_instance where res_id=%s and wkf_id=%s", (id_new, activity["subflow_id"]) ) id_new = cr.fetchone()[0] else: id_new = instance.create(cr, ident, activity["subflow_id"]) cr.execute("update wkf_workitem set subflow_id=%s where id=%s", (id_new, workitem["id"])) workitem["subflow_id"] = id_new if workitem["state"] == "running": cr.execute("select state from wkf_instance where id=%s", (workitem["subflow_id"],)) state = cr.fetchone()[0] if state == "complete": _state_set(cr, workitem, activity, "complete", ident) for t in signal_todo: instance.validate(cr, t[0], t[1], t[2], force_running=True) return result