2009-10-20 10:52:23 +00:00
# -*- coding: utf-8 -*-
2006-12-07 13:41:40 +00:00
##############################################################################
2010-06-18 10:16:41 +00:00
#
2009-10-14 12:32:15 +00:00
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
2008-06-16 07:24:04 +00:00
#
2008-11-03 18:27:16 +00:00
# This program is free software: you can redistribute it and/or modify
2009-10-14 12:32:15 +00:00
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
2006-12-07 13:41:40 +00:00
#
2008-11-03 18:27:16 +00:00
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2009-10-14 12:32:15 +00:00
# GNU Affero General Public License for more details.
2006-12-07 13:41:40 +00:00
#
2009-10-14 12:32:15 +00:00
# You should have received a copy of the GNU Affero General Public License
2010-06-18 10:16:41 +00:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2006-12-07 13:41:40 +00:00
#
2008-11-03 18:27:16 +00:00
##############################################################################
2006-12-07 13:41:40 +00:00
#
# TODO:
2008-12-09 12:37:22 +00:00
# cr.execute('delete from wkf_triggers where model=%s and res_id=%s', (res_type,res_id))
2006-12-07 13:41:40 +00:00
#
2013-03-19 16:31:33 +00:00
import logging
2006-12-07 13:41:40 +00:00
import instance
import wkf_expr
2013-03-19 16:31:33 +00:00
logger = logging . getLogger ( __name__ )
2006-12-07 13:41:40 +00:00
2008-06-15 00:25:47 +00:00
def create ( cr , act_datas , inst_id , ident , stack ) :
2008-07-22 14:24:36 +00:00
for act in act_datas :
cr . execute ( " select nextval( ' wkf_workitem_id_seq ' ) " )
id_new = cr . fetchone ( ) [ 0 ]
2008-12-09 12:37:22 +00:00
cr . execute ( " insert into wkf_workitem (id,act_id,inst_id,state) values ( %s , %s , %s , ' active ' ) " , ( id_new , act [ ' id ' ] , inst_id ) )
cr . execute ( ' select * from wkf_workitem where id= %s ' , ( id_new , ) )
2008-07-22 14:24:36 +00:00
res = cr . dictfetchone ( )
2013-03-19 16:31:33 +00:00
logger . info ( ' Created workflow item in activity %s ' ,
act [ ' id ' ] , extra = { ' ident ' : ident } )
2008-07-22 14:24:36 +00:00
process ( cr , res , ident , stack = stack )
2006-12-07 13:41:40 +00:00
2008-06-15 00:25:47 +00:00
def process ( cr , workitem , ident , signal = None , force_running = False , stack = None ) :
2013-03-19 15:48:57 +00:00
assert stack is not None
2008-12-09 12:37:22 +00:00
cr . execute ( ' select * from wkf_activity where id= %s ' , ( workitem [ ' act_id ' ] , ) )
2008-07-22 14:24:36 +00:00
activity = cr . dictfetchone ( )
2013-03-19 15:48:57 +00:00
if workitem [ ' state ' ] == ' running ' :
return True
2008-07-22 14:24:36 +00:00
triggers = False
2013-03-19 15:48:57 +00:00
if workitem [ ' state ' ] == ' active ' :
2008-07-22 14:24:36 +00:00
triggers = True
2013-03-19 15:48:57 +00:00
if not _execute ( cr , workitem , activity , ident , stack ) :
2008-07-22 14:24:36 +00:00
return False
2013-03-19 15:48:57 +00:00
if force_running or workitem [ ' state ' ] == ' complete ' :
2008-07-22 14:24:36 +00:00
ok = _split_test ( cr , workitem , activity [ ' split_mode ' ] , ident , signal , stack )
triggers = triggers and not ok
if triggers :
2008-12-09 12:37:22 +00:00
cr . execute ( ' select * from wkf_transition where act_from= %s ' , ( workitem [ ' act_id ' ] , ) )
2013-03-19 15:48:57 +00:00
for trans in cr . dictfetchall ( ) :
2008-07-22 14:24:36 +00:00
if trans [ ' trigger_model ' ] :
ids = wkf_expr . _eval_expr ( cr , ident , workitem , trans [ ' trigger_expr_id ' ] )
for res_id in ids :
cr . execute ( ' select nextval( \' wkf_triggers_id_seq \' ) ' )
id = cr . fetchone ( ) [ 0 ]
2008-12-09 12:37:22 +00:00
cr . execute ( ' insert into wkf_triggers (model,res_id,instance_id,workitem_id,id) values ( %s , %s , %s , %s , %s ) ' , ( trans [ ' trigger_model ' ] , res_id , workitem [ ' inst_id ' ] , workitem [ ' id ' ] , id ) )
2008-07-22 14:24:36 +00:00
2013-03-19 15:48:57 +00:00
return True
2006-12-07 13:41:40 +00:00
# ---------------------- PRIVATE FUNCS --------------------------------
def _state_set ( cr , workitem , activity , state , ident ) :
2008-12-09 12:37:22 +00:00
cr . execute ( ' update wkf_workitem set state= %s where id= %s ' , ( state , workitem [ ' id ' ] ) )
2008-07-22 14:24:36 +00:00
workitem [ ' state ' ] = state
2013-03-19 16:31:33 +00:00
logger . info ( " Changed state of work item %s to \" %s \" in activity %s " ,
workitem [ ' id ' ] , state , activity [ ' id ' ] , extra = { ' ident ' : ident } )
2006-12-07 13:41:40 +00:00
2008-06-15 00:25:47 +00:00
def _execute ( cr , workitem , activity , ident , stack ) :
2008-07-22 14:24:36 +00:00
result = True
#
# send a signal to parent workflow (signal: subflow.signal_name)
#
2009-06-18 20:32:32 +00:00
signal_todo = [ ]
2008-07-22 14:24:36 +00:00
if ( workitem [ ' state ' ] == ' active ' ) and activity [ ' signal_send ' ] :
2010-06-18 10:16:41 +00:00
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 ' ] , ) )
2008-07-22 14:24:36 +00:00
for i in cr . fetchall ( ) :
2009-06-18 20:32:32 +00:00
signal_todo . append ( ( i [ 0 ] , ( ident [ 0 ] , i [ 1 ] , i [ 2 ] ) , activity [ ' signal_send ' ] ) )
2008-07-22 14:24:36 +00:00
if activity [ ' kind ' ] == ' dummy ' :
if workitem [ ' state ' ] == ' active ' :
_state_set ( cr , workitem , activity , ' complete ' , ident )
2008-11-26 23:52:20 +00:00
if activity [ ' action_id ' ] :
res2 = wkf_expr . execute_action ( cr , ident , workitem , activity )
if res2 :
stack . append ( res2 )
result = res2
2008-07-22 14:24:36 +00:00
elif activity [ ' kind ' ] == ' function ' :
if workitem [ ' state ' ] == ' active ' :
_state_set ( cr , workitem , activity , ' running ' , ident )
2011-12-11 10:21:40 +00:00
returned_action = wkf_expr . execute ( cr , ident , workitem , activity )
if type ( returned_action ) in ( dict , ) :
stack . append ( returned_action )
2008-07-22 14:24:36 +00:00
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 )
2008-12-09 12:37:22 +00:00
cr . execute ( ' delete from wkf_workitem where inst_id= %s and id<> %s ' , ( workitem [ ' inst_id ' ] , workitem [ ' id ' ] ) )
2008-07-22 14:24:36 +00:00
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 )
2012-12-14 12:38:03 +00:00
if not id_new :
2008-07-22 14:24:36 +00:00
cr . execute ( ' delete from wkf_workitem where id= %s ' , ( workitem [ ' id ' ] , ) )
return False
assert type ( id_new ) == type ( 1 ) or type ( id_new ) == type ( 1 L ) , ' Wrong return value: ' + str ( id_new ) + ' ' + str ( type ( id_new ) )
2008-12-09 12:37:22 +00:00
cr . execute ( ' select id from wkf_instance where res_id= %s and wkf_id= %s ' , ( id_new , activity [ ' subflow_id ' ] ) )
2008-07-22 14:24:36 +00:00
id_new = cr . fetchone ( ) [ 0 ]
else :
id_new = instance . create ( cr , ident , activity [ ' subflow_id ' ] )
2008-12-09 12:37:22 +00:00
cr . execute ( ' update wkf_workitem set subflow_id= %s where id= %s ' , ( id_new , workitem [ ' id ' ] ) )
2008-07-22 14:24:36 +00:00
workitem [ ' subflow_id ' ] = id_new
if workitem [ ' state ' ] == ' running ' :
2008-12-09 12:37:22 +00:00
cr . execute ( " select state from wkf_instance where id= %s " , ( workitem [ ' subflow_id ' ] , ) )
2008-07-22 14:24:36 +00:00
state = cr . fetchone ( ) [ 0 ]
if state == ' complete ' :
_state_set ( cr , workitem , activity , ' complete ' , ident )
2009-06-18 20:32:32 +00:00
for t in signal_todo :
instance . validate ( cr , t [ 0 ] , t [ 1 ] , t [ 2 ] , force_running = True )
2008-07-22 14:24:36 +00:00
return result
2006-12-07 13:41:40 +00:00
2008-06-15 00:25:47 +00:00
def _split_test ( cr , workitem , split_mode , ident , signal = None , stack = None ) :
2008-12-09 12:37:22 +00:00
cr . execute ( ' select * from wkf_transition where act_from= %s ' , ( workitem [ ' act_id ' ] , ) )
2008-07-22 14:24:36 +00:00
test = False
transitions = [ ]
alltrans = cr . dictfetchall ( )
if split_mode == ' XOR ' or split_mode == ' OR ' :
for transition in alltrans :
if wkf_expr . check ( cr , workitem , ident , transition , signal ) :
test = True
transitions . append ( ( transition [ ' id ' ] , workitem [ ' inst_id ' ] ) )
if split_mode == ' XOR ' :
break
else :
test = True
for transition in alltrans :
if not wkf_expr . check ( cr , workitem , ident , transition , signal ) :
test = False
break
2008-12-09 12:37:22 +00:00
cr . execute ( ' select count(*) from wkf_witm_trans where trans_id= %s and inst_id= %s ' , ( transition [ ' id ' ] , workitem [ ' inst_id ' ] ) )
2008-07-22 14:24:36 +00:00
if not cr . fetchone ( ) [ 0 ] :
transitions . append ( ( transition [ ' id ' ] , workitem [ ' inst_id ' ] ) )
if test and len ( transitions ) :
2008-12-09 12:37:22 +00:00
cr . executemany ( ' insert into wkf_witm_trans (trans_id,inst_id) values ( %s , %s ) ' , transitions )
cr . execute ( ' delete from wkf_workitem where id= %s ' , ( workitem [ ' id ' ] , ) )
2008-07-22 14:24:36 +00:00
for t in transitions :
_join_test ( cr , t [ 0 ] , t [ 1 ] , ident , stack )
return True
return False
2006-12-07 13:41:40 +00:00
2008-06-15 00:25:47 +00:00
def _join_test ( cr , trans_id , inst_id , ident , stack ) :
2008-12-09 12:37:22 +00:00
cr . execute ( ' select * from wkf_activity where id=(select act_to from wkf_transition where id= %s ) ' , ( trans_id , ) )
2008-07-22 14:24:36 +00:00
activity = cr . dictfetchone ( )
if activity [ ' join_mode ' ] == ' XOR ' :
create ( cr , [ activity ] , inst_id , ident , stack )
2008-12-09 12:37:22 +00:00
cr . execute ( ' delete from wkf_witm_trans where inst_id= %s and trans_id= %s ' , ( inst_id , trans_id ) )
2008-07-22 14:24:36 +00:00
else :
2008-12-09 12:37:22 +00:00
cr . execute ( ' select id from wkf_transition where act_to= %s ' , ( activity [ ' id ' ] , ) )
2008-07-22 14:24:36 +00:00
trans_ids = cr . fetchall ( )
ok = True
for ( id , ) in trans_ids :
2008-12-09 12:37:22 +00:00
cr . execute ( ' select count(*) from wkf_witm_trans where trans_id= %s and inst_id= %s ' , ( id , inst_id ) )
2008-07-22 14:24:36 +00:00
res = cr . fetchone ( ) [ 0 ]
if not res :
ok = False
break
if ok :
for ( id , ) in trans_ids :
2008-12-09 12:37:22 +00:00
cr . execute ( ' delete from wkf_witm_trans where trans_id= %s and inst_id= %s ' , ( id , inst_id ) )
2008-07-22 14:24:36 +00:00
create ( cr , [ activity ] , inst_id , ident , stack )
2008-07-23 15:01:27 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: