openerp-community team mailing list archive
-
openerp-community team
-
Mailing list archive
-
Message #00733
[Merge] lp:~openerp-community/openobject-server/context-in-workflows into lp:openobject-server
Raphaël Valyi - http://www.akretion.com has proposed merging lp:~openerp-community/openobject-server/context-in-workflows into lp:openobject-server.
Requested reviews:
Raphaël Valyi - http://www.akretion.com (rvalyi)
OpenERP Core Team (openerp)
For more details, see:
https://code.launchpad.net/~openerp-community/openobject-server/context-in-workflows/+merge/85518
Work in progress, seem my merge message.
A way to test the current limitation where a bug is caused because the workflow engine would pass some unexpected context param is just to create an order with manual invoicing. Validate it and then create the invoice from the sale order.
A bug like that will result:
[..]
File "/home/rvalyi/DEV/openerp/openerp6.1/addons/sale/sale.py", line 457, in manual_invoice
[..]
File "/home/rvalyi/DEV/openerp/openerp6.1/server/openerp/workflow/wkf_expr.py", line 85, in check
return _eval_expr(cr, ident, workitem, transition['condition'], context)
File "/home/rvalyi/DEV/openerp/openerp6.1/server/openerp/workflow/wkf_expr.py", line 59, in _eval_expr
ret = eval(line, env, nocopy=True)
File "/home/rvalyi/DEV/openerp/openerp6.1/server/openerp/tools/safe_eval.py", line 294, in safe_eval
return eval(test_expr(expr,_SAFE_OPCODES, mode=mode), globals_dict, locals_dict)
File "", line 1, in <module>
File "/home/rvalyi/DEV/openerp/openerp6.1/server/openerp/osv/orm.py", line 396, in function_proxy
return attr(self._cr, self._uid, [self._id], *args, **kwargs)
TypeError: test_state() got an unexpected keyword argument 'context'
Probably, to make it compatible we should inspect the method signature a bit like Albert did in it former "browse_executer" here:
https://code.launchpad.net/~albert-nan/openobject-server/workflow-context/+merge/12256
(in orm.py)
--
https://code.launchpad.net/~openerp-community/openobject-server/context-in-workflows/+merge/85518
Your team OpenERP Community is subscribed to branch lp:~openerp-community/openobject-server/context-in-workflows.
=== modified file 'openerp/osv/osv.py'
--- openerp/osv/osv.py 2011-10-01 01:22:10 +0000
+++ openerp/osv/osv.py 2011-12-13 17:01:27 +0000
@@ -180,16 +180,16 @@
cr.close()
return res
- def exec_workflow_cr(self, cr, uid, obj, method, *args):
+ def exec_workflow_cr(self, cr, uid, obj, method, id, context=None):
wf_service = netsvc.LocalService("workflow")
- return wf_service.trg_validate(uid, obj, args[0], method, cr)
+ return wf_service.trg_validate(uid, obj, id, method, cr, context)
@check
- def exec_workflow(self, db, uid, obj, method, *args):
+ def exec_workflow(self, db, uid, obj, method, id, context=None):
cr = pooler.get_db(db).cursor()
try:
try:
- res = self.exec_workflow_cr(cr, uid, obj, method, *args)
+ res = self.exec_workflow_cr(cr, uid, obj, method, id, context)
cr.commit()
except Exception:
cr.rollback()
=== modified file 'openerp/workflow/instance.py'
--- openerp/workflow/instance.py 2011-02-07 12:57:23 +0000
+++ openerp/workflow/instance.py 2011-12-13 17:01:27 +0000
@@ -25,14 +25,14 @@
import openerp.netsvc as netsvc
import openerp.pooler as pooler
-def create(cr, ident, wkf_id):
+def create(cr, ident, wkf_id, context=None):
(uid,res_type,res_id) = ident
cr.execute('insert into wkf_instance (res_type,res_id,uid,wkf_id) values (%s,%s,%s,%s) RETURNING id', (res_type,res_id,uid,wkf_id))
id_new = cr.fetchone()[0]
cr.execute('select * from wkf_activity where flow_start=True and wkf_id=%s', (wkf_id,))
res = cr.dictfetchall()
stack = []
- workitem.create(cr, res, id_new, ident, stack=stack)
+ workitem.create(cr, res, id_new, ident, stack=stack, context=context)
update(cr, id_new, ident)
return id_new
@@ -40,24 +40,24 @@
(uid,res_type,res_id) = ident
cr.execute('delete from wkf_instance where res_id=%s and res_type=%s', (res_id,res_type))
-def validate(cr, inst_id, ident, signal, force_running=False):
+def validate(cr, inst_id, ident, signal, force_running=False, context=None):
cr.execute("select * from wkf_workitem where inst_id=%s", (inst_id,))
stack = []
for witem in cr.dictfetchall():
stack = []
- workitem.process(cr, witem, ident, signal, force_running, stack=stack)
+ workitem.process(cr, witem, ident, signal, force_running, stack=stack, context=context)
# An action is returned
- _update_end(cr, inst_id, ident)
+ _update_end(cr, inst_id, ident, context)
return stack and stack[0] or False
-def update(cr, inst_id, ident):
+def update(cr, inst_id, ident, context=None):
cr.execute("select * from wkf_workitem where inst_id=%s", (inst_id,))
for witem in cr.dictfetchall():
stack = []
- workitem.process(cr, witem, ident, stack=stack)
- return _update_end(cr, inst_id, ident)
+ workitem.process(cr, witem, ident, stack=stack, context=context)
+ return _update_end(cr, inst_id, ident, context)
-def _update_end(cr, inst_id, ident):
+def _update_end(cr, inst_id, ident, context=None):
cr.execute('select wkf_id from wkf_instance where id=%s', (inst_id,))
wkf_id = cr.fetchone()[0]
cr.execute('select state,flow_stop from wkf_workitem w left join wkf_activity a on (a.id=w.act_id) where w.inst_id=%s', (inst_id,))
@@ -74,7 +74,7 @@
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)", (inst_id,))
for i in cr.fetchall():
for act_name in act_names:
- validate(cr, i[0], (ident[0],i[1],i[2]), 'subflow.'+act_name[0])
+ validate(cr, i[0], (ident[0],i[1],i[2]), 'subflow.'+act_name[0], context)
return ok
=== modified file 'openerp/workflow/wkf_expr.py'
--- openerp/workflow/wkf_expr.py 2011-09-14 10:25:05 +0000
+++ openerp/workflow/wkf_expr.py 2011-12-13 17:01:27 +0000
@@ -26,22 +26,23 @@
from openerp.tools.safe_eval import safe_eval as eval
class Env(dict):
- def __init__(self, cr, uid, model, ids):
+ def __init__(self, cr, uid, model, ids, context=None):
self.cr = cr
self.uid = uid
self.model = model
self.ids = ids
+ self.context = context
self.obj = pooler.get_pool(cr.dbname).get(model)
self.columns = self.obj._columns.keys() + self.obj._inherit_fields.keys()
def __getitem__(self, key):
if (key in self.columns) or (key in dir(self.obj)):
- res = self.obj.browse(self.cr, self.uid, self.ids[0])
+ res = self.obj.browse(self.cr, self.uid, self.ids[0], self.context)
return res[key]
else:
return super(Env, self).__getitem__(key)
-def _eval_expr(cr, ident, workitem, action):
+def _eval_expr(cr, ident, workitem, action, context=None):
ret=False
assert action, 'You used a NULL action in a workflow, use dummy node instead.'
for line in action.split('\n'):
@@ -54,20 +55,23 @@
elif line =='False':
ret=False
else:
- env = Env(cr, uid, model, ids)
+ env = Env(cr, uid, model, ids, context)
ret = eval(line, env, nocopy=True)
return ret
-def execute_action(cr, ident, workitem, activity):
+def execute_action(cr, ident, workitem, activity, context=None):
obj = pooler.get_pool(cr.dbname).get('ir.actions.server')
+ ctx = {}
+ if context is not None:
+ ctx.update( context )
ctx = {'active_model':ident[1], 'active_id':ident[2], 'active_ids':[ident[2]]}
result = obj.run(cr, ident[0], [activity['action_id']], ctx)
return result
-def execute(cr, ident, workitem, activity):
- return _eval_expr(cr, ident, workitem, activity['action'])
+def execute(cr, ident, workitem, activity, context=None):
+ return _eval_expr(cr, ident, workitem, activity['action'], context)
-def check(cr, workitem, ident, transition, signal):
+def check(cr, workitem, ident, transition, signal, context=None):
if transition['signal'] and signal != transition['signal']:
return False
@@ -78,8 +82,7 @@
if not transition['group_id'] in user_groups:
return False
- return _eval_expr(cr, ident, workitem, transition['condition'])
-
+ return _eval_expr(cr, ident, workitem, transition['condition'], context)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== modified file 'openerp/workflow/wkf_service.py'
--- openerp/workflow/wkf_service.py 2011-09-24 14:52:58 +0000
+++ openerp/workflow/wkf_service.py 2011-12-13 17:01:27 +0000
@@ -44,7 +44,10 @@
def clear_cache(self, cr, uid):
self.wkf_on_create_cache[cr.dbname]={}
- def trg_write(self, uid, res_type, res_id, cr):
+ def trg_write(self, uid, res_type, res_id, cr, context=None):
+ print "WWWWWWWWWWWWW", context
+ import traceback
+ traceback.print_stack()
"""
Reevaluates the specified workflow instance. Thus if any condition for
a transition have been changed in the backend, then running ``trg_write``
@@ -57,9 +60,10 @@
ident = (uid,res_type,res_id)
cr.execute('select id from wkf_instance where res_id=%s and res_type=%s and state=%s', (res_id or None,res_type or None, 'active'))
for (id,) in cr.fetchall():
- instance.update(cr, id, ident)
+ instance.update(cr, id, ident, context)
- def trg_trigger(self, uid, res_type, res_id, cr):
+ def trg_trigger(self, uid, res_type, res_id, cr, context=None):
+ print "TTTTTTTTTTTTTTT", context
"""
Activate a trigger.
@@ -75,7 +79,7 @@
for (instance_id,) in res:
cr.execute('select %s,res_type,res_id from wkf_instance where id=%s', (uid, instance_id,))
ident = cr.fetchone()
- instance.update(cr, instance_id, ident)
+ instance.update(cr, instance_id, ident, context)
def trg_delete(self, uid, res_type, res_id, cr):
"""
@@ -88,7 +92,7 @@
ident = (uid,res_type,res_id)
instance.delete(cr, ident)
- def trg_create(self, uid, res_type, res_id, cr):
+ def trg_create(self, uid, res_type, res_id, cr, context=None):
"""
Create a new workflow instance
@@ -105,9 +109,10 @@
wkf_ids = cr.fetchall()
self.wkf_on_create_cache[cr.dbname][res_type] = wkf_ids
for (wkf_id,) in wkf_ids:
- instance.create(cr, ident, wkf_id)
+ instance.create(cr, ident, wkf_id, context)
- def trg_validate(self, uid, res_type, res_id, signal, cr):
+ def trg_validate(self, uid, res_type, res_id, signal, cr, context=None):
+ print "VVVVVVVVVVV", context
"""
Fire a signal on a given workflow instance
@@ -121,7 +126,7 @@
# ids of all active workflow instances for a corresponding resource (id, model_nam)
cr.execute('select id from wkf_instance where res_id=%s and res_type=%s and state=%s', (res_id, res_type, 'active'))
for (id,) in cr.fetchall():
- res2 = instance.validate(cr, id, ident, signal)
+ res2 = instance.validate(cr, id, ident, signal, context=context)
result = result or res2
return result
=== modified file 'openerp/workflow/workitem.py'
--- openerp/workflow/workitem.py 2011-12-11 10:21:40 +0000
+++ openerp/workflow/workitem.py 2011-12-13 17:01:27 +0000
@@ -30,7 +30,7 @@
import wkf_expr
import wkf_logs
-def create(cr, act_datas, inst_id, ident, stack):
+def create(cr, act_datas, inst_id, ident, stack, context=None):
for act in act_datas:
cr.execute("select nextval('wkf_workitem_id_seq')")
id_new = cr.fetchone()[0]
@@ -38,9 +38,9 @@
cr.execute('select * from wkf_workitem where id=%s',(id_new,))
res = cr.dictfetchone()
wkf_logs.log(cr,ident,act['id'],'active')
- process(cr, res, ident, stack=stack)
+ process(cr, res, ident, stack=stack, context=context)
-def process(cr, workitem, ident, signal=None, force_running=False, stack=None):
+def process(cr, workitem, ident, signal=None, force_running=False, stack=None, context=None):
if stack is None:
raise 'Error !!!'
result = True
@@ -50,7 +50,7 @@
triggers = False
if workitem['state']=='active':
triggers = True
- result = _execute(cr, workitem, activity, ident, stack)
+ result = _execute(cr, workitem, activity, ident, stack, context)
if not result:
return False
@@ -58,7 +58,7 @@
pass
if workitem['state']=='complete' or force_running:
- ok = _split_test(cr, workitem, activity['split_mode'], ident, signal, stack)
+ ok = _split_test(cr, workitem, activity['split_mode'], ident, signal, stack, context)
triggers = triggers and not ok
if triggers:
@@ -66,7 +66,7 @@
alltrans = cr.dictfetchall()
for trans in alltrans:
if trans['trigger_model']:
- ids = wkf_expr._eval_expr(cr,ident,workitem,trans['trigger_expr_id'])
+ ids = wkf_expr._eval_expr(cr,ident,workitem,trans['trigger_expr_id'], context)
for res_id in ids:
cr.execute('select nextval(\'wkf_triggers_id_seq\')')
id =cr.fetchone()[0]
@@ -82,7 +82,7 @@
workitem['state'] = state
wkf_logs.log(cr,ident,activity['id'],state)
-def _execute(cr, workitem, activity, ident, stack):
+def _execute(cr, workitem, activity, ident, stack, context=None):
result = True
#
# send a signal to parent workflow (signal: subflow.signal_name)
@@ -97,18 +97,18 @@
if workitem['state']=='active':
_state_set(cr, workitem, activity, 'complete', ident)
if activity['action_id']:
- res2 = wkf_expr.execute_action(cr, ident, workitem, activity)
+ res2 = wkf_expr.execute_action(cr, ident, workitem, activity, context)
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)
+ returned_action = wkf_expr.execute(cr, ident, workitem, activity, context)
if type(returned_action) in (dict,):
stack.append(returned_action)
if activity['action_id']:
- res2 = wkf_expr.execute_action(cr, ident, workitem, activity)
+ res2 = wkf_expr.execute_action(cr, ident, workitem, activity, context)
# A client action has been returned
if res2:
stack.append(res2)
@@ -119,13 +119,13 @@
_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)
+ wkf_expr.execute(cr, ident, workitem, activity, context)
_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)
+ id_new = wkf_expr.execute(cr, ident, workitem, activity, context)
if not (id_new):
cr.execute('delete from wkf_workitem where id=%s', (workitem['id'],))
return False
@@ -133,7 +133,7 @@
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'])
+ id_new = instance.create(cr, ident, activity['subflow_id'], context)
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':
@@ -142,11 +142,11 @@
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)
+ instance.validate(cr, t[0], t[1], t[2], force_running=True, context=context)
return result
-def _split_test(cr, workitem, split_mode, ident, signal=None, stack=None):
+def _split_test(cr, workitem, split_mode, ident, signal=None, stack=None, context=None):
if stack is None:
raise 'Error !!!'
cr.execute('select * from wkf_transition where act_from=%s', (workitem['act_id'],))
@@ -155,7 +155,7 @@
alltrans = cr.dictfetchall()
if split_mode=='XOR' or split_mode=='OR':
for transition in alltrans:
- if wkf_expr.check(cr, workitem, ident, transition,signal):
+ if wkf_expr.check(cr, workitem, ident, transition, signal, context):
test = True
transitions.append((transition['id'], workitem['inst_id']))
if split_mode=='XOR':
@@ -163,7 +163,7 @@
else:
test = True
for transition in alltrans:
- if not wkf_expr.check(cr, workitem, ident, transition,signal):
+ if not wkf_expr.check(cr, workitem, ident, transition, signal, context):
test = False
break
cr.execute('select count(*) from wkf_witm_trans where trans_id=%s and inst_id=%s', (transition['id'], workitem['inst_id']))
@@ -173,15 +173,15 @@
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'],))
for t in transitions:
- _join_test(cr, t[0], t[1], ident, stack)
+ _join_test(cr, t[0], t[1], ident, stack, context)
return True
return False
-def _join_test(cr, trans_id, inst_id, ident, stack):
+def _join_test(cr, trans_id, inst_id, ident, stack, context=None):
cr.execute('select * from wkf_activity where id=(select act_to from wkf_transition where id=%s)', (trans_id,))
activity = cr.dictfetchone()
if activity['join_mode']=='XOR':
- create(cr,[activity], inst_id, ident, stack)
+ create(cr,[activity], inst_id, ident, stack, context)
cr.execute('delete from wkf_witm_trans where inst_id=%s and trans_id=%s', (inst_id,trans_id))
else:
cr.execute('select id from wkf_transition where act_to=%s', (activity['id'],))
@@ -196,7 +196,7 @@
if ok:
for (id,) in trans_ids:
cr.execute('delete from wkf_witm_trans where trans_id=%s and inst_id=%s', (id,inst_id))
- create(cr, [activity], inst_id, ident, stack)
+ create(cr, [activity], inst_id, ident, stack, context)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
Follow ups